@strictly/define 0.0.12 → 0.0.14
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/.out/transformers/flatteners/json_path.d.ts +6 -2
- package/.out/transformers/flatteners/json_path.js +15 -2
- package/.out/transformers/flatteners/specs/json_paths.tests.d.ts +1 -0
- package/.out/transformers/flatteners/specs/json_paths.tests.js +50 -0
- package/.out/tsconfig.tsbuildinfo +1 -1
- package/.out/types/builders.d.ts +21 -20
- package/.out/types/builders.js +8 -5
- package/.out/types/flattened_types_of_validating_type.d.ts +4 -4
- package/.out/types/flattened_validators_of_validating_type.d.ts +7 -6
- package/.out/types/specs/flattened_validators_of_validating_type.tests.js +2 -2
- package/.out/types/validating_definitions.d.ts +14 -12
- package/.out/types/validating_type_def_with_error.d.ts +13 -13
- package/.out/validation/validator.d.ts +1 -0
- package/.out/validation/validator.js +4 -0
- package/.out/validation/validators/composite_validator.d.ts +7 -0
- package/.out/validation/validators/composite_validator.js +32 -0
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-check-types.log +1 -1
- package/dist/index.cjs +86 -33
- package/dist/index.d.cts +85 -79
- package/dist/index.d.ts +85 -79
- package/dist/index.js +62 -9
- package/package.json +1 -1
- package/transformers/flatteners/json_path.ts +44 -4
- package/transformers/flatteners/specs/json_paths.tests.ts +69 -0
- package/types/builders.ts +46 -26
- package/types/flattened_types_of_validating_type.ts +5 -2
- package/types/flattened_validators_of_validating_type.ts +7 -9
- package/types/specs/builder.tests.ts +31 -31
- package/types/specs/flattened_validators_of_validating_type.tests.ts +7 -7
- package/types/validating_definitions.ts +27 -15
- package/types/validating_type_def_with_error.ts +23 -23
- package/validation/validator.ts +21 -0
- package/validation/validators/composite_validator.ts +42 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IsEqual, Simplify, UnionToIntersection, SimplifyDeep } from 'type-fest';
|
|
2
|
-
import { IsFieldReadonly } from '@strictly/base';
|
|
2
|
+
import { IsFieldReadonly, StringConcatOf } from '@strictly/base';
|
|
3
3
|
|
|
4
4
|
type Type<T extends TypeDef = TypeDef> = {
|
|
5
5
|
readonly definition: T;
|
|
@@ -198,50 +198,75 @@ declare function flattenJsonValueToTypePathsOf<T extends Type, R extends Record<
|
|
|
198
198
|
|
|
199
199
|
declare function flattenTypesOfType<T extends StrictType>(t: T): Record<string, Type>;
|
|
200
200
|
|
|
201
|
+
type Annotations = {
|
|
202
|
+
readonly required: boolean;
|
|
203
|
+
readonly readonly: boolean;
|
|
204
|
+
};
|
|
205
|
+
type FunctionalValidator<V = any, E = any, ValuePath extends string = any, Context = any> = (v: V, valuePath: ValuePath, context: Context) => E | null;
|
|
206
|
+
type AnnotatedValidator<V = any, E = any, ValuePath extends string = any, Context = any> = {
|
|
207
|
+
readonly validate: (v: V, valuePath: ValuePath, context: Context) => E | null;
|
|
208
|
+
readonly annotations: (valuePath: ValuePath, context: Context) => Annotations;
|
|
209
|
+
};
|
|
210
|
+
type Validator<V = any, E = any, ValuePath extends string = any, Context = any> = FunctionalValidator<V, E, ValuePath, Context> | AnnotatedValidator<V, E, ValuePath, Context>;
|
|
211
|
+
type ErrorOfValidator<V extends Validator> = V extends Validator<infer _V, infer E> ? E : never;
|
|
212
|
+
type ValidationError<Type extends string, Data = {}> = Simplify<{
|
|
213
|
+
type: Type;
|
|
214
|
+
} & Data>;
|
|
215
|
+
declare function isFunctionalValidator<V, E, ValuePath extends string, Context>(v: Validator<V, E, ValuePath, Context>): v is FunctionalValidator<V, E, ValuePath, Context>;
|
|
216
|
+
declare function isAnnotatedValidator<V, E, ValuePath extends string, Context>(v: Validator<V, E, ValuePath, Context>): v is AnnotatedValidator<V, E, ValuePath, Context>;
|
|
217
|
+
declare function validate<V = any, E = any, ValuePath extends string = any, Context = any>(validator: Validator<V, E, ValuePath, Context>, v: V, valuePath: ValuePath, context: Context): E | null;
|
|
218
|
+
declare function mergeValidators<V = any, E1 = any, E2 = any, ValuePath extends string = any, C1 = any, C2 = any>(v1: Validator<V, E1, ValuePath, C1>, v2: Validator<V, E2, ValuePath, C2>): Validator<V, E1 | E2, ValuePath, C1 & C2>;
|
|
219
|
+
declare function annotations<V = any, E = any, ValuePath extends string = any, Context = any>(validator: Validator<V, E, ValuePath, Context>, valuePath: ValuePath, context: Context): Annotations;
|
|
220
|
+
declare function mergeAnnotations(a1: Annotations, a2: Annotations): {
|
|
221
|
+
readonly: boolean;
|
|
222
|
+
required: boolean;
|
|
223
|
+
};
|
|
224
|
+
|
|
201
225
|
type ValidatingType<T extends ValidatingTypeDef = ValidatingTypeDef> = {
|
|
202
226
|
readonly definition: T;
|
|
203
227
|
};
|
|
204
|
-
type Rule<E = any, V = any> = (v: V) => E | null;
|
|
205
228
|
type ErrorOfValidatingTypeDef<T extends ValidatingTypeDef> = T extends ValidatingTypeDef<infer E> ? E : never;
|
|
206
|
-
type
|
|
229
|
+
type ContextOfValidatingTypeDef<T extends ValidatingTypeDef> = T extends ValidatingTypeDef<infer _E, infer C> ? C : never;
|
|
230
|
+
type Rule<E, C, V = any> = FunctionalValidator<V, E, string, C>;
|
|
231
|
+
type ValidatingTypeDef<E = any, C = any> = ValidatingLiteralTypeDef<E, C> | ValidatingListTypeDef<E, C> | ValidatingRecordTypeDef<E, C> | ValidatingObjectTypeDef<E, C> | ValidatingUnionTypeDef<E, C>;
|
|
207
232
|
type AnyTypeDef = any;
|
|
208
|
-
type ValidatingLiteralTypeDef<E = any, V = any> = {
|
|
233
|
+
type ValidatingLiteralTypeDef<E = any, C = any, V = any> = {
|
|
209
234
|
readonly type: TypeDefType.Literal;
|
|
210
235
|
readonly valuePrototype: [V];
|
|
211
|
-
readonly rule: Rule<E>;
|
|
236
|
+
readonly rule: Rule<E, C>;
|
|
212
237
|
readonly required: boolean;
|
|
213
238
|
readonly readonly: boolean;
|
|
214
239
|
};
|
|
215
|
-
type ValidatingListTypeDef<E = any, Ele extends ValidatingTypeDef = AnyTypeDef> = {
|
|
240
|
+
type ValidatingListTypeDef<E = any, C = any, Ele extends ValidatingTypeDef = AnyTypeDef> = {
|
|
216
241
|
readonly type: TypeDefType.List;
|
|
217
242
|
readonly elements: Ele;
|
|
218
|
-
readonly rule: Rule<E>;
|
|
243
|
+
readonly rule: Rule<E, C>;
|
|
219
244
|
readonly required: boolean;
|
|
220
245
|
readonly readonly: boolean;
|
|
221
246
|
};
|
|
222
|
-
type ValidatingRecordTypeDef<E = any, K extends RecordKeyType = RecordKeyType, V extends ValidatingTypeDef | undefined = AnyTypeDef> = {
|
|
247
|
+
type ValidatingRecordTypeDef<E = any, C = any, K extends RecordKeyType = RecordKeyType, V extends ValidatingTypeDef | undefined = AnyTypeDef> = {
|
|
223
248
|
readonly type: TypeDefType.Record;
|
|
224
249
|
readonly keyPrototype: K;
|
|
225
250
|
readonly valueTypeDef: V;
|
|
226
|
-
readonly rule: Rule<E>;
|
|
251
|
+
readonly rule: Rule<E, C>;
|
|
227
252
|
readonly required: boolean;
|
|
228
253
|
readonly readonly: boolean;
|
|
229
254
|
};
|
|
230
255
|
type ValidatingObjectTypeDefFields = {
|
|
231
256
|
[Key: ObjectFieldKey]: AnyTypeDef;
|
|
232
257
|
};
|
|
233
|
-
type ValidatingObjectTypeDef<E = any, Fields extends ValidatingObjectTypeDefFields = ValidatingObjectTypeDefFields> = {
|
|
258
|
+
type ValidatingObjectTypeDef<E = any, C = any, Fields extends ValidatingObjectTypeDefFields = ValidatingObjectTypeDefFields> = {
|
|
234
259
|
readonly type: TypeDefType.Object;
|
|
235
260
|
readonly fields: Fields;
|
|
236
|
-
readonly rule: Rule<E>;
|
|
261
|
+
readonly rule: Rule<E, C>;
|
|
237
262
|
readonly required: boolean;
|
|
238
263
|
readonly readonly: boolean;
|
|
239
264
|
};
|
|
240
|
-
type ValidatingUnionTypeDef<E = any, D extends string | null = string | null, U extends Readonly<Record<UnionKey, AnyTypeDef>> = Readonly<Record<UnionKey, AnyTypeDef>>> = {
|
|
265
|
+
type ValidatingUnionTypeDef<E = any, C = any, D extends string | null = string | null, U extends Readonly<Record<UnionKey, AnyTypeDef>> = Readonly<Record<UnionKey, AnyTypeDef>>> = {
|
|
241
266
|
readonly discriminator: D;
|
|
242
267
|
readonly type: TypeDefType.Union;
|
|
243
268
|
readonly unions: U;
|
|
244
|
-
readonly rule: Rule<E>;
|
|
269
|
+
readonly rule: Rule<E, C>;
|
|
245
270
|
readonly required: boolean;
|
|
246
271
|
readonly readonly: boolean;
|
|
247
272
|
};
|
|
@@ -254,52 +279,32 @@ type InternalFlattenedTypeDefsOfChildren<T extends TypeDef, SegmentOverride exte
|
|
|
254
279
|
type InternalFlattenedTypeDefsOfLiteralChildren = {};
|
|
255
280
|
type InternalFlattenedTypeDefsOfListChildren<T extends ValidatingListTypeDef, SegmentOverride extends string | null, Path extends string, Depth extends number> = InternalFlattenedTypeDefsOf<T['elements'], SegmentOverride, PathOf<Path, number, SegmentOverride>, '', Depth>;
|
|
256
281
|
type InternalFlattenedTypeDefsOfRecordChildren<T extends ValidatingRecordTypeDef, SegmentOverride extends string | null, Path extends string, Depth extends number> = InternalFlattenedTypeDefsOf<T['valueTypeDef'], SegmentOverride, PathOf<Path, T['keyPrototype'], SegmentOverride>, '', Depth>;
|
|
257
|
-
type InternalFlattenedTypeDefsOfObjectChildren<T extends ValidatingObjectTypeDef, SegmentOverride extends string | null, Path extends string, Qualifier extends string, Depth extends number> = T extends ValidatingObjectTypeDef<infer _E, infer Fields> ? keyof Fields extends string ? UnionToIntersection<{
|
|
258
|
-
readonly [K in keyof Fields]-?: undefined extends Fields[K] ? InternalFlattenedTypeDefsOf<ValidatingUnionTypeDef<ErrorOfValidatingTypeDef<Exclude<Fields[K], undefined>>, null, {
|
|
282
|
+
type InternalFlattenedTypeDefsOfObjectChildren<T extends ValidatingObjectTypeDef, SegmentOverride extends string | null, Path extends string, Qualifier extends string, Depth extends number> = T extends ValidatingObjectTypeDef<infer _E, infer _C, infer Fields> ? keyof Fields extends string ? UnionToIntersection<{
|
|
283
|
+
readonly [K in keyof Fields]-?: undefined extends Fields[K] ? InternalFlattenedTypeDefsOf<ValidatingUnionTypeDef<ErrorOfValidatingTypeDef<Exclude<Fields[K], undefined>>, ContextOfValidatingTypeDef<Exclude<Fields[K], undefined>>, null, {
|
|
259
284
|
readonly '0': Exclude<Fields[K], undefined>;
|
|
260
285
|
readonly '1': ValidatingLiteralTypeDef<undefined>;
|
|
261
286
|
}>, SegmentOverride, PathOf<Path, `${Qualifier}${K}`, null>, '', Depth> : InternalFlattenedTypeDefsOf<Exclude<Fields[K], undefined>, SegmentOverride, PathOf<Path, `${Qualifier}${K}`, null>, '', Depth>;
|
|
262
287
|
}[keyof Fields]> : never : never;
|
|
263
|
-
type InternalFlattenedTypeDefsOfUnionChildren<T extends ValidatingUnionTypeDef, SegmentOverride extends string | null, Path extends string, Qualifier extends string, Depth extends number> = T extends ValidatingUnionTypeDef<infer _E, infer D, infer Unions> ? keyof Unions extends string ? D extends null ? UnionToIntersection<{
|
|
288
|
+
type InternalFlattenedTypeDefsOfUnionChildren<T extends ValidatingUnionTypeDef, SegmentOverride extends string | null, Path extends string, Qualifier extends string, Depth extends number> = T extends ValidatingUnionTypeDef<infer _E, infer _C, infer D, infer Unions> ? keyof Unions extends string ? D extends null ? UnionToIntersection<{
|
|
264
289
|
readonly [K in keyof Unions]: InternalFlattenedTypeDefsOfChildren<Unions[K], SegmentOverride, Path, '', Depth>;
|
|
265
290
|
}[keyof Unions]> : UnionToIntersection<{
|
|
266
291
|
readonly [K in keyof Unions]: InternalFlattenedTypeDefsOfChildren<Unions[K], SegmentOverride, Path, `${Qualifier}${K}:`, Depth>;
|
|
267
292
|
}[keyof Unions]> : never : never;
|
|
268
293
|
|
|
269
|
-
type
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
type FunctionalValidator<V = any, E = any, ValuePath extends string = any, Context = any> = (v: V, valuePath: ValuePath, context: Context) => E | null;
|
|
274
|
-
type AnnotatedValidator<V = any, E = any, ValuePath extends string = any, Context = any> = {
|
|
275
|
-
readonly validate: (v: V, valuePath: ValuePath, context: Context) => E | null;
|
|
276
|
-
readonly annotations: (valuePath: ValuePath, context: Context) => Annotations;
|
|
277
|
-
};
|
|
278
|
-
type Validator<V = any, E = any, ValuePath extends string = any, Context = any> = FunctionalValidator<V, E, ValuePath, Context> | AnnotatedValidator<V, E, ValuePath, Context>;
|
|
279
|
-
type ErrorOfValidator<V extends Validator> = V extends Validator<infer _V, infer E> ? E : never;
|
|
280
|
-
type ValidationError<Type extends string, Data = {}> = Simplify<{
|
|
281
|
-
type: Type;
|
|
282
|
-
} & Data>;
|
|
283
|
-
declare function isFunctionalValidator<V, E, ValuePath extends string, Context>(v: Validator<V, E, ValuePath, Context>): v is FunctionalValidator<V, E, ValuePath, Context>;
|
|
284
|
-
declare function isAnnotatedValidator<V, E, ValuePath extends string, Context>(v: Validator<V, E, ValuePath, Context>): v is AnnotatedValidator<V, E, ValuePath, Context>;
|
|
285
|
-
declare function validate<V = any, E = any, ValuePath extends string = any, Context = any>(validator: Validator<V, E, ValuePath, Context>, v: V, valuePath: ValuePath, context: Context): E | null;
|
|
286
|
-
declare function annotations<V = any, E = any, ValuePath extends string = any, Context = any>(validator: Validator<V, E, ValuePath, Context>, valuePath: ValuePath, context: Context): Annotations;
|
|
287
|
-
declare function mergeAnnotations(a1: Annotations, a2: Annotations): {
|
|
288
|
-
readonly: boolean;
|
|
289
|
-
required: boolean;
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
type ValidatorOfValidatingType<T extends ValidatingTypeDef, ValuePath extends string, Context> = T extends ValidatingTypeDef<infer E> ? Validator<ValueOfTypeDef<ReadonlyOfTypeDef<T>>, E, ValuePath, Context> : never;
|
|
293
|
-
type FlattenedValidatorsOfValidatingType<T extends ValidatingType, TypePathsToValuePaths extends Readonly<Record<keyof FlattenedTypes, string>>, FlattenedTypes extends Readonly<Record<string, ValidatingType>> = FlattenedTypesOfType<T, '*'>, Context = ValueOfType<ReadonlyTypeOfType<T>>> = {
|
|
294
|
-
[K in keyof FlattenedTypes as ErrorOfValidatingTypeDef<FlattenedTypes[K]['definition']> extends never ? never : K]: ValidatorOfValidatingType<FlattenedTypes[K]['definition'], TypePathsToValuePaths[K], Context>;
|
|
295
|
-
};
|
|
294
|
+
type ValidatorOfValidatingType<T extends ValidatingTypeDef, ValuePath extends string> = T extends ValidatingTypeDef<infer E, infer C> ? Validator<ValueOfTypeDef<ReadonlyOfTypeDef<T>>, E, ValuePath, C> : never;
|
|
295
|
+
type FlattenedValidatorsOfValidatingType<T extends ValidatingType, TypePathsToValuePaths extends Readonly<Record<keyof FlattenedTypes, string>>, FlattenedTypes extends Readonly<Record<string, ValidatingType>> = FlattenedTypesOfType<T, '*'>> = Simplify<{
|
|
296
|
+
[K in keyof FlattenedTypes as ErrorOfValidatingTypeDef<FlattenedTypes[K]['definition']> extends never ? never : K]: ValidatorOfValidatingType<FlattenedTypes[K]['definition'], TypePathsToValuePaths[K]>;
|
|
297
|
+
}>;
|
|
296
298
|
|
|
297
299
|
declare function flattenValidatorsOfValidatingType<T extends ValidatingType, TypePathsToValuePaths extends Readonly<Record<keyof FlattenedTypes, string>>, FlattenedTypes extends Readonly<Record<string, ValidatingType>> = FlattenedTypesOfValidatingType<T, '*'>>(type: T): FlattenedValidatorsOfValidatingType<T, TypePathsToValuePaths, FlattenedTypes>;
|
|
298
300
|
|
|
299
301
|
declare function flattenValuesOfType<T extends Type>(typeDef: Type, value: ValueOfType<T>): Readonly<Record<string, any>>;
|
|
300
302
|
|
|
301
|
-
declare function jsonPath
|
|
302
|
-
declare function
|
|
303
|
+
declare function jsonPath<Prefix extends string, Segment extends number | string>(prefix: Prefix, segment: Segment): `${Prefix}.${Segment}`;
|
|
304
|
+
declare function jsonPath<Prefix extends string, Segment extends number | string, Qualifier extends string>(prefix: Prefix, segment: Segment, qualifier: Qualifier): `${Prefix}.${Qualifier}${Segment}`;
|
|
305
|
+
declare function jsonPathPop<Path extends string>(path: Path): [string, string] | null;
|
|
306
|
+
declare function jsonPathPrefix<Prefix extends string, Path extends string>(prefix: Prefix, path: Path): Path extends StringConcatOf<'$', infer ToMount> ? `${Prefix}${ToMount}` : never;
|
|
307
|
+
declare function jsonPathUnprefix<Prefix extends string, Path extends string>(prefix: Prefix, path: Path): Path extends StringConcatOf<Prefix, infer ToUnmount> ? `$${ToUnmount}` : never;
|
|
303
308
|
|
|
304
309
|
declare function valuePathToTypePath<ValuePathsToTypePaths extends Record<string, string>, ValuePath extends keyof ValuePathsToTypePaths>({ definition: typeDef }: Type, valuePath: ValuePath, allowMissingPaths?: boolean): ValuePathsToTypePaths[ValuePath];
|
|
305
310
|
|
|
@@ -349,54 +354,54 @@ type TypeDefOfUnionTypeDef<T extends UnionTypeDef> = T extends UnionTypeDef<infe
|
|
|
349
354
|
};
|
|
350
355
|
} : never;
|
|
351
356
|
|
|
352
|
-
type ValidatingTypeDefWithError<T extends ValidatingTypeDef, E> = T extends ValidatingLiteralTypeDef ? ValidatingLiteralTypeDefWithError<T, E> : T extends ValidatingListTypeDef ? ValidatingListTypeDefWithError<T, E> : T extends ValidatingRecordTypeDef ? ValidatingRecordTypeDefWithError<T, E> : T extends ValidatingObjectTypeDef ? ValidatingObjectTypeDefWithError<T, E> : T extends ValidatingUnionTypeDef ? ValidatingUnionTypeDefWithError<T, E> : never;
|
|
353
|
-
type ValidatingLiteralTypeDefWithError<T extends ValidatingLiteralTypeDef, E2> = T extends ValidatingLiteralTypeDef<infer E1, infer V> ? {
|
|
357
|
+
type ValidatingTypeDefWithError<T extends ValidatingTypeDef, E, C> = T extends ValidatingLiteralTypeDef ? ValidatingLiteralTypeDefWithError<T, E, C> : T extends ValidatingListTypeDef ? ValidatingListTypeDefWithError<T, E, C> : T extends ValidatingRecordTypeDef ? ValidatingRecordTypeDefWithError<T, E, C> : T extends ValidatingObjectTypeDef ? ValidatingObjectTypeDefWithError<T, E, C> : T extends ValidatingUnionTypeDef ? ValidatingUnionTypeDefWithError<T, E, C> : never;
|
|
358
|
+
type ValidatingLiteralTypeDefWithError<T extends ValidatingLiteralTypeDef, E2, C2> = T extends ValidatingLiteralTypeDef<infer E1, infer C1, infer V> ? {
|
|
354
359
|
readonly type: TypeDefType.Literal;
|
|
355
360
|
readonly valuePrototype: [V];
|
|
356
|
-
readonly rule: Rule<E1 | E2>;
|
|
361
|
+
readonly rule: Rule<E1 | E2, C1 & C2>;
|
|
357
362
|
readonly required: boolean;
|
|
358
363
|
readonly readonly: boolean;
|
|
359
364
|
} : never;
|
|
360
|
-
type ValidatingListTypeDefWithError<T extends ValidatingListTypeDef, E2> = T extends ValidatingListTypeDef<infer E1, infer E> ? IsFieldReadonly<T, 'elements'> extends true ? {
|
|
365
|
+
type ValidatingListTypeDefWithError<T extends ValidatingListTypeDef, E2, C2> = T extends ValidatingListTypeDef<infer E1, infer C1, infer E> ? IsFieldReadonly<T, 'elements'> extends true ? {
|
|
361
366
|
readonly type: TypeDefType.List;
|
|
362
367
|
readonly elements: E;
|
|
363
|
-
readonly rule: Rule<E1 | E2>;
|
|
368
|
+
readonly rule: Rule<E1 | E2, C1 & C2>;
|
|
364
369
|
readonly required: boolean;
|
|
365
370
|
readonly readonly: boolean;
|
|
366
371
|
} : {
|
|
367
372
|
readonly type: TypeDefType.List;
|
|
368
373
|
elements: E;
|
|
369
|
-
readonly rule: Rule<E1 | E2>;
|
|
374
|
+
readonly rule: Rule<E1 | E2, C1 & C2>;
|
|
370
375
|
readonly required: boolean;
|
|
371
376
|
readonly readonly: boolean;
|
|
372
377
|
} : never;
|
|
373
|
-
type ValidatingRecordTypeDefWithError<T extends ValidatingRecordTypeDef, E2> = T extends ValidatingRecordTypeDef<infer E1, infer K, infer V> ? IsFieldReadonly<T, 'valueTypeDef'> extends true ? {
|
|
378
|
+
type ValidatingRecordTypeDefWithError<T extends ValidatingRecordTypeDef, E2, C2> = T extends ValidatingRecordTypeDef<infer E1, infer C1, infer K, infer V> ? IsFieldReadonly<T, 'valueTypeDef'> extends true ? {
|
|
374
379
|
readonly type: TypeDefType.Record;
|
|
375
380
|
readonly keyPrototype: K;
|
|
376
381
|
readonly valueTypeDef: V;
|
|
377
|
-
readonly rule: Rule<E1 | E2>;
|
|
382
|
+
readonly rule: Rule<E1 | E2, C1 & C2>;
|
|
378
383
|
readonly required: boolean;
|
|
379
384
|
readonly readonly: boolean;
|
|
380
385
|
} : {
|
|
381
386
|
readonly type: TypeDefType.Record;
|
|
382
387
|
readonly keyPrototype: K;
|
|
383
388
|
valueTypeDef: V;
|
|
384
|
-
readonly rule: Rule<E1 | E2>;
|
|
389
|
+
readonly rule: Rule<E1 | E2, C1 & C2>;
|
|
385
390
|
readonly required: boolean;
|
|
386
391
|
readonly readonly: boolean;
|
|
387
392
|
} : never;
|
|
388
|
-
type ValidatingObjectTypeDefWithError<T extends ValidatingObjectTypeDef, E2> = T extends ValidatingObjectTypeDef<infer E1, infer Fields> ? {
|
|
393
|
+
type ValidatingObjectTypeDefWithError<T extends ValidatingObjectTypeDef, E2, C2> = T extends ValidatingObjectTypeDef<infer E1, infer C1, infer Fields> ? {
|
|
389
394
|
readonly type: TypeDefType.Object;
|
|
390
395
|
readonly fields: Fields;
|
|
391
|
-
readonly rule: Rule<E1 | E2>;
|
|
396
|
+
readonly rule: Rule<E1 | E2, C1 & C2>;
|
|
392
397
|
readonly required: boolean;
|
|
393
398
|
readonly readonly: boolean;
|
|
394
399
|
} : never;
|
|
395
|
-
type ValidatingUnionTypeDefWithError<T extends ValidatingUnionTypeDef, E2> = T extends ValidatingUnionTypeDef<infer E1, infer D, infer U> ? {
|
|
400
|
+
type ValidatingUnionTypeDefWithError<T extends ValidatingUnionTypeDef, E2, C2> = T extends ValidatingUnionTypeDef<infer E1, infer C1, infer D, infer U> ? {
|
|
396
401
|
readonly type: TypeDefType.Union;
|
|
397
402
|
readonly discriminator: D;
|
|
398
403
|
readonly unions: U;
|
|
399
|
-
readonly rule: Rule<E1 | E2>;
|
|
404
|
+
readonly rule: Rule<E1 | E2, C1 & C2>;
|
|
400
405
|
readonly required: boolean;
|
|
401
406
|
readonly readonly: boolean;
|
|
402
407
|
} : never;
|
|
@@ -404,7 +409,8 @@ type ValidatingUnionTypeDefWithError<T extends ValidatingUnionTypeDef, E2> = T e
|
|
|
404
409
|
declare class TypeDefBuilder<T extends ValidatingTypeDef> implements ValidatingType<T> {
|
|
405
410
|
readonly definition: T;
|
|
406
411
|
constructor(definition: T);
|
|
407
|
-
enforce<E2
|
|
412
|
+
enforce<E2, C2>(): TypeDefBuilder<ValidatingTypeDefWithError<T, E2, C2>>;
|
|
413
|
+
enforce<E2, C2>(rule: Validator<ValueOfType<Type<T>>, E2, string, C2>): TypeDefBuilder<ValidatingTypeDefWithError<T, E2, C2>>;
|
|
408
414
|
required(): TypeDefBuilder<T>;
|
|
409
415
|
readonly(): TypeDefBuilder<T>;
|
|
410
416
|
get _type(): TypeOfType<Type<T>>;
|
|
@@ -444,29 +450,29 @@ declare class RecordTypeDefBuilder<T extends ValidatingRecordTypeDef> extends Ty
|
|
|
444
450
|
readonly readonly: boolean;
|
|
445
451
|
}>;
|
|
446
452
|
}
|
|
447
|
-
declare class ObjectTypeDefBuilder<E, Fields extends Readonly<Record<ObjectFieldKey, ValidatingTypeDef>> = {}> extends TypeDefBuilder<ValidatingObjectTypeDef<E, Fields>> {
|
|
448
|
-
field<Name extends string, T extends ValidatingTypeDef>(name: Name, { definition }: Type<T>): ObjectTypeDefBuilder<E, Fields & Record<Name, T>>;
|
|
449
|
-
field<Name extends string, T extends ValidatingTypeDef, RequiredError>(name: Name, { definition }: Type<T>, rule: Rule<RequiredError, ValueOfTypeDef<T>>): ObjectTypeDefBuilder<E, Fields & Record<Name, ValidatingTypeDefWithError<T, RequiredError>>>;
|
|
450
|
-
readonlyField<Name extends string, T extends ValidatingTypeDef>(name: Name, { definition }: Type<T>): ObjectTypeDefBuilder<E, Fields & Readonly<Record<Name, T>>>;
|
|
451
|
-
optionalField<Name extends string, T extends ValidatingTypeDef>(name: Name, { definition }: Type<T>): ObjectTypeDefBuilder<E, Fields & Partial<Record<Name, T>>>;
|
|
452
|
-
readonlyOptionalField<Name extends string, T extends TypeDef>(name: Name, { definition }: Type<T>): ObjectTypeDefBuilder<E, Fields & Partial<Readonly<Record<Name, T>>>>;
|
|
453
|
+
declare class ObjectTypeDefBuilder<E, C, Fields extends Readonly<Record<ObjectFieldKey, ValidatingTypeDef>> = {}> extends TypeDefBuilder<ValidatingObjectTypeDef<E, C, Fields>> {
|
|
454
|
+
field<Name extends string, T extends ValidatingTypeDef>(name: Name, { definition }: Type<T>): ObjectTypeDefBuilder<E, C, Fields & Record<Name, T>>;
|
|
455
|
+
field<Name extends string, T extends ValidatingTypeDef, RequiredError, C2>(name: Name, { definition }: Type<T>, rule: Rule<RequiredError, ValueOfTypeDef<T>>): ObjectTypeDefBuilder<E, C & C2, Fields & Record<Name, ValidatingTypeDefWithError<T, RequiredError, C & C2>>>;
|
|
456
|
+
readonlyField<Name extends string, T extends ValidatingTypeDef>(name: Name, { definition }: Type<T>): ObjectTypeDefBuilder<E, C, Fields & Readonly<Record<Name, T>>>;
|
|
457
|
+
optionalField<Name extends string, T extends ValidatingTypeDef>(name: Name, { definition }: Type<T>): ObjectTypeDefBuilder<E, C, Fields & Partial<Record<Name, T>>>;
|
|
458
|
+
readonlyOptionalField<Name extends string, T extends TypeDef>(name: Name, { definition }: Type<T>): ObjectTypeDefBuilder<E, C, Fields & Partial<Readonly<Record<Name, T>>>>;
|
|
453
459
|
}
|
|
454
|
-
declare class UnionTypeDefBuilder<E, D extends string | null, U extends Record<UnionKey, TypeDef>> extends TypeDefBuilder<ValidatingUnionTypeDef<E, D, U>> {
|
|
455
|
-
or<K extends Exclude<UnionKey, keyof U>, T extends TypeDef>(k: K, { definition: typeDef, }: Type<T>): UnionTypeDefBuilder<E, D, Readonly<Record<K, T>> & U>;
|
|
460
|
+
declare class UnionTypeDefBuilder<E, C, D extends string | null, U extends Record<UnionKey, TypeDef>> extends TypeDefBuilder<ValidatingUnionTypeDef<E, C, D, U>> {
|
|
461
|
+
or<K extends Exclude<UnionKey, keyof U>, T extends TypeDef>(k: K, { definition: typeDef, }: Type<T>): UnionTypeDefBuilder<E, C, D, Readonly<Record<K, T>> & U>;
|
|
456
462
|
}
|
|
457
|
-
declare function literal<T>(value?: [T]): TypeDefBuilder<ValidatingLiteralTypeDef<never, T>>;
|
|
458
|
-
declare const stringType: TypeDefBuilder<ValidatingLiteralTypeDef<never, string>>;
|
|
459
|
-
declare const numberType: TypeDefBuilder<ValidatingLiteralTypeDef<never, number>>;
|
|
460
|
-
declare const booleanType: TypeDefBuilder<ValidatingLiteralTypeDef<never, boolean>>;
|
|
461
|
-
declare const nullType: TypeDefBuilder<ValidatingLiteralTypeDef<never, null>>;
|
|
462
|
-
declare function nullable<T extends ValidatingTypeDef>(nonNullable: ValidatingType<T>): UnionTypeDefBuilder<never, null, {
|
|
463
|
+
declare function literal<T>(value?: [T]): TypeDefBuilder<ValidatingLiteralTypeDef<never, {}, T>>;
|
|
464
|
+
declare const stringType: TypeDefBuilder<ValidatingLiteralTypeDef<never, {}, string>>;
|
|
465
|
+
declare const numberType: TypeDefBuilder<ValidatingLiteralTypeDef<never, {}, number>>;
|
|
466
|
+
declare const booleanType: TypeDefBuilder<ValidatingLiteralTypeDef<never, {}, boolean>>;
|
|
467
|
+
declare const nullType: TypeDefBuilder<ValidatingLiteralTypeDef<never, {}, null>>;
|
|
468
|
+
declare function nullable<T extends ValidatingTypeDef>(nonNullable: ValidatingType<T>): UnionTypeDefBuilder<never, {}, null, {
|
|
463
469
|
readonly ['0']: T;
|
|
464
|
-
readonly ['1']: ValidatingLiteralTypeDef<never, null>;
|
|
470
|
+
readonly ['1']: ValidatingLiteralTypeDef<never, {}, null>;
|
|
465
471
|
}>;
|
|
466
472
|
declare function list<T extends ValidatingTypeDef>(elements: ValidatingType<T>): ListTypeDefBuilder<{
|
|
467
473
|
readonly type: TypeDefType.List;
|
|
468
474
|
elements: T;
|
|
469
|
-
readonly rule: Rule<never>;
|
|
475
|
+
readonly rule: Rule<never, {}>;
|
|
470
476
|
readonly readonly: boolean;
|
|
471
477
|
readonly required: boolean;
|
|
472
478
|
}>;
|
|
@@ -474,13 +480,13 @@ declare function record<V extends ValidatingType, K extends RecordKeyType>({ def
|
|
|
474
480
|
readonly type: TypeDefType.Record;
|
|
475
481
|
readonly keyPrototype: K;
|
|
476
482
|
valueTypeDef: V["definition"];
|
|
477
|
-
readonly rule: Rule<never>;
|
|
483
|
+
readonly rule: Rule<never, {}>;
|
|
478
484
|
readonly readonly: boolean;
|
|
479
485
|
readonly required: boolean;
|
|
480
486
|
}>;
|
|
481
487
|
declare function object(): ObjectTypeDefBuilder<never, {}>;
|
|
482
|
-
declare function union<D extends null>(): UnionTypeDefBuilder<never, D, {}>;
|
|
483
|
-
declare function union<D extends string>(discriminator: D): UnionTypeDefBuilder<never, D, {}>;
|
|
488
|
+
declare function union<D extends null>(): UnionTypeDefBuilder<never, {}, D, {}>;
|
|
489
|
+
declare function union<D extends string>(discriminator: D): UnionTypeDefBuilder<never, {}, D, {}>;
|
|
484
490
|
|
|
485
491
|
type PathsOfType<T extends Type, SegmentOverride extends string | null = null, Prefix extends string = '$'> = InternalJsonPathsOf<T['definition'], Prefix, SegmentOverride, StartingDepth>;
|
|
486
492
|
type InternalJsonPathsOf<F extends TypeDef, Prefix extends string, SegmentOverride extends string | null, Depth extends number, NextDepth extends number = Depths[Depth]> = InternalJsonPathsOfChildren<F, Prefix, SegmentOverride, '', NextDepth> | Prefix;
|
|
@@ -592,4 +598,4 @@ type ValidatorsOfValues<FlattenedValues extends Readonly<Record<string, any>>, T
|
|
|
592
598
|
readonly [K in keyof FlattenedValues]: Validator<FlattenedValues[K], any, TypePathsToValuePaths[K], Context>;
|
|
593
599
|
};
|
|
594
600
|
|
|
595
|
-
export { type Accessor, type AnnotatedValidator, type Annotations, type AnyValueType, DefinedValidator, type ErrorOfValidator, type FlattenedAccessorsOfType, type FlattenedTypesOfType, type FlattenedValuesOfType, type FunctionalValidator, type InternalJsonPathsOf, type IsStrictUnion, type ListTypeDef, type LiteralTypeDef, type Mapper, type MinimumStringLengthValidationError, MinimumStringLengthValidationErrorType, MinimumStringLengthValidator, type MobxObservable, type MobxValueOfType, type NonMobxObservable, type ObjectFieldKey, type ObjectTypeDef, type ObjectTypeDefFields, OptionalValidatorProxy, type PathsOfType, type ReadonlyOfTypeDef, type ReadonlyTypeOfType, type RecordKeyType, type RecordTypeDef, type RegexpValidationError, RegexpValidationErrorType, RegexpValidator, type Setter, type StrictListTypeDef, type StrictLiteralTypeDef, type StrictObjectTypeDef, type StrictObjectTypeDefFields, type StrictRecordTypeDef, type StrictType, type StrictTypeDef, type StrictUnionTypeDef, type Type, type TypeDef, TypeDefType, type UnionKey, type UnionTypeDef, type ValidationError, type Validator, type ValidatorsOfValues, type ValueOfType, type ValueOfTypeDef, type ValueToTypePathsOfType, type ValueTypesOfDiscriminatedUnion, annotations, booleanType, copy, flattenAccessorsOfType, flattenJsonValueToTypePathsOf, flattenTypesOfType, flattenValidatorsOfValidatingType, flattenValueTo, flattenValuesOfType, getUnionTypeDef, isAnnotatedValidator, isFunctionalValidator, jsonPath, jsonPathPop, list, literal, mergeAnnotations, mobxCopy, nullType, nullable, numberType, object, record, stringType, union, validate, valuePathToTypePath };
|
|
601
|
+
export { type Accessor, type AnnotatedValidator, type Annotations, type AnyValueType, DefinedValidator, type ErrorOfValidator, type FlattenedAccessorsOfType, type FlattenedTypesOfType, type FlattenedValuesOfType, type FunctionalValidator, type InternalJsonPathsOf, type IsStrictUnion, type ListTypeDef, type LiteralTypeDef, type Mapper, type MinimumStringLengthValidationError, MinimumStringLengthValidationErrorType, MinimumStringLengthValidator, type MobxObservable, type MobxValueOfType, type NonMobxObservable, type ObjectFieldKey, type ObjectTypeDef, type ObjectTypeDefFields, OptionalValidatorProxy, type PathsOfType, type ReadonlyOfTypeDef, type ReadonlyTypeOfType, type RecordKeyType, type RecordTypeDef, type RegexpValidationError, RegexpValidationErrorType, RegexpValidator, type Setter, type StrictListTypeDef, type StrictLiteralTypeDef, type StrictObjectTypeDef, type StrictObjectTypeDefFields, type StrictRecordTypeDef, type StrictType, type StrictTypeDef, type StrictUnionTypeDef, type Type, type TypeDef, TypeDefType, type UnionKey, type UnionTypeDef, type ValidationError, type Validator, type ValidatorsOfValues, type ValueOfType, type ValueOfTypeDef, type ValueToTypePathsOfType, type ValueTypesOfDiscriminatedUnion, annotations, booleanType, copy, flattenAccessorsOfType, flattenJsonValueToTypePathsOf, flattenTypesOfType, flattenValidatorsOfValidatingType, flattenValueTo, flattenValuesOfType, getUnionTypeDef, isAnnotatedValidator, isFunctionalValidator, jsonPath, jsonPathPop, jsonPathPrefix, jsonPathUnprefix, list, literal, mergeAnnotations, mergeValidators, mobxCopy, nullType, nullable, numberType, object, record, stringType, union, validate, valuePathToTypePath };
|
package/dist/index.js
CHANGED
|
@@ -185,8 +185,12 @@ import {
|
|
|
185
185
|
} from "@strictly/base";
|
|
186
186
|
|
|
187
187
|
// transformers/flatteners/json_path.ts
|
|
188
|
-
|
|
189
|
-
|
|
188
|
+
import {
|
|
189
|
+
assertEqual,
|
|
190
|
+
assertState
|
|
191
|
+
} from "@strictly/base";
|
|
192
|
+
function jsonPath(prefix, segment, qualifier) {
|
|
193
|
+
const s = `.${qualifier != null ? qualifier : ""}${segment}`;
|
|
190
194
|
return `${prefix}${s}`;
|
|
191
195
|
}
|
|
192
196
|
function jsonPathPop(path) {
|
|
@@ -199,6 +203,14 @@ function jsonPathPop(path) {
|
|
|
199
203
|
parts.pop()
|
|
200
204
|
];
|
|
201
205
|
}
|
|
206
|
+
function jsonPathPrefix(prefix, path) {
|
|
207
|
+
assertEqual(path[0], "$", "{} should start with $", path);
|
|
208
|
+
return `${prefix}${path.slice(1)}`;
|
|
209
|
+
}
|
|
210
|
+
function jsonPathUnprefix(prefix, path) {
|
|
211
|
+
assertState(path.startsWith(prefix), "{} should start with {}", path, prefix);
|
|
212
|
+
return `$${path.slice(prefix.length)}`;
|
|
213
|
+
}
|
|
202
214
|
|
|
203
215
|
// transformers/flatteners/flatten_value_to.ts
|
|
204
216
|
function flattenValueTo({ definition }, v, setter, mapper2) {
|
|
@@ -523,7 +535,7 @@ function flattenValuesOfType(typeDef, value) {
|
|
|
523
535
|
|
|
524
536
|
// transformers/flatteners/value_path_to_type_path.ts
|
|
525
537
|
import {
|
|
526
|
-
assertEqual,
|
|
538
|
+
assertEqual as assertEqual2,
|
|
527
539
|
assertExists,
|
|
528
540
|
assertExistsAndReturn,
|
|
529
541
|
PreconditionFailedError,
|
|
@@ -532,7 +544,7 @@ import {
|
|
|
532
544
|
} from "@strictly/base";
|
|
533
545
|
function valuePathToTypePath({ definition: typeDef }, valuePath, allowMissingPaths = false) {
|
|
534
546
|
const valueSteps = valuePath.split(/\.|\[/g);
|
|
535
|
-
|
|
547
|
+
assertEqual2(valueSteps[0], "$");
|
|
536
548
|
const typeSteps = internalJsonValuePathToTypePath(
|
|
537
549
|
typeDef,
|
|
538
550
|
valueSteps.slice(1),
|
|
@@ -660,6 +672,40 @@ function internalJsonValuePathToTypePath(typeDef, valueSteps, allowMissingPaths,
|
|
|
660
672
|
}
|
|
661
673
|
}
|
|
662
674
|
|
|
675
|
+
// validation/validators/composite_validator.ts
|
|
676
|
+
var CompositeValidator = class {
|
|
677
|
+
constructor(...validators) {
|
|
678
|
+
__publicField(this, "validators");
|
|
679
|
+
this.validators = validators;
|
|
680
|
+
}
|
|
681
|
+
validate(v, valuePath, context) {
|
|
682
|
+
return this.validators.reduce((error, validator) => {
|
|
683
|
+
if (error != null) {
|
|
684
|
+
return error;
|
|
685
|
+
}
|
|
686
|
+
return validate(validator, v, valuePath, context);
|
|
687
|
+
}, null);
|
|
688
|
+
}
|
|
689
|
+
annotations(valuePath, context) {
|
|
690
|
+
return this.validators.reduce(({
|
|
691
|
+
required,
|
|
692
|
+
readonly
|
|
693
|
+
}, validator) => {
|
|
694
|
+
const {
|
|
695
|
+
readonly: validatorReadonly,
|
|
696
|
+
required: validatorRequired
|
|
697
|
+
} = annotations(validator, valuePath, context);
|
|
698
|
+
return {
|
|
699
|
+
required: required || validatorRequired,
|
|
700
|
+
readonly: readonly || validatorReadonly
|
|
701
|
+
};
|
|
702
|
+
}, {
|
|
703
|
+
required: false,
|
|
704
|
+
readonly: false
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
|
|
663
709
|
// validation/validator.ts
|
|
664
710
|
function isFunctionalValidator(v) {
|
|
665
711
|
return typeof v === "function";
|
|
@@ -674,6 +720,9 @@ function validate(validator, v, valuePath, context) {
|
|
|
674
720
|
return validator(v, valuePath, context);
|
|
675
721
|
}
|
|
676
722
|
}
|
|
723
|
+
function mergeValidators(v1, v2) {
|
|
724
|
+
return new CompositeValidator(v1, v2);
|
|
725
|
+
}
|
|
677
726
|
function annotations(validator, valuePath, context) {
|
|
678
727
|
if (isAnnotatedValidator(validator)) {
|
|
679
728
|
return validator.annotations(valuePath, context);
|
|
@@ -782,11 +831,11 @@ var TypeDefBuilder = class _TypeDefBuilder {
|
|
|
782
831
|
enforce(rule) {
|
|
783
832
|
return new _TypeDefBuilder(
|
|
784
833
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
785
|
-
__spreadProps(__spreadValues(__spreadValues({}, this.definition), isAnnotatedValidator(rule) ? mergeAnnotations(rule.annotations(null, null), this.definition) : {}), {
|
|
834
|
+
__spreadProps(__spreadValues(__spreadValues({}, this.definition), rule != null && isAnnotatedValidator(rule) ? mergeAnnotations(rule.annotations(null, null), this.definition) : {}), {
|
|
786
835
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
787
|
-
rule: (value) => {
|
|
836
|
+
rule: (value, valuePath, context) => {
|
|
788
837
|
var _a;
|
|
789
|
-
return (_a = this.definition.rule(value)) != null ? _a : validate(rule, value,
|
|
838
|
+
return (_a = this.definition.rule(value, valuePath, context)) != null ? _a : rule && validate(rule, value, valuePath, context);
|
|
790
839
|
}
|
|
791
840
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
792
841
|
})
|
|
@@ -850,8 +899,9 @@ var ObjectTypeDefBuilder = class _ObjectTypeDefBuilder extends TypeDefBuilder {
|
|
|
850
899
|
fields: __spreadProps(__spreadValues({}, this.definition.fields), {
|
|
851
900
|
[name]: __spreadProps(__spreadValues({}, definition), {
|
|
852
901
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
853
|
-
rule: function(v) {
|
|
854
|
-
|
|
902
|
+
rule: function(v, valuePath, context) {
|
|
903
|
+
var _a;
|
|
904
|
+
return (_a = definition.rule(v, valuePath, context)) != null ? _a : rule && validate(rule, v, valuePath, context);
|
|
855
905
|
}
|
|
856
906
|
})
|
|
857
907
|
})
|
|
@@ -1107,9 +1157,12 @@ export {
|
|
|
1107
1157
|
isFunctionalValidator,
|
|
1108
1158
|
jsonPath,
|
|
1109
1159
|
jsonPathPop,
|
|
1160
|
+
jsonPathPrefix,
|
|
1161
|
+
jsonPathUnprefix,
|
|
1110
1162
|
list,
|
|
1111
1163
|
literal,
|
|
1112
1164
|
mergeAnnotations,
|
|
1165
|
+
mergeValidators,
|
|
1113
1166
|
mobxCopy,
|
|
1114
1167
|
nullType,
|
|
1115
1168
|
nullable,
|
package/package.json
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
assertEqual,
|
|
3
|
+
assertState,
|
|
4
|
+
type StringConcatOf,
|
|
5
|
+
} from '@strictly/base'
|
|
6
|
+
|
|
7
|
+
export function jsonPath<
|
|
8
|
+
Prefix extends string,
|
|
9
|
+
Segment extends number | string,
|
|
10
|
+
>(prefix: Prefix, segment: Segment): `${Prefix}.${Segment}`
|
|
11
|
+
export function jsonPath<
|
|
12
|
+
Prefix extends string,
|
|
13
|
+
Segment extends number | string,
|
|
14
|
+
Qualifier extends string,
|
|
15
|
+
>(prefix: Prefix, segment: Segment, qualifier: Qualifier): `${Prefix}.${Qualifier}${Segment}`
|
|
16
|
+
export function jsonPath<
|
|
17
|
+
Prefix extends string,
|
|
18
|
+
Segment extends number | string,
|
|
19
|
+
Qualifier extends string = '',
|
|
20
|
+
>(prefix: Prefix, segment: Segment, qualifier?: Qualifier) {
|
|
21
|
+
const s = `.${qualifier ?? ''}${segment}`
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
23
|
+
return `${prefix}${s}` as `${Prefix}.${Qualifier}${Segment}`
|
|
4
24
|
}
|
|
5
25
|
|
|
6
|
-
|
|
26
|
+
// TODO type safety
|
|
27
|
+
export function jsonPathPop<Path extends string>(path: Path): [string, string] | null {
|
|
7
28
|
const parts = path.split('.')
|
|
8
29
|
if (parts.length <= 1) {
|
|
9
30
|
return null
|
|
@@ -13,3 +34,22 @@ export function jsonPathPop(path: string): [string, string] | null {
|
|
|
13
34
|
parts.pop()!,
|
|
14
35
|
]
|
|
15
36
|
}
|
|
37
|
+
|
|
38
|
+
export function jsonPathPrefix<
|
|
39
|
+
Prefix extends string,
|
|
40
|
+
Path extends string,
|
|
41
|
+
>(prefix: Prefix, path: Path): Path extends StringConcatOf<'$', infer ToMount> ? `${Prefix}${ToMount}` : never {
|
|
42
|
+
assertEqual(path[0], '$', '{} should start with $', path)
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
44
|
+
return `${prefix}${path.slice(1)}` as Path extends StringConcatOf<'$', infer ToMount> ? `${Prefix}${ToMount}` : never
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function jsonPathUnprefix<
|
|
48
|
+
Prefix extends string,
|
|
49
|
+
Path extends string,
|
|
50
|
+
>(prefix: Prefix, path: Path): Path extends StringConcatOf<Prefix, infer ToUnmount> ? `$${ToUnmount}` : never {
|
|
51
|
+
assertState(path.startsWith(prefix), '{} should start with {}', path, prefix)
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
53
|
+
return `$${path.slice(prefix.length)}` as Path extends StringConcatOf<Prefix, infer ToUnmount> ? `$${ToUnmount}`
|
|
54
|
+
: never
|
|
55
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
jsonPath,
|
|
3
|
+
jsonPathPrefix,
|
|
4
|
+
jsonPathUnprefix,
|
|
5
|
+
} from 'transformers/flatteners/json_path'
|
|
6
|
+
|
|
7
|
+
describe('json_paths', () => {
|
|
8
|
+
describe('jsonPath', () => {
|
|
9
|
+
describe('simple', () => {
|
|
10
|
+
const path = jsonPath('$', 'thing')
|
|
11
|
+
|
|
12
|
+
it('has the expected type', () => {
|
|
13
|
+
expectTypeOf(path).toEqualTypeOf<'$.thing'>()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('has the expected value', () => {
|
|
17
|
+
expect(path).toEqual('$.thing')
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
describe('indexed', () => {
|
|
22
|
+
const path = jsonPath<`$.${number}`, number>(`$.${1}`, 1)
|
|
23
|
+
|
|
24
|
+
it('has the expected type', () => {
|
|
25
|
+
expectTypeOf(path).toEqualTypeOf<`$.${number}.${number}`>()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('has the expected value', () => {
|
|
29
|
+
expect(path).toEqual('$.1.1')
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('qualified', () => {
|
|
34
|
+
const path = jsonPath('$', 'x', 'y:')
|
|
35
|
+
|
|
36
|
+
it('has the expected type', () => {
|
|
37
|
+
expectTypeOf(path).toEqualTypeOf<'$.y:x'>()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('has the expected value', () => {
|
|
41
|
+
expect(path).toEqual('$.y:x')
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('jsonPathPrefix', () => {
|
|
47
|
+
const path = jsonPathPrefix('$.x', '$.x.y')
|
|
48
|
+
|
|
49
|
+
it('has the expected type', () => {
|
|
50
|
+
expectTypeOf(path).toEqualTypeOf<'$.x.x.y'>()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('has the expected value', () => {
|
|
54
|
+
expect(path).toEqual('$.x.x.y')
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
describe('jsonPathUnprefix', () => {
|
|
59
|
+
const path = jsonPathUnprefix('$.x.x.x', '$.x.x.x.x.y')
|
|
60
|
+
|
|
61
|
+
it('has the expected type', () => {
|
|
62
|
+
expectTypeOf(path).toEqualTypeOf<'$.x.y'>()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('has the expected value', () => {
|
|
66
|
+
expect(path).toEqual('$.x.y')
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
})
|