@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
package/.eslintrc.cjs ADDED
@@ -0,0 +1,31 @@
1
+ /* eslint-env node */
2
+ /** @type {import('@types/eslint').Linter.Config} */
3
+ module.exports = {
4
+ root: true,
5
+ extends: ['../../.eslintrc.cjs'],
6
+ parserOptions: {
7
+ project: [
8
+ 'tsconfig.json',
9
+ 'tsconfig.build.json',
10
+ ],
11
+ tsconfigRootDir: __dirname,
12
+ sourceType: 'module',
13
+ ecmaVersion: '2015',
14
+ },
15
+ rules: {
16
+ 'import/no-extraneous-dependencies': [
17
+ 'warn',
18
+ {
19
+ packageDir: [
20
+ '.',
21
+ '../..',
22
+ ],
23
+ },
24
+ ],
25
+ // the no-unsafe rules are not particularly compatible with the type definitions
26
+ '@typescript-eslint/no-unsafe-argument': 'off',
27
+ '@typescript-eslint/no-unsafe-call': 'off',
28
+ '@typescript-eslint/no-unsafe-member-access': 'off',
29
+ '@typescript-eslint/no-unsafe-return': 'off',
30
+ },
31
+ }
@@ -0,0 +1,20 @@
1
+ export * from './transformers/copies/copy';
2
+ export * from './transformers/copies/mobx_copy';
3
+ export * from './transformers/flatteners/flatten_accessors_of';
4
+ export * from './transformers/flatteners/flatten_json_value_to_type_paths_of';
5
+ export * from './transformers/flatteners/flatten_type_defs_of';
6
+ export * from './transformers/flatteners/flatten_value_type_to';
7
+ export * from './transformers/flatteners/json_path';
8
+ export * from './transformers/flatteners/value_path_to_type_path';
9
+ export * from './types/builders';
10
+ export * from './types/definitions';
11
+ export * from './types/flattened_accessors_of';
12
+ export * from './types/flattened_type_defs_of';
13
+ export * from './types/flattened_value_types_of';
14
+ export * from './types/json_paths_of';
15
+ export * from './types/mobx_value_type_of';
16
+ export * from './types/readonly_type_def_of';
17
+ export * from './types/strict_definitions';
18
+ export * from './types/value_to_type_paths_of';
19
+ export * from './types/value_type_of';
20
+ export * from './types/value_types_of_discriminated_union';
package/.out/index.js ADDED
@@ -0,0 +1,20 @@
1
+ export * from './transformers/copies/copy';
2
+ export * from './transformers/copies/mobx_copy';
3
+ export * from './transformers/flatteners/flatten_accessors_of';
4
+ export * from './transformers/flatteners/flatten_json_value_to_type_paths_of';
5
+ export * from './transformers/flatteners/flatten_type_defs_of';
6
+ export * from './transformers/flatteners/flatten_value_type_to';
7
+ export * from './transformers/flatteners/json_path';
8
+ export * from './transformers/flatteners/value_path_to_type_path';
9
+ export * from './types/builders';
10
+ export * from './types/definitions';
11
+ export * from './types/flattened_accessors_of';
12
+ export * from './types/flattened_type_defs_of';
13
+ export * from './types/flattened_value_types_of';
14
+ export * from './types/json_paths_of';
15
+ export * from './types/mobx_value_type_of';
16
+ export * from './types/readonly_type_def_of';
17
+ export * from './types/strict_definitions';
18
+ export * from './types/value_to_type_paths_of';
19
+ export * from './types/value_type_of';
20
+ export * from './types/value_types_of_discriminated_union';
@@ -0,0 +1,4 @@
1
+ import { type ReadonlyTypeDefOf } from 'types/readonly_type_def_of';
2
+ import { type StrictType } from 'types/strict_definitions';
3
+ import { type ValueTypeOf } from 'types/value_type_of';
4
+ export declare function copy<T extends StrictType>(t: T, proto: ValueTypeOf<ReadonlyTypeDefOf<T>>): ValueTypeOf<T>;
@@ -0,0 +1,7 @@
1
+ import { copyTo, } from './copy_to';
2
+ function identity(v) {
3
+ return v;
4
+ }
5
+ export function copy(t, proto) {
6
+ return copyTo(t, proto, identity);
7
+ }
@@ -0,0 +1,6 @@
1
+ import { type ReadonlyTypeDefOf } from 'types/readonly_type_def_of';
2
+ import { type StrictType, type StrictTypeDef } from 'types/strict_definitions';
3
+ import { type ValueTypeOf } from 'types/value_type_of';
4
+ export type AnyValueType = any;
5
+ export type Copier<R> = (v: AnyValueType, t: StrictTypeDef) => R;
6
+ export declare function copyTo<T extends StrictType, R extends ValueTypeOf<ReadonlyTypeDefOf<T>>>({ definition }: T, value: ValueTypeOf<ReadonlyTypeDefOf<T>>, copier: Copier<R>): R;
@@ -0,0 +1,91 @@
1
+ import { map, reduce, UnexpectedImplementationError, UnreachableError, } from '@strictly/base';
2
+ import { TypeDefType, } from 'types/definitions';
3
+ export function copyTo({ definition }, value, copier) {
4
+ return internalCopyTo(definition, value, copier);
5
+ }
6
+ /**
7
+ * Creates a copy of the supplied value
8
+ * @param def description of the object to create
9
+ * @param value the value to populate the object from
10
+ * @returns a copy of the supplied value
11
+ */
12
+ function internalCopyTo(definition, value, copier) {
13
+ switch (definition.type) {
14
+ case TypeDefType.Literal:
15
+ return copyLiteral(definition, value, copier);
16
+ case TypeDefType.List:
17
+ return copyList(definition, value, copier);
18
+ case TypeDefType.Record:
19
+ return copyRecord(definition, value, copier);
20
+ case TypeDefType.Object:
21
+ return copyObject(definition, value, copier);
22
+ case TypeDefType.Union:
23
+ return copyUnion(definition, value, copier);
24
+ default:
25
+ throw new UnreachableError(definition);
26
+ }
27
+ }
28
+ function copyLiteral(typeDef, value, copier) {
29
+ // mutable and immutable literals should be the same type
30
+ return copier(value, typeDef);
31
+ }
32
+ function copyList(typeDef, arr, copier) {
33
+ const { elements, } = typeDef;
34
+ const list = arr.map(function (value) {
35
+ return internalCopyTo(elements, value, copier);
36
+ });
37
+ return copier(list, typeDef);
38
+ }
39
+ function copyRecord(typeDef, value, copier) {
40
+ const { valueTypeDef, } = typeDef;
41
+ const record = map(value, function (_key, value) {
42
+ return internalCopyTo(valueTypeDef, value, copier);
43
+ });
44
+ return copier(record, typeDef);
45
+ }
46
+ function copyObjectFields(fields, value, copier, extra) {
47
+ const record = reduce(fields, function (acc, key, field) {
48
+ const fieldValue = value[key];
49
+ acc[key] = fieldValue != null
50
+ ? internalCopyTo(field, fieldValue, copier)
51
+ : fieldValue;
52
+ return acc;
53
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
54
+ }, extra);
55
+ return record;
56
+ }
57
+ function copyObject(typeDef, value, copier) {
58
+ const { fields, } = typeDef;
59
+ const record = copyObjectFields(fields, value, copier, {});
60
+ return copier(record, typeDef);
61
+ }
62
+ function copyUnion(typeDef, value, copier) {
63
+ const { discriminator, unions, } = typeDef;
64
+ // is it a discriminated union with a struct?
65
+ if (discriminator != null) {
66
+ const discriminatorValue = value[discriminator];
67
+ const discriminatingUnion = {
68
+ ...internalCopyTo(unions[discriminatorValue], value, copier),
69
+ [discriminator]: discriminatorValue,
70
+ };
71
+ return copier(discriminatingUnion, typeDef);
72
+ }
73
+ // is it a `<constant1> | <constant2> | X`? We can handle that
74
+ // a good example is when we `| null` something
75
+ const allTypeDefs = Object.values(unions);
76
+ const variableTypeDefs = allTypeDefs.filter(function (typeDef) {
77
+ return typeDef.type !== TypeDefType.Literal || typeDef.valuePrototype == null;
78
+ });
79
+ if (variableTypeDefs.length <= 1) {
80
+ // can handle up to one non-constant value
81
+ const targetTypeDef = allTypeDefs.find(function (typeDef) {
82
+ return typeDef.type === TypeDefType.Literal
83
+ && typeDef.valuePrototype != null
84
+ && typeDef.valuePrototype.indexOf(value) >= 0;
85
+ }) || variableTypeDefs[0];
86
+ return internalCopyTo(targetTypeDef, value, copier);
87
+ }
88
+ // oh dear!
89
+ // this should have caused a type error already
90
+ throw new UnexpectedImplementationError('unions must be strict in order to be copied');
91
+ }
@@ -0,0 +1,5 @@
1
+ import { type MobxValueTypeOf } from 'types/mobx_value_type_of';
2
+ import { type ReadonlyTypeDefOf } from 'types/readonly_type_def_of';
3
+ import { type StrictType } from 'types/strict_definitions';
4
+ import { type ValueTypeOf } from 'types/value_type_of';
5
+ export declare function mobxCopy<T extends StrictType>(t: T, proto: ValueTypeOf<ReadonlyTypeDefOf<T>>): MobxValueTypeOf<T>;
@@ -0,0 +1,42 @@
1
+ import { reduce, UnreachableError, } from '@strictly/base';
2
+ import { makeObservable, observable, } from 'mobx';
3
+ import { getUnionTypeDef } from 'transformers/flatteners/flatten_value_type_to';
4
+ import { TypeDefType, } from 'types/definitions';
5
+ import { copyTo, } from './copy_to';
6
+ function observeValue(v, def) {
7
+ if (v == null) {
8
+ return v;
9
+ }
10
+ switch (def.type) {
11
+ case TypeDefType.Literal:
12
+ return v;
13
+ case TypeDefType.List:
14
+ // can't work out that an observable array is an array
15
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
16
+ return observable.array(v, { deep: false });
17
+ case TypeDefType.Record:
18
+ // observable observes all fields
19
+ return observable(v, {}, {
20
+ deep: false,
21
+ });
22
+ case TypeDefType.Object:
23
+ // `makeObservable` only observes the specified props
24
+ return makeObservable(v, reduce(def.fields, function (acc, k) {
25
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
26
+ acc[k] = observable;
27
+ return acc;
28
+ },
29
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
30
+ {}), {
31
+ deep: false,
32
+ });
33
+ case TypeDefType.Union:
34
+ // delegate to the underlying value
35
+ return observeValue(v, getUnionTypeDef(def, v));
36
+ default:
37
+ throw new UnreachableError(def);
38
+ }
39
+ }
40
+ export function mobxCopy(t, proto) {
41
+ return copyTo(t, proto, observeValue);
42
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,97 @@
1
+ import { copyTo, } from 'transformers/copies/copy_to';
2
+ import { booleanType, list, literal, numberType, object, record, stringType, union, } from 'types/builders';
3
+ import { TypeDefType } from 'types/definitions';
4
+ describe('copyTo', function () {
5
+ function toString(v, t) {
6
+ if (t.type === TypeDefType.Literal) {
7
+ return JSON.stringify(v);
8
+ }
9
+ else {
10
+ return v;
11
+ }
12
+ }
13
+ describe('literal', function () {
14
+ const type = literal();
15
+ it('copies', function () {
16
+ const c = copyTo(type, 1, toString);
17
+ expect(c).toEqual('1');
18
+ });
19
+ });
20
+ describe('list', function () {
21
+ const typeDef = list(literal());
22
+ it('copies', function () {
23
+ const c = copyTo(typeDef, [
24
+ 1,
25
+ 2,
26
+ 3,
27
+ ], toString);
28
+ expect(c).toEqual([
29
+ '1',
30
+ '2',
31
+ '3',
32
+ ]);
33
+ });
34
+ });
35
+ describe('record', function () {
36
+ const typeDef = record(numberType);
37
+ it('copies', function () {
38
+ const c = copyTo(typeDef, {
39
+ a: 1,
40
+ b: 2,
41
+ }, toString);
42
+ expect(c).toEqual({
43
+ a: '1',
44
+ b: '2',
45
+ });
46
+ });
47
+ });
48
+ describe('object', function () {
49
+ const typeDef = object()
50
+ .set('a', numberType)
51
+ .set('b', booleanType)
52
+ .set('c', stringType);
53
+ it('copies', function () {
54
+ const c = copyTo(typeDef, {
55
+ a: 1,
56
+ b: true,
57
+ c: 'a',
58
+ }, toString);
59
+ expect(c).toEqual({
60
+ a: '1',
61
+ b: 'true',
62
+ c: '"a"',
63
+ });
64
+ });
65
+ });
66
+ describe('union', function () {
67
+ describe('non-discriminated', function () {
68
+ const typeDef = union()
69
+ .add('0', list(numberType))
70
+ .add('1', literal(['b']))
71
+ .add('2', literal([false]));
72
+ it('copies string literal', function () {
73
+ const c = copyTo(typeDef, 'b', toString);
74
+ expect(c).toEqual('"b"');
75
+ });
76
+ it('copies boolean literal', function () {
77
+ const c = copyTo(typeDef, false, toString);
78
+ expect(c).toEqual('false');
79
+ });
80
+ });
81
+ describe('discriminated', function () {
82
+ const typeDef = union('d')
83
+ .add('a', object().set('x', numberType))
84
+ .add('b', object().set('y', booleanType));
85
+ it('copies', function () {
86
+ const c = copyTo(typeDef, {
87
+ d: 'a',
88
+ x: 1,
89
+ }, toString);
90
+ expect(c).toEqual({
91
+ d: 'a',
92
+ x: '1',
93
+ });
94
+ });
95
+ });
96
+ });
97
+ });
@@ -0,0 +1,19 @@
1
+ import { mobxCopy } from 'transformers/copies/mobx_copy';
2
+ import { numberType, object, } from 'types/builders';
3
+ describe('mobxCopy', function () {
4
+ describe('object', function () {
5
+ describe('optional field', function () {
6
+ const type = object().setOptional('n', numberType);
7
+ it('copies unpopulated', function () {
8
+ const v = {};
9
+ const c = mobxCopy(type, v);
10
+ expect(c).toEqual(v);
11
+ });
12
+ it('copies populated', function () {
13
+ const v = { n: 1 };
14
+ const c = mobxCopy(type, v);
15
+ expect(c).toEqual(v);
16
+ });
17
+ });
18
+ });
19
+ });
@@ -0,0 +1,5 @@
1
+ import { type Type } from 'types/definitions';
2
+ import { type Accessor, type FlattenedAccessorsOf } from 'types/flattened_accessors_of';
3
+ import { type ValueTypeOf } from 'types/value_type_of';
4
+ import { type Setter } from './flatten_value_type_to';
5
+ export declare function flattenAccessorsOf<T extends Type, R extends Readonly<Record<string, Accessor<any>>> = FlattenedAccessorsOf<T>>(t: T, value: ValueTypeOf<T>, setValue: Setter<ValueTypeOf<T>>): R;
@@ -0,0 +1,11 @@
1
+ import { flattenValueTypeTo, } from './flatten_value_type_to';
2
+ function mapAccessor(_t, value, set) {
3
+ return {
4
+ value,
5
+ set,
6
+ };
7
+ }
8
+ export function flattenAccessorsOf(t, value, setValue) {
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ return flattenValueTypeTo(t, value, setValue, mapAccessor);
11
+ }
@@ -0,0 +1,3 @@
1
+ import { type Type } from 'types/definitions';
2
+ import { type ValueTypeOf } from 'types/value_type_of';
3
+ export declare function flattenJsonValueToTypePathsOf<T extends Type, R extends Record<string, string | number | symbol>>(t: T, value: ValueTypeOf<T>): R;
@@ -0,0 +1,10 @@
1
+ import { flattenValueTypeTo, } from './flatten_value_type_to';
2
+ function mapTypePaths(_t, _value, _set, typePath) {
3
+ return typePath;
4
+ }
5
+ export function flattenJsonValueToTypePathsOf(t, value) {
6
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
7
+ return flattenValueTypeTo(t, value, function () {
8
+ // do nothing
9
+ }, mapTypePaths);
10
+ }
@@ -0,0 +1,4 @@
1
+ import { type StrictType, type StrictTypeDef } from 'types/strict_definitions';
2
+ export type AnyValueType = any;
3
+ export type Mapper<R> = (t: StrictTypeDef) => R;
4
+ export declare function flattenTypeDefTo<M, R extends Readonly<Record<string, M>>>({ definition }: StrictType, mapper: Mapper<M>): R;
@@ -0,0 +1,49 @@
1
+ import { reduce, UnreachableError, } from '@strictly/base';
2
+ import { TypeDefType, } from 'types/definitions';
3
+ import { jsonPath } from './json_path';
4
+ export function flattenTypeDefTo({ definition }, mapper) {
5
+ const typeDefs = internalFlattenTypeDef('$', definition, {});
6
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
7
+ return reduce(typeDefs, function (acc, key, typeDef) {
8
+ acc[key] = mapper(typeDef);
9
+ return acc;
10
+ },
11
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12
+ {});
13
+ }
14
+ function internalFlattenTypeDef(path, t, r) {
15
+ r[path] = t;
16
+ return internalFlattenTypeDefChildren(path, '', t, r);
17
+ }
18
+ function internalFlattenTypeDefChildren(path, qualifier, t, r) {
19
+ switch (t.type) {
20
+ case TypeDefType.Literal:
21
+ return r;
22
+ case TypeDefType.List:
23
+ return internalFlattenedListTypeDefChildren(path, t, r);
24
+ case TypeDefType.Record:
25
+ return internalFlattenRecordTypeDefChildren(path, t, r);
26
+ case TypeDefType.Object:
27
+ return internalFlattenObjectTypeDefChildren(path, qualifier, t, r);
28
+ case TypeDefType.Union:
29
+ return internalFlattenUnionTypeDefChildren(path, qualifier, t, r);
30
+ default:
31
+ throw new UnreachableError(t);
32
+ }
33
+ }
34
+ function internalFlattenedListTypeDefChildren(path, { elements }, r) {
35
+ return internalFlattenTypeDef(jsonPath(path, '*'), elements, r);
36
+ }
37
+ function internalFlattenRecordTypeDefChildren(path, { valueTypeDef }, r) {
38
+ return internalFlattenTypeDef(jsonPath(path, '*'), valueTypeDef, r);
39
+ }
40
+ function internalFlattenObjectTypeDefChildren(path, qualifier, { fields }, r) {
41
+ return reduce(fields, function (acc, fieldName, fieldTypeDef) {
42
+ return internalFlattenTypeDef(jsonPath(path, fieldName, qualifier), fieldTypeDef, acc);
43
+ }, r);
44
+ }
45
+ function internalFlattenUnionTypeDefChildren(path, qualifier, { discriminator, unions, }, r) {
46
+ return reduce(unions, function (acc, key, typeDef) {
47
+ return internalFlattenTypeDefChildren(path, discriminator != null ? `${qualifier}${key}:` : qualifier, typeDef, acc);
48
+ }, r);
49
+ }
@@ -0,0 +1,3 @@
1
+ import { type Type } from 'types/definitions';
2
+ import { type StrictType } from 'types/strict_definitions';
3
+ export declare function flattenTypeDefsOf<T extends StrictType>(t: T): Record<string, Type>;
@@ -0,0 +1,7 @@
1
+ import { flattenTypeDefTo } from './flatten_type_def_to';
2
+ export function flattenTypeDefsOf(t) {
3
+ // Type should be FlattenedTypeDefsOf<T>, but infinite depth error
4
+ return flattenTypeDefTo(t, function (definition) {
5
+ return { definition };
6
+ });
7
+ }
@@ -0,0 +1,11 @@
1
+ import { type UnionTypeDef } from 'types/definitions';
2
+ import { type ReadonlyTypeDefOf } from 'types/readonly_type_def_of';
3
+ import { type StrictType, type StrictTypeDef } from 'types/strict_definitions';
4
+ import { type ValueTypeOf } from 'types/value_type_of';
5
+ export type AnyValueType = any;
6
+ export type Setter<V> = (v: V) => void;
7
+ export type Mapper<R> = (t: StrictTypeDef, v: AnyValueType, setter: Setter<AnyValueType>, typePath: string, valuePath: string) => R;
8
+ export declare function flattenValueTypeTo<T extends StrictType, M, R extends Readonly<Record<string, M>>>({ definition }: T, v: ValueTypeOf<T>, setter: Setter<ValueTypeOf<T>>, mapper: Mapper<M>): R;
9
+ export declare function getUnionTypeDef<T extends UnionTypeDef>(typeDef: T, v: ValueTypeOf<ReadonlyTypeDefOf<{
10
+ definition: T;
11
+ }>>): any;
@@ -0,0 +1,79 @@
1
+ import { reduce, UnreachableError, } from '@strictly/base';
2
+ import { TypeDefType, } from 'types/definitions';
3
+ import { jsonPath } from './json_path';
4
+ export function flattenValueTypeTo({ definition }, v, setter, mapper) {
5
+ const r = {};
6
+ internalFlattenValue('$', '$', definition, v, setter, mapper, r);
7
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8
+ return r;
9
+ }
10
+ function internalFlattenValue(valuePath, typePath, typeDef, v, setter, mapper, r) {
11
+ r[valuePath] = mapper(typeDef, v, setter, typePath, valuePath);
12
+ return internalFlattenValueChildren(valuePath, typePath, '', typeDef, v, mapper, r);
13
+ }
14
+ function internalFlattenValueChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r) {
15
+ switch (typeDef.type) {
16
+ case TypeDefType.Literal:
17
+ // no children
18
+ return r;
19
+ case TypeDefType.List:
20
+ return internalFlattenListChildren(valuePath, typePath, typeDef, v, mapper, r);
21
+ case TypeDefType.Record:
22
+ return internalFlattenRecordChildren(valuePath, typePath, typeDef, v, mapper, r);
23
+ case TypeDefType.Object:
24
+ return internalFlattenObjectChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r);
25
+ case TypeDefType.Union:
26
+ return internalFlattenUnionChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r);
27
+ default:
28
+ throw new UnreachableError(typeDef);
29
+ }
30
+ }
31
+ function internalFlattenListChildren(valuePath, typePath, { elements }, v, mapper, r) {
32
+ const newTypePath = jsonPath(typePath, '*');
33
+ return v.reduce(function (r, e, i) {
34
+ return internalFlattenValue(jsonPath(valuePath, i), newTypePath, elements, e, (e) => {
35
+ v[i] = e;
36
+ }, mapper, r);
37
+ }, r);
38
+ }
39
+ function internalFlattenRecordChildren(valuePath, typePath, { valueTypeDef }, v, mapper, r) {
40
+ const newTypePath = jsonPath(typePath, '*');
41
+ return reduce(v, function (r, k, value) {
42
+ return internalFlattenValue(jsonPath(valuePath, k), newTypePath, valueTypeDef, value, (value) => {
43
+ v[k] = value;
44
+ }, mapper, r);
45
+ }, r);
46
+ }
47
+ function internalFlattenObjectChildren(valuePath, typePath, qualifier, { fields }, v, mapper, r) {
48
+ return reduce(fields, function (r, k, fieldTypeDef) {
49
+ const fieldValue = v[k];
50
+ return internalFlattenValue(jsonPath(valuePath, k, qualifier), jsonPath(typePath, k, qualifier), fieldTypeDef, fieldValue, (value) => {
51
+ v[k] = value;
52
+ }, mapper, r);
53
+ }, r);
54
+ }
55
+ function internalFlattenUnionChildren(valuePath, typePath, qualifier, typeDef, v, mapper, r) {
56
+ const childTypeDef = getUnionTypeDef(typeDef, v);
57
+ const newQualifier = typeDef.discriminator != null ? `${qualifier}${v[typeDef.discriminator]}:` : qualifier;
58
+ return internalFlattenValueChildren(valuePath, typePath, newQualifier, childTypeDef, v, mapper, r);
59
+ }
60
+ export function getUnionTypeDef(typeDef, v) {
61
+ if (typeDef.discriminator == null) {
62
+ // find either a literal who's prototype we match, or assume that
63
+ // we match the non-literal, or the literal value with no prototype, value
64
+ return reduce(typeDef.unions, function (acc, _k, t) {
65
+ if (t.type === TypeDefType.Literal && t.valuePrototype) {
66
+ if (t.valuePrototype.indexOf(v) >= 0) {
67
+ return t;
68
+ }
69
+ }
70
+ else {
71
+ if (acc == null) {
72
+ return t;
73
+ }
74
+ }
75
+ return acc;
76
+ }, null);
77
+ }
78
+ return typeDef.unions[v[typeDef.discriminator]];
79
+ }
@@ -0,0 +1,3 @@
1
+ import { type Type } from 'types/definitions';
2
+ import { type ValueTypeOf } from 'types/value_type_of';
3
+ export declare function flattenValueTypesOf<T extends Type>(typeDef: Type, value: ValueTypeOf<T>): Readonly<Record<string, any>>;
@@ -0,0 +1,7 @@
1
+ import { flattenValueTypeTo, } from './flatten_value_type_to';
2
+ function mapper(_t, v) {
3
+ return v;
4
+ }
5
+ export function flattenValueTypesOf(typeDef, value) {
6
+ return flattenValueTypeTo(typeDef, value, () => { }, mapper);
7
+ }
@@ -0,0 +1,2 @@
1
+ export declare function jsonPath(prefix: string, segment: number | string, qualifier?: string): string;
2
+ export declare function jsonPathPop(path: string): [string, string] | null;
@@ -0,0 +1,14 @@
1
+ export function jsonPath(prefix, segment, qualifier = '') {
2
+ const s = `.${qualifier}${segment}`;
3
+ return `${prefix}${s}`;
4
+ }
5
+ export function jsonPathPop(path) {
6
+ const parts = path.split('.');
7
+ if (parts.length <= 1) {
8
+ return null;
9
+ }
10
+ return [
11
+ parts.slice(0, -1).join('.'),
12
+ parts.pop(),
13
+ ];
14
+ }