@effect-app/infra 4.0.0-beta.211 → 4.0.0-beta.213
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/CHANGELOG.md +18 -0
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +6 -2
- package/dist/Model/Repository/validation.d.ts +8 -8
- package/dist/Model/query/dsl.d.ts +51 -1
- package/dist/Model/query/dsl.d.ts.map +1 -1
- package/dist/Model/query/dsl.js +54 -1
- package/dist/Model/query/new-kid-interpreter.d.ts +18 -2
- package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
- package/dist/Model/query/new-kid-interpreter.js +58 -4
- package/dist/RequestContext.d.ts +12 -12
- package/dist/Store/Cosmos/query.d.ts +5 -1
- package/dist/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/Store/Cosmos/query.js +41 -23
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +1 -1
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +33 -2
- package/dist/Store/SQL/Pg.d.ts.map +1 -1
- package/dist/Store/SQL/Pg.js +1 -1
- package/dist/Store/SQL/query.d.ts +5 -1
- package/dist/Store/SQL/query.d.ts.map +1 -1
- package/dist/Store/SQL/query.js +25 -1
- package/dist/Store/SQL.d.ts.map +1 -1
- package/dist/Store/SQL.js +1 -1
- package/dist/Store/service.d.ts +5 -2
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +1 -1
- package/examples/query.ts +3 -3
- package/package.json +2 -2
- package/src/Model/Repository/internal/internal.ts +5 -1
- package/src/Model/query/dsl.ts +106 -0
- package/src/Model/query/new-kid-interpreter.ts +78 -4
- package/src/Store/Cosmos/query.ts +57 -23
- package/src/Store/Cosmos.ts +10 -2
- package/src/Store/Memory.ts +53 -4
- package/src/Store/SQL/Pg.ts +10 -1
- package/src/Store/SQL/query.ts +35 -1
- package/src/Store/SQL.ts +19 -2
- package/src/Store/service.ts +9 -2
- package/test/dist/fixtures.d.ts +1 -1
- package/test/query.test.ts +69 -4
- package/test/rawQuery.test.ts +36 -1
- package/test/sql-store.test.ts +61 -0
package/dist/Store/service.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { OptimisticConcurrencyException } from "../errors.js";
|
|
|
4
4
|
import type { FilterResult } from "../Model/filter/filterApi.js";
|
|
5
5
|
import type { FieldValues } from "../Model/filter/types.js";
|
|
6
6
|
import type { FieldPath } from "../Model/filter/types/path/index.js";
|
|
7
|
-
import {
|
|
7
|
+
import type { ComputedProjectionIrExpression, RawQuery } from "../Model/query.js";
|
|
8
8
|
export interface StoreConfig<E> {
|
|
9
9
|
partitionValue: (e?: E) => string;
|
|
10
10
|
/**
|
|
@@ -60,6 +60,9 @@ export interface FilterArgs<Encoded extends FieldValues, U extends keyof Encoded
|
|
|
60
60
|
select?: NonEmptyReadonlyArray<U | {
|
|
61
61
|
key: string;
|
|
62
62
|
subKeys: readonly string[];
|
|
63
|
+
} | {
|
|
64
|
+
key: string;
|
|
65
|
+
computed: ComputedProjectionIrExpression;
|
|
63
66
|
}> | undefined;
|
|
64
67
|
order?: NonEmptyReadonlyArray<O<NoInfer<Encoded>>>;
|
|
65
68
|
limit?: number | undefined;
|
|
@@ -116,4 +119,4 @@ export interface StorageConfig {
|
|
|
116
119
|
dbName: string;
|
|
117
120
|
}
|
|
118
121
|
export {};
|
|
119
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
122
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL1N0b3JlL3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQzlDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUsscUJBQXFCLEVBQUUsS0FBSyxNQUFNLEVBQUUsS0FBSyxRQUFRLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFFcEcsT0FBTyxLQUFLLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFDbEUsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sOEJBQThCLENBQUE7QUFDaEUsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDM0QsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0scUNBQXFDLENBQUE7QUFDcEUsT0FBTyxLQUFLLEVBQUUsOEJBQThCLEVBQUUsUUFBUSxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFFakYsTUFBTSxXQUFXLFdBQVcsQ0FBQyxDQUFDO0lBQzVCLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxNQUFNLENBQUE7SUFDakM7OztPQUdHO0lBQ0gsY0FBYyxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsTUFBTSxLQUFLLE9BQU8sQ0FBQTtJQUMvQzs7T0FFRztJQUNILGFBQWEsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUUxQjs7O09BR0c7SUFDSCxXQUFXLENBQUMsRUFBRSxNQUFNLENBQUE7SUFFcEI7O09BRUc7SUFDSCxVQUFVLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQTtDQUN6QjtBQUVELE1BQU0sTUFBTSxlQUFlLEdBQUcsTUFBTSxHQUFHLE9BQU8sR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFBO0FBQzlELE1BQU0sTUFBTSxn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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/Store/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,qBAAqB,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEpG,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AACpE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/Store/service.ts"],"names":[],"mappings":"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"}
|
package/dist/Store/service.js
CHANGED
|
@@ -86,4 +86,4 @@ export const makeContextMap = () => {
|
|
|
86
86
|
const makeMap = Effect.sync(() => makeContextMap());
|
|
87
87
|
export class ContextMap extends Context.Opaque()("effect-app/ContextMap", { make: makeMap }) {
|
|
88
88
|
}
|
|
89
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
89
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9TdG9yZS9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUEwRCxNQUFNLFlBQVksQ0FBQTtBQUNwRyxPQUFPLEtBQUssU0FBUyxNQUFNLGtCQUFrQixDQUFBO0FBcUc3QyxNQUFNLE9BQU8sVUFBVyxTQUFRLE9BQU8sQ0FBQyxNQUFNLEVBTzFDLENBQUMsdUJBQXVCLENBQUM7Q0FDNUI7QUFFRCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsR0FBRyxFQUFFO0lBQ2pDLE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFBO0lBQ3ZDLE1BQU0sT0FBTyxHQUFHLENBQUMsRUFBVSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQzdDLE1BQU0sT0FBTyxHQUFHLENBQUMsRUFBVSxFQUFFLElBQXdCLEVBQUUsRUFBRTtRQUN2RCxJQUFJLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN2QixLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ2xCLENBQUM7YUFBTSxDQUFDO1lBQ04sS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDckIsQ0FBQztJQUNILENBQUMsQ0FBQTtJQUVELCtCQUErQjtJQUMvQiwyQkFBMkI7SUFDM0IsZ0RBQWdEO0lBQ2hELE1BQU07SUFFTiwrQkFBK0I7SUFDL0IsMkJBQTJCO0lBQzNCLHNDQUFzQztJQUN0QyxNQUFNO0lBRU4sa0NBQWtDO0lBQ2xDLHdCQUF3QjtJQUN4QixvQ0FBb0M7SUFDcEMsU0FBUztJQUNULDJCQUEyQjtJQUMzQixjQUFjO0lBQ2QsSUFBSTtJQUVKLGlDQUFpQztJQUNqQyxvRkFBb0Y7SUFDcEYsb0lBQW9JO0lBQ3BJLGdCQUFnQjtJQUNoQixhQUFhO0lBQ2IsNEdBQTRHO0lBQzVHLHNDQUFzQztJQUN0QyxrRUFBa0U7SUFDbEUsdURBQXVEO0lBQ3ZELHNCQUFzQjtJQUN0QixzQkFBc0I7SUFDdEIsU0FBUztJQUNULHFDQUFxQztJQUNyQyx5Q0FBeUM7SUFDekMsaUJBQWlCO0lBQ2pCLDZCQUE2QjtJQUM3QixtQkFBbUI7SUFDbkIsK0NBQStDO0lBQy9DLHFCQUFxQjtJQUNyQixtQkFBbUI7SUFDbkIsMkNBQTJDO0lBQzNDLHlCQUF5QjtJQUN6QixzQkFBc0I7SUFDdEIsWUFBWTtJQUNaLGlCQUFpQjtJQUNqQix5Q0FBeUM7SUFDekMscURBQXFEO0lBQ3JELG9CQUFvQjtJQUNwQixVQUFVO0lBQ1YsUUFBUTtJQUNSLE1BQU07SUFDTixJQUFJO0lBRUosTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQW1CLENBQUE7SUFDeEMsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUVuQyxPQUFPO1FBQ0wsR0FBRyxFQUFFLE9BQU87UUFDWixHQUFHLEVBQUUsT0FBTztRQUNaLGdCQUFnQixFQUFFLENBQUksR0FBVyxFQUFFLElBQWEsRUFBSyxFQUFFO1lBQ3JELElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFrQixDQUFBO1lBQzNDLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUN4QixLQUFLLEdBQUcsSUFBSSxFQUFFLENBQUE7Z0JBQ2QsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDdkIsQ0FBQztZQUNELE9BQU8sS0FBSyxDQUFBO1FBQ2QsQ0FBQztRQUNELHNCQUFzQixFQUFFLENBQVUsR0FBVyxFQUFFLElBQTRCLEVBQTBCLEVBQUUsQ0FDckcsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO1lBQzVELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFrQixDQUFBO1lBQzdDLElBQUksS0FBSyxLQUFLLFNBQVM7Z0JBQUUsT0FBTyxLQUFLLENBQUE7WUFDckMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFBO1lBQ3JCLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFBO1lBQ2pCLE9BQU8sQ0FBQyxDQUFBO1FBQ1YsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUNQLENBQUE7QUFDSCxDQUFDLENBQUE7QUFFRCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUE7QUFFbkQsTUFBTSxPQUFPLFVBQVcsU0FBUSxPQUFPLENBQUMsTUFBTSxFQUFjLENBQUMsdUJBQXVCLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7Q0FDdkcifQ==
|
package/examples/query.ts
CHANGED
|
@@ -9,14 +9,14 @@ const num = S.Struct({ _tag: S.Literal("number"), value: S.Finite })
|
|
|
9
9
|
const someUnion = S.Union(str, num)
|
|
10
10
|
|
|
11
11
|
export class Something extends S.Opaque<Something>()(S.TaggedStruct("Something", {
|
|
12
|
-
id: S.StringId.
|
|
12
|
+
id: S.StringId.withConstructorDefault,
|
|
13
13
|
displayName: S.NonEmptyString255,
|
|
14
|
-
n: S.Date.
|
|
14
|
+
n: S.Date.withConstructorDefault,
|
|
15
15
|
union: someUnion.pipe(S.withConstructorDefault(Effect.succeed({ _tag: "string" as const, value: "hi" })))
|
|
16
16
|
})) {}
|
|
17
17
|
|
|
18
18
|
export class SomethingElse extends S.Opaque<SomethingElse>()(S.TaggedStruct("SomethingElse", {
|
|
19
|
-
id: S.StringId.
|
|
19
|
+
id: S.StringId.withConstructorDefault,
|
|
20
20
|
banana: S.NonEmptyString255
|
|
21
21
|
})) {}
|
|
22
22
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.213",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"proper-lockfile": "^4.1.2",
|
|
14
14
|
"pure-rand": "8.4.0",
|
|
15
15
|
"query-string": "^9.3.1",
|
|
16
|
-
"effect-app": "4.0.0-beta.
|
|
16
|
+
"effect-app": "4.0.0-beta.213"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@azure/cosmos": "^4.9.3",
|
|
@@ -314,7 +314,11 @@ export function makeRepoInternal<
|
|
|
314
314
|
q: Q.QAll<NoInfer<Encoded>, NoInfer<EncodedRefined>, A, R>
|
|
315
315
|
): Effect.Effect<readonly A[], never, Exclude<R, RCtx>>
|
|
316
316
|
} = (<A, R, EncodedRefined extends Encoded = Encoded>(q: Q.QAll<Encoded, EncodedRefined, A, R>) => {
|
|
317
|
-
const a = Q.toFilter(q)
|
|
317
|
+
const a = Q.toFilter(q, schema)
|
|
318
|
+
// Mode dispatch — see `Q.project` JSDoc for the contract:
|
|
319
|
+
// project : decode raw encoded rows with schema; no PM reverse-mapping; SchemaError surfaces.
|
|
320
|
+
// collect : same as project, but schema yields Option and None rows are dropped.
|
|
321
|
+
// transform: PM reverse-map (re-inject _etag/PM state from cms cache) then decode; orDie.
|
|
318
322
|
const eff = a.mode === "project"
|
|
319
323
|
? filter(a)
|
|
320
324
|
// TODO: mapFrom but need to support per field and dependencies
|
package/src/Model/query/dsl.ts
CHANGED
|
@@ -97,6 +97,22 @@ export type QueryProjection<
|
|
|
97
97
|
R,
|
|
98
98
|
TType
|
|
99
99
|
>
|
|
100
|
+
|
|
101
|
+
export type ComputedProjectionOperation = (q: Query<any>) => QueryWhere<any, any, any>
|
|
102
|
+
|
|
103
|
+
export type ComputedProjectionExpression =
|
|
104
|
+
| {
|
|
105
|
+
readonly _tag: "relation-count"
|
|
106
|
+
readonly path: string
|
|
107
|
+
readonly operation?: ComputedProjectionOperation
|
|
108
|
+
}
|
|
109
|
+
| {
|
|
110
|
+
readonly _tag: "relation-any"
|
|
111
|
+
readonly path: string
|
|
112
|
+
readonly operation?: ComputedProjectionOperation
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type ComputedProjectionMap = Readonly<Record<string, ComputedProjectionExpression>>
|
|
100
116
|
export type Q<TFieldValues extends FieldValues> =
|
|
101
117
|
| Initial<TFieldValues>
|
|
102
118
|
| Where<TFieldValues>
|
|
@@ -211,6 +227,7 @@ export class Project<A, TFieldValues extends FieldValues, R, TType extends "one"
|
|
|
211
227
|
current: Query<TFieldValues> | QueryWhere<any, TFieldValues> | QueryEnd<TFieldValues, TType>
|
|
212
228
|
schema: S.Codec<A, TFieldValues, R>
|
|
213
229
|
mode: "collect" | "project" | "transform"
|
|
230
|
+
computed?: ComputedProjectionMap
|
|
214
231
|
}>
|
|
215
232
|
implements QueryProjection<TFieldValues, A, R>
|
|
216
233
|
{
|
|
@@ -299,6 +316,35 @@ export const count: {
|
|
|
299
316
|
): QueryProjection<ExtractFieldValuesRefined<Q>, NonNegativeInt, never, "count", ExtractExclusiveness<Q>>
|
|
300
317
|
} = (current) => new Count({ current })
|
|
301
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Attach a projection schema to a query.
|
|
321
|
+
*
|
|
322
|
+
* The `select` clause sent to the store is derived from the schema's encoded
|
|
323
|
+
* AST property names (top-level + per-array sub-keys), so a projection always
|
|
324
|
+
* narrows what is read from the store. The repository augments that select
|
|
325
|
+
* with `id` and `_etag` for change tracking. See {@link toFilter} and the
|
|
326
|
+
* dispatch in `Repository/internal/internal.ts`.
|
|
327
|
+
*
|
|
328
|
+
* Modes — pick based on shape of the decoded value and on whether the
|
|
329
|
+
* persistence-model (PM) reverse-mapping is needed:
|
|
330
|
+
*
|
|
331
|
+
* - `"transform"` (default when `mode` omitted): goes through the repo's
|
|
332
|
+
* `parseMany`/`parseMany2` pipeline. The raw row is reverse-mapped via the
|
|
333
|
+
* etag/PM cache (re-injecting `_etag` and any PM-shape state) before
|
|
334
|
+
* decoding. Decode failures `orDie` (error channel = `never`). Use when
|
|
335
|
+
* the schema operates on the full PM shape (e.g. full-entity reads that
|
|
336
|
+
* must preserve etag tracking).
|
|
337
|
+
*
|
|
338
|
+
* - `"project"`: decodes the raw encoded row directly with the supplied
|
|
339
|
+
* schema. No PM reverse-mapping, no etag cache merge. Decode failures
|
|
340
|
+
* surface as `S.SchemaError`. Use for slim DTOs / aggregations that do not
|
|
341
|
+
* need etag tracking and whose schema input is a plain subset of `Encoded`.
|
|
342
|
+
*
|
|
343
|
+
* - `"collect"`: like `"project"`, but the schema yields `Option<A>` and
|
|
344
|
+
* `None` values are dropped post-decode (`Array.getSomes`). Use to filter
|
|
345
|
+
* rows during decode (e.g. discriminated-union narrowing where some rows
|
|
346
|
+
* should not appear in the result).
|
|
347
|
+
*/
|
|
302
348
|
export const project: {
|
|
303
349
|
<
|
|
304
350
|
Q extends Query<any> | QueryWhere<any, any, any> | QueryEnd<any, "one" | "many", any>,
|
|
@@ -356,6 +402,66 @@ export const project: {
|
|
|
356
402
|
) => QueryProjection<ExtractFieldValuesRefined<Q>, A, R, ExtractTType<Q>, E>
|
|
357
403
|
} = (schema: any, mode = "transform") => (current: any) => new Project({ current, schema, mode } as any)
|
|
358
404
|
|
|
405
|
+
export const relation = <TFieldValues extends FieldValues>(
|
|
406
|
+
path: FieldPath<TFieldValues>
|
|
407
|
+
) => ({
|
|
408
|
+
count: (operation?: ComputedProjectionOperation): ComputedProjectionExpression =>
|
|
409
|
+
operation
|
|
410
|
+
? {
|
|
411
|
+
_tag: "relation-count",
|
|
412
|
+
path: path as string,
|
|
413
|
+
operation
|
|
414
|
+
}
|
|
415
|
+
: {
|
|
416
|
+
_tag: "relation-count",
|
|
417
|
+
path: path as string
|
|
418
|
+
},
|
|
419
|
+
any: (operation?: ComputedProjectionOperation): ComputedProjectionExpression =>
|
|
420
|
+
operation
|
|
421
|
+
? {
|
|
422
|
+
_tag: "relation-any",
|
|
423
|
+
path: path as string,
|
|
424
|
+
operation
|
|
425
|
+
}
|
|
426
|
+
: {
|
|
427
|
+
_tag: "relation-any",
|
|
428
|
+
path: path as string
|
|
429
|
+
}
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
export const computed = <T extends ComputedProjectionMap>(value: T): T => value
|
|
433
|
+
|
|
434
|
+
export const projectComputed: {
|
|
435
|
+
<
|
|
436
|
+
Q extends Query<any> | QueryWhere<any, any, any> | QueryEnd<any, "one" | "many", any>,
|
|
437
|
+
I extends Record<string, unknown>,
|
|
438
|
+
A = ExtractFieldValuesRefined<Q>,
|
|
439
|
+
R = never,
|
|
440
|
+
E extends boolean = ExtractExclusiveness<Q>
|
|
441
|
+
>(
|
|
442
|
+
schema: S.Codec<Option.Option<A>, I, R>,
|
|
443
|
+
computedProjection: ComputedProjectionMap,
|
|
444
|
+
mode: "collect"
|
|
445
|
+
): (
|
|
446
|
+
current: Q
|
|
447
|
+
) => QueryProjection<ExtractFieldValuesRefined<Q>, A, R, ExtractTType<Q>, E>
|
|
448
|
+
|
|
449
|
+
<
|
|
450
|
+
Q extends Query<any> | QueryWhere<any, any, any> | QueryEnd<any, "one" | "many", any>,
|
|
451
|
+
I extends Record<string, unknown>,
|
|
452
|
+
A = ExtractFieldValuesRefined<Q>,
|
|
453
|
+
R = never,
|
|
454
|
+
E extends boolean = ExtractExclusiveness<Q>
|
|
455
|
+
>(
|
|
456
|
+
schema: S.Codec<A, I, R>,
|
|
457
|
+
computedProjection: ComputedProjectionMap,
|
|
458
|
+
mode?: "project"
|
|
459
|
+
): (
|
|
460
|
+
current: Q
|
|
461
|
+
) => QueryProjection<ExtractFieldValuesRefined<Q>, A, R, ExtractTType<Q>, E>
|
|
462
|
+
} = (schema: any, computedProjection: ComputedProjectionMap, mode = "project") => (current: any) =>
|
|
463
|
+
new Project({ current, schema, mode, computed: computedProjection } as any)
|
|
464
|
+
|
|
359
465
|
type GetArV<T> = T extends readonly (infer R)[] ? R : never
|
|
360
466
|
|
|
361
467
|
export type FilterContinuations<IsCurrentInitial extends boolean = false> = {
|
|
@@ -8,6 +8,18 @@ import type { FieldValues } from "../filter/types.js"
|
|
|
8
8
|
import type { FieldPath } from "../filter/types/path/eager.js"
|
|
9
9
|
import { make, type Q, type QAll } from "../query/dsl.js"
|
|
10
10
|
|
|
11
|
+
export type ComputedProjectionIrExpression =
|
|
12
|
+
| {
|
|
13
|
+
readonly _tag: "relation-count"
|
|
14
|
+
readonly path: string
|
|
15
|
+
readonly filter: readonly FilterResult[]
|
|
16
|
+
}
|
|
17
|
+
| {
|
|
18
|
+
readonly _tag: "relation-any"
|
|
19
|
+
readonly path: string
|
|
20
|
+
readonly filter: readonly FilterResult[]
|
|
21
|
+
}
|
|
22
|
+
|
|
11
23
|
type Result<TFieldValues extends FieldValues, A = TFieldValues, R = never> = {
|
|
12
24
|
filter: FilterResult[]
|
|
13
25
|
schema: S.Codec<A, TFieldValues, R> | undefined
|
|
@@ -16,6 +28,7 @@ type Result<TFieldValues extends FieldValues, A = TFieldValues, R = never> = {
|
|
|
16
28
|
order: { key: FieldPath<TFieldValues>; direction: "ASC" | "DESC" }[]
|
|
17
29
|
ttype: "one" | "many" | "count" | undefined
|
|
18
30
|
mode: "collect" | "project" | "transform" | undefined
|
|
31
|
+
computed: Record<string, ComputedProjectionIrExpression> | undefined
|
|
19
32
|
}
|
|
20
33
|
|
|
21
34
|
const interpret = <
|
|
@@ -33,7 +46,8 @@ const interpret = <
|
|
|
33
46
|
skip: undefined,
|
|
34
47
|
order: [],
|
|
35
48
|
ttype: undefined,
|
|
36
|
-
mode: undefined
|
|
49
|
+
mode: undefined,
|
|
50
|
+
computed: undefined
|
|
37
51
|
}
|
|
38
52
|
|
|
39
53
|
const upd = (
|
|
@@ -46,6 +60,7 @@ const interpret = <
|
|
|
46
60
|
if (v.ttype !== undefined) data.ttype = v.ttype
|
|
47
61
|
if (v.schema !== undefined) data.schema = v.schema
|
|
48
62
|
if (v.mode !== undefined) data.mode = v.mode
|
|
63
|
+
if (v.computed !== undefined) data.computed = v.computed
|
|
49
64
|
}
|
|
50
65
|
|
|
51
66
|
const applyPath = (path: string) => (_: FilterResult): FilterResult =>
|
|
@@ -135,8 +150,22 @@ const interpret = <
|
|
|
135
150
|
},
|
|
136
151
|
project: (v) => {
|
|
137
152
|
upd(interpret(v.current))
|
|
153
|
+
if (v.computed && v.mode === "transform") {
|
|
154
|
+
throw new Error("Computed projections require mode 'project' or 'collect', not 'transform'")
|
|
155
|
+
}
|
|
138
156
|
data.schema = v.schema
|
|
139
|
-
data.mode = v.
|
|
157
|
+
data.mode = v.computed
|
|
158
|
+
? v.mode === "collect" ? "collect" : "project"
|
|
159
|
+
: v.mode
|
|
160
|
+
data.computed = v.computed
|
|
161
|
+
? Object.fromEntries(
|
|
162
|
+
Object.entries(v.computed).map(([key, expression]) => {
|
|
163
|
+
const e = expression
|
|
164
|
+
const filter = e.operation ? interpret(e.operation(make())).filter.map(applyPath(e.path)) : []
|
|
165
|
+
return [key, { _tag: e._tag, path: e.path, filter } as const]
|
|
166
|
+
})
|
|
167
|
+
)
|
|
168
|
+
: undefined
|
|
140
169
|
}
|
|
141
170
|
})
|
|
142
171
|
)
|
|
@@ -157,12 +186,16 @@ export const toFilter = <
|
|
|
157
186
|
R,
|
|
158
187
|
TFieldValuesRefined extends TFieldValues = TFieldValues
|
|
159
188
|
>(
|
|
160
|
-
q: QAll<TFieldValues, TFieldValuesRefined, A, R
|
|
189
|
+
q: QAll<TFieldValues, TFieldValuesRefined, A, R>,
|
|
190
|
+
baseSchema?: S.Schema<unknown>
|
|
161
191
|
) => {
|
|
162
192
|
// TODO: Native interpreter for each db adapter, instead of the intermediate "new-kid" format
|
|
163
193
|
const a = interpret(q)
|
|
164
194
|
const schema = a.schema
|
|
165
|
-
let select: (keyof TFieldValues | { key: string; subKeys: string[] }
|
|
195
|
+
let select: (keyof TFieldValues | { key: string; subKeys: string[] } | {
|
|
196
|
+
key: string
|
|
197
|
+
computed: ComputedProjectionIrExpression
|
|
198
|
+
})[] = []
|
|
166
199
|
// TODO: support more complex (nested) schemas?
|
|
167
200
|
if (schema) {
|
|
168
201
|
const t = walkTransformation(SchemaAST.toEncoded(schema.ast))
|
|
@@ -194,12 +227,53 @@ export const toFilter = <
|
|
|
194
227
|
}
|
|
195
228
|
}
|
|
196
229
|
}
|
|
230
|
+
const computed = a.computed
|
|
231
|
+
const getSelectKey = (_: (typeof select)[number]) => {
|
|
232
|
+
if (typeof _ === "string") {
|
|
233
|
+
return _
|
|
234
|
+
}
|
|
235
|
+
if (typeof _ === "object" && _ !== null && "key" in _) {
|
|
236
|
+
return _.key
|
|
237
|
+
}
|
|
238
|
+
return String(_)
|
|
239
|
+
}
|
|
240
|
+
const schemaKeys = select.map(getSelectKey)
|
|
241
|
+
const nonEncodedSchemaKeys = (() => {
|
|
242
|
+
if (!baseSchema) {
|
|
243
|
+
return [] as string[]
|
|
244
|
+
}
|
|
245
|
+
const encoded = walkTransformation(SchemaAST.toEncoded(baseSchema.ast))
|
|
246
|
+
if (!S.AST.isObjects(encoded)) {
|
|
247
|
+
return [] as string[]
|
|
248
|
+
}
|
|
249
|
+
const encodedKeys = encoded.propertySignatures.map((_) => _.name as string)
|
|
250
|
+
return schemaKeys.filter((key) => !encodedKeys.includes(key))
|
|
251
|
+
})()
|
|
252
|
+
const missingComputedKeys = nonEncodedSchemaKeys.filter((key) => !(computed && key in computed))
|
|
253
|
+
|
|
254
|
+
if (Array.isArrayNonEmpty(missingComputedKeys)) {
|
|
255
|
+
throw new Error(`Missing computed projections for schema keys: ${missingComputedKeys.join(", ")}`)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (computed) {
|
|
259
|
+
const computedKeys = Object.keys(computed)
|
|
260
|
+
const extraComputedKeys = computedKeys.filter((key) => !schemaKeys.includes(key))
|
|
261
|
+
if (Array.isArrayNonEmpty(extraComputedKeys)) {
|
|
262
|
+
throw new Error(`Computed projection keys must exist in projection schema: ${extraComputedKeys.join(", ")}`)
|
|
263
|
+
}
|
|
264
|
+
select = select.filter((_) => {
|
|
265
|
+
const key = getSelectKey(_)
|
|
266
|
+
return !(key in computed)
|
|
267
|
+
})
|
|
268
|
+
select.push(...Object.entries(computed).map(([key, expression]) => ({ key, computed: expression })))
|
|
269
|
+
}
|
|
197
270
|
return dropUndefinedT({
|
|
198
271
|
t: null as unknown as TFieldValues,
|
|
199
272
|
limit: a.limit,
|
|
200
273
|
skip: a.skip,
|
|
201
274
|
select: Option.getOrUndefined(toNonEmptyArray(select)),
|
|
202
275
|
schema,
|
|
276
|
+
computed,
|
|
203
277
|
order: Option.getOrUndefined(toNonEmptyArray(a.order)),
|
|
204
278
|
ttype: a.ttype,
|
|
205
279
|
mode: a.mode ?? "transform",
|
|
@@ -4,6 +4,7 @@ import { Array, Effect, type NonEmptyReadonlyArray } from "effect-app"
|
|
|
4
4
|
import { assertUnreachable } from "effect-app/utils"
|
|
5
5
|
import { InfraLogger } from "../../logger.js"
|
|
6
6
|
import type { FilterR, FilterResult, Ops } from "../../Model/filter/filterApi.js"
|
|
7
|
+
import type { ComputedProjectionIrExpression } from "../../Model/query.js"
|
|
7
8
|
import { isRelationCheck } from "../codeFilter.js"
|
|
8
9
|
import type { SupportedValues } from "../service.js"
|
|
9
10
|
|
|
@@ -40,12 +41,20 @@ export function buildWhereCosmosQuery3(
|
|
|
40
41
|
filter: readonly FilterResult[],
|
|
41
42
|
name: string,
|
|
42
43
|
defaultValues: Record<string, unknown>,
|
|
43
|
-
select?: NonEmptyReadonlyArray<
|
|
44
|
+
select?: NonEmptyReadonlyArray<
|
|
45
|
+
string | {
|
|
46
|
+
key: string
|
|
47
|
+
subKeys: readonly string[]
|
|
48
|
+
} | {
|
|
49
|
+
key: string
|
|
50
|
+
computed: ComputedProjectionIrExpression
|
|
51
|
+
}
|
|
52
|
+
>,
|
|
44
53
|
order?: NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }>,
|
|
45
54
|
skip?: number,
|
|
46
55
|
limit?: number
|
|
47
56
|
) {
|
|
48
|
-
const statement = (x: FilterR, i: number
|
|
57
|
+
const statement = (x: FilterR, i: number) => {
|
|
49
58
|
if (x.path === idKey) {
|
|
50
59
|
x = { ...x, path: "id" }
|
|
51
60
|
}
|
|
@@ -60,8 +69,6 @@ export function buildWhereCosmosQuery3(
|
|
|
60
69
|
|
|
61
70
|
const v = "@v" + i
|
|
62
71
|
|
|
63
|
-
const realValue = values[i]
|
|
64
|
-
|
|
65
72
|
switch (x.op) {
|
|
66
73
|
case "in":
|
|
67
74
|
return `ARRAY_CONTAINS(${v}, ${k})`
|
|
@@ -74,14 +81,22 @@ export function buildWhereCosmosQuery3(
|
|
|
74
81
|
return `(NOT ARRAY_CONTAINS(${k}, ${v}))`
|
|
75
82
|
|
|
76
83
|
case "includes-any":
|
|
77
|
-
return `ARRAY_CONTAINS_ANY(${k}, ${
|
|
84
|
+
return `ARRAY_CONTAINS_ANY(${k}, ${
|
|
85
|
+
(x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
|
|
86
|
+
})`
|
|
78
87
|
case "notIncludes-any":
|
|
79
|
-
return `(NOT ARRAY_CONTAINS_ANY(${k}, ${
|
|
88
|
+
return `(NOT ARRAY_CONTAINS_ANY(${k}, ${
|
|
89
|
+
(x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
|
|
90
|
+
}))`
|
|
80
91
|
|
|
81
92
|
case "includes-all":
|
|
82
|
-
return `ARRAY_CONTAINS_ALL(${k}, ${
|
|
93
|
+
return `ARRAY_CONTAINS_ALL(${k}, ${
|
|
94
|
+
(x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
|
|
95
|
+
})`
|
|
83
96
|
case "notIncludes-all":
|
|
84
|
-
return `(NOT ARRAY_CONTAINS_ALL(${k}, ${
|
|
97
|
+
return `(NOT ARRAY_CONTAINS_ALL(${k}, ${
|
|
98
|
+
(x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
|
|
99
|
+
}))`
|
|
85
100
|
|
|
86
101
|
case "contains":
|
|
87
102
|
return `CONTAINS(${k}, ${v}, true)`
|
|
@@ -165,7 +180,7 @@ export function buildWhereCosmosQuery3(
|
|
|
165
180
|
: _
|
|
166
181
|
: _
|
|
167
182
|
|
|
168
|
-
const print = (state: readonly FilterResult[],
|
|
183
|
+
const print = (state: readonly FilterResult[], isRelation: string | null, every: boolean) => {
|
|
169
184
|
let s = ""
|
|
170
185
|
let l = 0
|
|
171
186
|
const printN = (n: number) => {
|
|
@@ -174,13 +189,13 @@ export function buildWhereCosmosQuery3(
|
|
|
174
189
|
for (const e of state) {
|
|
175
190
|
switch (e.t) {
|
|
176
191
|
case "where":
|
|
177
|
-
s += statement(e, i
|
|
192
|
+
s += statement(e, i++)
|
|
178
193
|
break
|
|
179
194
|
case "or":
|
|
180
|
-
s += ` OR ${statement(e, i
|
|
195
|
+
s += ` OR ${statement(e, i++)}`
|
|
181
196
|
break
|
|
182
197
|
case "and":
|
|
183
|
-
s += ` AND ${statement(e, i
|
|
198
|
+
s += ` AND ${statement(e, i++)}`
|
|
184
199
|
break
|
|
185
200
|
case "or-scope": {
|
|
186
201
|
++l
|
|
@@ -189,7 +204,7 @@ export function buildWhereCosmosQuery3(
|
|
|
189
204
|
if (rel) {
|
|
190
205
|
const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
|
|
191
206
|
s += isRelation
|
|
192
|
-
? ` OR (\n${printN(l + 1)}${print(e.result,
|
|
207
|
+
? ` OR (\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
|
|
193
208
|
: ` OR (\n${printN(l + 1)}${
|
|
194
209
|
every ? "NOT " : ""
|
|
195
210
|
}EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
|
|
@@ -197,13 +212,12 @@ export function buildWhereCosmosQuery3(
|
|
|
197
212
|
e
|
|
198
213
|
.result
|
|
199
214
|
.map(flip(every)),
|
|
200
|
-
values,
|
|
201
215
|
rel,
|
|
202
216
|
every
|
|
203
217
|
)
|
|
204
218
|
}))`
|
|
205
219
|
} else {
|
|
206
|
-
s += ` OR (\n${printN(l + 1)}${print(e.result,
|
|
220
|
+
s += ` OR (\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
|
|
207
221
|
}
|
|
208
222
|
--l
|
|
209
223
|
break
|
|
@@ -215,14 +229,14 @@ export function buildWhereCosmosQuery3(
|
|
|
215
229
|
if (rel) {
|
|
216
230
|
const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
|
|
217
231
|
s += isRelation
|
|
218
|
-
? ` AND (\n${printN(l + 1)}${print(e.result,
|
|
232
|
+
? ` AND (\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
|
|
219
233
|
: ` AND (\n${printN(l + 1)}${
|
|
220
234
|
every ? "NOT " : ""
|
|
221
235
|
}EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
|
|
222
|
-
print(e.result.map(flip(every)),
|
|
236
|
+
print(e.result.map(flip(every)), rel, every)
|
|
223
237
|
}))`
|
|
224
238
|
} else {
|
|
225
|
-
s += ` AND (\n${printN(l + 1)}${print(e.result,
|
|
239
|
+
s += ` AND (\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
|
|
226
240
|
}
|
|
227
241
|
--l
|
|
228
242
|
break
|
|
@@ -234,12 +248,12 @@ export function buildWhereCosmosQuery3(
|
|
|
234
248
|
if (rel) {
|
|
235
249
|
const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
|
|
236
250
|
s += isRelation
|
|
237
|
-
? `(\n${printN(l + 1)}${print(e.result,
|
|
251
|
+
? `(\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
|
|
238
252
|
: `(\n${printN(l + 1)}${every ? "NOT " : ""}EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
|
|
239
|
-
print(e.result.map(flip(every)),
|
|
253
|
+
print(e.result.map(flip(every)), rel, every)
|
|
240
254
|
}))`
|
|
241
255
|
} else {
|
|
242
|
-
s += `(\n${printN(l + 1)}${print(e.result,
|
|
256
|
+
s += `(\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
|
|
243
257
|
}
|
|
244
258
|
// ;--l
|
|
245
259
|
break
|
|
@@ -272,7 +286,25 @@ export function buildWhereCosmosQuery3(
|
|
|
272
286
|
? getValues(_.result)
|
|
273
287
|
: [_]
|
|
274
288
|
)
|
|
275
|
-
const
|
|
289
|
+
const computedFilters = select
|
|
290
|
+
? select.flatMap((_) => typeof _ === "object" && "computed" in _ ? getValues(_.computed.filter) : [])
|
|
291
|
+
: []
|
|
292
|
+
const values = [...computedFilters, ...getValues(filter)]
|
|
293
|
+
|
|
294
|
+
const computedSelectExpr = (key: string, computed: ComputedProjectionIrExpression) => {
|
|
295
|
+
const relationPath = computed.path
|
|
296
|
+
const relationAlias = relationPath
|
|
297
|
+
const relationSource = dottedToAccess(`f.${relationPath}`)
|
|
298
|
+
const where = computed.filter.length > 0
|
|
299
|
+
? ` WHERE ${print(computed.filter, relationPath, false)}`
|
|
300
|
+
: ""
|
|
301
|
+
switch (computed._tag) {
|
|
302
|
+
case "relation-count":
|
|
303
|
+
return `(SELECT VALUE COUNT(1) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
304
|
+
case "relation-any":
|
|
305
|
+
return `EXISTS(SELECT VALUE ${relationAlias} FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
306
|
+
}
|
|
307
|
+
}
|
|
276
308
|
// with joins, you should use DISTINCT
|
|
277
309
|
// or you can end up with duplicates
|
|
278
310
|
return {
|
|
@@ -283,6 +315,8 @@ export function buildWhereCosmosQuery3(
|
|
|
283
315
|
.map((s) =>
|
|
284
316
|
typeof s === "string"
|
|
285
317
|
? dottedToAccess(s === idKey ? "f.id" : `f.${s}`) // x["y"} vs x.y, helps with reserved keywords like "value"
|
|
318
|
+
: "computed" in s
|
|
319
|
+
? computedSelectExpr(s.key, s.computed)
|
|
286
320
|
: `ARRAY (SELECT ${s.subKeys.map((_) => dottedToAccess(`t.${_}`)).join(",")}
|
|
287
321
|
FROM t in ${dottedToAccess(`f.${s.key}`)}) AS ${s.key}`
|
|
288
322
|
)
|
|
@@ -291,7 +325,7 @@ export function buildWhereCosmosQuery3(
|
|
|
291
325
|
}
|
|
292
326
|
FROM ${name} f
|
|
293
327
|
|
|
294
|
-
${filter.length ? `WHERE (${print(filter,
|
|
328
|
+
${filter.length ? `WHERE (${print(filter, null, false)})` : ""}
|
|
295
329
|
${order ? `ORDER BY ${order.map((_) => `${dottedToAccess(`f.${_.key}`)} ${_.direction}`).join(", ")}` : ""}
|
|
296
330
|
${skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""}`,
|
|
297
331
|
parameters: values
|
package/src/Store/Cosmos.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { CosmosClient, CosmosClientLayer } from "../adapters/cosmos-client.js"
|
|
|
7
7
|
import { OptimisticConcurrencyException } from "../errors.js"
|
|
8
8
|
import { InfraLogger } from "../logger.js"
|
|
9
9
|
import type { FieldValues } from "../Model/filter/types.js"
|
|
10
|
-
import { type RawQuery } from "../Model/query.js"
|
|
10
|
+
import { type ComputedProjectionIrExpression, type RawQuery } from "../Model/query.js"
|
|
11
11
|
import { annotateCosmosResponse, annotateDb } from "../otel.js"
|
|
12
12
|
import { buildWhereCosmosQuery3, logQuery } from "./Cosmos/query.js"
|
|
13
13
|
import { storeId } from "./Memory.js"
|
|
@@ -451,7 +451,15 @@ const makeCosmosStore = Effect.fnUntraced(function*({ prefix }: StorageConfig) {
|
|
|
451
451
|
name,
|
|
452
452
|
defaultValues,
|
|
453
453
|
f.select as
|
|
454
|
-
| NonEmptyReadonlyArray<
|
|
454
|
+
| NonEmptyReadonlyArray<
|
|
455
|
+
string | {
|
|
456
|
+
key: string
|
|
457
|
+
subKeys: readonly string[]
|
|
458
|
+
} | {
|
|
459
|
+
key: string
|
|
460
|
+
computed: ComputedProjectionIrExpression
|
|
461
|
+
}
|
|
462
|
+
>
|
|
455
463
|
| undefined,
|
|
456
464
|
f.order as NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }> | undefined,
|
|
457
465
|
skip,
|