Skip to content

Commit 5774d0f

Browse files
authored
Merge pull request #56 from x0k/omit-extra-data
Omit extra data
2 parents 8c1393d + bb51624 commit 5774d0f

15 files changed

+1659
-374
lines changed

.changeset/late-roses-cheat.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sjsf/form": minor
3+
---
4+
5+
Add omit extra data submodule

.changeset/ten-gorillas-accept.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"docs": patch
3+
---
4+
5+
Update state transformation guide

.changeset/twelve-papayas-reply.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sjsf/sveltekit": patch
3+
---
4+
5+
Reuse core schema utils

apps/docs/src/content/docs/advanced/state-transformation.mdx

+3-7
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ For this you can use `omitExtraData` function.
1616

1717
:::note
1818

19-
Currently function `omitExtraData` is imported from `@sjsf/form/legacy-omit-extra-data` and
20-
will be deprecated because it's implementation does not meet the requirements of our code base.
21-
22-
It will be replaced with `@sjsf/form/omit-extra-data` import in the major release.
19+
The `omitExtraData` function does not perform data validation!
2320

2421
:::
2522

@@ -29,11 +26,10 @@ It will be replaced with `@sjsf/form/omit-extra-data` import in the major releas
2926
import { createForm3 } from "@sjsf/form";
3027
import { translation } from "@sjsf/form/translations/en";
3128
import { theme } from "@sjsf/form/basic-theme";
32-
import { omitExtraData2 } from "@sjsf/form/legacy-omit-extra-data";
29+
import { omitExtraData } from "@sjsf/form/omit-extra-data";
3330
3431
import { schema, uiSchema, initialValue } from "./schema";
3532
import { validator } from "./validator";
36-
import { transform } from "./transform";
3733
3834
const form = createForm3({
3935
...theme,
@@ -43,7 +39,7 @@ It will be replaced with `@sjsf/form/omit-extra-data` import in the major releas
4339
validator,
4440
translation,
4541
getSnapshot() {
46-
return omitExtraData2(validator, defaultMerger, schema, $state.snapshot(form.formValue))
42+
return omitExtraData(validator, defaultMerger, schema, $state.snapshot(form.formValue))
4743
},
4844
onSubmit(value) {
4945
console.log("transformed", value);

packages/form/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@
8282
"types": "./dist/focus-on-first-error.d.ts",
8383
"svelte": "./dist/focus-on-first-error.js"
8484
},
85+
"./omit-extra-data": {
86+
"types": "./dist/omit-extra-data.d.ts",
87+
"default": "./dist/omit-extra-data.js"
88+
},
8589
"./legacy-omit-extra-data": {
8690
"types": "./dist/legacy-omit-extra-data.d.ts",
8791
"default": "./dist/legacy-omit-extra-data.js"

packages/form/src/core/definitions.ts

+21-8
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,37 @@
44

55
import jsonpointer from "jsonpointer";
66

7-
import { REF_KEY, type Schema } from "./schema.js";
7+
import {
8+
isSchema,
9+
REF_KEY,
10+
type Schema,
11+
type SchemaDefinition,
12+
} from "./schema.js";
813
import { mergeSchemas } from "./merge.js";
914

10-
export function findSchemaDefinition(
11-
ref: string,
12-
rootSchema: Schema,
13-
stack = new Set<string>()
14-
): Schema {
15+
export function resolveRef(ref: string, rootSchema: Schema) {
1516
if (!ref.startsWith("#")) {
1617
throw new Error(`Invalid reference: ${ref}, must start with #`);
1718
}
18-
const current: Schema | undefined = jsonpointer.get(
19+
const schemaDef: SchemaDefinition | undefined = jsonpointer.get(
1920
rootSchema,
2021
decodeURIComponent(ref.substring(1))
2122
);
22-
if (current === undefined) {
23+
if (schemaDef === undefined) {
2324
throw new Error(`Could not find a definition for ${ref}.`);
2425
}
26+
return schemaDef;
27+
}
28+
29+
export function findSchemaDefinition(
30+
ref: string,
31+
rootSchema: Schema,
32+
stack = new Set<string>()
33+
): Schema {
34+
const current = resolveRef(ref, rootSchema);
35+
if (!isSchema(current)) {
36+
throw new Error(`Definition for ${ref} should be a schema (object)`);
37+
}
2538
const nextRef = current[REF_KEY];
2639
if (nextRef) {
2740
// Check for circular references.

packages/form/src/core/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export * from "./value.js";
66
export * from "./is-select.js";
77
export * from "./default-state.js";
88
export * from "./merge.js";
9+
export * from "./definitions.js";
910
export * from "./order-properties.js";
1011
export * from "./is-additional-property.js";
1112
export * from "./is-file-schema.js";
@@ -25,3 +26,4 @@ export * from "./schema-value-traverser.js";
2526
export * from "./schema-transformer.js";
2627
export * from "./path.js";
2728
export * from "./deep-equal.js";
29+
export * from "./known-properties.js";
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { resolveRef } from "./definitions.js";
2+
import { isSchema, type Schema } from "./schema.js";
3+
4+
export function* getKnownProperties(
5+
{ $ref: ref, properties, dependencies, oneOf, allOf, anyOf }: Schema,
6+
rootSchema: Schema,
7+
stack = new Set<string>()
8+
): Generator<string> {
9+
if (ref) {
10+
if (stack.has(ref)) {
11+
return;
12+
}
13+
stack.add(ref);
14+
const resolved = resolveRef(ref, rootSchema);
15+
if (isSchema(resolved)) {
16+
yield* getKnownProperties(resolved, rootSchema, stack);
17+
}
18+
return;
19+
}
20+
if (properties) {
21+
for (const key of Object.keys(properties)) {
22+
yield key;
23+
}
24+
}
25+
for (const alternatives of [oneOf, allOf, anyOf]) {
26+
if (Array.isArray(alternatives)) {
27+
for (const alternative of alternatives) {
28+
if (isSchema(alternative)) {
29+
yield* getKnownProperties(alternative, rootSchema, stack);
30+
}
31+
}
32+
}
33+
}
34+
if (dependencies !== undefined) {
35+
for (const dependency of Object.values(dependencies)) {
36+
if (!Array.isArray(dependency) && isSchema(dependency)) {
37+
yield* getKnownProperties(dependency, rootSchema, stack);
38+
}
39+
}
40+
}
41+
}

packages/form/src/core/type.ts

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Schema, SchemaType } from "./schema.js";
1+
import { isSchema, type Schema, type SchemaType } from "./schema.js";
22

33
export function typeOfValue(
44
value: null | boolean | number | string | object
@@ -29,12 +29,29 @@ export function typeOfSchema(schema: Schema): SchemaType | SchemaType[] {
2929
if (schema.const !== undefined) {
3030
return typeOfValue(schema.const);
3131
}
32-
if (schema.properties || schema.additionalProperties) {
32+
if (
33+
schema.properties ||
34+
schema.additionalProperties ||
35+
schema.propertyNames ||
36+
schema.patternProperties
37+
) {
3338
return "object";
3439
}
3540
if (Array.isArray(schema.enum) && schema.enum.length > 0) {
3641
return Array.from(new Set(schema.enum.map(typeOfValue)));
3742
}
43+
const alt = schema.allOf ?? schema.anyOf ?? schema.oneOf;
44+
if (alt) {
45+
let types: SchemaType[] = [];
46+
for (let i = 0; i < alt.length; i++) {
47+
const item = alt[i]!;
48+
if (!isSchema(item)) {
49+
continue;
50+
}
51+
types = types.concat(typeOfSchema(item));
52+
}
53+
return Array.from(new Set(types));
54+
}
3855
return "null";
3956
}
4057

packages/form/src/legacy-omit-extra-data.ts

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ export function omitExtraData(
7373
return omitExtraData2(validator, merger, schema, formData);
7474
}
7575

76+
/**
77+
* @deprecated use `omitExtraData` from `form/omit-extra-data` instead
78+
*/
7679
export function omitExtraData2(
7780
validator: Validator,
7881
merger: Merger2,

0 commit comments

Comments
 (0)