Skip to content

Commit fd40b74

Browse files
committed
[sveltekit] Refactor form data entry converter
1 parent c204d6e commit fd40b74

File tree

8 files changed

+94
-87
lines changed

8 files changed

+94
-87
lines changed

.changeset/real-flowers-bathe.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sjsf/sveltekit": major
3+
---
4+
5+
Refactor form data entry converter

packages/sveltekit/src/lib/server/convert-form-data-entries.test.ts renamed to packages/sveltekit/src/lib/server/convert-form-data-entry.test.ts

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { beforeEach, describe, expect, it } from 'vitest';
2-
import type { Schema } from '@sjsf/form/core';
2+
import type { RPath, Schema } from '@sjsf/form/core';
33
import { createMerger } from '@sjsf/form/mergers/modern';
44
import { createFormValidator } from '@sjsf/ajv8-validator';
55

66
import {
7-
createFormDataEntriesConverter,
7+
createFormDataEntryConverter,
88
type FormDataConverterOptions
9-
} from './convert-form-data-entries.js';
10-
import type { Entries } from './entry.js';
9+
} from './convert-form-data-entry.js';
1110

1211
const defaultOptions: FormDataConverterOptions = {
1312
validator: createFormValidator(),
@@ -16,7 +15,7 @@ const defaultOptions: FormDataConverterOptions = {
1615
rootUiSchema: {}
1716
};
1817

19-
const convert = createFormDataEntriesConverter(defaultOptions);
18+
const convert = createFormDataEntryConverter(defaultOptions);
2019

2120
describe('convertFormDataEntries', async () => {
2221
let c: AbortController;
@@ -32,45 +31,48 @@ describe('convertFormDataEntries', async () => {
3231
type: ['string', 'null']
3332
},
3433
uiSchema: {},
35-
entries: []
34+
path: [],
35+
value: undefined
3636
})
3737
).toBeNull();
3838
});
3939
it('Should convert boolean', async () => {
4040
const schema: Schema = { title: 'A boolean', type: 'boolean', default: false };
41-
const entries: Entries<string> = [['root.fixedNoToolbar.1', 'on']];
42-
await expect(convert(c.signal, { schema, uiSchema: {}, entries })).resolves.toEqual(true);
41+
await expect(
42+
convert(c.signal, { schema, uiSchema: {}, path: ['fixedNoToolbar', 1], value: 'on' })
43+
).resolves.toEqual(true);
4344
});
4445
it('Should convert number', async () => {
4546
const schema: Schema = { title: 'A number', type: 'number', default: 42 };
46-
const entries: Entries<string> = [['root.fixedNoToolbar.0', '42']];
47-
await expect(convert(c.signal, { schema, uiSchema: {}, entries })).resolves.toEqual(42);
47+
await expect(
48+
convert(c.signal, { schema, uiSchema: {}, path: ['fixedNoToolbar', 0], value: '42' })
49+
).resolves.toEqual(42);
4850
});
4951
it('Should convert enum value', async () => {
5052
const schema: Schema = {
5153
type: 'string',
5254
enum: ['foo', 'bar', 'baz']
5355
};
54-
const entries: Entries<string> = [['root', 'bar']];
55-
await expect(convert(c.signal, { schema, uiSchema: {}, entries })).resolves.toEqual('bar');
56+
await expect(
57+
convert(c.signal, { schema, uiSchema: {}, path: [], value: 'bar' })
58+
).resolves.toEqual('bar');
5659
});
5760
it('Should return correct value from enum of string numbers', async () => {
5861
const schema: Schema = {
5962
type: 'string',
6063
enum: ['1', '2', '3']
6164
};
65+
const path: RPath = [];
6266
// First, the value is treated as an index
63-
await expect(
64-
convert(c.signal, { schema, uiSchema: {}, entries: [['root', '0']] })
65-
).resolves.toEqual('1');
67+
await expect(convert(c.signal, { schema, uiSchema: {}, path, value: '0' })).resolves.toEqual(
68+
'1'
69+
);
6670
// Then we check if there is a value in the enumeration
67-
await expect(
68-
convert(c.signal, { schema, uiSchema: {}, entries: [['root', '3']] })
69-
).resolves.toEqual('3');
71+
await expect(convert(c.signal, { schema, uiSchema: {}, path, value: '3' })).resolves.toEqual(
72+
'3'
73+
);
7074
// If nothing fits, it's an error
71-
await expect(
72-
convert(c.signal, { schema, uiSchema: {}, entries: [['root', '4']] })
73-
).rejects.toThrow();
75+
await expect(convert(c.signal, { schema, uiSchema: {}, path, value: '4' })).rejects.toThrow();
7476
});
7577
it('Should return correct value from anyOf', async () => {
7678
const schema: Schema = {
@@ -94,8 +96,9 @@ describe('convertFormDataEntries', async () => {
9496
}
9597
]
9698
};
97-
const entries: Entries<string> = [['root.currentColor', '1']];
98-
await expect(convert(c.signal, { schema, uiSchema: {}, entries })).resolves.toEqual('#00ff00');
99+
await expect(
100+
convert(c.signal, { schema, uiSchema: {}, path: ['currentColor'], value: '1' })
101+
).resolves.toEqual('#00ff00');
99102
});
100103
it('Should return correct value from oneOf', async () => {
101104
const schema: Schema = {
@@ -106,12 +109,14 @@ describe('convertFormDataEntries', async () => {
106109
{ title: 'Disable', const: false }
107110
]
108111
};
109-
const entries: Entries<string> = [['root.toggleMask', '0']];
110-
await expect(convert(c.signal, { schema, uiSchema: {}, entries })).resolves.toEqual(true);
112+
await expect(
113+
convert(c.signal, { schema, uiSchema: {}, path: ['toggleMask'], value: '0' })
114+
).resolves.toEqual(true);
111115
});
112116
it('Should return correct value from enum', async () => {
113117
const schema: Schema = { type: 'string', enum: ['foo', 'bar', 'fuzz', 'qux'] };
114-
const entries: Entries<string> = [['root.multipleChoicesList', '1']];
115-
await expect(convert(c.signal, { schema, uiSchema: {}, entries })).resolves.toEqual('bar');
118+
await expect(
119+
convert(c.signal, { schema, uiSchema: {}, path: ['multipleChoicesList'], value: '1' })
120+
).resolves.toEqual('bar');
116121
});
117122
});

packages/sveltekit/src/lib/server/convert-form-data-entries.ts renamed to packages/sveltekit/src/lib/server/convert-form-data-entry.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@ import {
1010
} from '@sjsf/form/core';
1111
import { DEFAULT_BOOLEAN_ENUM, type FieldValue, type Schema, type UiSchemaRoot } from '@sjsf/form';
1212

13-
import type { EntriesConverter, EntriesConverterOptions } from './entry.js';
13+
import type { EntryConverter, EntryConverterOptions } from './entry.js';
1414

1515
export type UnknownEntryConverter = (
16-
key: string,
17-
value: string,
18-
options: EntriesConverterOptions<FormDataEntryValue>
16+
options: EntryConverterOptions<FormDataEntryValue>
1917
) => Promise<FieldValue> | FieldValue;
2018
export interface FormDataConverterOptions {
2119
validator: Validator;
@@ -27,27 +25,26 @@ export interface FormDataConverterOptions {
2725

2826
const DEFAULT_BOOLEAN_ENUM_KEYS_SET = new Set(Object.keys(DEFAULT_BOOLEAN_ENUM));
2927

30-
export function createFormDataEntriesConverter({
28+
export function createFormDataEntryConverter({
3129
validator,
3230
merger,
3331
rootSchema,
3432
rootUiSchema,
3533
convertUnknownEntry
36-
}: FormDataConverterOptions): EntriesConverter<FormDataEntryValue> {
34+
}: FormDataConverterOptions): EntryConverter<FormDataEntryValue> {
3735
return async (signal, options) => {
38-
const { entries, schema, uiSchema } = options;
36+
const { value, schema, uiSchema } = options;
3937
if (typeof schema === 'boolean') {
40-
return schema ? (entries[0]?.[1] as FieldValue) : undefined;
38+
return schema ? (value as FieldValue) : undefined;
4139
}
4240
const typeOrTypes = typeOfSchema(schema);
4341
const type = Array.isArray(typeOrTypes) ? pickSchemaType(typeOrTypes) : typeOrTypes;
44-
if (entries.length === 0) {
42+
if (value === undefined) {
4543
if (type === 'boolean') {
4644
return false;
4745
}
4846
return isNullableSchemaType(typeOrTypes) ? null : undefined;
4947
}
50-
const value = entries[0][1];
5148
if (value instanceof File) {
5249
if (value.name === '' && value.size === 0) {
5350
return undefined;
@@ -84,7 +81,7 @@ export function createFormDataEntriesConverter({
8481
throw new Error(`Value "${value}" does not match the schema: ${JSON.stringify(schema)}`);
8582
}
8683
if (type === 'unknown' && convertUnknownEntry) {
87-
return await convertUnknownEntry(entries[0][0], value, options);
84+
return await convertUnknownEntry(options);
8885
}
8986
switch (type) {
9087
case 'string':
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import type { MaybePromise } from '@sjsf/form/lib/types';
2-
import type { SchemaDefinition, SchemaValue } from '@sjsf/form/core';
2+
import type { RPath, SchemaDefinition, SchemaValue } from '@sjsf/form/core';
33
import type { UiSchema } from '@sjsf/form';
44

55
export type Entry<T> = [key: string, value: T];
66

77
export type Entries<T> = Entry<T>[];
88

9-
export interface EntriesConverterOptions<T> {
9+
export interface EntryConverterOptions<T> {
1010
schema: SchemaDefinition;
1111
uiSchema: UiSchema;
12-
entries: Entries<T>;
12+
path: RPath;
13+
value: T | undefined;
1314
}
1415

15-
export type EntriesConverter<T> = (
16+
export type EntryConverter<T> = (
1617
signal: AbortSignal,
17-
options: EntriesConverterOptions<T>
18+
options: EntryConverterOptions<T>
1819
) => MaybePromise<SchemaValue | undefined>;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export * from './entry.js';
22
export * from './server.js';
3-
export * from './convert-form-data-entries.js';
3+
export * from './convert-form-data-entry.js';
44
export * from './schema-value-parser.js';
55
export * from './id-prefix-parser.js';

packages/sveltekit/src/lib/server/schema-value-parser.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { createFormValidator } from '@sjsf/ajv8-validator';
55

66
import type { Entries } from './entry.js';
77
import { parseSchemaValue, type SchemaValueParserOptions } from './schema-value-parser.js';
8-
import { createFormDataEntriesConverter } from './convert-form-data-entries.js';
8+
import { createFormDataEntryConverter } from './convert-form-data-entry.js';
99

1010
const opts = ({
1111
schema = {},
@@ -17,7 +17,7 @@ const opts = ({
1717
idPseudoSeparator = '::',
1818
validator = createFormValidator(),
1919
merger = createMerger(),
20-
convertEntries = createFormDataEntriesConverter({
20+
convertEntry: convertEntry = createFormDataEntryConverter({
2121
merger,
2222
validator,
2323
rootSchema: schema,
@@ -35,7 +35,7 @@ const opts = ({
3535
idPseudoSeparator,
3636
validator,
3737
merger,
38-
convertEntries
38+
convertEntry: convertEntry
3939
});
4040

4141
describe('parseSchemaValue', async () => {

0 commit comments

Comments
 (0)