@valbuild/core 0.12.0 → 0.13.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/README.md +25 -37
- package/jest.config.js +4 -0
- package/package.json +1 -1
- package/src/Json.ts +4 -0
- package/src/expr/README.md +193 -0
- package/src/expr/eval.test.ts +202 -0
- package/src/expr/eval.ts +248 -0
- package/src/expr/expr.ts +91 -0
- package/src/expr/index.ts +3 -0
- package/src/expr/parser.test.ts +158 -0
- package/src/expr/parser.ts +229 -0
- package/src/expr/repl.ts +93 -0
- package/src/expr/tokenizer.test.ts +539 -0
- package/src/expr/tokenizer.ts +117 -0
- package/src/fetchVal.test.ts +164 -0
- package/src/fetchVal.ts +211 -0
- package/src/fp/array.ts +30 -0
- package/src/fp/index.ts +3 -0
- package/src/fp/result.ts +214 -0
- package/src/fp/util.ts +52 -0
- package/src/index.ts +55 -0
- package/src/initSchema.ts +45 -0
- package/src/initVal.ts +96 -0
- package/src/module.test.ts +170 -0
- package/src/module.ts +333 -0
- package/src/patch/deref.test.ts +300 -0
- package/src/patch/deref.ts +128 -0
- package/src/patch/index.ts +11 -0
- package/src/patch/json.test.ts +583 -0
- package/src/patch/json.ts +304 -0
- package/src/patch/operation.ts +74 -0
- package/src/patch/ops.ts +83 -0
- package/src/patch/parse.test.ts +202 -0
- package/src/patch/parse.ts +187 -0
- package/src/patch/patch.ts +46 -0
- package/src/patch/util.ts +67 -0
- package/src/schema/array.ts +52 -0
- package/src/schema/boolean.ts +38 -0
- package/src/schema/i18n.ts +65 -0
- package/src/schema/image.ts +70 -0
- package/src/schema/index.ts +46 -0
- package/src/schema/literal.ts +42 -0
- package/src/schema/number.ts +45 -0
- package/src/schema/object.ts +67 -0
- package/src/schema/oneOf.ts +60 -0
- package/src/schema/richtext.ts +417 -0
- package/src/schema/string.ts +49 -0
- package/src/schema/union.ts +62 -0
- package/src/selector/ExprProxy.test.ts +203 -0
- package/src/selector/ExprProxy.ts +209 -0
- package/src/selector/SelectorProxy.test.ts +172 -0
- package/src/selector/SelectorProxy.ts +237 -0
- package/src/selector/array.ts +37 -0
- package/src/selector/boolean.ts +4 -0
- package/src/selector/file.ts +14 -0
- package/src/selector/i18n.ts +13 -0
- package/src/selector/index.ts +159 -0
- package/src/selector/number.ts +4 -0
- package/src/selector/object.ts +22 -0
- package/src/selector/primitive.ts +17 -0
- package/src/selector/remote.ts +9 -0
- package/src/selector/selector.test.ts +453 -0
- package/src/selector/selectorOf.ts +7 -0
- package/src/selector/string.ts +4 -0
- package/src/source/file.ts +45 -0
- package/src/source/i18n.ts +60 -0
- package/src/source/index.ts +50 -0
- package/src/source/remote.ts +54 -0
- package/src/val/array.ts +10 -0
- package/src/val/index.ts +90 -0
- package/src/val/object.ts +13 -0
- package/src/val/primitive.ts +8 -0
package/README.md
CHANGED
@@ -54,14 +54,15 @@ Val is built on top of TypeScript and Git, letting you use types, branches, vers
|
|
54
54
|
|
55
55
|
## Installation
|
56
56
|
|
57
|
-
- Make sure you have TypeScript 4.9+, Next
|
57
|
+
- Make sure you have TypeScript 4.9+, Next 12+ (other meta frameworks will come), React 18+ (other frontend frameworks will come)
|
58
|
+
- **NOTE**: THIS GUIDE is using the Next `/pages` directory NOT the new `/app` directory!
|
58
59
|
- Install the packages:
|
59
60
|
|
60
61
|
```sh
|
61
62
|
npm install @valbuild/core @valbuild/react @valbuild/server
|
62
63
|
```
|
63
64
|
|
64
|
-
- Create your val.config.ts file:
|
65
|
+
- Create your val.config.ts file. NOTE: this file should be in the same directory as `tsconfig.json`:
|
65
66
|
|
66
67
|
```ts
|
67
68
|
// ./val.config.ts
|
@@ -83,7 +84,6 @@ export { s, val };
|
|
83
84
|
///...
|
84
85
|
"strict": true,
|
85
86
|
///...
|
86
|
-
"jsx": "react-jsx",
|
87
87
|
"jsxImportSource": "@valbuild/react"
|
88
88
|
//...
|
89
89
|
}
|
@@ -94,7 +94,7 @@ export { s, val };
|
|
94
94
|
- Enable contextual editing: setup Val endpoints
|
95
95
|
|
96
96
|
```ts
|
97
|
-
// ./pages/api/val/[...val].ts
|
97
|
+
// ./src/pages/api/val/[...val].ts
|
98
98
|
|
99
99
|
import { createRequestListener } from "@valbuild/server";
|
100
100
|
import { NextApiHandler } from "next";
|
@@ -113,32 +113,23 @@ export const config = {
|
|
113
113
|
};
|
114
114
|
```
|
115
115
|
|
116
|
-
- Enable contextual editing: Use the Val provider in
|
116
|
+
- Enable contextual editing: Use the Val provider in the \_app file:
|
117
117
|
|
118
118
|
```tsx
|
119
|
-
// ./
|
119
|
+
// ./src/pages/_app.tsx
|
120
120
|
|
121
121
|
import { ValProvider } from "@valbuild/react";
|
122
|
-
import "
|
122
|
+
import type { AppProps } from "next/app";
|
123
123
|
|
124
|
-
|
125
|
-
children,
|
126
|
-
}: {
|
127
|
-
children: React.ReactNode;
|
128
|
-
}) {
|
124
|
+
function MyApp({ Component, pageProps }: AppProps) {
|
129
125
|
return (
|
130
|
-
<
|
131
|
-
{
|
132
|
-
|
133
|
-
head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
|
134
|
-
*/}
|
135
|
-
<head />
|
136
|
-
<body>
|
137
|
-
<ValProvider host="/api/val">{children}</ValProvider>
|
138
|
-
</body>
|
139
|
-
</html>
|
126
|
+
<ValProvider host="/api/val">
|
127
|
+
<Component {...pageProps} />
|
128
|
+
</ValProvider>
|
140
129
|
);
|
141
130
|
}
|
131
|
+
|
132
|
+
export default MyApp;
|
142
133
|
```
|
143
134
|
|
144
135
|
## Getting started
|
@@ -150,12 +141,12 @@ Content defined in Val is always defined `.val.{ts|js}` files.
|
|
150
141
|
They must export a default `val.content` where the first argument equals the path of the file relative to the `val.config.{js|ts}` file.
|
151
142
|
|
152
143
|
```ts
|
153
|
-
// ./
|
144
|
+
// ./src/content/example/blogs.val.ts
|
154
145
|
|
155
|
-
import { s, val } from "
|
146
|
+
import { s, val } from "../../../val.config";
|
156
147
|
|
157
148
|
export default val.content(
|
158
|
-
"/
|
149
|
+
"/src/content/example/blogs", // <- NOTE: this must be the same path as the file
|
159
150
|
s.array(s.object({ title: s.string(), text: s.string() })),
|
160
151
|
[
|
161
152
|
{
|
@@ -173,30 +164,27 @@ export default val.content(
|
|
173
164
|
### Use your content
|
174
165
|
|
175
166
|
```tsx
|
176
|
-
// /
|
167
|
+
// ./src/pages/example/index.tsx
|
177
168
|
|
178
169
|
import { NextPage } from "next";
|
179
170
|
import { useVal } from "@valbuild/react";
|
180
|
-
import blogsVal from "
|
181
|
-
import { val } from "val.config";
|
171
|
+
import blogsVal from "@/content/example/blogs.val";
|
182
172
|
|
183
|
-
const
|
184
|
-
const
|
173
|
+
const Blog: NextPage = () => {
|
174
|
+
const blog = useVal(blogsVal[0]);
|
185
175
|
return (
|
186
176
|
<main>
|
187
177
|
<article>
|
188
|
-
|
189
|
-
<
|
190
|
-
|
191
|
-
|
192
|
-
</section>
|
193
|
-
))}
|
178
|
+
<section>
|
179
|
+
<h1>{blog.title}</h1>
|
180
|
+
<p>{blog.text}</p>
|
181
|
+
</section>
|
194
182
|
</article>
|
195
183
|
</main>
|
196
184
|
);
|
197
185
|
};
|
198
186
|
|
199
|
-
export default
|
187
|
+
export default Blog;
|
200
188
|
```
|
201
189
|
|
202
190
|
## Concepts
|
package/jest.config.js
ADDED
package/package.json
CHANGED
package/src/Json.ts
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# Visp
|
2
|
+
|
3
|
+
Visp (as in Val Lisp or whisk in Norwegian) is a Lisp used to serialize Val `Selector`s.
|
4
|
+
|
5
|
+
It is an INTERNAL language - it is NOT designed to be used by end-users.
|
6
|
+
This document is architectural overview for this INTERNAL language - it is documentation for developers working on Val.
|
7
|
+
|
8
|
+
Visp exists since Val clients must be able to execute remote `Selector`s.
|
9
|
+
See the docs for remote `Schema`s for more about this.
|
10
|
+
|
11
|
+
The design goals are as follows:
|
12
|
+
|
13
|
+
- evaluate to `Val` objects
|
14
|
+
- easy to parse and serialize
|
15
|
+
- easy to evaluate in JavaScript
|
16
|
+
- readable by Vals developers (for internal debugging)
|
17
|
+
- stable language semantics to avoid breaking changes as Visp is part of the (internal) API versioning
|
18
|
+
- does not support more functionality than what is required to serialize `Selector`s
|
19
|
+
|
20
|
+
The non-goals are:
|
21
|
+
|
22
|
+
- Visp does not need to be convenient to write - `Selector`s are used to write it
|
23
|
+
- Visp does not need to be easily understandable by end-users of Val
|
24
|
+
|
25
|
+
## Syntax
|
26
|
+
|
27
|
+
Visp is a Lisp which only can evaluate one expression at a time.
|
28
|
+
|
29
|
+
Read more about how it works in sections that follows.
|
30
|
+
|
31
|
+
### Property access
|
32
|
+
|
33
|
+
```visp
|
34
|
+
('title' foo)
|
35
|
+
```
|
36
|
+
|
37
|
+
corresponds to:
|
38
|
+
|
39
|
+
```js
|
40
|
+
foo["title"];
|
41
|
+
```
|
42
|
+
|
43
|
+
There are no numbers in Visp, so arrays are indexed in the same way:
|
44
|
+
|
45
|
+
```visp
|
46
|
+
('0' foo)
|
47
|
+
```
|
48
|
+
|
49
|
+
corresponds to:
|
50
|
+
|
51
|
+
```js
|
52
|
+
foo["0"]; // same as foo[0]
|
53
|
+
```
|
54
|
+
|
55
|
+
### Function calls
|
56
|
+
|
57
|
+
Function calls are similar to property access, but with arguments separated by whitespace:
|
58
|
+
|
59
|
+
```visp
|
60
|
+
(fnname foo arg1 arg2)
|
61
|
+
```
|
62
|
+
|
63
|
+
corresponds to:
|
64
|
+
|
65
|
+
```js
|
66
|
+
foo["fnname"](arg1, arg2); // same as foo.fname(arg1, arg2)
|
67
|
+
```
|
68
|
+
|
69
|
+
#### Higher order functions
|
70
|
+
|
71
|
+
Higher order functions must be prefixed with the `!` character.
|
72
|
+
Arguments can be accessed using the `@` character. The `@` must be suffixed with indexes, e.g. `@[0,0]`, the first one corresponding to the stack depth and the second corresponds to index of the argument list.
|
73
|
+
|
74
|
+
```visp
|
75
|
+
!(map foo @[0,0])
|
76
|
+
```
|
77
|
+
|
78
|
+
corresponds to:
|
79
|
+
|
80
|
+
```js
|
81
|
+
foo.map((v) => v);
|
82
|
+
```
|
83
|
+
|
84
|
+
Here we access the second argument of a function:
|
85
|
+
|
86
|
+
```visp
|
87
|
+
!(map foo @[0,1])
|
88
|
+
```
|
89
|
+
|
90
|
+
corresponds to:
|
91
|
+
|
92
|
+
```js
|
93
|
+
foo.map((_, i) => i);
|
94
|
+
```
|
95
|
+
|
96
|
+
This example shows how higher functions and arguments can be nested:
|
97
|
+
|
98
|
+
```visp
|
99
|
+
!(map foo !(map @[0,0] (slice @[1,0] @[0,1])))
|
100
|
+
```
|
101
|
+
|
102
|
+
corresponds to:
|
103
|
+
|
104
|
+
```js
|
105
|
+
foo.map((v, i) => v.map((j) => j.slice(i)));
|
106
|
+
```
|
107
|
+
|
108
|
+
### Literals
|
109
|
+
|
110
|
+
Visp only supports string literals.
|
111
|
+
|
112
|
+
Example:
|
113
|
+
|
114
|
+
```visp
|
115
|
+
'foo'
|
116
|
+
```
|
117
|
+
|
118
|
+
corresponds to:
|
119
|
+
|
120
|
+
```js
|
121
|
+
"foo";
|
122
|
+
```
|
123
|
+
|
124
|
+
### String templates
|
125
|
+
|
126
|
+
Val has support for string templates similar to JavaScript.
|
127
|
+
They are denoted using single quotes `'` (as string literal), but can inject expressions using `${}`.
|
128
|
+
|
129
|
+
Example:
|
130
|
+
|
131
|
+
```visp
|
132
|
+
'foo ${('title' obj)} bar'
|
133
|
+
```
|
134
|
+
|
135
|
+
corresponds to:
|
136
|
+
|
137
|
+
```js
|
138
|
+
`foo ${obj["title"]} bar`;
|
139
|
+
```
|
140
|
+
|
141
|
+
### Special symbols
|
142
|
+
|
143
|
+
### `()`
|
144
|
+
|
145
|
+
The `()` symbol evaluates to `undefined`.
|
146
|
+
|
147
|
+
#### `@`
|
148
|
+
|
149
|
+
This symbol can be used to access arguments in [higher order functions](#higher-order-functions).
|
150
|
+
|
151
|
+
### `!`
|
152
|
+
|
153
|
+
This is a prefix to a [higher order function](#higher-order-functions).
|
154
|
+
|
155
|
+
### val
|
156
|
+
|
157
|
+
The `val` symbol is used to access data from a Val module.
|
158
|
+
|
159
|
+
Example:
|
160
|
+
|
161
|
+
```visp
|
162
|
+
(val '/foo/bar`)
|
163
|
+
```
|
164
|
+
|
165
|
+
Returns the `Source` of a Val module of id `/foo/bar`.
|
166
|
+
|
167
|
+
### json
|
168
|
+
|
169
|
+
The `json` symbol is used to parse json strings.
|
170
|
+
|
171
|
+
Example:
|
172
|
+
|
173
|
+
```visp
|
174
|
+
(json '{"foo": "bar"}')
|
175
|
+
```
|
176
|
+
|
177
|
+
To create numbers, lists etc, the `json` symbol can be used.
|
178
|
+
|
179
|
+
It is also possible to use `json` with string templates:
|
180
|
+
|
181
|
+
```visp
|
182
|
+
(json '{ "foo": ${('title' obj)} }')
|
183
|
+
```
|
184
|
+
|
185
|
+
corresponds to:
|
186
|
+
|
187
|
+
```js
|
188
|
+
JSON.parse(`{ "foo": ${obj["title"]} }`);
|
189
|
+
```
|
190
|
+
|
191
|
+
### More
|
192
|
+
|
193
|
+
More examples can be found in the [eval.test](eval.test.ts)
|
@@ -0,0 +1,202 @@
|
|
1
|
+
import { pipe, result } from "../../fp";
|
2
|
+
import { Path } from "../selector";
|
3
|
+
import { newSelectorProxy, selectorToVal } from "../selector/SelectorProxy";
|
4
|
+
import { Source } from "../source";
|
5
|
+
import { SourcePath } from "../val";
|
6
|
+
import { evaluate } from "./eval";
|
7
|
+
import { parse } from "./parser";
|
8
|
+
|
9
|
+
const sources = {
|
10
|
+
"/app/text": "text1",
|
11
|
+
"/numbers": [0, 1, 2],
|
12
|
+
"/articles": [{ title: "title1" }, { title: "title2" }],
|
13
|
+
"/app/blogs": [
|
14
|
+
{ title: "blog1", text: "text1" },
|
15
|
+
{ title: "blog2", text: "text2" },
|
16
|
+
],
|
17
|
+
};
|
18
|
+
|
19
|
+
const EvalTestCases: {
|
20
|
+
expr: string;
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
22
|
+
expected: result.Result<{ val: Source; [Path]: any }, any>;
|
23
|
+
focus?: boolean; // use focus to specify a single test case
|
24
|
+
}[] = [
|
25
|
+
{
|
26
|
+
expr: `'hello world'`,
|
27
|
+
expected: result.ok({ val: "hello world", [Path]: undefined }),
|
28
|
+
},
|
29
|
+
{
|
30
|
+
expr: `(val '/numbers')`,
|
31
|
+
expected: result.ok({ val: [0, 1, 2], [Path]: "/numbers" }),
|
32
|
+
},
|
33
|
+
{
|
34
|
+
expr: `('hello world')`,
|
35
|
+
expected: result.ok({ val: "hello world", [Path]: undefined }),
|
36
|
+
},
|
37
|
+
{
|
38
|
+
expr: `()`,
|
39
|
+
expected: result.ok({ val: null, [Path]: undefined }),
|
40
|
+
},
|
41
|
+
{
|
42
|
+
expr: `(eq 'value' 'show me')`,
|
43
|
+
expected: result.ok({ val: false, [Path]: undefined }),
|
44
|
+
},
|
45
|
+
{
|
46
|
+
expr: `(eq 'value' 'value')`,
|
47
|
+
expected: result.ok({ val: true, [Path]: undefined }),
|
48
|
+
},
|
49
|
+
{
|
50
|
+
expr: `!(andThen 'value' 'show me')`,
|
51
|
+
expected: result.ok({ val: "show me", [Path]: undefined }),
|
52
|
+
},
|
53
|
+
{
|
54
|
+
expr: `!(andThen '' ('do NOT show me'))`,
|
55
|
+
expected: result.ok({ val: "", [Path]: undefined }),
|
56
|
+
},
|
57
|
+
{
|
58
|
+
expr: `!(andThen 'text1' @[0,0])`,
|
59
|
+
expected: result.ok({ val: "text1", [Path]: undefined }),
|
60
|
+
},
|
61
|
+
{
|
62
|
+
expr: `(json '1')`,
|
63
|
+
expected: result.ok({ val: 1, [Path]: undefined }),
|
64
|
+
},
|
65
|
+
{
|
66
|
+
expr: `(json '"1"')`,
|
67
|
+
expected: result.ok({ val: "1", [Path]: undefined }),
|
68
|
+
},
|
69
|
+
{
|
70
|
+
expr: `(json '{"foo": "bar"}')`,
|
71
|
+
expected: result.ok({ val: { foo: "bar" }, [Path]: undefined }),
|
72
|
+
},
|
73
|
+
{
|
74
|
+
expr: `(json '\${(json '1')}')`,
|
75
|
+
expected: result.ok({ val: 1, [Path]: undefined }),
|
76
|
+
},
|
77
|
+
{
|
78
|
+
expr: `(json '\${(json '"1"')}')`,
|
79
|
+
expected: result.ok({ val: "1", [Path]: undefined }),
|
80
|
+
},
|
81
|
+
{
|
82
|
+
expr: `(json '{"foo": \${(json '"1"')}}')`,
|
83
|
+
expected: result.ok({
|
84
|
+
val: {
|
85
|
+
foo: "1",
|
86
|
+
},
|
87
|
+
[Path]: undefined,
|
88
|
+
}),
|
89
|
+
},
|
90
|
+
{
|
91
|
+
expr: `(json '\${(val '/numbers')}')`,
|
92
|
+
expected: result.ok({
|
93
|
+
val: sources["/numbers"],
|
94
|
+
[Path]: "/numbers",
|
95
|
+
}),
|
96
|
+
},
|
97
|
+
{
|
98
|
+
expr: `('test' (json '{ "test": \${((json '0') (val '/numbers'))} }'))`,
|
99
|
+
expected: result.ok({
|
100
|
+
val: 0,
|
101
|
+
[Path]: "/numbers.0",
|
102
|
+
}),
|
103
|
+
},
|
104
|
+
{
|
105
|
+
expr: `((json '1') ('foo' (json '{"foo": \${(val '/numbers')}}')))`,
|
106
|
+
expected: result.ok({ val: 1, [Path]: "/numbers.1" }),
|
107
|
+
},
|
108
|
+
{
|
109
|
+
expr: `(length (val '/numbers'))`,
|
110
|
+
expected: result.ok({
|
111
|
+
val: sources["/numbers"].length,
|
112
|
+
[Path]: undefined,
|
113
|
+
}),
|
114
|
+
},
|
115
|
+
{
|
116
|
+
expr: `('0' (val '/articles'))`,
|
117
|
+
expected: result.ok({
|
118
|
+
val: sources["/articles"][0],
|
119
|
+
[Path]: "/articles.0",
|
120
|
+
}),
|
121
|
+
},
|
122
|
+
{
|
123
|
+
expr: `!(map (val '/articles') @[0,0])`,
|
124
|
+
expected: result.ok({
|
125
|
+
val: sources["/articles"].map((v) => v),
|
126
|
+
[Path]: "/articles",
|
127
|
+
}),
|
128
|
+
},
|
129
|
+
{
|
130
|
+
expr: `('0' !(map (val '/articles') ('title' @[0,0])))`,
|
131
|
+
expected: result.ok({
|
132
|
+
val: sources["/articles"].map((v) => v["title"])[0],
|
133
|
+
[Path]: '/articles.0."title"',
|
134
|
+
}),
|
135
|
+
},
|
136
|
+
{
|
137
|
+
expr: `!(map (val '/articles') ('title' @[0,0]))`,
|
138
|
+
expected: result.ok({
|
139
|
+
val: sources["/articles"].map((v) => v["title"]),
|
140
|
+
[Path]: "/articles",
|
141
|
+
}),
|
142
|
+
},
|
143
|
+
{
|
144
|
+
expr: `(eq !(andThen (val '/app/text') ()) 'foo')`,
|
145
|
+
expected: result.ok({
|
146
|
+
val: false,
|
147
|
+
[Path]: undefined,
|
148
|
+
}),
|
149
|
+
},
|
150
|
+
{
|
151
|
+
expr: `!(filter (val '/app/blogs') (eq ('title' @[0,0]) 'blog1'))`,
|
152
|
+
expected: result.ok({
|
153
|
+
val: [
|
154
|
+
{
|
155
|
+
text: "text1",
|
156
|
+
title: "blog1",
|
157
|
+
},
|
158
|
+
],
|
159
|
+
[Path]: "/app/blogs",
|
160
|
+
}),
|
161
|
+
},
|
162
|
+
{
|
163
|
+
expr: `(json '{"title": \${()}}')`,
|
164
|
+
expected: result.ok({
|
165
|
+
val: {
|
166
|
+
title: null,
|
167
|
+
},
|
168
|
+
|
169
|
+
[Path]: undefined,
|
170
|
+
}),
|
171
|
+
},
|
172
|
+
];
|
173
|
+
|
174
|
+
describe("eval", () => {
|
175
|
+
test.each(
|
176
|
+
EvalTestCases.filter(({ focus }) =>
|
177
|
+
EvalTestCases.some((v) => v.focus) ? focus : true
|
178
|
+
)
|
179
|
+
)('evaluate: "$expr"', ({ expr, expected }) => {
|
180
|
+
const parseRes = parse(expr);
|
181
|
+
if (result.isErr(parseRes)) {
|
182
|
+
return expect(parseRes).toHaveProperty("value");
|
183
|
+
}
|
184
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
185
|
+
expect(
|
186
|
+
pipe(
|
187
|
+
evaluate(
|
188
|
+
parseRes.value,
|
189
|
+
(ref) => {
|
190
|
+
return newSelectorProxy(
|
191
|
+
sources[ref as keyof typeof sources],
|
192
|
+
ref as SourcePath
|
193
|
+
);
|
194
|
+
},
|
195
|
+
[]
|
196
|
+
),
|
197
|
+
result.map((v) => selectorToVal(v))
|
198
|
+
)
|
199
|
+
).toStrictEqual(expected);
|
200
|
+
});
|
201
|
+
//
|
202
|
+
});
|