@strictly/define 0.0.21 → 0.0.23

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 (38) hide show
  1. package/.out/transformers/flatteners/flatten_type_to.js +1 -1
  2. package/.out/transformers/flatteners/flatten_value_to.js +9 -9
  3. package/.out/transformers/flatteners/json_path.d.ts +1 -1
  4. package/.out/transformers/flatteners/json_path.js +2 -2
  5. package/.out/transformers/flatteners/specs/flatten_json_value_to_type_paths_of.tests.js +2 -2
  6. package/.out/transformers/flatteners/specs/flatten_type_to.tests.js +2 -2
  7. package/.out/transformers/flatteners/specs/flatten_value_to.tests.js +2 -2
  8. package/.out/transformers/flatteners/specs/json_paths.tests.js +2 -2
  9. package/.out/transformers/flatteners/specs/value_path_to_type_path.tests.js +82 -8
  10. package/.out/transformers/flatteners/value_path_to_type_path.js +26 -25
  11. package/.out/tsconfig.tsbuildinfo +1 -1
  12. package/.out/types/flattened_types_of_type.d.ts +11 -11
  13. package/.out/types/flattened_types_of_validating_type.d.ts +11 -11
  14. package/.out/types/paths_of_type.d.ts +7 -7
  15. package/.out/types/value_to_type_paths_of_type.d.ts +7 -7
  16. package/.turbo/turbo-build.log +8 -8
  17. package/.turbo/turbo-release$colon$exports.log +1 -1
  18. package/dist/index.cjs +52 -40
  19. package/dist/index.d.cts +37 -37
  20. package/dist/index.d.ts +37 -37
  21. package/dist/index.js +52 -40
  22. package/package.json +5 -3
  23. package/transformers/flatteners/flatten_type_to.ts +2 -2
  24. package/transformers/flatteners/flatten_value_to.ts +8 -12
  25. package/transformers/flatteners/json_path.ts +3 -3
  26. package/transformers/flatteners/specs/flatten_json_value_to_type_paths_of.tests.ts +2 -2
  27. package/transformers/flatteners/specs/flatten_type_to.tests.ts +2 -2
  28. package/transformers/flatteners/specs/flatten_value_to.tests.ts +2 -2
  29. package/transformers/flatteners/specs/json_paths.tests.ts +3 -3
  30. package/transformers/flatteners/specs/value_path_to_type_path.tests.ts +92 -8
  31. package/transformers/flatteners/value_path_to_type_path.ts +37 -23
  32. package/types/flattened_types_of_type.ts +7 -18
  33. package/types/flattened_types_of_validating_type.ts +7 -19
  34. package/types/paths_of_type.ts +16 -22
  35. package/types/specs/flattened_types_of_type.tests.ts +6 -6
  36. package/types/specs/paths_of_type.tests.ts +2 -2
  37. package/types/specs/value_to_type_paths_of_type.tests.ts +4 -4
  38. package/types/value_to_type_paths_of_type.ts +5 -12
@@ -44,6 +44,6 @@ function internalFlattenObjectTypeDefChildren(path, qualifier, { fields }, r) {
44
44
  }
45
45
  function internalFlattenUnionTypeDefChildren(path, qualifier, { discriminator, unions, }, r) {
46
46
  return reduce(unions, function (acc, key, typeDef) {
47
- return internalFlattenTypeDefChildren(path, discriminator != null ? `${qualifier}${key}:` : qualifier, typeDef, acc);
47
+ return internalFlattenTypeDefChildren(discriminator != null ? `${path}:${qualifier}` : path, key, typeDef, acc);
48
48
  }, r);
49
49
  }
@@ -12,11 +12,11 @@ function internalFlattenValue(valuePath, typePath, typeDef, v, setter, mapper, r
12
12
  // assume undefined means the field is optional and not populated
13
13
  // TODO: actually capture if field is optional in typedef (or in builder for creating validator)
14
14
  if (v !== undefined) {
15
- return internalFlattenValueChildren(valuePath, typePath, '', typeDef, v, mapper, r);
15
+ return internalFlattenValueChildren(valuePath, typePath, typeDef, v, mapper, r);
16
16
  }
17
17
  return r;
18
18
  }
19
- function internalFlattenValueChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r) {
19
+ function internalFlattenValueChildren(valuePath, typePath, typeDef, v, mapper, r) {
20
20
  switch (typeDef.type) {
21
21
  case TypeDefType.Literal:
22
22
  // no children
@@ -26,9 +26,9 @@ function internalFlattenValueChildren(valuePath, typePath, qualifier, typeDef, v
26
26
  case TypeDefType.Record:
27
27
  return internalFlattenRecordChildren(valuePath, typePath, typeDef, v, mapper, r);
28
28
  case TypeDefType.Object:
29
- return internalFlattenObjectChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r);
29
+ return internalFlattenObjectChildren(valuePath, typePath, typeDef, v, mapper, r);
30
30
  case TypeDefType.Union:
31
- return internalFlattenUnionChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r);
31
+ return internalFlattenUnionChildren(valuePath, typePath, typeDef, v, mapper, r);
32
32
  default:
33
33
  throw new UnreachableError(typeDef);
34
34
  }
@@ -49,18 +49,18 @@ function internalFlattenRecordChildren(valuePath, typePath, { valueTypeDef }, v,
49
49
  }, mapper, r);
50
50
  }, r);
51
51
  }
52
- function internalFlattenObjectChildren(valuePath, typePath, qualifier, { fields }, v, mapper, r) {
52
+ function internalFlattenObjectChildren(valuePath, typePath, { fields }, v, mapper, r) {
53
53
  return reduce(fields, function (r, k, fieldTypeDef) {
54
54
  const fieldValue = v[k];
55
- return internalFlattenValue(jsonPath(valuePath, k, qualifier), jsonPath(typePath, k, qualifier), fieldTypeDef, fieldValue, (value) => {
55
+ return internalFlattenValue(jsonPath(valuePath, k), jsonPath(typePath, k), fieldTypeDef, fieldValue, (value) => {
56
56
  v[k] = value;
57
57
  }, mapper, r);
58
58
  }, r);
59
59
  }
60
- function internalFlattenUnionChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r) {
60
+ function internalFlattenUnionChildren(valuePath, typePath, typeDef, v, mapper, r) {
61
61
  const childTypeDef = getUnionTypeDef(typeDef, v);
62
- const newQualifier = typeDef.discriminator != null ? `${qualifier}${v[typeDef.discriminator]}:` : qualifier;
63
- return internalFlattenValueChildren(valuePath, typePath, newQualifier, childTypeDef, v, mapper, r);
62
+ const qualifier = typeDef.discriminator != null ? `:${v[typeDef.discriminator]}` : '';
63
+ return internalFlattenValueChildren(`${valuePath}${qualifier}`, `${typePath}${qualifier}`, childTypeDef, v, mapper, r);
64
64
  }
65
65
  export function getUnionTypeDef(typeDef, v) {
66
66
  if (typeDef.discriminator == null) {
@@ -1,6 +1,6 @@
1
1
  import { type StringConcatOf } from '@strictly/base';
2
2
  export declare function jsonPath<Prefix extends string, Segment extends number | string>(prefix: Prefix, segment: Segment): `${Prefix}.${Segment}`;
3
- export declare function jsonPath<Prefix extends string, Segment extends number | string, Qualifier extends string>(prefix: Prefix, segment: Segment, qualifier: Qualifier): `${Prefix}.${Qualifier}${Segment}`;
3
+ export declare function jsonPath<Prefix extends string, Segment extends number | string, Qualifier extends string>(prefix: Prefix, segment: Segment, qualifier: Qualifier): `${Prefix}${Qualifier}.${Segment}`;
4
4
  export declare function jsonPathPop<Path extends string>(path: Path): [string, string] | null;
5
5
  export declare function jsonPathPrefix<Prefix extends string, Path extends string>(prefix: Prefix, path: Path): Path extends StringConcatOf<'$', infer ToMount> ? `${Prefix}${ToMount}` : never;
6
6
  export declare function jsonPathUnprefix<Prefix extends string, Path extends string>(prefix: Prefix, path: Path): Path extends StringConcatOf<Prefix, infer ToUnmount> ? `$${ToUnmount}` : never;
@@ -1,8 +1,8 @@
1
1
  import { assertEqual, assertState, } from '@strictly/base';
2
2
  export function jsonPath(prefix, segment, qualifier) {
3
- const s = `.${qualifier !== null && qualifier !== void 0 ? qualifier : ''}${segment}`;
3
+ const s = `.${segment}`;
4
4
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
5
- return `${prefix}${s}`;
5
+ return `${prefix}${qualifier !== null && qualifier !== void 0 ? qualifier : ''}${s}`;
6
6
  }
7
7
  // TODO type safety
8
8
  export function jsonPathPop(path) {
@@ -85,8 +85,8 @@ describe('flattenJsonValueToTypePathsOf', function () {
85
85
  it('equals expected value', function () {
86
86
  expect(flattened).toEqual({
87
87
  $: '$',
88
- '$.x:a': '$.x:a',
89
- '$.x:b': '$.x:b',
88
+ '$:x.a': '$:x.a',
89
+ '$:x.b': '$:x.b',
90
90
  });
91
91
  });
92
92
  });
@@ -100,8 +100,8 @@ describe('flattenTypeDefTo', function () {
100
100
  it('equals expected type', function () {
101
101
  expect(flattened).toEqual({
102
102
  $: TypeDefType.Union,
103
- '$.a:a': TypeDefType.Literal,
104
- '$.b:b': TypeDefType.Literal,
103
+ '$:a.a': TypeDefType.Literal,
104
+ '$:b.b': TypeDefType.Literal,
105
105
  });
106
106
  });
107
107
  it('calls the mapper function', function () {
@@ -209,7 +209,7 @@ describe('flattenValueTo', function () {
209
209
  it('equals expected type', function () {
210
210
  expect(flattened).toEqual({
211
211
  $: '{"d":"1","a":2}',
212
- ['$.1:a']: '2',
212
+ ['$:1.a']: '2',
213
213
  });
214
214
  });
215
215
  });
@@ -227,7 +227,7 @@ describe('flattenValueTo', function () {
227
227
  expect(setter).toHaveBeenCalledWith(value);
228
228
  });
229
229
  it('sets an internal value', function () {
230
- flattened['$.1:a'](1);
230
+ flattened['$:1.a'](1);
231
231
  expect(u).toEqual({
232
232
  d: '1',
233
233
  a: 1,
@@ -20,12 +20,12 @@ describe('json_paths', () => {
20
20
  });
21
21
  });
22
22
  describe('qualified', () => {
23
- const path = jsonPath('$', 'x', 'y:');
23
+ const path = jsonPath('$', 'x', ':y');
24
24
  it('has the expected type', () => {
25
25
  expectTypeOf(path).toEqualTypeOf();
26
26
  });
27
27
  it('has the expected value', () => {
28
- expect(path).toEqual('$.y:x');
28
+ expect(path).toEqual('$:y.x');
29
29
  });
30
30
  });
31
31
  });
@@ -131,20 +131,20 @@ describe('valuePathToTypePath', function () {
131
131
  '$',
132
132
  ],
133
133
  [
134
- '$.x:a',
135
- '$.x:a',
134
+ '$:x.a',
135
+ '$:x.a',
136
136
  ],
137
137
  [
138
- '$.x:b',
139
- '$.x:b',
138
+ '$:x.b',
139
+ '$:x.b',
140
140
  ],
141
141
  [
142
- '$.y:b',
143
- '$.y:b',
142
+ '$:y.b',
143
+ '$:y.b',
144
144
  ],
145
145
  [
146
- '$.y:c',
147
- '$.y:c',
146
+ '$:y.c',
147
+ '$:y.c',
148
148
  ],
149
149
  ])('it maps %s', function (from, to) {
150
150
  const typePath = valuePathToTypePath(typeDef, from);
@@ -164,6 +164,80 @@ describe('valuePathToTypePath', function () {
164
164
  expectTypeOf(fakeTypePath).toEqualTypeOf();
165
165
  });
166
166
  });
167
+ describe('nested discriminated', () => {
168
+ const nestedTypeDef = object().field('o', typeDef);
169
+ describe.each([
170
+ [
171
+ '$',
172
+ '$',
173
+ ],
174
+ [
175
+ '$.o',
176
+ '$.o',
177
+ ],
178
+ [
179
+ '$.o:x.a',
180
+ '$.o:x.a',
181
+ ],
182
+ [
183
+ '$.o:x.b',
184
+ '$.o:x.b',
185
+ ],
186
+ [
187
+ '$.o:y.b',
188
+ '$.o:y.b',
189
+ ],
190
+ [
191
+ '$.o:y.c',
192
+ '$.o:y.c',
193
+ ],
194
+ ])('it maps %s', function (from, to) {
195
+ const typePath = valuePathToTypePath(nestedTypeDef, from);
196
+ it('maps a value path to the expected type path', function () {
197
+ expect(typePath).toEqual(to);
198
+ });
199
+ it('has expected type', function () {
200
+ expectTypeOf(typePath).toEqualTypeOf(to);
201
+ });
202
+ });
203
+ });
204
+ describe('list discriminated', () => {
205
+ const listTypeDef = list(typeDef);
206
+ describe.each([
207
+ [
208
+ '$',
209
+ '$',
210
+ ],
211
+ [
212
+ '$.0',
213
+ '$.*',
214
+ ],
215
+ [
216
+ '$.0:x.a',
217
+ '$.*:x.a',
218
+ ],
219
+ [
220
+ '$.0:x.b',
221
+ '$.*:x.b',
222
+ ],
223
+ [
224
+ '$.99:y.b',
225
+ '$.*:y.b',
226
+ ],
227
+ [
228
+ '$.1:y.c',
229
+ '$.*:y.c',
230
+ ],
231
+ ])('it maps %s', function (from, to) {
232
+ const typePath = valuePathToTypePath(listTypeDef, from);
233
+ it('maps a value path to the expected type path', function () {
234
+ expect(typePath).toEqual(to);
235
+ });
236
+ it('has expected type', function () {
237
+ expectTypeOf(typePath).toEqualTypeOf(to);
238
+ });
239
+ });
240
+ });
167
241
  });
168
242
  });
169
243
  });
@@ -3,19 +3,23 @@ import { TypeDefType, } from 'types/definitions';
3
3
  export function valuePathToTypePath({ definition: typeDef }, valuePath, allowMissingPaths = false) {
4
4
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
5
5
  const valueSteps = valuePath.split(/\.|\[/g);
6
- assertEqual(valueSteps[0], '$');
7
- const typeSteps = internalJsonValuePathToTypePath(typeDef, valueSteps.slice(1), allowMissingPaths,
6
+ const parts = valueSteps[0].split(':');
7
+ const [first, ...qualifiers] = parts;
8
+ assertEqual(first, '$');
9
+ const typeSteps = internalJsonValuePathToTypePath(typeDef, qualifiers, valueSteps.slice(1), allowMissingPaths,
8
10
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
9
11
  valuePath);
10
- typeSteps.unshift('$');
12
+ typeSteps.unshift(valueSteps[0]);
11
13
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12
14
  return typeSteps.join('.');
13
15
  }
14
- function internalJsonValuePathToTypePath(typeDef, valueSteps, allowMissingPaths, originalValuePath) {
16
+ function internalJsonValuePathToTypePath(typeDef, qualifiers, valueSteps, allowMissingPaths, originalValuePath) {
15
17
  if (valueSteps.length === 0) {
16
18
  return [];
17
19
  }
18
- const [valueStep, ...remainingValueSteps] = valueSteps;
20
+ const [nextValueStepAndQualifiersString, ...remainingValueSteps] = valueSteps;
21
+ const nextValueStepAndQualifiers = nextValueStepAndQualifiersString.split(':');
22
+ const [valueStep, ...nextQualifiers] = nextValueStepAndQualifiers;
19
23
  switch (typeDef.type) {
20
24
  case TypeDefType.Literal:
21
25
  if (allowMissingPaths) {
@@ -23,18 +27,24 @@ function internalJsonValuePathToTypePath(typeDef, valueSteps, allowMissingPaths,
23
27
  return valueSteps;
24
28
  }
25
29
  else {
26
- throw new PreconditionFailedError('literal should terminate path {} ({})', originalValuePath, valueStep);
30
+ throw new PreconditionFailedError('literal should terminate path {} ({})', originalValuePath, nextValueStepAndQualifiersString);
27
31
  }
28
32
  case TypeDefType.List:
29
33
  // TODO assert format of current step
30
34
  return [
31
- '*',
32
- ...internalJsonValuePathToTypePath(typeDef.elements, remainingValueSteps, allowMissingPaths, originalValuePath),
35
+ [
36
+ '*',
37
+ ...nextQualifiers,
38
+ ].join(':'),
39
+ ...internalJsonValuePathToTypePath(typeDef.elements, nextQualifiers, remainingValueSteps, allowMissingPaths, originalValuePath),
33
40
  ];
34
41
  case TypeDefType.Record:
35
42
  return [
36
- '*',
37
- ...internalJsonValuePathToTypePath(typeDef.valueTypeDef, remainingValueSteps, allowMissingPaths, originalValuePath),
43
+ [
44
+ '*',
45
+ ...nextQualifiers,
46
+ ].join(':'),
47
+ ...internalJsonValuePathToTypePath(typeDef.valueTypeDef, nextQualifiers, remainingValueSteps, allowMissingPaths, originalValuePath),
38
48
  ];
39
49
  case TypeDefType.Object:
40
50
  if (allowMissingPaths) {
@@ -47,8 +57,8 @@ function internalJsonValuePathToTypePath(typeDef, valueSteps, allowMissingPaths,
47
57
  assertExists(typeDef.fields[valueStep], 'missing field in {} ({})', originalValuePath, valueStep);
48
58
  }
49
59
  return [
50
- valueStep,
51
- ...internalJsonValuePathToTypePath(typeDef.fields[valueStep], remainingValueSteps, allowMissingPaths, originalValuePath),
60
+ nextValueStepAndQualifiersString,
61
+ ...internalJsonValuePathToTypePath(typeDef.fields[valueStep], nextQualifiers, remainingValueSteps, allowMissingPaths, originalValuePath),
52
62
  ];
53
63
  case TypeDefType.Union:
54
64
  if (typeDef.discriminator == null) {
@@ -61,7 +71,7 @@ function internalJsonValuePathToTypePath(typeDef, valueSteps, allowMissingPaths,
61
71
  return acc;
62
72
  }, null);
63
73
  assertExists(union, 'expected a complex union {}', originalValuePath);
64
- return internalJsonValuePathToTypePath(union, valueSteps, allowMissingPaths, originalValuePath);
74
+ return internalJsonValuePathToTypePath(union, nextQualifiers, valueSteps, allowMissingPaths, originalValuePath);
65
75
  }
66
76
  else {
67
77
  // doesn't really matter
@@ -69,8 +79,7 @@ function internalJsonValuePathToTypePath(typeDef, valueSteps, allowMissingPaths,
69
79
  }
70
80
  }
71
81
  else {
72
- const qualifierIndex = valueStep.indexOf(':');
73
- if (qualifierIndex < 0) {
82
+ if (qualifiers.length === 0) {
74
83
  if (allowMissingPaths) {
75
84
  return valueSteps;
76
85
  }
@@ -78,17 +87,9 @@ function internalJsonValuePathToTypePath(typeDef, valueSteps, allowMissingPaths,
78
87
  throw new PreconditionFailedError('mismatched qualifiers in {} (at {})', originalValuePath, valueStep);
79
88
  }
80
89
  }
81
- const qualifier = valueStep.substring(0, qualifierIndex);
82
- const remainder = valueStep.substring(qualifierIndex + 1);
90
+ const [qualifier, ...remainingQualifiers] = qualifiers;
83
91
  const union = assertExistsAndReturn(typeDef.unions[qualifier], 'missing union {}', qualifier);
84
- const [typeStep, ...remainingTypeSteps] = internalJsonValuePathToTypePath(union, [
85
- remainder,
86
- ...remainingValueSteps,
87
- ], allowMissingPaths, originalValuePath);
88
- return [
89
- `${qualifier}:${typeStep}`,
90
- ...remainingTypeSteps,
91
- ];
92
+ return internalJsonValuePathToTypePath(union, remainingQualifiers, valueSteps, allowMissingPaths, originalValuePath);
92
93
  }
93
94
  default:
94
95
  throw new UnreachableError(typeDef);