sveltekit-discriminated-fields 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +181 -69
- package/dist/FieldVariants.svelte +234 -0
- package/dist/FieldVariants.svelte.d.ts +95 -0
- package/dist/discriminated.d.ts +74 -0
- package/dist/discriminated.js +62 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +4 -4
- package/package.json +1 -1
- package/dist/UnionVariants.svelte +0 -361
- package/dist/UnionVariants.svelte.d.ts +0 -115
- package/dist/discriminated-fields.d.ts +0 -70
- package/dist/discriminated-fields.js +0 -35
- package/dist/infer-discriminator.d.ts +0 -11
- package/dist/infer-discriminator.js +0 -5
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from "svelte";
|
|
2
|
-
import type { InferDiscriminator } from "./infer-discriminator.js";
|
|
3
|
-
type DiscriminatorValues<K extends string, T> = T extends Record<K, {
|
|
4
|
-
value(): infer V;
|
|
5
|
-
}> ? V extends string ? V : never : never;
|
|
6
|
-
type NarrowToVariant<K extends string, T, V> = T extends Record<K, {
|
|
7
|
-
value(): V;
|
|
8
|
-
}> ? T : never;
|
|
9
|
-
type ReservedProps = "fields" | "key" | "fallback" | "partial";
|
|
10
|
-
type FieldKeys<T> = {
|
|
11
|
-
[P in keyof T]: T[P] extends {
|
|
12
|
-
value(): unknown;
|
|
13
|
-
} ? P : never;
|
|
14
|
-
}[keyof T];
|
|
15
|
-
type VariantFieldKeys<K extends string, T, V extends string> = Exclude<FieldKeys<NarrowToVariant<K, T, V>>, K>;
|
|
16
|
-
type OtherVariantsFieldKeys<K extends string, T, V extends string, OtherV extends string = Exclude<DiscriminatorValues<K, T>, V>> = OtherV extends OtherV ? VariantFieldKeys<K, T, OtherV> : never;
|
|
17
|
-
type SharedFieldKeys<K extends string, T, V extends string> = VariantFieldKeys<K, T, V> & OtherVariantsFieldKeys<K, T, V>;
|
|
18
|
-
type AllSharedFieldKeys<K extends string, T, V extends string = DiscriminatorValues<K, T>> = V extends V ? SharedFieldKeys<K, T, V> : never;
|
|
19
|
-
type HasField<T, P> = P extends keyof T ? T[P] extends {
|
|
20
|
-
value(): unknown;
|
|
21
|
-
} ? true : false : false;
|
|
22
|
-
type FieldExistsInAll<K extends string, T, P extends string, V extends string = DiscriminatorValues<K, T>> = V extends V ? HasField<NarrowToVariant<K, T, V>, P> : never;
|
|
23
|
-
type IsCommonField<K extends string, T, P extends string> = false extends FieldExistsInAll<K, T, P> ? false : true;
|
|
24
|
-
type FieldValueType<K extends string, T, V extends string, P extends string> = NarrowToVariant<K, T, V>[P & keyof NarrowToVariant<K, T, V>] extends {
|
|
25
|
-
value(): infer R;
|
|
26
|
-
} ? R : never;
|
|
27
|
-
type AllFieldValueTypes<K extends string, T, P extends string, V extends string = DiscriminatorValues<K, T>> = V extends V ? FieldValueType<K, T, V, P> : never;
|
|
28
|
-
type FieldTypeMatchesInVariant<K extends string, T, P extends string, V extends string, Union = AllFieldValueTypes<K, T, P>> = [Union] extends [FieldValueType<K, T, V, P>] ? true : false;
|
|
29
|
-
type FieldHasSameTypeInAll<K extends string, T, P extends string, V extends string = DiscriminatorValues<K, T>> = V extends V ? FieldTypeMatchesInVariant<K, T, P, V> : never;
|
|
30
|
-
type IsUniformTypeField<K extends string, T, P extends string> = false extends FieldHasSameTypeInAll<K, T, P> ? false : true;
|
|
31
|
-
type PartiallySharedFieldKeys<K extends string, T> = {
|
|
32
|
-
[P in AllSharedFieldKeys<K, T>]: IsCommonField<K, T, P & string> extends true ? never : P;
|
|
33
|
-
}[AllSharedFieldKeys<K, T>];
|
|
34
|
-
type MixedTypeFieldKeys<K extends string, T> = {
|
|
35
|
-
[P in AllSharedFieldKeys<K, T>]: IsCommonField<K, T, P & string> extends true ? IsUniformTypeField<K, T, P & string> extends true ? never : P : never;
|
|
36
|
-
}[AllSharedFieldKeys<K, T>];
|
|
37
|
-
type CommonFieldKeys<K extends string, T> = {
|
|
38
|
-
[P in AllSharedFieldKeys<K, T>]: IsCommonField<K, T, P & string> extends true ? IsUniformTypeField<K, T, P & string> extends true ? P : never : never;
|
|
39
|
-
}[AllSharedFieldKeys<K, T>];
|
|
40
|
-
type ValidateNoPartiallySharedFields<K extends string, T> = [
|
|
41
|
-
PartiallySharedFieldKeys<K, T>
|
|
42
|
-
] extends [never] ? T : `Error: Field '${PartiallySharedFieldKeys<K, T> & string}' exists in some variants but not all. Fields must be either unique to one variant or common to all variants.`;
|
|
43
|
-
type ValidateNoMixedTypeFields<K extends string, T> = [MixedTypeFieldKeys<K, T>] extends [never] ? T : `Error: Field '${MixedTypeFieldKeys<K, T> & string}' exists in all variants but with different types. Shared fields must have the same type across all variants.`;
|
|
44
|
-
type ValidateFields<K extends string, T> = [PartiallySharedFieldKeys<K, T>] extends [never] ? [MixedTypeFieldKeys<K, T>] extends [never] ? T : ValidateNoMixedTypeFields<K, T> : ValidateNoPartiallySharedFields<K, T>;
|
|
45
|
-
type VariantOnlyFields<K extends string, T, V extends string> = Omit<NarrowToVariant<K, T, V>, CommonFieldKeys<K, T>>;
|
|
46
|
-
type VariantSnippets<K extends string, T, V extends string, IsPartial extends boolean> = IsPartial extends true ? {
|
|
47
|
-
[P in Exclude<V, ReservedProps>]?: Snippet<[VariantOnlyFields<K, T, P>]>;
|
|
48
|
-
} : {
|
|
49
|
-
[P in Exclude<V, ReservedProps>]: Snippet<[VariantOnlyFields<K, T, P>]>;
|
|
50
|
-
};
|
|
51
|
-
export type UnionVariantsPropsWithKey<K extends string, T extends Record<K, {
|
|
52
|
-
value(): unknown;
|
|
53
|
-
}>, V extends string = DiscriminatorValues<K, T>, IsPartial extends boolean = false> = {
|
|
54
|
-
fields: ValidateFields<K, T>;
|
|
55
|
-
key: K;
|
|
56
|
-
/** Optional snippet shown when no variant is selected */
|
|
57
|
-
fallback?: Snippet;
|
|
58
|
-
/** When true, variant snippets are optional (default: false) */
|
|
59
|
-
partial?: IsPartial;
|
|
60
|
-
/**
|
|
61
|
-
* CSS selector for the discriminator input element (select or radio container).
|
|
62
|
-
* When provided, uses this selector instead of the default name-based lookup.
|
|
63
|
-
* Example: "#method-select" for a select, or "#radio-group" for radios
|
|
64
|
-
*/
|
|
65
|
-
selector?: string;
|
|
66
|
-
} & VariantSnippets<K, T, V, IsPartial>;
|
|
67
|
-
export type UnionVariantsPropsInferred<T extends Record<string, {
|
|
68
|
-
value(): unknown;
|
|
69
|
-
}>, K extends string = InferDiscriminator<T> extends infer I ? (I extends string ? I : never) : never, V extends string = DiscriminatorValues<K, T>, IsPartial extends boolean = false> = InferDiscriminator<T> extends string ? {
|
|
70
|
-
fields: ValidateFields<K, T>;
|
|
71
|
-
key?: K;
|
|
72
|
-
fallback?: Snippet;
|
|
73
|
-
partial?: IsPartial;
|
|
74
|
-
selector?: string;
|
|
75
|
-
} & VariantSnippets<K, T, V, IsPartial> : {
|
|
76
|
-
fields: InferDiscriminator<T>;
|
|
77
|
-
key: never;
|
|
78
|
-
};
|
|
79
|
-
export type UnionVariantsProps<K extends string, T extends Record<K, {
|
|
80
|
-
value(): unknown;
|
|
81
|
-
}>, V extends string = DiscriminatorValues<K, T>, IsPartial extends boolean = false> = UnionVariantsPropsWithKey<K, T, V, IsPartial>;
|
|
82
|
-
declare function $$render<K extends string, T extends Record<K, {
|
|
83
|
-
value(): unknown;
|
|
84
|
-
}>, V extends string = DiscriminatorValues<K, T>, IsPartial extends boolean = false>(): {
|
|
85
|
-
props: UnionVariantsProps<K, T, V, IsPartial>;
|
|
86
|
-
exports: {};
|
|
87
|
-
bindings: "";
|
|
88
|
-
slots: {};
|
|
89
|
-
events: {};
|
|
90
|
-
};
|
|
91
|
-
declare class __sveltets_Render<K extends string, T extends Record<K, {
|
|
92
|
-
value(): unknown;
|
|
93
|
-
}>, V extends string = DiscriminatorValues<K, T>, IsPartial extends boolean = false> {
|
|
94
|
-
props(): ReturnType<typeof $$render<K, T, V, IsPartial>>['props'];
|
|
95
|
-
events(): ReturnType<typeof $$render<K, T, V, IsPartial>>['events'];
|
|
96
|
-
slots(): ReturnType<typeof $$render<K, T, V, IsPartial>>['slots'];
|
|
97
|
-
bindings(): "";
|
|
98
|
-
exports(): {};
|
|
99
|
-
}
|
|
100
|
-
interface $$IsomorphicComponent {
|
|
101
|
-
new <K extends string, T extends Record<K, {
|
|
102
|
-
value(): unknown;
|
|
103
|
-
}>, V extends string = DiscriminatorValues<K, T>, IsPartial extends boolean = false>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<K, T, V, IsPartial>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<K, T, V, IsPartial>['props']>, ReturnType<__sveltets_Render<K, T, V, IsPartial>['events']>, ReturnType<__sveltets_Render<K, T, V, IsPartial>['slots']>> & {
|
|
104
|
-
$$bindings?: ReturnType<__sveltets_Render<K, T, V, IsPartial>['bindings']>;
|
|
105
|
-
} & ReturnType<__sveltets_Render<K, T, V, IsPartial>['exports']>;
|
|
106
|
-
<K extends string, T extends Record<K, {
|
|
107
|
-
value(): unknown;
|
|
108
|
-
}>, V extends string = DiscriminatorValues<K, T>, IsPartial extends boolean = false>(internal: unknown, props: ReturnType<__sveltets_Render<K, T, V, IsPartial>['props']> & {}): ReturnType<__sveltets_Render<K, T, V, IsPartial>['exports']>;
|
|
109
|
-
z_$$bindings?: ReturnType<__sveltets_Render<any, any, any, any>['bindings']>;
|
|
110
|
-
}
|
|
111
|
-
declare const UnionVariants: $$IsomorphicComponent;
|
|
112
|
-
type UnionVariants<K extends string, T extends Record<K, {
|
|
113
|
-
value(): unknown;
|
|
114
|
-
}>, V extends string = DiscriminatorValues<K, T>, IsPartial extends boolean = false> = InstanceType<typeof UnionVariants<K, T, V, IsPartial>>;
|
|
115
|
-
export default UnionVariants;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { RemoteFormField, RemoteFormFieldType } from '@sveltejs/kit';
|
|
2
|
-
export type DiscriminatedData<T> = T extends {
|
|
3
|
-
set: (v: infer D) => unknown;
|
|
4
|
-
} ? D : never;
|
|
5
|
-
type ExtractFieldValue<F> = F extends RemoteFormField<infer V> ? V : never;
|
|
6
|
-
type RadioProps = {
|
|
7
|
-
name: string;
|
|
8
|
-
type: 'radio';
|
|
9
|
-
value?: string;
|
|
10
|
-
'aria-invalid': boolean | 'false' | 'true' | undefined;
|
|
11
|
-
get checked(): boolean;
|
|
12
|
-
set checked(value: boolean);
|
|
13
|
-
};
|
|
14
|
-
type NonRadioAsArgs<Type extends string, Value> = Type extends 'checkbox' ? Value extends string[] ? [type: Type, value: Value[number] | (string & {})] : [type: Type] : Type extends 'submit' | 'hidden' ? [type: Type, value: Value | (string & {})] : [type: Type];
|
|
15
|
-
type StrictDiscriminatorField<Value extends string, BaseField extends RemoteFormField<Value>> = Omit<BaseField, 'as'> & {
|
|
16
|
-
as(type: 'radio', value: Value): RadioProps;
|
|
17
|
-
as<T extends Exclude<RemoteFormFieldType<Value>, 'radio'>>(...args: NonRadioAsArgs<T, Value>): ReturnType<BaseField['as']>;
|
|
18
|
-
};
|
|
19
|
-
type UnifyField<F, V extends string = ExtractFieldValue<F> & string> = StrictDiscriminatorField<V, RemoteFormField<V>>;
|
|
20
|
-
type Setter<K extends string, T, D = DiscriminatedData<T>> = {
|
|
21
|
-
set: <V extends D[K & keyof D]>(data: Extract<D, {
|
|
22
|
-
[P in K]: V;
|
|
23
|
-
}>) => void;
|
|
24
|
-
};
|
|
25
|
-
type Keys<T> = T extends unknown ? keyof T : never;
|
|
26
|
-
type KeyValue<K extends string, V> = {
|
|
27
|
-
[P in `${K}Value`]: V;
|
|
28
|
-
};
|
|
29
|
-
type Fields<T> = {
|
|
30
|
-
[P in Keys<T>]: T extends Record<P, infer V> ? V : never;
|
|
31
|
-
};
|
|
32
|
-
type Variant<K extends string, T, V> = KeyValue<K, V> & Fields<T>;
|
|
33
|
-
type Narrowed<K extends string, T> = T extends {
|
|
34
|
-
[P in K]: {
|
|
35
|
-
value(): infer V;
|
|
36
|
-
};
|
|
37
|
-
} ? Variant<K, T, V> : never;
|
|
38
|
-
type Union<K extends string, T> = Narrowed<K, T> | Variant<K, T, undefined>;
|
|
39
|
-
type FieldUnion<K extends string, T> = T extends Record<K, infer F> ? F : never;
|
|
40
|
-
type UnifiedDiscriminator<K extends string, T, F = FieldUnion<K, T>> = {
|
|
41
|
-
readonly [P in K]: [F] extends [never] ? never : UnifyField<F>;
|
|
42
|
-
};
|
|
43
|
-
type DiscriminatedFields<K extends string, T> = Setter<K, T> & Union<K, T> & UnifiedDiscriminator<K, T>;
|
|
44
|
-
/**
|
|
45
|
-
* Wraps discriminated union form fields for type-safe access.
|
|
46
|
-
* - All original fields pass through unchanged (type, issues, allIssues, etc.)
|
|
47
|
-
* - `set` is overridden with type-safe version
|
|
48
|
-
* - `${key}Value` is added for discriminator value (e.g., `reward.typeValue`)
|
|
49
|
-
* - Discriminator field `.as("radio", value)` is type-safe (only valid values allowed)
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```svelte
|
|
53
|
-
* <script>
|
|
54
|
-
* const priority = $derived(discriminatedFields("level", priorityForm.fields));
|
|
55
|
-
* </script>
|
|
56
|
-
*
|
|
57
|
-
* <input {...priority.level.as("radio", "high")} /> <!-- type-safe: only valid values allowed -->
|
|
58
|
-
* ```
|
|
59
|
-
*
|
|
60
|
-
* @param key - Discriminator key (e.g. 'type')
|
|
61
|
-
* @param fields - Form fields from a discriminated union schema
|
|
62
|
-
* @returns Passthrough object with type-safe set(), ${key}Value, and .as("radio", value)
|
|
63
|
-
*/
|
|
64
|
-
export declare function discriminatedFields<K extends string, T extends {
|
|
65
|
-
set: (v: never) => unknown;
|
|
66
|
-
} & Record<K, {
|
|
67
|
-
value(): unknown;
|
|
68
|
-
as(type: 'radio', value: string): object;
|
|
69
|
-
}>>(key: K, fields: T): DiscriminatedFields<K, T>;
|
|
70
|
-
export {};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wraps discriminated union form fields for type-safe access.
|
|
3
|
-
* - All original fields pass through unchanged (type, issues, allIssues, etc.)
|
|
4
|
-
* - `set` is overridden with type-safe version
|
|
5
|
-
* - `${key}Value` is added for discriminator value (e.g., `reward.typeValue`)
|
|
6
|
-
* - Discriminator field `.as("radio", value)` is type-safe (only valid values allowed)
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```svelte
|
|
10
|
-
* <script>
|
|
11
|
-
* const priority = $derived(discriminatedFields("level", priorityForm.fields));
|
|
12
|
-
* </script>
|
|
13
|
-
*
|
|
14
|
-
* <input {...priority.level.as("radio", "high")} /> <!-- type-safe: only valid values allowed -->
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* @param key - Discriminator key (e.g. 'type')
|
|
18
|
-
* @param fields - Form fields from a discriminated union schema
|
|
19
|
-
* @returns Passthrough object with type-safe set(), ${key}Value, and .as("radio", value)
|
|
20
|
-
*/
|
|
21
|
-
export function discriminatedFields(key, fields) {
|
|
22
|
-
const proxy = new Proxy(fields, {
|
|
23
|
-
get(target, prop) {
|
|
24
|
-
if (prop === `${key}Value`)
|
|
25
|
-
return target[key].value();
|
|
26
|
-
if (prop === 'set')
|
|
27
|
-
return (data) => target.set(data);
|
|
28
|
-
return Reflect.get(target, prop);
|
|
29
|
-
},
|
|
30
|
-
has(target, prop) {
|
|
31
|
-
return prop === `${key}Value` || prop in target;
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
return proxy;
|
|
35
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
type AllKeys<T> = T extends T ? keyof T : never;
|
|
2
|
-
type HasLiteralValue<T, K> = K extends keyof T ? T[K] extends {
|
|
3
|
-
value(): infer V;
|
|
4
|
-
} ? V extends string ? string extends V ? false : true : false : false : false;
|
|
5
|
-
type IsDiscriminatorInAll<T, K> = T extends T ? HasLiteralValue<T, K> : never;
|
|
6
|
-
type IsDiscriminator<T, K> = [IsDiscriminatorInAll<T, K>] extends [true] ? true : false;
|
|
7
|
-
type DiscriminatorKeys<T, K = AllKeys<T>> = K extends K ? IsDiscriminator<T, K> extends true ? K : never : never;
|
|
8
|
-
type IsUnion<T, U = T> = T extends T ? ([U] extends [T] ? false : true) : never;
|
|
9
|
-
export type InferDiscriminator<T> = DiscriminatorKeys<T> extends infer Keys ? [Keys] extends [never] ? "Error: No valid discriminator found. A discriminator must exist in all variants with distinct string literal values." : IsUnion<Keys> extends true ? `Error: Multiple discriminator candidates found: ${Keys & string}. Please specify the key explicitly.` : Keys : never;
|
|
10
|
-
export type IsValidInference<T> = InferDiscriminator<T> extends `Error: ${string}` ? false : true;
|
|
11
|
-
export type { DiscriminatorKeys };
|