Skip to content

Commit a4eaff9

Browse files
authored
Merge pull request #3 from duplojs/feat/1
feat(01): toJsonSchema
2 parents 1846407 + c99d8f5 commit a4eaff9

102 files changed

Lines changed: 4175 additions & 47 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

integration/.gitkeep

Whitespace-only changes.

integration/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"name": "integrations",
33
"type": "module",
44
"scripts": {
5-
"test:int:to-ts": "tsx ./toTypescript/index.ts"
5+
"test:int:to-ts": "tsx ./toTypescript/index.ts",
6+
"test:int:to-json": "tsx ./toJsonSchema/index.ts"
67
},
78
"dependencies": {
89
"@duplojs/data-parser-tools": "file:.."
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`integration 1`] = `
4+
{
5+
"$ref": "#/definitions/UserProfile",
6+
"$schema": "http://json-schema.org/draft-07/schema#",
7+
"definitions": {
8+
"UserProfile": {
9+
"properties": {
10+
"address": {
11+
"properties": {
12+
"city": {
13+
"type": "string",
14+
},
15+
"country": {
16+
"const": "FR",
17+
"type": "string",
18+
},
19+
"street": {
20+
"type": "string",
21+
},
22+
"zip": {
23+
"pattern": "^\\\\d{5}$",
24+
"type": "string",
25+
},
26+
},
27+
"required": [
28+
"street",
29+
"city",
30+
"zip",
31+
"country",
32+
],
33+
"type": "object",
34+
},
35+
"age": {
36+
"anyOf": [
37+
{
38+
"minimum": 0,
39+
"type": "number",
40+
},
41+
{
42+
"type": "string",
43+
},
44+
],
45+
},
46+
"contact": {
47+
"anyOf": [
48+
{
49+
"properties": {
50+
"phone": {
51+
"pattern": "^[+\\\\d][\\\\d\\\\s-]{5,}$",
52+
"type": "string",
53+
},
54+
},
55+
"required": [
56+
"phone",
57+
],
58+
"type": "object",
59+
},
60+
{
61+
"properties": {
62+
"email": {
63+
"format": "email",
64+
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\\.)+[A-Za-z]{2,}$",
65+
"type": "string",
66+
},
67+
},
68+
"required": [
69+
"email",
70+
],
71+
"type": "object",
72+
},
73+
],
74+
},
75+
"createdAt": {
76+
"anyOf": [
77+
{
78+
"format": "date-time",
79+
"pattern": "^date(?<value>\\d{1,16})(?<sign>[+-])$",
80+
"type": "string",
81+
},
82+
{
83+
"type": "number",
84+
},
85+
{
86+
"format": "date",
87+
"type": "string",
88+
},
89+
{
90+
"format": "date-time",
91+
"type": "string",
92+
},
93+
],
94+
},
95+
"email": {
96+
"format": "email",
97+
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\\.)+[A-Za-z]{2,}$",
98+
"type": "string",
99+
},
100+
"id": {
101+
"pattern": "^(?:user\\-)(?:[0-9]+(\\.[0-9]+)?)(?:\\-db1)$",
102+
"type": "string",
103+
},
104+
"location": {
105+
"additionalItems": {
106+
"type": "number",
107+
},
108+
"items": [
109+
{
110+
"type": "number",
111+
},
112+
{
113+
"type": "number",
114+
},
115+
],
116+
"minItems": 2,
117+
"type": "array",
118+
},
119+
"metadata": {
120+
"additionalProperties": {
121+
"type": "string",
122+
},
123+
"propertyNames": {
124+
"type": "string",
125+
},
126+
"type": "object",
127+
},
128+
"name": {
129+
"minLength": 2,
130+
"type": "string",
131+
},
132+
"preferences": {
133+
"anyOf": [
134+
{
135+
"properties": {
136+
"newsletter": {
137+
"type": "boolean",
138+
},
139+
"theme": {
140+
"anyOf": [
141+
{
142+
"const": "light",
143+
"type": "string",
144+
},
145+
{
146+
"const": "dark",
147+
"type": "string",
148+
},
149+
],
150+
},
151+
},
152+
"required": [
153+
"theme",
154+
"newsletter",
155+
],
156+
"type": "object",
157+
},
158+
{
159+
"type": "null",
160+
},
161+
],
162+
},
163+
"role": {
164+
"anyOf": [
165+
{
166+
"const": "admin",
167+
"type": "string",
168+
},
169+
{
170+
"const": "editor",
171+
"type": "string",
172+
},
173+
{
174+
"const": "viewer",
175+
"type": "string",
176+
},
177+
],
178+
},
179+
"roles": {
180+
"items": {
181+
"anyOf": [
182+
{
183+
"const": "admin",
184+
"type": "string",
185+
},
186+
{
187+
"const": "editor",
188+
"type": "string",
189+
},
190+
{
191+
"const": "viewer",
192+
"type": "string",
193+
},
194+
],
195+
},
196+
"minItems": 1,
197+
"type": "array",
198+
},
199+
},
200+
"required": [
201+
"id",
202+
"name",
203+
"email",
204+
"role",
205+
"contact",
206+
"address",
207+
"roles",
208+
"preferences",
209+
"metadata",
210+
"location",
211+
"createdAt",
212+
],
213+
"type": "object",
214+
},
215+
},
216+
}
217+
`;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { render, defaultTransformers } from "@duplojs/data-parser-tools/toJsonSchema";
2+
import { DPE } from "@duplojs/utils";
3+
4+
it("integration", () => {
5+
const userSchema = DPE.object({
6+
id: DPE.templateLiteral(["user-", DPE.number(), "-db1"]),
7+
name: DPE.string().min(2),
8+
email: DPE.email(),
9+
role: DPE.literal(["admin", "editor", "viewer"]),
10+
age: DPE.coerce.number().min(0).optional(),
11+
contact: DPE.union([
12+
DPE.object({
13+
phone: DPE.string().regex(/^[+\\d][\\d\\s-]{5,}$/),
14+
}),
15+
DPE.object({
16+
email: DPE.email(),
17+
}),
18+
]),
19+
address: DPE.object({
20+
street: DPE.string(),
21+
city: DPE.string(),
22+
zip: DPE.string().regex(/^\\d{5}$/),
23+
country: DPE.literal("FR"),
24+
}),
25+
roles: DPE.literal(["admin", "editor", "viewer"]).array().min(1),
26+
preferences: DPE.object({
27+
theme: DPE.literal(["light", "dark"]),
28+
newsletter: DPE.boolean(),
29+
}).nullable(),
30+
metadata: DPE.record(DPE.string(), DPE.string(), { requireKey: null }),
31+
location: DPE.tuple([DPE.number(), DPE.number()], { rest: DPE.number() }),
32+
createdAt: DPE.date({ coerce: true }),
33+
}).addIdentifier("UserProfile");
34+
35+
const result = render(
36+
userSchema,
37+
{
38+
identifier: "UserProfile",
39+
mode: "in",
40+
transformers: defaultTransformers,
41+
version: "jsonSchema7",
42+
},
43+
);
44+
45+
expect(result).toMatchSnapshot();
46+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`integration 1`] = `
4+
"export type UserProfile = {
5+
id: \`user-\${number}-db1\`;
6+
name: string;
7+
email: string;
8+
role: "admin" | "editor" | "viewer";
9+
age: number;
10+
contact: {
11+
phone: string;
12+
} | {
13+
email: string;
14+
};
15+
address: {
16+
street: string;
17+
city: string;
18+
zip: string;
19+
country: "FR";
20+
};
21+
roles: ("admin" | "editor" | "viewer")[];
22+
preferences: {
23+
theme: "light" | "dark";
24+
newsletter: boolean;
25+
};
26+
metadata: Record<string, string>;
27+
location: [
28+
number,
29+
number,
30+
number
31+
];
32+
createdAt: \`date\${number}\${"-" | "+"}\`;
33+
};"
34+
`;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { render, defaultTransformers } from "@duplojs/data-parser-tools/toTypescript";
2+
import { DPE } from "@duplojs/utils";
3+
4+
it("integration", () => {
5+
const userSchema = DPE.object({
6+
id: DPE.templateLiteral(["user-", DPE.number(), "-db1"]),
7+
name: DPE.string().min(2),
8+
email: DPE.email(),
9+
role: DPE.literal(["admin", "editor", "viewer"]),
10+
age: DPE.coerce.number().min(0).optional(),
11+
contact: DPE.union([
12+
DPE.object({
13+
phone: DPE.string().regex(/^[+\\d][\\d\\s-]{5,}$/),
14+
}),
15+
DPE.object({
16+
email: DPE.email(),
17+
}),
18+
]),
19+
address: DPE.object({
20+
street: DPE.string(),
21+
city: DPE.string(),
22+
zip: DPE.string().regex(/^\\d{5}$/),
23+
country: DPE.literal("FR"),
24+
}),
25+
roles: DPE.literal(["admin", "editor", "viewer"]).array().min(1),
26+
preferences: DPE.object({
27+
theme: DPE.literal(["light", "dark"]),
28+
newsletter: DPE.boolean(),
29+
}).nullable(),
30+
metadata: DPE.record(DPE.string(), DPE.string(), { requireKey: null }),
31+
location: DPE.tuple([DPE.number(), DPE.number()], { rest: DPE.number() }),
32+
createdAt: DPE.date({ coerce: true }),
33+
}).addIdentifier("UserProfile");
34+
35+
const result = render(
36+
userSchema,
37+
{
38+
identifier: "UserProfile",
39+
mode: "out",
40+
transformers: defaultTransformers,
41+
},
42+
);
43+
44+
expect(result).toMatchSnapshot();
45+
});

integration/toTypescript/index.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)