@strictly/define 0.0.1
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/.eslintrc.cjs +31 -0
- package/.out/index.d.ts +20 -0
- package/.out/index.js +20 -0
- package/.out/transformers/copies/copy.d.ts +4 -0
- package/.out/transformers/copies/copy.js +7 -0
- package/.out/transformers/copies/copy_to.d.ts +6 -0
- package/.out/transformers/copies/copy_to.js +91 -0
- package/.out/transformers/copies/mobx_copy.d.ts +5 -0
- package/.out/transformers/copies/mobx_copy.js +42 -0
- package/.out/transformers/copies/specs/copy_to.tests.d.ts +1 -0
- package/.out/transformers/copies/specs/copy_to.tests.js +97 -0
- package/.out/transformers/copies/specs/mobx_copy.tests.d.ts +1 -0
- package/.out/transformers/copies/specs/mobx_copy.tests.js +19 -0
- package/.out/transformers/flatteners/flatten_accessors_of.d.ts +5 -0
- package/.out/transformers/flatteners/flatten_accessors_of.js +11 -0
- package/.out/transformers/flatteners/flatten_json_value_to_type_paths_of.d.ts +3 -0
- package/.out/transformers/flatteners/flatten_json_value_to_type_paths_of.js +10 -0
- package/.out/transformers/flatteners/flatten_type_def_to.d.ts +4 -0
- package/.out/transformers/flatteners/flatten_type_def_to.js +49 -0
- package/.out/transformers/flatteners/flatten_type_defs_of.d.ts +3 -0
- package/.out/transformers/flatteners/flatten_type_defs_of.js +7 -0
- package/.out/transformers/flatteners/flatten_value_type_to.d.ts +11 -0
- package/.out/transformers/flatteners/flatten_value_type_to.js +79 -0
- package/.out/transformers/flatteners/flatten_value_types_of.d.ts +3 -0
- package/.out/transformers/flatteners/flatten_value_types_of.js +7 -0
- package/.out/transformers/flatteners/json_path.d.ts +2 -0
- package/.out/transformers/flatteners/json_path.js +14 -0
- package/.out/transformers/flatteners/specs/flatten_accessors_of.tests.d.ts +1 -0
- package/.out/transformers/flatteners/specs/flatten_accessors_of.tests.js +90 -0
- package/.out/transformers/flatteners/specs/flatten_json_value_to_type_paths_of.tests.d.ts +1 -0
- package/.out/transformers/flatteners/specs/flatten_json_value_to_type_paths_of.tests.js +94 -0
- package/.out/transformers/flatteners/specs/flatten_type_def_to.tests.d.ts +1 -0
- package/.out/transformers/flatteners/specs/flatten_type_def_to.tests.js +110 -0
- package/.out/transformers/flatteners/specs/flatten_type_defs_of.tests.d.ts +1 -0
- package/.out/transformers/flatteners/specs/flatten_type_defs_of.tests.js +17 -0
- package/.out/transformers/flatteners/specs/flatten_value_type_to.tests.d.ts +1 -0
- package/.out/transformers/flatteners/specs/flatten_value_type_to.tests.js +297 -0
- package/.out/transformers/flatteners/specs/flatten_value_types_of.tests.d.ts +1 -0
- package/.out/transformers/flatteners/specs/flatten_value_types_of.tests.js +37 -0
- package/.out/transformers/flatteners/specs/value_path_to_type_path.tests.d.ts +1 -0
- package/.out/transformers/flatteners/specs/value_path_to_type_path.tests.js +167 -0
- package/.out/transformers/flatteners/value_path_to_type_path.d.ts +2 -0
- package/.out/transformers/flatteners/value_path_to_type_path.js +96 -0
- package/.out/tsconfig.json +15 -0
- package/.out/tsconfig.tsbuildinfo +1 -0
- package/.out/tsup.config.d.ts +3 -0
- package/.out/tsup.config.js +12 -0
- package/.out/types/builders.d.ts +62 -0
- package/.out/types/builders.js +148 -0
- package/.out/types/definitions.d.ts +41 -0
- package/.out/types/definitions.js +26 -0
- package/.out/types/flattened.d.ts +2 -0
- package/.out/types/flattened.js +1 -0
- package/.out/types/flattened_accessors_of.d.ts +9 -0
- package/.out/types/flattened_accessors_of.js +1 -0
- package/.out/types/flattened_type_defs_of.d.ts +21 -0
- package/.out/types/flattened_type_defs_of.js +1 -0
- package/.out/types/flattened_value_types_of.d.ts +6 -0
- package/.out/types/flattened_value_types_of.js +1 -0
- package/.out/types/json_path_of.d.ts +1 -0
- package/.out/types/json_path_of.js +1 -0
- package/.out/types/json_paths_of.d.ts +16 -0
- package/.out/types/json_paths_of.js +1 -0
- package/.out/types/mobx_value_type_of.d.ts +11 -0
- package/.out/types/mobx_value_type_of.js +2 -0
- package/.out/types/partial_type_def_of.d.ts +40 -0
- package/.out/types/partial_type_def_of.js +1 -0
- package/.out/types/readonly_type_def_of.d.ts +29 -0
- package/.out/types/readonly_type_def_of.js +1 -0
- package/.out/types/specs/builder.tests.d.ts +1 -0
- package/.out/types/specs/builder.tests.js +93 -0
- package/.out/types/specs/flattened_accessors_of.tests.d.ts +1 -0
- package/.out/types/specs/flattened_accessors_of.tests.js +11 -0
- package/.out/types/specs/flattened_type_defs_of.tests.d.ts +1 -0
- package/.out/types/specs/flattened_type_defs_of.tests.js +71 -0
- package/.out/types/specs/flattened_value_types_of.tests.d.ts +1 -0
- package/.out/types/specs/flattened_value_types_of.tests.js +11 -0
- package/.out/types/specs/json_paths_of.tests.d.ts +1 -0
- package/.out/types/specs/json_paths_of.tests.js +199 -0
- package/.out/types/specs/partial_type_def_of.tests.d.ts +1 -0
- package/.out/types/specs/partial_type_def_of.tests.js +50 -0
- package/.out/types/specs/readonly_type_def_of.tests.d.ts +1 -0
- package/.out/types/specs/readonly_type_def_of.tests.js +55 -0
- package/.out/types/specs/strict_definitions.tests.d.ts +1 -0
- package/.out/types/specs/strict_definitions.tests.js +42 -0
- package/.out/types/specs/value_to_type_paths_of.tests.d.ts +1 -0
- package/.out/types/specs/value_to_type_paths_of.tests.js +90 -0
- package/.out/types/specs/value_type_of.tests.d.ts +1 -0
- package/.out/types/specs/value_type_of.tests.js +91 -0
- package/.out/types/specs/value_types_of_discriminated_union.tests.d.ts +1 -0
- package/.out/types/specs/value_types_of_discriminated_union.tests.js +9 -0
- package/.out/types/strict_definitions.d.ts +44 -0
- package/.out/types/strict_definitions.js +1 -0
- package/.out/types/value_to_type_paths_of.d.ts +22 -0
- package/.out/types/value_to_type_paths_of.js +1 -0
- package/.out/types/value_type_of.d.ts +24 -0
- package/.out/types/value_type_of.js +1 -0
- package/.out/types/value_types_of_discriminated_union.d.ts +9 -0
- package/.out/types/value_types_of_discriminated_union.js +1 -0
- package/.out/vitest.workspace.d.ts +2 -0
- package/.out/vitest.workspace.js +7 -0
- package/.turbo/turbo-build.log +18 -0
- package/.turbo/turbo-check-types.log +3 -0
- package/.turbo/turbo-release$colon$exports.log +3 -0
- package/README.md +12 -0
- package/dist/index.cjs +798 -0
- package/dist/index.d.cts +301 -0
- package/dist/index.d.ts +301 -0
- package/dist/index.js +775 -0
- package/index.ts +20 -0
- package/package.exports.json +18 -0
- package/package.json +45 -0
- package/transformers/copies/copy.ts +18 -0
- package/transformers/copies/copy_to.ts +226 -0
- package/transformers/copies/mobx_copy.ts +81 -0
- package/transformers/copies/specs/copy_to.tests.ts +143 -0
- package/transformers/copies/specs/mobx_copy.tests.ts +26 -0
- package/transformers/flatteners/flatten_accessors_of.ts +43 -0
- package/transformers/flatteners/flatten_json_value_to_type_paths_of.ts +39 -0
- package/transformers/flatteners/flatten_type_def_to.ts +127 -0
- package/transformers/flatteners/flatten_type_defs_of.ts +16 -0
- package/transformers/flatteners/flatten_value_type_to.ts +227 -0
- package/transformers/flatteners/flatten_value_types_of.ts +23 -0
- package/transformers/flatteners/json_path.ts +15 -0
- package/transformers/flatteners/specs/flatten_accessors_of.tests.ts +113 -0
- package/transformers/flatteners/specs/flatten_json_value_to_type_paths_of.tests.ts +115 -0
- package/transformers/flatteners/specs/flatten_type_def_to.tests.ts +146 -0
- package/transformers/flatteners/specs/flatten_type_defs_of.tests.ts +26 -0
- package/transformers/flatteners/specs/flatten_value_type_to.tests.ts +452 -0
- package/transformers/flatteners/specs/flatten_value_types_of.tests.ts +46 -0
- package/transformers/flatteners/specs/value_path_to_type_path.tests.ts +240 -0
- package/transformers/flatteners/value_path_to_type_path.ts +164 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +16 -0
- package/types/builders.ts +284 -0
- package/types/definitions.ts +106 -0
- package/types/flattened.ts +5 -0
- package/types/flattened_accessors_of.ts +15 -0
- package/types/flattened_type_defs_of.ts +130 -0
- package/types/flattened_value_types_of.ts +11 -0
- package/types/json_path_of.ts +7 -0
- package/types/json_paths_of.ts +129 -0
- package/types/mobx_value_type_of.ts +16 -0
- package/types/partial_type_def_of.ts +64 -0
- package/types/readonly_type_def_of.ts +53 -0
- package/types/specs/builder.tests.ts +295 -0
- package/types/specs/flattened_accessors_of.tests.ts +27 -0
- package/types/specs/flattened_type_defs_of.tests.ts +212 -0
- package/types/specs/flattened_value_types_of.tests.ts +21 -0
- package/types/specs/json_paths_of.tests.ts +304 -0
- package/types/specs/partial_type_def_of.tests.ts +251 -0
- package/types/specs/readonly_type_def_of.tests.ts +158 -0
- package/types/specs/strict_definitions.tests.ts +184 -0
- package/types/specs/value_to_type_paths_of.tests.ts +181 -0
- package/types/specs/value_type_of.tests.ts +329 -0
- package/types/specs/value_types_of_discriminated_union.tests.ts +30 -0
- package/types/strict_definitions.ts +107 -0
- package/types/value_to_type_paths_of.ts +184 -0
- package/types/value_type_of.ts +84 -0
- package/types/value_types_of_discriminated_union.ts +14 -0
- package/vitest.workspace.ts +11 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import {
|
|
2
|
+
reduce,
|
|
3
|
+
UnreachableError,
|
|
4
|
+
} from '@strictly/base'
|
|
5
|
+
import {
|
|
6
|
+
TypeDefType,
|
|
7
|
+
} from 'types/definitions'
|
|
8
|
+
import {
|
|
9
|
+
type StrictListTypeDef,
|
|
10
|
+
type StrictObjectTypeDef,
|
|
11
|
+
type StrictRecordTypeDef,
|
|
12
|
+
type StrictType,
|
|
13
|
+
type StrictTypeDef,
|
|
14
|
+
type StrictUnionTypeDef,
|
|
15
|
+
} from 'types/strict_definitions'
|
|
16
|
+
import { jsonPath } from './json_path'
|
|
17
|
+
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
export type AnyValueType = any
|
|
20
|
+
|
|
21
|
+
export type Mapper<R> = (t: StrictTypeDef) => R
|
|
22
|
+
|
|
23
|
+
export function flattenTypeDefTo<M, R extends Readonly<Record<string, M>>>(
|
|
24
|
+
{ definition }: StrictType,
|
|
25
|
+
mapper: Mapper<M>,
|
|
26
|
+
): R {
|
|
27
|
+
const typeDefs = internalFlattenTypeDef('$', definition, {})
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
29
|
+
return reduce(
|
|
30
|
+
typeDefs,
|
|
31
|
+
function (acc, key, typeDef) {
|
|
32
|
+
acc[key] = mapper(typeDef)
|
|
33
|
+
return acc
|
|
34
|
+
},
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
36
|
+
{} as Record<string, M>,
|
|
37
|
+
) as R
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function internalFlattenTypeDef(
|
|
41
|
+
path: string,
|
|
42
|
+
t: StrictTypeDef,
|
|
43
|
+
r: Record<string, StrictTypeDef>,
|
|
44
|
+
): Record<string, StrictTypeDef> {
|
|
45
|
+
r[path] = t
|
|
46
|
+
return internalFlattenTypeDefChildren(path, '', t, r)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function internalFlattenTypeDefChildren(
|
|
50
|
+
path: string,
|
|
51
|
+
qualifier: string,
|
|
52
|
+
t: StrictTypeDef,
|
|
53
|
+
r: Record<string, StrictTypeDef>,
|
|
54
|
+
): Record<string, StrictTypeDef> {
|
|
55
|
+
switch (t.type) {
|
|
56
|
+
case TypeDefType.Literal:
|
|
57
|
+
return r
|
|
58
|
+
case TypeDefType.List:
|
|
59
|
+
return internalFlattenedListTypeDefChildren(path, t, r)
|
|
60
|
+
case TypeDefType.Record:
|
|
61
|
+
return internalFlattenRecordTypeDefChildren(path, t, r)
|
|
62
|
+
case TypeDefType.Object:
|
|
63
|
+
return internalFlattenObjectTypeDefChildren(path, qualifier, t, r)
|
|
64
|
+
case TypeDefType.Union:
|
|
65
|
+
return internalFlattenUnionTypeDefChildren(path, qualifier, t, r)
|
|
66
|
+
default:
|
|
67
|
+
throw new UnreachableError(t)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function internalFlattenedListTypeDefChildren(
|
|
72
|
+
path: string,
|
|
73
|
+
{ elements }: StrictListTypeDef,
|
|
74
|
+
r: Record<string, StrictTypeDef>,
|
|
75
|
+
): Record<string, StrictTypeDef> {
|
|
76
|
+
return internalFlattenTypeDef(jsonPath(path, '*'), elements, r)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function internalFlattenRecordTypeDefChildren(
|
|
80
|
+
path: string,
|
|
81
|
+
{ valueTypeDef }: StrictRecordTypeDef,
|
|
82
|
+
r: Record<string, StrictTypeDef>,
|
|
83
|
+
): Record<string, StrictTypeDef> {
|
|
84
|
+
return internalFlattenTypeDef(jsonPath(path, '*'), valueTypeDef, r)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function internalFlattenObjectTypeDefChildren(
|
|
88
|
+
path: string,
|
|
89
|
+
qualifier: string,
|
|
90
|
+
{ fields }: StrictObjectTypeDef,
|
|
91
|
+
r: Record<string, StrictTypeDef>,
|
|
92
|
+
): Record<string, StrictTypeDef> {
|
|
93
|
+
return reduce(
|
|
94
|
+
fields,
|
|
95
|
+
function (acc, fieldName, fieldTypeDef) {
|
|
96
|
+
return internalFlattenTypeDef(
|
|
97
|
+
jsonPath(path, fieldName, qualifier),
|
|
98
|
+
fieldTypeDef,
|
|
99
|
+
acc,
|
|
100
|
+
)
|
|
101
|
+
},
|
|
102
|
+
r,
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function internalFlattenUnionTypeDefChildren(
|
|
107
|
+
path: string,
|
|
108
|
+
qualifier: string,
|
|
109
|
+
{
|
|
110
|
+
discriminator,
|
|
111
|
+
unions,
|
|
112
|
+
}: StrictUnionTypeDef,
|
|
113
|
+
r: Record<string, StrictTypeDef>,
|
|
114
|
+
): Record<string, StrictTypeDef> {
|
|
115
|
+
return reduce(
|
|
116
|
+
unions,
|
|
117
|
+
function (acc, key, typeDef: StrictTypeDef) {
|
|
118
|
+
return internalFlattenTypeDefChildren(
|
|
119
|
+
path,
|
|
120
|
+
discriminator != null ? `${qualifier}${key}:` : qualifier,
|
|
121
|
+
typeDef,
|
|
122
|
+
acc,
|
|
123
|
+
)
|
|
124
|
+
},
|
|
125
|
+
r,
|
|
126
|
+
)
|
|
127
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Type,
|
|
3
|
+
type TypeDef,
|
|
4
|
+
} from 'types/definitions'
|
|
5
|
+
import { type StrictType } from 'types/strict_definitions'
|
|
6
|
+
import { flattenTypeDefTo } from './flatten_type_def_to'
|
|
7
|
+
|
|
8
|
+
export function flattenTypeDefsOf<T extends StrictType>(t: T) {
|
|
9
|
+
// Type should be FlattenedTypeDefsOf<T>, but infinite depth error
|
|
10
|
+
return flattenTypeDefTo<StrictType, Record<string, Type>>(
|
|
11
|
+
t,
|
|
12
|
+
function (definition: TypeDef) {
|
|
13
|
+
return { definition }
|
|
14
|
+
},
|
|
15
|
+
)
|
|
16
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import {
|
|
2
|
+
reduce,
|
|
3
|
+
UnreachableError,
|
|
4
|
+
} from '@strictly/base'
|
|
5
|
+
import {
|
|
6
|
+
type TypeDef,
|
|
7
|
+
TypeDefType,
|
|
8
|
+
type UnionTypeDef,
|
|
9
|
+
} from 'types/definitions'
|
|
10
|
+
import { type ReadonlyTypeDefOf } from 'types/readonly_type_def_of'
|
|
11
|
+
import {
|
|
12
|
+
type StrictListTypeDef,
|
|
13
|
+
type StrictObjectTypeDef,
|
|
14
|
+
type StrictRecordTypeDef,
|
|
15
|
+
type StrictType,
|
|
16
|
+
type StrictTypeDef,
|
|
17
|
+
type StrictUnionTypeDef,
|
|
18
|
+
} from 'types/strict_definitions'
|
|
19
|
+
import { type ValueTypeOf } from 'types/value_type_of'
|
|
20
|
+
import { jsonPath } from './json_path'
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
export type AnyValueType = any
|
|
24
|
+
export type Setter<V> = (v: V) => void
|
|
25
|
+
|
|
26
|
+
export type Mapper<R> = (
|
|
27
|
+
t: StrictTypeDef,
|
|
28
|
+
v: AnyValueType,
|
|
29
|
+
setter: Setter<AnyValueType>,
|
|
30
|
+
typePath: string,
|
|
31
|
+
valuePath: string,
|
|
32
|
+
) => R
|
|
33
|
+
|
|
34
|
+
export function flattenValueTypeTo<
|
|
35
|
+
T extends StrictType,
|
|
36
|
+
M,
|
|
37
|
+
R extends Readonly<Record<string, M>>,
|
|
38
|
+
>(
|
|
39
|
+
{ definition }: T,
|
|
40
|
+
v: ValueTypeOf<T>,
|
|
41
|
+
setter: Setter<ValueTypeOf<T>>,
|
|
42
|
+
mapper: Mapper<M>,
|
|
43
|
+
): R {
|
|
44
|
+
const r: Record<string, AnyValueType> = {}
|
|
45
|
+
internalFlattenValue(
|
|
46
|
+
'$',
|
|
47
|
+
'$',
|
|
48
|
+
definition,
|
|
49
|
+
v,
|
|
50
|
+
setter,
|
|
51
|
+
mapper,
|
|
52
|
+
r,
|
|
53
|
+
)
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
55
|
+
return r as R
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function internalFlattenValue<M>(
|
|
59
|
+
valuePath: string,
|
|
60
|
+
typePath: string,
|
|
61
|
+
typeDef: StrictTypeDef,
|
|
62
|
+
v: AnyValueType,
|
|
63
|
+
setter: Setter<AnyValueType>,
|
|
64
|
+
mapper: Mapper<M>,
|
|
65
|
+
r: Record<string, M>,
|
|
66
|
+
) {
|
|
67
|
+
r[valuePath] = mapper(typeDef, v, setter, typePath, valuePath)
|
|
68
|
+
return internalFlattenValueChildren(valuePath, typePath, '', typeDef, v, mapper, r)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function internalFlattenValueChildren<M>(
|
|
72
|
+
valuePath: string,
|
|
73
|
+
typePath: string,
|
|
74
|
+
qualifier: string,
|
|
75
|
+
typeDef: StrictTypeDef,
|
|
76
|
+
v: AnyValueType,
|
|
77
|
+
mapper: Mapper<M>,
|
|
78
|
+
r: Record<string, M>,
|
|
79
|
+
) {
|
|
80
|
+
switch (typeDef.type) {
|
|
81
|
+
case TypeDefType.Literal:
|
|
82
|
+
// no children
|
|
83
|
+
return r
|
|
84
|
+
case TypeDefType.List:
|
|
85
|
+
return internalFlattenListChildren(valuePath, typePath, typeDef, v, mapper, r)
|
|
86
|
+
case TypeDefType.Record:
|
|
87
|
+
return internalFlattenRecordChildren(valuePath, typePath, typeDef, v, mapper, r)
|
|
88
|
+
case TypeDefType.Object:
|
|
89
|
+
return internalFlattenObjectChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r)
|
|
90
|
+
case TypeDefType.Union:
|
|
91
|
+
return internalFlattenUnionChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r)
|
|
92
|
+
default:
|
|
93
|
+
throw new UnreachableError(typeDef)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function internalFlattenListChildren<M>(
|
|
98
|
+
valuePath: string,
|
|
99
|
+
typePath: string,
|
|
100
|
+
{ elements }: StrictListTypeDef,
|
|
101
|
+
v: AnyValueType[],
|
|
102
|
+
mapper: Mapper<M>,
|
|
103
|
+
r: Record<string, M>,
|
|
104
|
+
) {
|
|
105
|
+
const newTypePath = jsonPath(typePath, '*')
|
|
106
|
+
return v.reduce(function (r, e, i) {
|
|
107
|
+
return internalFlattenValue(
|
|
108
|
+
jsonPath(valuePath, i),
|
|
109
|
+
newTypePath,
|
|
110
|
+
elements,
|
|
111
|
+
e,
|
|
112
|
+
(e: AnyValueType) => {
|
|
113
|
+
v[i] = e
|
|
114
|
+
},
|
|
115
|
+
mapper,
|
|
116
|
+
r,
|
|
117
|
+
)
|
|
118
|
+
}, r)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function internalFlattenRecordChildren<M>(
|
|
122
|
+
valuePath: string,
|
|
123
|
+
typePath: string,
|
|
124
|
+
{ valueTypeDef }: StrictRecordTypeDef,
|
|
125
|
+
v: Record<string, AnyValueType>,
|
|
126
|
+
mapper: Mapper<M>,
|
|
127
|
+
r: Record<string, M>,
|
|
128
|
+
): Record<string, M> {
|
|
129
|
+
const newTypePath = jsonPath(typePath, '*')
|
|
130
|
+
return reduce(
|
|
131
|
+
v,
|
|
132
|
+
function (r, k, value) {
|
|
133
|
+
return internalFlattenValue(
|
|
134
|
+
jsonPath(valuePath, k),
|
|
135
|
+
newTypePath,
|
|
136
|
+
valueTypeDef,
|
|
137
|
+
value,
|
|
138
|
+
(value: AnyValueType) => {
|
|
139
|
+
v[k] = value
|
|
140
|
+
},
|
|
141
|
+
mapper,
|
|
142
|
+
r,
|
|
143
|
+
)
|
|
144
|
+
},
|
|
145
|
+
r,
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function internalFlattenObjectChildren<M>(
|
|
150
|
+
valuePath: string,
|
|
151
|
+
typePath: string,
|
|
152
|
+
qualifier: string,
|
|
153
|
+
{ fields }: StrictObjectTypeDef,
|
|
154
|
+
v: Record<string, AnyValueType>,
|
|
155
|
+
mapper: Mapper<M>,
|
|
156
|
+
r: Record<string, M>,
|
|
157
|
+
): Record<string, M> {
|
|
158
|
+
return reduce(
|
|
159
|
+
fields,
|
|
160
|
+
function (r, k, fieldTypeDef) {
|
|
161
|
+
const fieldValue = v[k]
|
|
162
|
+
return internalFlattenValue(
|
|
163
|
+
jsonPath(valuePath, k, qualifier),
|
|
164
|
+
jsonPath(typePath, k, qualifier),
|
|
165
|
+
fieldTypeDef,
|
|
166
|
+
fieldValue,
|
|
167
|
+
(value: AnyValueType) => {
|
|
168
|
+
v[k] = value
|
|
169
|
+
},
|
|
170
|
+
mapper,
|
|
171
|
+
r,
|
|
172
|
+
)
|
|
173
|
+
},
|
|
174
|
+
r,
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function internalFlattenUnionChildren<M>(
|
|
179
|
+
valuePath: string,
|
|
180
|
+
typePath: string,
|
|
181
|
+
qualifier: string,
|
|
182
|
+
typeDef: StrictUnionTypeDef,
|
|
183
|
+
v: AnyValueType,
|
|
184
|
+
mapper: Mapper<M>,
|
|
185
|
+
r: Record<string, M>,
|
|
186
|
+
): AnyValueType {
|
|
187
|
+
const childTypeDef = getUnionTypeDef(typeDef, v)
|
|
188
|
+
const newQualifier = typeDef.discriminator != null ? `${qualifier}${v[typeDef.discriminator]}:` : qualifier
|
|
189
|
+
return internalFlattenValueChildren(
|
|
190
|
+
valuePath,
|
|
191
|
+
typePath,
|
|
192
|
+
newQualifier,
|
|
193
|
+
childTypeDef,
|
|
194
|
+
v,
|
|
195
|
+
mapper,
|
|
196
|
+
r,
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function getUnionTypeDef<T extends UnionTypeDef>(
|
|
201
|
+
typeDef: T,
|
|
202
|
+
v: ValueTypeOf<ReadonlyTypeDefOf<{
|
|
203
|
+
definition: T,
|
|
204
|
+
}>>,
|
|
205
|
+
) {
|
|
206
|
+
if (typeDef.discriminator == null) {
|
|
207
|
+
// find either a literal who's prototype we match, or assume that
|
|
208
|
+
// we match the non-literal, or the literal value with no prototype, value
|
|
209
|
+
return reduce<string, TypeDef, null | TypeDef>(
|
|
210
|
+
typeDef.unions,
|
|
211
|
+
function (acc, _k, t) {
|
|
212
|
+
if (t.type === TypeDefType.Literal && t.valuePrototype) {
|
|
213
|
+
if (t.valuePrototype.indexOf(v) >= 0) {
|
|
214
|
+
return t
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
if (acc == null) {
|
|
218
|
+
return t
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return acc
|
|
222
|
+
},
|
|
223
|
+
null,
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
return typeDef.unions[v[typeDef.discriminator]]
|
|
227
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Type } from 'types/definitions'
|
|
2
|
+
import { type StrictTypeDef } from 'types/strict_definitions'
|
|
3
|
+
import { type ValueTypeOf } from 'types/value_type_of'
|
|
4
|
+
import {
|
|
5
|
+
type AnyValueType,
|
|
6
|
+
flattenValueTypeTo,
|
|
7
|
+
} from './flatten_value_type_to'
|
|
8
|
+
|
|
9
|
+
function mapper(_t: StrictTypeDef, v: AnyValueType) {
|
|
10
|
+
return v
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function flattenValueTypesOf<T extends Type>(
|
|
14
|
+
typeDef: Type,
|
|
15
|
+
value: ValueTypeOf<T>,
|
|
16
|
+
) {
|
|
17
|
+
return flattenValueTypeTo(
|
|
18
|
+
typeDef,
|
|
19
|
+
value,
|
|
20
|
+
() => {},
|
|
21
|
+
mapper,
|
|
22
|
+
)
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function jsonPath(prefix: string, segment: number | string, qualifier: string = ''): string {
|
|
2
|
+
const s = `.${qualifier}${segment}`
|
|
3
|
+
return `${prefix}${s}`
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function jsonPathPop(path: string): [string, string] | null {
|
|
7
|
+
const parts = path.split('.')
|
|
8
|
+
if (parts.length <= 1) {
|
|
9
|
+
return null
|
|
10
|
+
}
|
|
11
|
+
return [
|
|
12
|
+
parts.slice(0, -1).join('.'),
|
|
13
|
+
parts.pop()!,
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { expectDefinedAndReturn } from '@strictly/base'
|
|
2
|
+
import { flattenAccessorsOf } from 'transformers/flatteners/flatten_accessors_of'
|
|
3
|
+
import {
|
|
4
|
+
booleanType,
|
|
5
|
+
list,
|
|
6
|
+
numberType,
|
|
7
|
+
object,
|
|
8
|
+
} from 'types/builders'
|
|
9
|
+
import { type FlattenedAccessorsOf } from 'types/flattened_accessors_of'
|
|
10
|
+
import { type ValueTypeOf } from 'types/value_type_of'
|
|
11
|
+
import {
|
|
12
|
+
type Mock,
|
|
13
|
+
vi,
|
|
14
|
+
} from 'vitest'
|
|
15
|
+
|
|
16
|
+
describe('flattenAccessorsOf', function () {
|
|
17
|
+
let setter: Mock
|
|
18
|
+
const builder = object()
|
|
19
|
+
.set('a', list(numberType))
|
|
20
|
+
.set('b', booleanType)
|
|
21
|
+
.narrow
|
|
22
|
+
|
|
23
|
+
let flattened: FlattenedAccessorsOf<typeof builder>
|
|
24
|
+
let value: ValueTypeOf<typeof builder>
|
|
25
|
+
|
|
26
|
+
beforeEach(function () {
|
|
27
|
+
setter = vi.fn()
|
|
28
|
+
value = {
|
|
29
|
+
a: [
|
|
30
|
+
1,
|
|
31
|
+
2,
|
|
32
|
+
4,
|
|
33
|
+
],
|
|
34
|
+
b: false,
|
|
35
|
+
}
|
|
36
|
+
flattened = flattenAccessorsOf<typeof builder>(
|
|
37
|
+
builder,
|
|
38
|
+
value,
|
|
39
|
+
setter,
|
|
40
|
+
)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
// note that we already have tests for the type and the function that this calls, so
|
|
44
|
+
// this is only a sanity check
|
|
45
|
+
it('flattens to expected type', function () {
|
|
46
|
+
expect(flattened).toEqual({
|
|
47
|
+
$: {
|
|
48
|
+
value: {
|
|
49
|
+
a: [
|
|
50
|
+
1,
|
|
51
|
+
2,
|
|
52
|
+
4,
|
|
53
|
+
],
|
|
54
|
+
b: false,
|
|
55
|
+
},
|
|
56
|
+
set: setter,
|
|
57
|
+
},
|
|
58
|
+
'$.a': expect.objectContaining({
|
|
59
|
+
value: [
|
|
60
|
+
1,
|
|
61
|
+
2,
|
|
62
|
+
4,
|
|
63
|
+
],
|
|
64
|
+
}),
|
|
65
|
+
'$.a.0': expect.objectContaining({
|
|
66
|
+
value: 1,
|
|
67
|
+
}),
|
|
68
|
+
'$.a.1': expect.objectContaining({
|
|
69
|
+
value: 2,
|
|
70
|
+
}),
|
|
71
|
+
'$.a.2': expect.objectContaining({
|
|
72
|
+
value: 4,
|
|
73
|
+
}),
|
|
74
|
+
'$.b': expect.objectContaining({
|
|
75
|
+
value: false,
|
|
76
|
+
}),
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('sets an internal value of a struct', function () {
|
|
81
|
+
expectDefinedAndReturn(flattened['$.a']).set([5])
|
|
82
|
+
|
|
83
|
+
expect(value).toEqual({
|
|
84
|
+
a: [5],
|
|
85
|
+
b: false,
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('sets an internal value of an array', function () {
|
|
90
|
+
expectDefinedAndReturn(flattened['$.a.1']).set(99)
|
|
91
|
+
|
|
92
|
+
expect(value).toEqual({
|
|
93
|
+
a: [
|
|
94
|
+
1,
|
|
95
|
+
99,
|
|
96
|
+
4,
|
|
97
|
+
],
|
|
98
|
+
b: false,
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('sets the top level value', function () {
|
|
103
|
+
const newValue: ValueTypeOf<typeof builder> = {
|
|
104
|
+
a: [
|
|
105
|
+
-1,
|
|
106
|
+
5,
|
|
107
|
+
],
|
|
108
|
+
b: true,
|
|
109
|
+
}
|
|
110
|
+
expectDefinedAndReturn(flattened.$).set(newValue)
|
|
111
|
+
expect(setter).toHaveBeenCalledWith(newValue)
|
|
112
|
+
})
|
|
113
|
+
})
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { flattenJsonValueToTypePathsOf } from 'transformers/flatteners/flatten_json_value_to_type_paths_of'
|
|
2
|
+
import {
|
|
3
|
+
booleanType,
|
|
4
|
+
list,
|
|
5
|
+
nullType,
|
|
6
|
+
numberType,
|
|
7
|
+
object,
|
|
8
|
+
record,
|
|
9
|
+
stringType,
|
|
10
|
+
union,
|
|
11
|
+
} from 'types/builders'
|
|
12
|
+
|
|
13
|
+
describe('flattenJsonValueToTypePathsOf', function () {
|
|
14
|
+
describe('literal', function () {
|
|
15
|
+
const typeDef = numberType
|
|
16
|
+
const flattened = flattenJsonValueToTypePathsOf(typeDef, 1)
|
|
17
|
+
|
|
18
|
+
it('equals expected value', function () {
|
|
19
|
+
expect(flattened).toEqual({
|
|
20
|
+
$: '$',
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('list', function () {
|
|
26
|
+
const typeDef = list(numberType)
|
|
27
|
+
const flattened = flattenJsonValueToTypePathsOf(typeDef, [
|
|
28
|
+
1,
|
|
29
|
+
2,
|
|
30
|
+
])
|
|
31
|
+
|
|
32
|
+
it('equals expected value', function () {
|
|
33
|
+
expect(flattened).toEqual({
|
|
34
|
+
$: '$',
|
|
35
|
+
'$.0': '$.*',
|
|
36
|
+
'$.1': '$.*',
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('record', function () {
|
|
42
|
+
const typeDef = record<typeof numberType, 'a' | 'b'>(numberType)
|
|
43
|
+
const flattened = flattenJsonValueToTypePathsOf(typeDef, {
|
|
44
|
+
a: 1,
|
|
45
|
+
b: 3,
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('equals expected value', function () {
|
|
49
|
+
expect(flattened).toEqual({
|
|
50
|
+
$: '$',
|
|
51
|
+
'$.a': '$.*',
|
|
52
|
+
'$.b': '$.*',
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
describe('object', function () {
|
|
58
|
+
const typeDef = object()
|
|
59
|
+
.set('a', numberType)
|
|
60
|
+
.set('b', booleanType)
|
|
61
|
+
const flattened = flattenJsonValueToTypePathsOf(typeDef, {
|
|
62
|
+
a: 1,
|
|
63
|
+
b: true,
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('equals expected value', function () {
|
|
67
|
+
expect(flattened).toEqual({
|
|
68
|
+
$: '$',
|
|
69
|
+
'$.a': '$.a',
|
|
70
|
+
'$.b': '$.b',
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
describe('union', function () {
|
|
76
|
+
describe('non-discriminated', function () {
|
|
77
|
+
const typeDef = union()
|
|
78
|
+
.add('a', list(numberType))
|
|
79
|
+
.add('b', nullType)
|
|
80
|
+
const flattened = flattenJsonValueToTypePathsOf(typeDef, [
|
|
81
|
+
1,
|
|
82
|
+
2,
|
|
83
|
+
3,
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
it('equals expected value', function () {
|
|
87
|
+
expect(flattened).toEqual({
|
|
88
|
+
$: '$',
|
|
89
|
+
'$.0': '$.*',
|
|
90
|
+
'$.1': '$.*',
|
|
91
|
+
'$.2': '$.*',
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
describe('discriminated', function () {
|
|
97
|
+
const typeDef = union('d')
|
|
98
|
+
.add('x', object().set('a', numberType).set('b', booleanType))
|
|
99
|
+
.add('y', object().set('c', stringType).set('d', booleanType))
|
|
100
|
+
const flattened = flattenJsonValueToTypePathsOf(typeDef, {
|
|
101
|
+
d: 'x',
|
|
102
|
+
a: 1,
|
|
103
|
+
b: true,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('equals expected value', function () {
|
|
107
|
+
expect(flattened).toEqual({
|
|
108
|
+
$: '$',
|
|
109
|
+
'$.x:a': '$.x:a',
|
|
110
|
+
'$.x:b': '$.x:b',
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
})
|