Skip to content

Commit 3c3cc59

Browse files
authored
Merge pull request #2 from cloudflare/celso/oneOf-fix
oneOf defaults support
2 parents d93d97f + 4e954b7 commit 3c3cc59

File tree

11 files changed

+300
-58
lines changed

11 files changed

+300
-58
lines changed

README.md

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
</a>
55
</div>
66

7-
87
<p align="center">
98
<em>Small, fast, eval-less, <a href="https://developers.cloudflare.com/workers/">Cloudflare Workers</a> compatible, dynamic JSON Schema validator.</em>
109
</p>
@@ -136,6 +135,51 @@ console.log(payload);
136135

137136
```
138137

138+
### oneOf defaults
139+
140+
Using `applyDefaults` with `oneOf` will one apply the default value of the sub-schema that matches the condition. For
141+
example, using this schema:
142+
143+
```javascript
144+
{
145+
type: "object",
146+
oneOf: [
147+
{
148+
type: "object",
149+
properties: {
150+
sun: {
151+
type: "number",
152+
default: 9000,
153+
},
154+
moon: {
155+
type: "number",
156+
default: 9000,
157+
},
158+
},
159+
required: ["sun"],
160+
},
161+
{
162+
type: "object",
163+
properties: {
164+
sun: {
165+
type: "number",
166+
default: 9000,
167+
},
168+
moon: {
169+
type: "number",
170+
default: 9000,
171+
},
172+
},
173+
required: ["moon"],
174+
},
175+
],
176+
};
177+
```
178+
179+
- The payload `{ sun: 10}` will be modified to `{ sun: 10, moon: 9000 }`.
180+
- The payload `{ moon: 10}` will be modified to `{ sun: 9000, moon: 10 }`.
181+
- The payload `{ saturn: 10}` will throw an error because no condition is met.
182+
139183
## Custom errors
140184

141185
If the new instance options has the `errorMessages` flag set to true, you can use the property `errorMessage` in the schema to define custom error messages.
@@ -160,7 +204,7 @@ const payload = {
160204

161205
cabidela.validate(payload);
162206
// throws "Error: prompt required"
163-
```
207+
````
164208

165209
## Tests
166210

@@ -236,7 +280,6 @@ We use Vitest's [bench](https://vitest.dev/api/#bench) feature to run the benchm
236280
npm run benchmark
237281
```
238282

239-
240283
## Current limitations
241284

242285
Cabidela supports most of JSON Schema specification, and should be useful for many applications, but it's not complete. **Currently** we do not support:
@@ -249,4 +292,3 @@ Cabidela supports most of JSON Schema specification, and should be useful for ma
249292
- `$ref`, `$defs` and `$id`
250293
251294
yet.
252-

demo/app/editor.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,15 @@ const codeValidators: any = {
1010
};
1111

1212
export const Editor = (props: any = {}) => {
13-
useEffect(() => {
14-
}, []);
13+
useEffect(() => {}, []);
1514

1615
return (
1716
<>
1817
<div className={`code overflow-auto`}>
1918
<ReactEditor
2019
value={props.content || ""}
2120
onValueChange={(code) => {
22-
props.setContent(code);
21+
props.setContent && props.setContent(code);
2322
}}
2423
highlight={(code) => {
2524
return props.validation && languages[props.validation]

demo/app/index.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import "~/common/styles/index.scss";
22
import React, { useContext, useEffect, useState } from "react";
33
import ReactDOM from "react-dom/client";
4-
import { Cabidela } from "@cloudflare/cabidela";
4+
import { Cabidela } from "../..";
55
import { Editor } from "./editor";
66
import { isJSON } from "./tools";
77
import { payloadExamples } from "./payloads";
@@ -14,6 +14,8 @@ const Validator = () => {
1414
select: 0,
1515
}) as any;
1616

17+
const [modified, setModified] = useState(false);
18+
1719
const [error, setError] = useState([] as Array<string>);
1820

1921
useEffect(() => {
@@ -24,10 +26,18 @@ const Validator = () => {
2426
if (!isJSON(forms.payload)) {
2527
errors.push("Payload is not valid JSON");
2628
}
29+
let payload;
2730
try {
28-
const cabidela = new Cabidela(JSON5.parse(forms.schema));
29-
cabidela.validate(JSON5.parse(forms.payload));
31+
payload = JSON5.parse(forms.payload);
32+
const cabidela = new Cabidela(JSON5.parse(forms.schema), { applyDefaults: true });
33+
cabidela.validate(payload);
34+
if (JSON.stringify(payload) !== JSON.stringify(JSON5.parse(forms.payload))) {
35+
setModified(payload);
36+
} else {
37+
setModified(false);
38+
}
3039
} catch (e: any) {
40+
setModified(false);
3141
errors.push(e.message);
3242
}
3343
setError(errors);
@@ -95,7 +105,6 @@ const Validator = () => {
95105
validation="json"
96106
content={forms.schema}
97107
setContent={(c: string) => {
98-
console.log("setting schema");
99108
setForms({ ...forms, schema: c });
100109
}}
101110
/>
@@ -108,11 +117,20 @@ const Validator = () => {
108117
validation="json"
109118
content={forms.payload}
110119
setContent={(c: string) => {
111-
console.log("setting schema");
112120
setForms({ ...forms, payload: c });
113121
}}
114122
/>
115123
</label>
124+
{modified && (
125+
<label>
126+
<span>Modified payload</span>
127+
<Editor
128+
validation="json"
129+
content={JSON5.stringify(modified, { replacer: null, space: 2, quote: '"' })}
130+
setContent={false}
131+
/>
132+
</label>
133+
)}
116134
</div>
117135
</div>
118136

@@ -132,8 +150,6 @@ const Validator = () => {
132150
<a href="https://github.com/cloudflare/cabidela">https://github.com/cloudflare/cabidela</a>
133151
</p>
134152
</div>
135-
136-
137153
</div>
138154
</>
139155
);

demo/app/payloads.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const payloadExamples = [
2222
{ type: "number", multipleOf: 3 },
2323
],
2424
},
25-
payload: 5
25+
payload: 5,
2626
},
2727
{
2828
title: "Two required properties",
@@ -134,4 +134,42 @@ export const payloadExamples = [
134134
prompt: "this doesn't make sense",
135135
},
136136
},
137+
{
138+
title: "oneOf defaults",
139+
schema: {
140+
type: "object",
141+
oneOf: [
142+
{
143+
properties: {
144+
sun: {
145+
type: "number",
146+
},
147+
moon: {
148+
type: "number",
149+
default: 9000,
150+
},
151+
flowers: {
152+
type: "number",
153+
default: 9000,
154+
},
155+
},
156+
required: ["sun"],
157+
},
158+
{
159+
properties: {
160+
sun: {
161+
type: "number",
162+
default: 9000,
163+
},
164+
moon: {
165+
type: "number",
166+
default: 9000,
167+
},
168+
},
169+
required: ["moon"],
170+
},
171+
],
172+
},
173+
payload: { sun: 10 },
174+
},
137175
];

demo/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"author": "",
1717
"license": "ISC",
1818
"devDependencies": {
19-
"@cloudflare/cabidela": "^0.0.17",
2019
"@headlessui/tailwindcss": "^0.2.1",
2120
"@rollup/plugin-commonjs": "^25.0.7",
2221
"@rollup/plugin-json": "^6.1.0",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cloudflare/cabidela",
3-
"version": "0.0.18",
3+
"version": "0.0.19",
44
"description": "Cabidela is a small, fast, eval-less, Cloudflare Workers compatible, dynamic JSON Schema validator",
55
"main": "dist/index.js",
66
"module": "dist/index.mjs",

src/helpers.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export type metaData = {
22
types: Set<string>;
33
size: number;
4-
properties: Set<string>;
4+
properties: Array<string>;
55
};
66

77
export type resolvedResponse = {
@@ -56,8 +56,8 @@ export const pathToString = (path: Array<string | number>) => {
5656

5757
export const getMetaData = (value: any): metaData => {
5858
let size = 0;
59-
let types = new Set([]);
60-
let properties = new Set([]);
59+
let types:any = new Set([]);
60+
let properties:any = [];
6161
if (value === null) {
6262
types.add("null");
6363
} else if (typeof value == "string") {
@@ -81,7 +81,7 @@ export const getMetaData = (value: any): metaData => {
8181
} else if (typeof value == "object") {
8282
types.add("object");
8383
size = Object.keys(value).length;
84-
properties = new Set(Object.keys(value));
84+
properties = Object.keys(value);
8585
}
8686
return { types, size, properties };
8787
};

0 commit comments

Comments
 (0)