@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.
Files changed (162) hide show
  1. package/.eslintrc.cjs +31 -0
  2. package/.out/index.d.ts +20 -0
  3. package/.out/index.js +20 -0
  4. package/.out/transformers/copies/copy.d.ts +4 -0
  5. package/.out/transformers/copies/copy.js +7 -0
  6. package/.out/transformers/copies/copy_to.d.ts +6 -0
  7. package/.out/transformers/copies/copy_to.js +91 -0
  8. package/.out/transformers/copies/mobx_copy.d.ts +5 -0
  9. package/.out/transformers/copies/mobx_copy.js +42 -0
  10. package/.out/transformers/copies/specs/copy_to.tests.d.ts +1 -0
  11. package/.out/transformers/copies/specs/copy_to.tests.js +97 -0
  12. package/.out/transformers/copies/specs/mobx_copy.tests.d.ts +1 -0
  13. package/.out/transformers/copies/specs/mobx_copy.tests.js +19 -0
  14. package/.out/transformers/flatteners/flatten_accessors_of.d.ts +5 -0
  15. package/.out/transformers/flatteners/flatten_accessors_of.js +11 -0
  16. package/.out/transformers/flatteners/flatten_json_value_to_type_paths_of.d.ts +3 -0
  17. package/.out/transformers/flatteners/flatten_json_value_to_type_paths_of.js +10 -0
  18. package/.out/transformers/flatteners/flatten_type_def_to.d.ts +4 -0
  19. package/.out/transformers/flatteners/flatten_type_def_to.js +49 -0
  20. package/.out/transformers/flatteners/flatten_type_defs_of.d.ts +3 -0
  21. package/.out/transformers/flatteners/flatten_type_defs_of.js +7 -0
  22. package/.out/transformers/flatteners/flatten_value_type_to.d.ts +11 -0
  23. package/.out/transformers/flatteners/flatten_value_type_to.js +79 -0
  24. package/.out/transformers/flatteners/flatten_value_types_of.d.ts +3 -0
  25. package/.out/transformers/flatteners/flatten_value_types_of.js +7 -0
  26. package/.out/transformers/flatteners/json_path.d.ts +2 -0
  27. package/.out/transformers/flatteners/json_path.js +14 -0
  28. package/.out/transformers/flatteners/specs/flatten_accessors_of.tests.d.ts +1 -0
  29. package/.out/transformers/flatteners/specs/flatten_accessors_of.tests.js +90 -0
  30. package/.out/transformers/flatteners/specs/flatten_json_value_to_type_paths_of.tests.d.ts +1 -0
  31. package/.out/transformers/flatteners/specs/flatten_json_value_to_type_paths_of.tests.js +94 -0
  32. package/.out/transformers/flatteners/specs/flatten_type_def_to.tests.d.ts +1 -0
  33. package/.out/transformers/flatteners/specs/flatten_type_def_to.tests.js +110 -0
  34. package/.out/transformers/flatteners/specs/flatten_type_defs_of.tests.d.ts +1 -0
  35. package/.out/transformers/flatteners/specs/flatten_type_defs_of.tests.js +17 -0
  36. package/.out/transformers/flatteners/specs/flatten_value_type_to.tests.d.ts +1 -0
  37. package/.out/transformers/flatteners/specs/flatten_value_type_to.tests.js +297 -0
  38. package/.out/transformers/flatteners/specs/flatten_value_types_of.tests.d.ts +1 -0
  39. package/.out/transformers/flatteners/specs/flatten_value_types_of.tests.js +37 -0
  40. package/.out/transformers/flatteners/specs/value_path_to_type_path.tests.d.ts +1 -0
  41. package/.out/transformers/flatteners/specs/value_path_to_type_path.tests.js +167 -0
  42. package/.out/transformers/flatteners/value_path_to_type_path.d.ts +2 -0
  43. package/.out/transformers/flatteners/value_path_to_type_path.js +96 -0
  44. package/.out/tsconfig.json +15 -0
  45. package/.out/tsconfig.tsbuildinfo +1 -0
  46. package/.out/tsup.config.d.ts +3 -0
  47. package/.out/tsup.config.js +12 -0
  48. package/.out/types/builders.d.ts +62 -0
  49. package/.out/types/builders.js +148 -0
  50. package/.out/types/definitions.d.ts +41 -0
  51. package/.out/types/definitions.js +26 -0
  52. package/.out/types/flattened.d.ts +2 -0
  53. package/.out/types/flattened.js +1 -0
  54. package/.out/types/flattened_accessors_of.d.ts +9 -0
  55. package/.out/types/flattened_accessors_of.js +1 -0
  56. package/.out/types/flattened_type_defs_of.d.ts +21 -0
  57. package/.out/types/flattened_type_defs_of.js +1 -0
  58. package/.out/types/flattened_value_types_of.d.ts +6 -0
  59. package/.out/types/flattened_value_types_of.js +1 -0
  60. package/.out/types/json_path_of.d.ts +1 -0
  61. package/.out/types/json_path_of.js +1 -0
  62. package/.out/types/json_paths_of.d.ts +16 -0
  63. package/.out/types/json_paths_of.js +1 -0
  64. package/.out/types/mobx_value_type_of.d.ts +11 -0
  65. package/.out/types/mobx_value_type_of.js +2 -0
  66. package/.out/types/partial_type_def_of.d.ts +40 -0
  67. package/.out/types/partial_type_def_of.js +1 -0
  68. package/.out/types/readonly_type_def_of.d.ts +29 -0
  69. package/.out/types/readonly_type_def_of.js +1 -0
  70. package/.out/types/specs/builder.tests.d.ts +1 -0
  71. package/.out/types/specs/builder.tests.js +93 -0
  72. package/.out/types/specs/flattened_accessors_of.tests.d.ts +1 -0
  73. package/.out/types/specs/flattened_accessors_of.tests.js +11 -0
  74. package/.out/types/specs/flattened_type_defs_of.tests.d.ts +1 -0
  75. package/.out/types/specs/flattened_type_defs_of.tests.js +71 -0
  76. package/.out/types/specs/flattened_value_types_of.tests.d.ts +1 -0
  77. package/.out/types/specs/flattened_value_types_of.tests.js +11 -0
  78. package/.out/types/specs/json_paths_of.tests.d.ts +1 -0
  79. package/.out/types/specs/json_paths_of.tests.js +199 -0
  80. package/.out/types/specs/partial_type_def_of.tests.d.ts +1 -0
  81. package/.out/types/specs/partial_type_def_of.tests.js +50 -0
  82. package/.out/types/specs/readonly_type_def_of.tests.d.ts +1 -0
  83. package/.out/types/specs/readonly_type_def_of.tests.js +55 -0
  84. package/.out/types/specs/strict_definitions.tests.d.ts +1 -0
  85. package/.out/types/specs/strict_definitions.tests.js +42 -0
  86. package/.out/types/specs/value_to_type_paths_of.tests.d.ts +1 -0
  87. package/.out/types/specs/value_to_type_paths_of.tests.js +90 -0
  88. package/.out/types/specs/value_type_of.tests.d.ts +1 -0
  89. package/.out/types/specs/value_type_of.tests.js +91 -0
  90. package/.out/types/specs/value_types_of_discriminated_union.tests.d.ts +1 -0
  91. package/.out/types/specs/value_types_of_discriminated_union.tests.js +9 -0
  92. package/.out/types/strict_definitions.d.ts +44 -0
  93. package/.out/types/strict_definitions.js +1 -0
  94. package/.out/types/value_to_type_paths_of.d.ts +22 -0
  95. package/.out/types/value_to_type_paths_of.js +1 -0
  96. package/.out/types/value_type_of.d.ts +24 -0
  97. package/.out/types/value_type_of.js +1 -0
  98. package/.out/types/value_types_of_discriminated_union.d.ts +9 -0
  99. package/.out/types/value_types_of_discriminated_union.js +1 -0
  100. package/.out/vitest.workspace.d.ts +2 -0
  101. package/.out/vitest.workspace.js +7 -0
  102. package/.turbo/turbo-build.log +18 -0
  103. package/.turbo/turbo-check-types.log +3 -0
  104. package/.turbo/turbo-release$colon$exports.log +3 -0
  105. package/README.md +12 -0
  106. package/dist/index.cjs +798 -0
  107. package/dist/index.d.cts +301 -0
  108. package/dist/index.d.ts +301 -0
  109. package/dist/index.js +775 -0
  110. package/index.ts +20 -0
  111. package/package.exports.json +18 -0
  112. package/package.json +45 -0
  113. package/transformers/copies/copy.ts +18 -0
  114. package/transformers/copies/copy_to.ts +226 -0
  115. package/transformers/copies/mobx_copy.ts +81 -0
  116. package/transformers/copies/specs/copy_to.tests.ts +143 -0
  117. package/transformers/copies/specs/mobx_copy.tests.ts +26 -0
  118. package/transformers/flatteners/flatten_accessors_of.ts +43 -0
  119. package/transformers/flatteners/flatten_json_value_to_type_paths_of.ts +39 -0
  120. package/transformers/flatteners/flatten_type_def_to.ts +127 -0
  121. package/transformers/flatteners/flatten_type_defs_of.ts +16 -0
  122. package/transformers/flatteners/flatten_value_type_to.ts +227 -0
  123. package/transformers/flatteners/flatten_value_types_of.ts +23 -0
  124. package/transformers/flatteners/json_path.ts +15 -0
  125. package/transformers/flatteners/specs/flatten_accessors_of.tests.ts +113 -0
  126. package/transformers/flatteners/specs/flatten_json_value_to_type_paths_of.tests.ts +115 -0
  127. package/transformers/flatteners/specs/flatten_type_def_to.tests.ts +146 -0
  128. package/transformers/flatteners/specs/flatten_type_defs_of.tests.ts +26 -0
  129. package/transformers/flatteners/specs/flatten_value_type_to.tests.ts +452 -0
  130. package/transformers/flatteners/specs/flatten_value_types_of.tests.ts +46 -0
  131. package/transformers/flatteners/specs/value_path_to_type_path.tests.ts +240 -0
  132. package/transformers/flatteners/value_path_to_type_path.ts +164 -0
  133. package/tsconfig.build.json +11 -0
  134. package/tsconfig.json +15 -0
  135. package/tsup.config.ts +16 -0
  136. package/types/builders.ts +284 -0
  137. package/types/definitions.ts +106 -0
  138. package/types/flattened.ts +5 -0
  139. package/types/flattened_accessors_of.ts +15 -0
  140. package/types/flattened_type_defs_of.ts +130 -0
  141. package/types/flattened_value_types_of.ts +11 -0
  142. package/types/json_path_of.ts +7 -0
  143. package/types/json_paths_of.ts +129 -0
  144. package/types/mobx_value_type_of.ts +16 -0
  145. package/types/partial_type_def_of.ts +64 -0
  146. package/types/readonly_type_def_of.ts +53 -0
  147. package/types/specs/builder.tests.ts +295 -0
  148. package/types/specs/flattened_accessors_of.tests.ts +27 -0
  149. package/types/specs/flattened_type_defs_of.tests.ts +212 -0
  150. package/types/specs/flattened_value_types_of.tests.ts +21 -0
  151. package/types/specs/json_paths_of.tests.ts +304 -0
  152. package/types/specs/partial_type_def_of.tests.ts +251 -0
  153. package/types/specs/readonly_type_def_of.tests.ts +158 -0
  154. package/types/specs/strict_definitions.tests.ts +184 -0
  155. package/types/specs/value_to_type_paths_of.tests.ts +181 -0
  156. package/types/specs/value_type_of.tests.ts +329 -0
  157. package/types/specs/value_types_of_discriminated_union.tests.ts +30 -0
  158. package/types/strict_definitions.ts +107 -0
  159. package/types/value_to_type_paths_of.ts +184 -0
  160. package/types/value_type_of.ts +84 -0
  161. package/types/value_types_of_discriminated_union.ts +14 -0
  162. 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
+ })