@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
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
|
+
}
|
package/.out/index.d.ts
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';
|
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,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 @@
|
|
|
1
|
+
export {};
|
|
@@ -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,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,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,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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|