@valbuild/core 0.26.0 → 0.27.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 (92) hide show
  1. package/package.json +12 -3
  2. package/CHANGELOG.md +0 -0
  3. package/ROADMAP.md +0 -106
  4. package/jest.config.js +0 -4
  5. package/src/Json.ts +0 -4
  6. package/src/ValApi.ts +0 -81
  7. package/src/expr/README.md +0 -193
  8. package/src/expr/eval.test.ts +0 -198
  9. package/src/expr/eval.ts +0 -251
  10. package/src/expr/expr.ts +0 -91
  11. package/src/expr/index.ts +0 -3
  12. package/src/expr/parser.test.ts +0 -158
  13. package/src/expr/parser.ts +0 -229
  14. package/src/expr/repl.ts +0 -88
  15. package/src/expr/tokenizer.test.ts +0 -539
  16. package/src/expr/tokenizer.ts +0 -117
  17. package/src/fp/array.ts +0 -30
  18. package/src/fp/index.ts +0 -3
  19. package/src/fp/result.ts +0 -214
  20. package/src/fp/util.ts +0 -52
  21. package/src/future/fetchVal.test.ts +0 -164
  22. package/src/future/fetchVal.ts +0 -206
  23. package/src/getSha256.ts +0 -8
  24. package/src/index.ts +0 -132
  25. package/src/initSchema.ts +0 -50
  26. package/src/initVal.ts +0 -73
  27. package/src/module.test.ts +0 -170
  28. package/src/module.ts +0 -397
  29. package/src/patch/deref.test.ts +0 -298
  30. package/src/patch/deref.ts +0 -136
  31. package/src/patch/index.ts +0 -12
  32. package/src/patch/json.test.ts +0 -582
  33. package/src/patch/json.ts +0 -304
  34. package/src/patch/operation.ts +0 -86
  35. package/src/patch/ops.ts +0 -83
  36. package/src/patch/parse.test.ts +0 -202
  37. package/src/patch/parse.ts +0 -202
  38. package/src/patch/patch.ts +0 -49
  39. package/src/patch/util.ts +0 -74
  40. package/src/schema/array.ts +0 -93
  41. package/src/schema/boolean.ts +0 -49
  42. package/src/schema/future/i18n.ts +0 -69
  43. package/src/schema/future/oneOf.ts +0 -63
  44. package/src/schema/image.ts +0 -137
  45. package/src/schema/index.ts +0 -70
  46. package/src/schema/keyOf.ts +0 -167
  47. package/src/schema/literal.ts +0 -63
  48. package/src/schema/number.ts +0 -56
  49. package/src/schema/object.ts +0 -110
  50. package/src/schema/record.ts +0 -103
  51. package/src/schema/richtext.ts +0 -44
  52. package/src/schema/string.ts +0 -95
  53. package/src/schema/union.ts +0 -63
  54. package/src/schema/validation/ValidationError.ts +0 -16
  55. package/src/schema/validation/ValidationFix.ts +0 -6
  56. package/src/schema/validation.test.ts +0 -291
  57. package/src/selector/SelectorProxy.ts +0 -238
  58. package/src/selector/array.ts +0 -13
  59. package/src/selector/boolean.ts +0 -4
  60. package/src/selector/file.ts +0 -6
  61. package/src/selector/future/ExprProxy.test.ts +0 -203
  62. package/src/selector/future/ExprProxy.ts +0 -216
  63. package/src/selector/future/SelectorProxy.test.ts +0 -172
  64. package/src/selector/future/SelectorProxy.ts +0 -238
  65. package/src/selector/future/array.ts +0 -37
  66. package/src/selector/future/boolean.ts +0 -4
  67. package/src/selector/future/file.ts +0 -14
  68. package/src/selector/future/i18n.ts +0 -13
  69. package/src/selector/future/index.ts +0 -169
  70. package/src/selector/future/number.ts +0 -4
  71. package/src/selector/future/object.ts +0 -22
  72. package/src/selector/future/primitive.ts +0 -17
  73. package/src/selector/future/remote.ts +0 -9
  74. package/src/selector/future/selector.test.ts +0 -429
  75. package/src/selector/future/selectorOf.ts +0 -7
  76. package/src/selector/future/string.ts +0 -4
  77. package/src/selector/index.ts +0 -121
  78. package/src/selector/number.ts +0 -4
  79. package/src/selector/object.ts +0 -5
  80. package/src/selector/primitive.ts +0 -4
  81. package/src/selector/string.ts +0 -4
  82. package/src/source/file.ts +0 -45
  83. package/src/source/future/i18n.ts +0 -60
  84. package/src/source/future/remote.ts +0 -54
  85. package/src/source/index.ts +0 -53
  86. package/src/source/link.ts +0 -14
  87. package/src/source/richtext.ts +0 -178
  88. package/src/val/array.ts +0 -10
  89. package/src/val/index.ts +0 -100
  90. package/src/val/object.ts +0 -13
  91. package/src/val/primitive.ts +0 -8
  92. package/tsconfig.json +0 -8
@@ -1,9 +0,0 @@
1
- import { Selector as UnknownSelector } from ".";
2
- import { RemoteCompatibleSource } from "../../source/future/remote";
3
-
4
- declare const brand: unique symbol;
5
-
6
- export type RemoteSelector<T extends RemoteCompatibleSource> =
7
- UnknownSelector<T> & {
8
- readonly [brand]: "RemoteSelector";
9
- };
@@ -1,429 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
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 { result } from "../../fp";
9
- import { object } from "../../schema/object";
10
- import { newSelectorProxy, selectorToVal } from "./SelectorProxy";
11
- import { newExprSelectorProxy, root } from "./ExprProxy";
12
-
13
- const modules = {
14
- "/app/text": "text1",
15
- "/app/texts": ["text1", "text2"] as string[],
16
- "/app/blog": { title: "blog1", text: "text1" } as {
17
- title: string | null;
18
- text: string;
19
- },
20
- "/app/blogs": [
21
- { title: "blog1", text: "text1" },
22
- { title: undefined, text: "text2" },
23
- ] as { title: string | null; text: string }[],
24
- "/app/empty": "",
25
- "/app/large/nested": BFV(),
26
- };
27
-
28
- const SelectorModuleTestCases: {
29
- description: string;
30
- input: (remote: boolean) => GenericSelector<Source>;
31
- expected: Expected;
32
- }[] = [
33
- {
34
- description: "string module lookup",
35
- input: (remote) => testModule("/app/text", remote),
36
- expected: {
37
- val: "text1",
38
- [Path]: "/app/text",
39
- },
40
- },
41
- {
42
- description: "basic eq",
43
- input: (remote) => testModule("/app/text", remote).eq("text1"),
44
- expected: {
45
- val: true,
46
- [Path]: undefined,
47
- },
48
- },
49
- {
50
- description: "andThen noop",
51
- input: (remote) => testModule("/app/text", remote).andThen((v) => v),
52
- expected: {
53
- val: "text1",
54
- [Path]: "/app/text",
55
- },
56
- },
57
- {
58
- description: "array module lookup",
59
- input: (remote) => testModule("/app/texts", remote),
60
- expected: {
61
- val: ["text1", "text2"],
62
- [Path]: "/app/texts",
63
- },
64
- },
65
- {
66
- description: "string andThen eq",
67
- input: (remote) =>
68
- testModule("/app/text", remote).andThen((v) => v.eq("text1")),
69
- expected: {
70
- val: true,
71
- [Path]: undefined,
72
- },
73
- },
74
- {
75
- description: "empty string andThen eq",
76
- input: (remote) =>
77
- testModule("/app/empty", remote).andThen((v) => v.eq("text1")),
78
- expected: {
79
- val: "",
80
- [Path]: "/app/empty",
81
- },
82
- },
83
- {
84
- description: "andThen literal eq",
85
- input: (remote) =>
86
- testModule("/app/text", remote)
87
- .andThen(() => "foo")
88
- .eq("foo"),
89
- expected: {
90
- val: true,
91
- [Path]: undefined,
92
- },
93
- },
94
- {
95
- description: "andThen undefined literal eq",
96
- input: (remote) =>
97
- testModule("/app/text", remote)
98
- .andThen(() => undefined)
99
- .eq("foo"),
100
- expected: {
101
- val: false,
102
- [Path]: undefined,
103
- },
104
- },
105
- {
106
- description: "empty andThen literal eq",
107
- input: (remote) =>
108
- testModule("/app/empty", remote)
109
- .andThen(() => "foo")
110
- .eq("foo"),
111
- expected: {
112
- val: false,
113
- [Path]: undefined,
114
- },
115
- },
116
- {
117
- description: "string andThen array literal and index",
118
- input: (remote) =>
119
- testModule("/app/text", remote).andThen((v) => [v, "text2"])[0],
120
- expected: { val: "text1", [Path]: "/app/text" },
121
- },
122
- {
123
- description: "string map undefined -> null literal conversion",
124
- input: (remote) =>
125
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
126
- testModule("/app/blogs", remote).map((v) => ({ title: undefined })),
127
- expected: {
128
- val: [{ title: null }, { title: null }],
129
- [Path]: "/app/blogs",
130
- },
131
- },
132
- {
133
- description: "array map noop",
134
- input: (remote) => testModule("/app/texts", remote).map((v) => v),
135
- expected: { val: ["text1", "text2"], [Path]: "/app/texts" },
136
- },
137
- {
138
- description: "array map projection with undefined",
139
- input: (remote) =>
140
- testModule("/app/blogs", remote).map((v) => ({
141
- otherTitle: v.title,
142
- other: undefined,
143
- })),
144
- expected: {
145
- val: [
146
- { otherTitle: "blog1", other: null },
147
- { otherTitle: null, other: null },
148
- ],
149
- [Path]: "/app/blogs",
150
- },
151
- },
152
- {
153
- description: "array index with eq",
154
- input: (remote) => testModule("/app/texts", remote)[0].eq("text1"),
155
- expected: { val: true, [Path]: undefined },
156
- },
157
- {
158
- description: "object module lookup",
159
- input: (remote) => testModule("/app/blog", remote),
160
- expected: { val: { text: "text1", title: "blog1" }, [Path]: "/app/blog" },
161
- },
162
- {
163
- description: "object andThen property lookup",
164
- input: (remote) => testModule("/app/blog", remote).andThen((v) => v.title),
165
- expected: { val: "blog1", [Path]: '/app/blog."title"' },
166
- },
167
- {
168
- description: "array object manipulation: basic indexed obj",
169
- input: (remote) =>
170
- testModule("/app/blogs", remote)
171
- .map((v) => v)[0]
172
- .title.eq("blog1"),
173
- expected: {
174
- val: true,
175
- [Path]: undefined,
176
- },
177
- },
178
- {
179
- description: "array object manipulation: filter",
180
- input: (remote) =>
181
- testModule("/app/blogs", remote).filter((v) => v.title.eq("blog1")),
182
- expected: {
183
- val: [{ text: "text1", title: "blog1" }],
184
- [Path]: "/app/blogs",
185
- },
186
- },
187
- {
188
- description: "array object manipulation: map with tuple literal",
189
- input: (remote) =>
190
- testModule("/app/blogs", remote).map((a) => [1, a.title]),
191
- expected: {
192
- val: [
193
- [1, "blog1"],
194
- [1, null],
195
- ],
196
- [Path]: "/app/blogs",
197
- },
198
- },
199
- // TODO: tuple literal was reverted
200
- // {
201
- // description: "array object manipulation: map with tuple literal",
202
- // input: (remote) =>
203
- // testModule("/app/blogs", remote).map((a) => [1, a])[0][1].title,
204
- // expected: {
205
- // val: "blog1",
206
- // [Path]: "/app/blogs.0.title",
207
- // },
208
- // },
209
- {
210
- description: "array object manipulation: with literals",
211
- input: (remote) =>
212
- testModule("/app/blogs", remote)
213
- .map((v) => ({
214
- title: {
215
- foo: "string",
216
- },
217
- subTitle: { bar: v.title },
218
- }))[0]
219
- .title.foo.eq("string"),
220
- expected: { val: true, [Path]: undefined },
221
- },
222
- {
223
- description: "array object manipulation: with literals",
224
- input: (remote) =>
225
- testModule("/app/blogs", remote)
226
- .map((v) => [v.title, v.title])[0][0]
227
- .eq("blog1"),
228
- expected: { val: true, [Path]: undefined },
229
- },
230
- {
231
- description: "array object manipulation: with large nested objects",
232
- input: (remote) =>
233
- testModule("/app/large/nested", remote).map((v) => ({
234
- title: {
235
- foo: "string",
236
- },
237
- subTitle: { bar: v },
238
- }))[0].subTitle.bar.that.even.more.even[0].more.even.more.even.more,
239
- expected: {
240
- val: "that.even.more.even.more",
241
- [Path]:
242
- '/app/large/nested.0."that"."even"."more"."even".0."more"."even"."more"."even"."more"',
243
- },
244
- },
245
- ];
246
-
247
- const RemoteAndLocaleSelectorModuleTestCases = SelectorModuleTestCases.flatMap(
248
- (testCase) => [
249
- {
250
- input: () => testCase.input(false),
251
- description: `local ${testCase.description}`,
252
- expected: testCase.expected,
253
- remote: false,
254
- },
255
- {
256
- input: () => testCase.input(true),
257
- description: `remote ${testCase.description}`,
258
- expected: testCase.expected,
259
- remote: true,
260
- },
261
- ]
262
- );
263
-
264
- describe("selector", () => {
265
- test.each(RemoteAndLocaleSelectorModuleTestCases)(
266
- "$description",
267
- ({ input, expected, remote }) => {
268
- if (input instanceof Error) {
269
- throw input;
270
- }
271
- // TODO: ideally we should be able to evaluate remote and local
272
- if (!remote) {
273
- const localeRes = input();
274
- expect(selectorToVal(localeRes)).toStrictEqual(expected);
275
- } else {
276
- const res = evaluate(
277
- // @ts-expect-error TODO: fix this
278
- input()[SourceOrExpr],
279
- (path) => modules[path as keyof typeof modules],
280
- []
281
- );
282
- if (result.isErr(res)) {
283
- throw res.error;
284
- }
285
- expect(selectorToVal(res.value)).toStrictEqual(
286
- // NOTE: all expected values for REMOTE should be changed to return Vals
287
- expected
288
- );
289
- }
290
- }
291
- );
292
- });
293
-
294
- type TestModules = typeof modules;
295
-
296
- type Expected = any; // TODO: should be Val | Expr
297
-
298
- function testModule<P extends keyof TestModules>(
299
- sourcePath: P,
300
- remote: boolean
301
- ): Selector<TestModules[P]> {
302
- try {
303
- if (remote) {
304
- return newExprSelectorProxy(
305
- root(sourcePath as SourcePath)
306
- ) as unknown as Selector<TestModules[P]>;
307
- }
308
- return newSelectorProxy(modules[sourcePath], sourcePath as SourcePath);
309
- } catch (e) {
310
- // avoid failing all test suite failure on test case creation, instead returns error and throws it inside the test
311
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
312
- return e as any;
313
- }
314
- }
315
-
316
- /** A big schema */
317
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
318
- function BFS() {
319
- return array(
320
- object({
321
- title: object({
322
- foo: object({
323
- inner: array(
324
- object({
325
- innerInnerTitle: object({
326
- even: object({
327
- more: string(),
328
- }),
329
- }),
330
- })
331
- ),
332
- }),
333
- }),
334
- bar: string(),
335
- many: array(string()),
336
- props: string(),
337
- are: string(),
338
- here: object({
339
- even: object({
340
- more: string(),
341
- }),
342
- }),
343
- for: string(),
344
- testing: string(),
345
- purposes: string(),
346
- and: string(),
347
- to: string(),
348
- make: string(),
349
- sure: string(),
350
- that: object({
351
- even: object({
352
- more: object({
353
- even: array(
354
- object({
355
- more: object({
356
- even: object({
357
- more: object({
358
- even: object({
359
- more: string(),
360
- }),
361
- }),
362
- }),
363
- }),
364
- })
365
- ),
366
- }),
367
- }),
368
- }),
369
- the: string(),
370
- type: string(),
371
- system: string(),
372
- works: string(),
373
- as: string(),
374
- expected: string(),
375
- })
376
- );
377
- }
378
-
379
- /** A big value */
380
- function BFV() {
381
- return [
382
- {
383
- title: {
384
- foo: {
385
- inner: [
386
- {
387
- innerInnerTitle: {
388
- even: { more: "inner.innerInnerTitle.even.more" },
389
- },
390
- },
391
- ],
392
- },
393
- },
394
- bar: "bar",
395
- many: ["many1", "many2", "many3"],
396
- props: "props",
397
- are: "are",
398
- here: { even: { more: "here.even.more" } },
399
- for: "for",
400
- testing: "testing",
401
- purposes: "purposes",
402
- and: "and",
403
- to: "to",
404
- make: "make",
405
- sure: "sure",
406
- that: {
407
- even: {
408
- more: {
409
- even: [
410
- {
411
- more: {
412
- even: {
413
- more: { even: { more: "that.even.more.even.more" } },
414
- },
415
- },
416
- },
417
- ],
418
- },
419
- },
420
- },
421
- the: "the",
422
- type: "type",
423
- system: "system",
424
- works: "works",
425
- as: "as",
426
- expected: "expected",
427
- },
428
- ];
429
- }
@@ -1,7 +0,0 @@
1
- import { Selector } from ".";
2
- import { newSelectorProxy } from "./SelectorProxy";
3
- import { Source } from "../../source";
4
-
5
- export function selectorOf<T extends Source>(t: T): Selector<T> {
6
- return newSelectorProxy(t);
7
- }
@@ -1,4 +0,0 @@
1
- import { Selector as PrimitiveSelector } from "./primitive";
2
-
3
- // TODO: docs
4
- export type Selector<T extends string> = PrimitiveSelector<T>;
@@ -1,121 +0,0 @@
1
- import { Selector as ObjectSelector } from "./object";
2
- import { UndistributedSourceArray as ArraySelector } from "./array";
3
- import { Selector as NumberSelector } from "./number";
4
- import { Selector as StringSelector } from "./string";
5
- import { Selector as BooleanSelector } from "./boolean";
6
- import { Selector as PrimitiveSelector } from "./primitive";
7
- import { FileSelector } from "./file";
8
- import { SourcePath } from "../val";
9
- import { Source, SourceArray, SourceObject, SourcePrimitive } from "../source";
10
- import { Schema } from "../schema";
11
- import type { A } from "ts-toolbelt";
12
- import { FileSource } from "../source/file";
13
- import { RichText, RichTextOptions, RichTextSource } from "../source/richtext";
14
-
15
- export type Selector<T extends Source> = Source extends T
16
- ? GenericSelector<T>
17
- : T extends FileSource
18
- ? FileSelector
19
- : T extends RichTextSource<infer O>
20
- ? RichText<O>
21
- : T extends SourceObject
22
- ? ObjectSelector<T>
23
- : T extends SourceArray
24
- ? ArraySelector<T>
25
- : T extends string
26
- ? StringSelector<T>
27
- : T extends number
28
- ? NumberSelector<T>
29
- : T extends boolean
30
- ? BooleanSelector<T>
31
- : T extends null
32
- ? PrimitiveSelector<null>
33
- : never;
34
-
35
- export type SelectorSource =
36
- | SourcePrimitive
37
- | undefined
38
- | readonly SelectorSource[]
39
- | {
40
- [key: string]: SelectorSource;
41
- }
42
- | FileSource
43
- | RichTextSource<RichTextOptions>
44
- | GenericSelector<Source>;
45
-
46
- /**
47
- * @internal
48
- */
49
- export const GetSchema = Symbol("GetSchema");
50
- /**
51
- /**
52
- * @internal
53
- */
54
- export const Path = Symbol("Path");
55
- /**
56
- * @internal
57
- */
58
- export const GetSource = Symbol("GetSource");
59
- /**
60
- * @internal
61
- */
62
- export const ValError = Symbol("ValError");
63
- export abstract class GenericSelector<
64
- out T extends Source,
65
- Error extends string | undefined = undefined
66
- > {
67
- readonly [Path]: SourcePath | undefined;
68
- readonly [GetSource]: T;
69
- readonly [ValError]: Error | undefined;
70
- readonly [GetSchema]: Schema<T> | undefined;
71
- constructor(
72
- valOrExpr: T,
73
- path: SourcePath | undefined,
74
- schema?: Schema<T>,
75
- error?: Error
76
- ) {
77
- this[Path] = path;
78
- this[GetSource] = valOrExpr;
79
- this[ValError] = error;
80
- this[GetSchema] = schema;
81
- }
82
- }
83
-
84
- export type SourceOf<T extends SelectorSource> = Source extends T
85
- ? Source
86
- : T extends Source
87
- ? T
88
- : T extends undefined
89
- ? null
90
- : T extends GenericSelector<infer S>
91
- ? S
92
- : T extends readonly (infer S)[] // NOTE: the infer S instead of Selector Source here, is to avoid infinite recursion
93
- ? S extends SelectorSource
94
- ? {
95
- [key in keyof T]: SourceOf<A.Try<T[key], SelectorSource>>;
96
- }
97
- : never
98
- : T extends { [key: string]: SelectorSource }
99
- ? {
100
- [key in keyof T]: SourceOf<A.Try<T[key], SelectorSource>>;
101
- }
102
- : never;
103
-
104
- /**
105
- * Use this type to convert types that accepts both Source and Selectors
106
- *
107
- * An example would be where literals are supported like in most higher order functions (e.g. map in array)
108
- **/
109
- export type SelectorOf<U extends SelectorSource> = Source extends U
110
- ? GenericSelector<Source>
111
- : SourceOf<U> extends infer S // we need this to avoid infinite recursion
112
- ? S extends Source
113
- ? Selector<S>
114
- : GenericSelector<Source, "Could not determine selector of source">
115
- : GenericSelector<Source, "Could not determine source">;
116
-
117
- export function getSchema(
118
- selector: Selector<Source>
119
- ): Schema<SelectorSource> | undefined {
120
- return selector[GetSchema];
121
- }
@@ -1,4 +0,0 @@
1
- import { Selector as PrimitiveSelector } from "./primitive";
2
-
3
- // TODO:
4
- export type Selector<T extends number> = PrimitiveSelector<T>;
@@ -1,5 +0,0 @@
1
- import { GenericSelector } from "./index";
2
- import { SourceObject } from "../source";
3
-
4
- // TODO: docs
5
- export type Selector<T extends SourceObject> = GenericSelector<T>;
@@ -1,4 +0,0 @@
1
- import { GenericSelector } from "./index";
2
- import { SourcePrimitive } from "../source";
3
-
4
- export type Selector<T extends SourcePrimitive> = GenericSelector<T>;
@@ -1,4 +0,0 @@
1
- import { Selector as PrimitiveSelector } from "./primitive";
2
-
3
- // TODO: docs
4
- export type Selector<T extends string> = PrimitiveSelector<T>;
@@ -1,45 +0,0 @@
1
- import { VAL_EXTENSION } from ".";
2
- import { JsonPrimitive } from "../Json";
3
-
4
- export const FILE_REF_PROP = "_ref" as const;
5
-
6
- /**
7
- * A file source represents the path to a (local) file.
8
- *
9
- * It will be resolved into a Asset object.
10
- *
11
- */
12
- export type FileSource<
13
- Metadata extends { readonly [key: string]: JsonPrimitive } | undefined =
14
- | { readonly [key: string]: JsonPrimitive }
15
- | undefined
16
- > = {
17
- readonly [FILE_REF_PROP]: string;
18
- readonly [VAL_EXTENSION]: "file";
19
- readonly metadata?: Metadata;
20
- };
21
-
22
- export function file<
23
- Metadata extends { readonly [key: string]: JsonPrimitive }
24
- >(ref: string, metadata: Metadata): FileSource<Metadata>;
25
- export function file(ref: string, metadata?: undefined): FileSource<undefined>;
26
- export function file<
27
- Metadata extends { readonly [key: string]: JsonPrimitive } | undefined
28
- >(ref: string, metadata?: Metadata): FileSource<Metadata> {
29
- return {
30
- [FILE_REF_PROP]: ref,
31
- [VAL_EXTENSION]: "file",
32
- metadata,
33
- } as FileSource<Metadata>;
34
- }
35
-
36
- export function isFile(obj: unknown): obj is FileSource {
37
- return (
38
- typeof obj === "object" &&
39
- obj !== null &&
40
- VAL_EXTENSION in obj &&
41
- obj[VAL_EXTENSION] === "file" &&
42
- FILE_REF_PROP in obj &&
43
- typeof obj[FILE_REF_PROP] === "string"
44
- );
45
- }
@@ -1,60 +0,0 @@
1
- import type { F } from "ts-toolbelt";
2
- import { SourcePrimitive, VAL_EXTENSION } from "..";
3
- import { FileSource } from "../file";
4
-
5
- /**
6
- * I18n sources cannot have nested remote sources.
7
- */
8
- export type I18nCompatibleSource =
9
- | SourcePrimitive
10
- | I18nObject
11
- | I18nArray
12
- | FileSource;
13
- export type I18nObject = { [key in string]: I18nCompatibleSource };
14
- export type I18nArray = readonly I18nCompatibleSource[];
15
-
16
- /**
17
- * An i18n source is a map of locales to sources.
18
- *
19
- * Its selector will default to the underlying source. It is possible to call `.all` on i18n sources, which returns an object with all the locales
20
- *
21
- */
22
- export type I18nSource<
23
- Locales extends readonly string[],
24
- T extends I18nCompatibleSource
25
- > = {
26
- readonly [locale in Locales[number]]: T;
27
- } & {
28
- readonly [VAL_EXTENSION]: "i18n";
29
- };
30
-
31
- export type I18n<Locales extends readonly string[]> = <
32
- Src extends I18nCompatibleSource
33
- >(source: {
34
- [locale in Locales[number]]: Src;
35
- }) => I18nSource<Locales, Src>;
36
- export function i18n<Locales extends readonly string[]>(
37
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
38
- locales: F.Narrow<Locales>
39
- ): <Src extends I18nCompatibleSource>(source: {
40
- [locale in Locales[number]]: Src;
41
- }) => I18nSource<Locales, Src> {
42
- return (source) => {
43
- return {
44
- ...source,
45
- [VAL_EXTENSION]: "i18n",
46
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
- } as I18nSource<Locales, any>;
48
- };
49
- }
50
-
51
- export function isI18n(
52
- obj: unknown
53
- ): obj is I18nSource<string[], I18nCompatibleSource> {
54
- return (
55
- typeof obj === "object" &&
56
- obj !== null &&
57
- VAL_EXTENSION in obj &&
58
- obj[VAL_EXTENSION] === "i18n"
59
- );
60
- }