@valbuild/core 0.15.0 → 0.17.0

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 (133) hide show
  1. package/ROADMAP.md +106 -0
  2. package/dist/declarations/src/ValApi.d.ts +26 -0
  3. package/dist/declarations/src/expr/eval.d.ts +1 -1
  4. package/dist/declarations/src/future/fetchVal.d.ts +5 -0
  5. package/dist/declarations/src/index.d.ts +38 -9
  6. package/dist/declarations/src/initSchema.d.ts +2 -10
  7. package/dist/declarations/src/initVal.d.ts +3 -21
  8. package/dist/declarations/src/module.d.ts +2 -14
  9. package/dist/declarations/src/patch/index.d.ts +1 -1
  10. package/dist/declarations/src/patch/util.d.ts +2 -0
  11. package/dist/declarations/src/schema/array.d.ts +3 -2
  12. package/dist/declarations/src/schema/boolean.d.ts +3 -2
  13. package/dist/declarations/src/schema/image.d.ts +4 -3
  14. package/dist/declarations/src/schema/index.d.ts +8 -7
  15. package/dist/declarations/src/schema/keyOf.d.ts +23 -0
  16. package/dist/declarations/src/schema/literal.d.ts +3 -2
  17. package/dist/declarations/src/schema/number.d.ts +3 -2
  18. package/dist/declarations/src/schema/object.d.ts +3 -2
  19. package/dist/declarations/src/schema/record.d.ts +19 -0
  20. package/dist/declarations/src/schema/richtext.d.ts +3 -2
  21. package/dist/declarations/src/schema/string.d.ts +3 -2
  22. package/dist/declarations/src/schema/union.d.ts +4 -2
  23. package/dist/declarations/src/schema/validation/ValidationError.d.ts +14 -0
  24. package/dist/declarations/src/schema/validation/ValidationFix.d.ts +2 -0
  25. package/dist/declarations/src/selector/SelectorProxy.d.ts +7 -0
  26. package/dist/declarations/src/selector/array.d.ts +2 -13
  27. package/dist/declarations/src/selector/file.d.ts +1 -4
  28. package/dist/declarations/src/selector/future/array.d.ts +17 -0
  29. package/dist/declarations/src/selector/future/boolean.d.ts +2 -0
  30. package/dist/declarations/src/selector/future/file.d.ts +9 -0
  31. package/dist/declarations/src/selector/{i18n.d.ts → future/i18n.d.ts} +2 -2
  32. package/dist/declarations/src/selector/future/index.d.ts +81 -0
  33. package/dist/declarations/src/selector/future/number.d.ts +2 -0
  34. package/dist/declarations/src/selector/future/object.d.ts +10 -0
  35. package/dist/declarations/src/selector/future/primitive.d.ts +9 -0
  36. package/dist/declarations/src/selector/{remote.d.ts → future/remote.d.ts} +1 -1
  37. package/dist/declarations/src/selector/future/string.d.ts +2 -0
  38. package/dist/declarations/src/selector/index.d.ts +5 -32
  39. package/dist/declarations/src/selector/object.d.ts +2 -9
  40. package/dist/declarations/src/selector/primitive.d.ts +3 -9
  41. package/dist/declarations/src/source/{i18n.d.ts → future/i18n.d.ts} +2 -2
  42. package/dist/declarations/src/source/{remote.d.ts → future/remote.d.ts} +3 -3
  43. package/dist/declarations/src/source/index.d.ts +4 -3
  44. package/dist/declarations/src/val/index.d.ts +2 -2
  45. package/dist/index-369caccf.esm.js +550 -0
  46. package/dist/{index-06df0a5b.esm.js → index-3e3e839e.esm.js} +190 -555
  47. package/dist/{index-9663f28a.cjs.dev.js → index-486c7fbf.cjs.dev.js} +224 -617
  48. package/dist/{index-b2270f8f.cjs.prod.js → index-601a7d73.cjs.prod.js} +224 -617
  49. package/dist/index-8706c87e.cjs.prod.js +582 -0
  50. package/dist/index-a6e642dd.cjs.dev.js +582 -0
  51. package/dist/ops-0d09f8ee.cjs.prod.js +684 -0
  52. package/dist/ops-23a5abb2.esm.js +671 -0
  53. package/dist/ops-f3015423.cjs.dev.js +684 -0
  54. package/dist/valbuild-core.cjs.dev.js +640 -633
  55. package/dist/valbuild-core.cjs.prod.js +640 -633
  56. package/dist/valbuild-core.esm.js +578 -572
  57. package/expr/dist/valbuild-core-expr.cjs.dev.js +8 -8
  58. package/expr/dist/valbuild-core-expr.cjs.prod.js +8 -8
  59. package/expr/dist/valbuild-core-expr.esm.js +2 -2
  60. package/package.json +2 -2
  61. package/patch/dist/valbuild-core-patch.cjs.dev.js +32 -23
  62. package/patch/dist/valbuild-core-patch.cjs.prod.js +32 -23
  63. package/patch/dist/valbuild-core-patch.esm.js +12 -4
  64. package/src/ValApi.ts +85 -0
  65. package/src/expr/eval.test.ts +2 -2
  66. package/src/expr/eval.ts +2 -2
  67. package/src/expr/repl.ts +2 -2
  68. package/src/{fetchVal.test.ts → future/fetchVal.test.ts} +57 -57
  69. package/src/{fetchVal.ts → future/fetchVal.ts} +17 -22
  70. package/src/index.ts +51 -14
  71. package/src/initSchema.ts +11 -12
  72. package/src/initVal.ts +42 -52
  73. package/src/module.test.ts +40 -40
  74. package/src/module.ts +53 -43
  75. package/src/patch/deref.test.ts +1 -1
  76. package/src/patch/deref.ts +1 -1
  77. package/src/patch/index.ts +1 -0
  78. package/src/patch/json.test.ts +0 -1
  79. package/src/patch/util.ts +7 -0
  80. package/src/schema/array.ts +45 -4
  81. package/src/schema/boolean.ts +14 -3
  82. package/src/schema/{i18n.ts → future/i18n.ts} +15 -11
  83. package/src/schema/{oneOf.ts → future/oneOf.ts} +21 -18
  84. package/src/schema/image.ts +66 -6
  85. package/src/schema/index.ts +37 -13
  86. package/src/schema/keyOf.ts +167 -0
  87. package/src/schema/literal.ts +24 -3
  88. package/src/schema/number.ts +14 -3
  89. package/src/schema/object.ts +50 -7
  90. package/src/schema/record.ts +103 -0
  91. package/src/schema/richtext.ts +63 -3
  92. package/src/schema/string.ts +14 -3
  93. package/src/schema/union.ts +4 -3
  94. package/src/schema/validation/ValidationError.ts +16 -0
  95. package/src/schema/validation/ValidationFix.ts +6 -0
  96. package/src/schema/validation.test.ts +291 -0
  97. package/src/selector/SelectorProxy.ts +16 -16
  98. package/src/selector/array.ts +2 -26
  99. package/src/selector/file.ts +1 -9
  100. package/src/selector/{ExprProxy.test.ts → future/ExprProxy.test.ts} +2 -2
  101. package/src/selector/{ExprProxy.ts → future/ExprProxy.ts} +9 -2
  102. package/src/selector/{SelectorProxy.test.ts → future/SelectorProxy.test.ts} +4 -4
  103. package/src/selector/future/SelectorProxy.ts +238 -0
  104. package/src/selector/future/array.ts +37 -0
  105. package/src/selector/future/boolean.ts +4 -0
  106. package/src/selector/future/file.ts +14 -0
  107. package/src/selector/{i18n.ts → future/i18n.ts} +2 -2
  108. package/src/selector/future/index.ts +165 -0
  109. package/src/selector/future/number.ts +4 -0
  110. package/src/selector/future/object.ts +22 -0
  111. package/src/selector/future/primitive.ts +17 -0
  112. package/src/selector/{remote.ts → future/remote.ts} +1 -1
  113. package/src/selector/{selector.test.ts → future/selector.test.ts} +8 -28
  114. package/src/selector/{selectorOf.ts → future/selectorOf.ts} +1 -1
  115. package/src/selector/future/string.ts +4 -0
  116. package/src/selector/index.ts +4 -46
  117. package/src/selector/object.ts +2 -19
  118. package/src/selector/primitive.ts +3 -16
  119. package/src/source/{i18n.ts → future/i18n.ts} +2 -2
  120. package/src/source/{remote.ts → future/remote.ts} +3 -3
  121. package/src/source/index.ts +3 -2
  122. package/src/val/array.ts +1 -1
  123. package/src/val/index.ts +2 -2
  124. package/src/val/object.ts +1 -1
  125. package/dist/createClass-012eebbf.esm.js +0 -109
  126. package/dist/createClass-a436dbfe.cjs.dev.js +0 -116
  127. package/dist/createClass-de7426aa.cjs.prod.js +0 -116
  128. package/dist/declarations/src/fetchVal.d.ts +0 -5
  129. package/dist/declarations/src/schema/i18n.d.ts +0 -21
  130. package/dist/declarations/src/schema/oneOf.d.ts +0 -22
  131. package/dist/ops-6fae92a1.esm.js +0 -12
  132. package/dist/ops-87cdbafc.cjs.dev.js +0 -14
  133. package/dist/ops-ae4d1bc2.cjs.prod.js +0 -14
@@ -0,0 +1,238 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { Path, GenericSelector, SourceOrExpr, GetSchema } from ".";
3
+ import { Expr } from "../../expr/expr";
4
+ import { Schema } from "../../schema";
5
+ import { convertFileSource } from "../../schema/image";
6
+ import { Source, SourcePrimitive, VAL_EXTENSION } from "../../source";
7
+ import { FILE_REF_PROP } from "../../source/file";
8
+ import { isSerializedVal, SourcePath } from "../../val";
9
+
10
+ function hasOwn<T extends PropertyKey>(obj: object, prop: T): boolean {
11
+ return Object.prototype.hasOwnProperty.call(obj, prop);
12
+ }
13
+
14
+ function andThen(f: (...args: any[]) => any, source: any, path?: SourcePath) {
15
+ if (source) {
16
+ return newSelectorProxy(f(newSelectorProxy(source, path)));
17
+ }
18
+ return newSelectorProxy(source, path);
19
+ }
20
+
21
+ export function isSelector(source: any): source is GenericSelector<Source> {
22
+ return (
23
+ typeof source === "object" &&
24
+ source !== null &&
25
+ (SourceOrExpr in source || Path in source)
26
+ );
27
+ }
28
+
29
+ export function newSelectorProxy(
30
+ source: any,
31
+ path?: SourcePath,
32
+ moduleSchema?: any
33
+ ): any {
34
+ if (typeof source === "object") {
35
+ if (isSelector(source)) {
36
+ return source;
37
+ } else if (isSerializedVal(source)) {
38
+ return newSelectorProxy(source.val, source.valPath);
39
+ }
40
+ }
41
+
42
+ if (source && source[FILE_REF_PROP] && source[VAL_EXTENSION] === "file") {
43
+ const fileRef = source[FILE_REF_PROP];
44
+ if (typeof fileRef !== "string") {
45
+ throw Error("Invalid file ref: " + fileRef);
46
+ }
47
+ return newSelectorProxy(convertFileSource(source), path, moduleSchema);
48
+ }
49
+
50
+ switch (typeof source) {
51
+ case "function":
52
+ case "symbol":
53
+ throw Error(`Invalid selector type: ${typeof source}: ${source}`);
54
+ case "object":
55
+ // Handles both objects and arrays!
56
+ if (source !== null) {
57
+ return new Proxy(source, {
58
+ // TODO: see proxy docs if we want more traps
59
+ has(target, prop: string | symbol) {
60
+ if (prop === SourceOrExpr) {
61
+ return true;
62
+ }
63
+ if (prop === Path) {
64
+ return true;
65
+ }
66
+ if (prop === "andThen") {
67
+ return true;
68
+ }
69
+ if (prop === GetSchema) {
70
+ return true;
71
+ }
72
+ return prop in target;
73
+ },
74
+ get(target, prop: string | symbol) {
75
+ if (prop === SourceOrExpr) {
76
+ return source;
77
+ }
78
+ if (prop === Path) {
79
+ return path;
80
+ }
81
+ if (prop === GetSchema) {
82
+ return moduleSchema;
83
+ }
84
+ if (prop === "andThen") {
85
+ return (f: any) => andThen(f, source, path);
86
+ }
87
+ if (Array.isArray(target)) {
88
+ if (prop === "filter") {
89
+ return (f: any) => {
90
+ const filtered = target
91
+ .map((a, i) =>
92
+ newSelectorProxy(
93
+ a,
94
+ createValPathOfItem(path, i),
95
+ moduleSchema?.item
96
+ )
97
+ )
98
+ .filter((a) => {
99
+ if (f && f instanceof Schema) {
100
+ return f.assert(unValify(a));
101
+ } else {
102
+ return unValify(f(a));
103
+ }
104
+ });
105
+ return newSelectorProxy(filtered, path, moduleSchema);
106
+ };
107
+ } else if (prop === "map") {
108
+ return (f: any) => {
109
+ const filtered = target.map((a, i) => {
110
+ const valueOrSelector = f(
111
+ newSelectorProxy(
112
+ a,
113
+ createValPathOfItem(path, i),
114
+ moduleSchema?.item
115
+ ),
116
+ newSelectorProxy(i)
117
+ );
118
+ if (isSelector(valueOrSelector)) {
119
+ return valueOrSelector;
120
+ }
121
+ return newSelectorProxy(valueOrSelector);
122
+ });
123
+ return newSelectorProxy(filtered, path, moduleSchema);
124
+ };
125
+ }
126
+ }
127
+ if (Array.isArray(target) && prop === "length") {
128
+ return newSelectorProxy(target.length);
129
+ }
130
+ const reflectedValue = Reflect.get(target, prop);
131
+
132
+ if (hasOwn(source, prop)) {
133
+ if (!Number.isNaN(Number(prop))) {
134
+ return newSelectorProxy(
135
+ reflectedValue,
136
+ createValPathOfItem(path, Number(prop)),
137
+ moduleSchema?.item
138
+ );
139
+ }
140
+ return newSelectorProxy(
141
+ reflectedValue,
142
+ createValPathOfItem(path, prop),
143
+ moduleSchema?.items[prop]
144
+ );
145
+ }
146
+ return reflectedValue;
147
+ },
148
+ });
149
+ }
150
+ // intentional fallthrough
151
+ // eslint-disable-next-line no-fallthrough
152
+ default:
153
+ return {
154
+ eq: (other: SourcePrimitive | GenericSelector<Source>) => {
155
+ let otherValue: any = other;
156
+ if (isSelector(other)) {
157
+ otherValue = other[SourceOrExpr];
158
+ if (otherValue instanceof Expr) {
159
+ throw Error("TODO: Cannot evaluate equality with an Expr");
160
+ }
161
+ }
162
+ return newSelectorProxy(source === otherValue, undefined);
163
+ },
164
+ andThen: (f: any) => {
165
+ return andThen(f, source === undefined ? null : source, path);
166
+ },
167
+ [SourceOrExpr]: source === undefined ? null : source,
168
+ [Path]: path,
169
+ [GetSchema]: moduleSchema,
170
+ };
171
+ }
172
+ }
173
+
174
+ function selectorAsVal(sel: any): any {
175
+ if (isSerializedVal(sel)) {
176
+ // is a serialized val
177
+ return selectorAsVal(newSelectorProxy(sel.val, sel.valPath));
178
+ } else if (
179
+ typeof sel === "object" &&
180
+ sel &&
181
+ !(SourceOrExpr in sel) &&
182
+ !Array.isArray(sel)
183
+ ) {
184
+ // is object
185
+ return Object.fromEntries(
186
+ Object.entries(sel).map(([k, v]) => [k, selectorAsVal(v)])
187
+ );
188
+ } else if (
189
+ typeof sel === "object" &&
190
+ sel &&
191
+ !(SourceOrExpr in sel) &&
192
+ Array.isArray(sel)
193
+ ) {
194
+ // is array
195
+ return sel.map((v) => selectorAsVal(v));
196
+ } else if (
197
+ typeof sel === "object" &&
198
+ sel &&
199
+ (SourceOrExpr in sel || Path in sel)
200
+ ) {
201
+ return selectorAsVal(sel?.[SourceOrExpr]);
202
+ } else if (sel === undefined) {
203
+ return null;
204
+ }
205
+ return sel;
206
+ }
207
+
208
+ export function createValPathOfItem(
209
+ arrayPath: SourcePath | undefined,
210
+ prop: string | number | symbol
211
+ ) {
212
+ if (typeof prop === "symbol") {
213
+ throw Error(
214
+ `Cannot create val path of array item with symbol prop: ${prop.toString()}`
215
+ );
216
+ }
217
+ return arrayPath && (`${arrayPath}.${JSON.stringify(prop)}` as SourcePath);
218
+ }
219
+
220
+ export function selectorToVal(s: any): any {
221
+ const v = selectorAsVal(s?.[SourceOrExpr]);
222
+ return {
223
+ val: v,
224
+ [Path]: s?.[Path],
225
+ };
226
+ }
227
+
228
+ // TODO: could we do .val on the objects instead?
229
+ function unValify(valueOrSelector: any) {
230
+ if (
231
+ typeof valueOrSelector === "object" &&
232
+ (SourceOrExpr in valueOrSelector || Path in valueOrSelector)
233
+ ) {
234
+ const selectorValue = valueOrSelector[SourceOrExpr];
235
+ return selectorValue;
236
+ }
237
+ return valueOrSelector;
238
+ }
@@ -0,0 +1,37 @@
1
+ import {
2
+ Selector as UnknownSelector,
3
+ GenericSelector,
4
+ SelectorOf,
5
+ SelectorSource,
6
+ } from ".";
7
+ import { Schema } from "../../schema";
8
+ import { Source, SourceArray } from "../../source";
9
+ import { Selector as BooleanSelector } from "./boolean";
10
+ import { Selector as NumberSelector } from "./number";
11
+
12
+ export type UndistributedSourceArray<T extends SourceArray> = [T] extends [
13
+ infer U // infer here to avoid Type instantiation is excessively deep and possibly infinite. See: https://github.com/microsoft/TypeScript/issues/30188#issuecomment-478938437. Avoiding infer extends to keep us below TS 4.9 compat
14
+ ]
15
+ ? U extends Source[]
16
+ ? Selector<U>
17
+ : never
18
+ : never;
19
+
20
+ // TODO: docs
21
+ export type Selector<T extends SourceArray> = GenericSelector<T> & {
22
+ readonly [key: number]: UnknownSelector<T[number]>;
23
+ } & {
24
+ length: NumberSelector<number>;
25
+ filter(
26
+ predicate: (
27
+ v: UnknownSelector<T[number]>
28
+ ) => BooleanSelector<boolean> | boolean
29
+ ): Selector<T>;
30
+ filter<U extends Source>(schema: Schema<U>): Selector<U[]>;
31
+ map<U extends SelectorSource>(
32
+ f: (v: UnknownSelector<T[number]>, i: UnknownSelector<number>) => U
33
+ ): SelectorOf<U[]>; // TODO: this should be SelectorOf<ArraySelectorSourceBranded<U[]>>;
34
+ andThen<U extends SelectorSource>(
35
+ f: (v: UnknownSelector<NonNullable<T>>) => U
36
+ ): SelectorOf<U | T>;
37
+ };
@@ -0,0 +1,4 @@
1
+ import { Selector as PrimitiveSelector } from "./primitive";
2
+
3
+ // TODO: docs
4
+ export type Selector<T extends boolean> = PrimitiveSelector<T>;
@@ -0,0 +1,14 @@
1
+ import {
2
+ Selector as UnknownSelector,
3
+ GenericSelector,
4
+ SelectorOf,
5
+ SelectorSource,
6
+ } from ".";
7
+
8
+ // TODO: docs
9
+ export type FileSelector = GenericSelector<{ url: string }> & {
10
+ readonly url: UnknownSelector<string>;
11
+ andThen<U extends SelectorSource>(
12
+ f: (v: UnknownSelector<NonNullable<{ url: string }>>) => U
13
+ ): SelectorOf<U> | UnknownSelector<boolean>;
14
+ };
@@ -1,6 +1,6 @@
1
- import { SourceArray, SourceObject, SourcePrimitive } from "../source";
1
+ import { SourceArray, SourceObject, SourcePrimitive } from "../../source";
2
2
  import { Selector as UnknownSelector } from ".";
3
- import { FileSource } from "../source/file";
3
+ import { FileSource } from "../../source/file";
4
4
 
5
5
  declare const brand: unique symbol;
6
6
 
@@ -0,0 +1,165 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { I18nSelector } from "./i18n";
3
+ import { Selector as ObjectSelector } from "./object";
4
+ import { UndistributedSourceArray as ArraySelector } from "./array";
5
+ import { Selector as NumberSelector } from "./number";
6
+ import { Selector as StringSelector } from "./string";
7
+ import { Selector as BooleanSelector } from "./boolean";
8
+ import { Selector as PrimitiveSelector } from "./primitive";
9
+ import { FileSelector } from "./file";
10
+ import { SourcePath } from "../../val";
11
+ import {
12
+ Source,
13
+ SourceArray,
14
+ SourceObject,
15
+ SourcePrimitive,
16
+ } from "../../source";
17
+ import { Schema } from "../../schema";
18
+ import { Expr } from "../../expr/expr";
19
+ import { RemoteSelector } from "./remote";
20
+ import { A } from "ts-toolbelt";
21
+ import { I18nSource, I18nCompatibleSource } from "../../source/future/i18n";
22
+ import {
23
+ RemoteCompatibleSource,
24
+ RemoteSource,
25
+ } from "../../source/future/remote";
26
+ import { FileSource } from "../../source/file";
27
+ import { RichText, RichTextSource } from "../../source/richtext";
28
+
29
+ /**
30
+ * Selectors can be used to select parts of a Val module.
31
+ * Unlike queries, joins, aggregates etc is and will not be supported.
32
+ *
33
+ * They are designed to be be used as if they were "normal" JSON data,
34
+ * though some concessions had to be made because of TypeScript limitations.
35
+ *
36
+ * Selectors works equally on source content, defined in code, and remote content.
37
+ *
38
+ * @example
39
+ * // Select the title of a document
40
+ * const titles = useVal(docsVal.map((doc) => doc.title));
41
+ *
42
+ * @example
43
+ * // Match on a union type
44
+ * const titles = useVal(docsVal.map((doc) => doc.fold("type")({
45
+ * newsletter: (newsletter) => newsletter.title,
46
+ * email: (email) => email.subject,
47
+ * }));
48
+ *
49
+ */
50
+ export type Selector<T extends Source> = Source extends T
51
+ ? GenericSelector<T>
52
+ : T extends I18nSource<infer L, infer S>
53
+ ? I18nSelector<L, S>
54
+ : T extends RemoteSource<infer S>
55
+ ? S extends RemoteCompatibleSource
56
+ ? RemoteSelector<S>
57
+ : GenericSelector<Source, "Could not determine remote source">
58
+ : T extends FileSource
59
+ ? FileSelector
60
+ : T extends RichTextSource
61
+ ? RichText
62
+ : T extends SourceObject
63
+ ? ObjectSelector<T>
64
+ : T extends SourceArray
65
+ ? ArraySelector<T>
66
+ : T extends string
67
+ ? StringSelector<T>
68
+ : T extends number
69
+ ? NumberSelector<T>
70
+ : T extends boolean
71
+ ? BooleanSelector<T>
72
+ : T extends null
73
+ ? PrimitiveSelector<null>
74
+ : never;
75
+
76
+ export type SelectorSource =
77
+ | SourcePrimitive
78
+ | undefined
79
+ | readonly SelectorSource[]
80
+ | {
81
+ [key: string]: SelectorSource;
82
+ }
83
+ | I18nSource<readonly string[], I18nCompatibleSource>
84
+ | RemoteSource<RemoteCompatibleSource>
85
+ | FileSource
86
+ | RichTextSource
87
+ | GenericSelector<Source>;
88
+
89
+ /**
90
+ * @internal
91
+ */
92
+ export const GetSchema = Symbol("GetSchema");
93
+ /**
94
+ /**
95
+ * @internal
96
+ */
97
+ export const Path = Symbol("Path");
98
+ /**
99
+ * @internal
100
+ */
101
+ export const SourceOrExpr = Symbol("SourceOrExpr");
102
+ /**
103
+ * @internal
104
+ */
105
+ export const ValError = Symbol("ValError");
106
+ export abstract class GenericSelector<
107
+ out T extends Source,
108
+ Error extends string | undefined = undefined
109
+ > {
110
+ readonly [Path]: SourcePath | undefined;
111
+ readonly [SourceOrExpr]: T | Expr;
112
+ readonly [ValError]: Error | undefined;
113
+ readonly [GetSchema]: Schema<T> | undefined;
114
+ constructor(
115
+ valOrExpr: T,
116
+ path: SourcePath | undefined,
117
+ schema?: Schema<T>,
118
+ error?: Error
119
+ ) {
120
+ this[Path] = path;
121
+ this[SourceOrExpr] = valOrExpr;
122
+ this[ValError] = error;
123
+ this[GetSchema] = schema;
124
+ }
125
+
126
+ assert<U extends Source, E extends Source = null>(
127
+ schema: Schema<U>,
128
+ other?: () => E
129
+ ): SelectorOf<U | E> {
130
+ throw new Error("Not implemented");
131
+ }
132
+ }
133
+
134
+ export type SourceOf<T extends SelectorSource> = Source extends T
135
+ ? Source
136
+ : T extends Source
137
+ ? T
138
+ : T extends undefined
139
+ ? null
140
+ : T extends GenericSelector<infer S>
141
+ ? S
142
+ : T extends readonly (infer S)[] // NOTE: the infer S instead of Selector Source here, is to avoid infinite recursion
143
+ ? S extends SelectorSource
144
+ ? {
145
+ [key in keyof T]: SourceOf<A.Try<T[key], SelectorSource>>;
146
+ }
147
+ : never
148
+ : T extends { [key: string]: SelectorSource }
149
+ ? {
150
+ [key in keyof T]: SourceOf<A.Try<T[key], SelectorSource>>;
151
+ }
152
+ : never;
153
+
154
+ /**
155
+ * Use this type to convert types that accepts both Source and Selectors
156
+ *
157
+ * An example would be where literals are supported like in most higher order functions (e.g. map in array)
158
+ **/
159
+ export type SelectorOf<U extends SelectorSource> = Source extends U
160
+ ? GenericSelector<Source>
161
+ : SourceOf<U> extends infer S // we need this to avoid infinite recursion
162
+ ? S extends Source
163
+ ? Selector<S>
164
+ : GenericSelector<Source, "Could not determine selector of source">
165
+ : GenericSelector<Source, "Could not determine source">;
@@ -0,0 +1,4 @@
1
+ import { Selector as PrimitiveSelector } from "./primitive";
2
+
3
+ // TODO:
4
+ export type Selector<T extends number> = PrimitiveSelector<T>;
@@ -0,0 +1,22 @@
1
+ import {
2
+ Selector as UnknownSelector,
3
+ GenericSelector,
4
+ SelectorOf,
5
+ SelectorSource,
6
+ } from ".";
7
+ import { SourceObject } from "../../source";
8
+
9
+ // TODO: docs
10
+ export type Selector<T extends SourceObject> = GenericSelector<T> & {
11
+ fold<Tag extends string>(
12
+ key: Tag
13
+ ): <U extends SelectorSource>(cases: {
14
+ [key in T[Tag & keyof T] & string]: (v: UnknownSelector<T>) => U;
15
+ }) => SelectorOf<U>;
16
+
17
+ andThen<U extends SelectorSource>(
18
+ f: (v: UnknownSelector<NonNullable<T>>) => U
19
+ ): SelectorOf<U>;
20
+ } & {
21
+ readonly [key in keyof T]: UnknownSelector<T[key]>;
22
+ };
@@ -0,0 +1,17 @@
1
+ import {
2
+ Selector as UnknownSelector,
3
+ GenericSelector,
4
+ SelectorOf,
5
+ SelectorSource,
6
+ } from ".";
7
+ import { Source, SourcePrimitive } from "../../source";
8
+ import { Selector as BooleanSelector } from "./boolean";
9
+
10
+ export type Selector<T extends SourcePrimitive> = GenericSelector<T> & {
11
+ eq(other: Source): BooleanSelector<boolean>;
12
+ andThen<U extends SelectorSource>(
13
+ f: (v: UnknownSelector<NonNullable<T>>) => U
14
+ ): SelectorOf<U | NullableOf<T>>;
15
+ };
16
+
17
+ type NullableOf<T extends Source> = T extends null ? null : never;
@@ -1,5 +1,5 @@
1
1
  import { Selector as UnknownSelector } from ".";
2
- import { RemoteCompatibleSource } from "../source/remote";
2
+ import { RemoteCompatibleSource } from "../../source/future/remote";
3
3
 
4
4
  declare const brand: unique symbol;
5
5
 
@@ -1,16 +1,14 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { Selector, GenericSelector, SourceOrExpr, Path } from ".";
3
- import { string } from "../schema/string";
4
- import { array } from "../schema/array";
5
- import { SourcePath } from "../val";
6
- import { Source } from "../source";
7
- import { evaluate } from "../expr/eval";
8
- import * as expr from "../expr/expr";
9
- import { result } from "../fp";
10
- import { object } from "../schema/object";
3
+ import { string } from "../../schema/string";
4
+ import { array } from "../../schema/array";
5
+ import { SourcePath } from "../../val";
6
+ import { Source } from "../../source";
7
+ import { evaluate } from "../../expr/eval";
8
+ import { result } from "../../fp";
9
+ import { object } from "../../schema/object";
11
10
  import { newSelectorProxy, selectorToVal } from "./SelectorProxy";
12
- import { newExprSelectorProxy } from "./ExprProxy";
13
- import { remote, RemoteSource } from "../source/remote";
11
+ import { newExprSelectorProxy, root } from "./ExprProxy";
14
12
 
15
13
  const modules = {
16
14
  "/app/text": "text1",
@@ -26,17 +24,6 @@ const modules = {
26
24
  "/app/empty": "",
27
25
  "/app/large/nested": BFV(),
28
26
  };
29
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
30
- const remoteModules: {
31
- [key in keyof TestModules]: RemoteSource<TestModules[key]>;
32
- } = {
33
- "/app/text": remote("/app/text"),
34
- "/app/texts": remote("/app/texts"),
35
- "/app/blog": remote("/app/blog"),
36
- "/app/blogs": remote("/app/blogs"),
37
- "/app/empty": remote("/app/empty"),
38
- "/app/large/nested": remote("/app/large/nested"),
39
- };
40
27
 
41
28
  const SelectorModuleTestCases: {
42
29
  description: string;
@@ -440,10 +427,3 @@ function BFV() {
440
427
  },
441
428
  ];
442
429
  }
443
-
444
- function root(sourcePath: string) {
445
- return new expr.Call(
446
- [new expr.Sym("val"), new expr.StringLiteral(sourcePath)],
447
- false
448
- );
449
- }
@@ -1,6 +1,6 @@
1
1
  import { Selector } from ".";
2
2
  import { newSelectorProxy } from "./SelectorProxy";
3
- import { Source } from "../source";
3
+ import { Source } from "../../source";
4
4
 
5
5
  export function selectorOf<T extends Source>(t: T): Selector<T> {
6
6
  return newSelectorProxy(t);
@@ -0,0 +1,4 @@
1
+ import { Selector as PrimitiveSelector } from "./primitive";
2
+
3
+ // TODO: docs
4
+ export type Selector<T extends string> = PrimitiveSelector<T>;
@@ -1,5 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import { I18nSelector } from "./i18n";
3
1
  import { Selector as ObjectSelector } from "./object";
4
2
  import { UndistributedSourceArray as ArraySelector } from "./array";
5
3
  import { Selector as NumberSelector } from "./number";
@@ -10,43 +8,12 @@ import { FileSelector } from "./file";
10
8
  import { SourcePath } from "../val";
11
9
  import { Source, SourceArray, SourceObject, SourcePrimitive } from "../source";
12
10
  import { Schema } from "../schema";
13
- import { Expr } from "../expr/expr";
14
- import { RemoteSelector } from "./remote";
15
- import { A } from "ts-toolbelt";
16
- import { I18nSource, I18nCompatibleSource } from "../source/i18n";
17
- import { RemoteCompatibleSource, RemoteSource } from "../source/remote";
11
+ import type { A } from "ts-toolbelt";
18
12
  import { FileSource } from "../source/file";
19
13
  import { RichText, RichTextSource } from "../source/richtext";
20
14
 
21
- /**
22
- * Selectors can be used to select parts of a Val module.
23
- * Unlike queries, joins, aggregates etc is and will not be supported.
24
- *
25
- * They are designed to be be used as if they were "normal" JSON data,
26
- * though some concessions had to be made because of TypeScript limitations.
27
- *
28
- * Selectors works equally on source content, defined in code, and remote content.
29
- *
30
- * @example
31
- * // Select the title of a document
32
- * const titles = useVal(docsVal.map((doc) => doc.title));
33
- *
34
- * @example
35
- * // Match on a union type
36
- * const titles = useVal(docsVal.map((doc) => doc.fold("type")({
37
- * newsletter: (newsletter) => newsletter.title,
38
- * email: (email) => email.subject,
39
- * }));
40
- *
41
- */
42
15
  export type Selector<T extends Source> = Source extends T
43
16
  ? GenericSelector<T>
44
- : T extends I18nSource<infer L, infer S>
45
- ? I18nSelector<L, S>
46
- : T extends RemoteSource<infer S>
47
- ? S extends RemoteCompatibleSource
48
- ? RemoteSelector<S>
49
- : GenericSelector<Source, "Could not determine remote source">
50
17
  : T extends FileSource
51
18
  ? FileSelector
52
19
  : T extends RichTextSource
@@ -72,8 +39,6 @@ export type SelectorSource =
72
39
  | {
73
40
  [key: string]: SelectorSource;
74
41
  }
75
- | I18nSource<readonly string[], I18nCompatibleSource>
76
- | RemoteSource<RemoteCompatibleSource>
77
42
  | FileSource
78
43
  | RichTextSource
79
44
  | GenericSelector<Source>;
@@ -90,7 +55,7 @@ export const Path = Symbol("Path");
90
55
  /**
91
56
  * @internal
92
57
  */
93
- export const SourceOrExpr = Symbol("SourceOrExpr");
58
+ export const GetSource = Symbol("GetSource");
94
59
  /**
95
60
  * @internal
96
61
  */
@@ -100,7 +65,7 @@ export abstract class GenericSelector<
100
65
  Error extends string | undefined = undefined
101
66
  > {
102
67
  readonly [Path]: SourcePath | undefined;
103
- readonly [SourceOrExpr]: T | Expr;
68
+ readonly [GetSource]: T;
104
69
  readonly [ValError]: Error | undefined;
105
70
  readonly [GetSchema]: Schema<T> | undefined;
106
71
  constructor(
@@ -110,17 +75,10 @@ export abstract class GenericSelector<
110
75
  error?: Error
111
76
  ) {
112
77
  this[Path] = path;
113
- this[SourceOrExpr] = valOrExpr;
78
+ this[GetSource] = valOrExpr;
114
79
  this[ValError] = error;
115
80
  this[GetSchema] = schema;
116
81
  }
117
-
118
- assert<U extends Source, E extends Source = null>(
119
- schema: Schema<U>,
120
- other?: () => E
121
- ): SelectorOf<U | E> {
122
- throw new Error("Not implemented");
123
- }
124
82
  }
125
83
 
126
84
  export type SourceOf<T extends SelectorSource> = Source extends T