effect-app 4.0.0-beta.307 → 4.0.0-beta.309
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 +8 -0
- package/dist/Model/Repository/dependency.d.ts +6 -0
- package/dist/Model/Repository/dependency.d.ts.map +1 -0
- package/dist/Model/Repository/dependency.js +29 -0
- package/dist/Model/Repository/ext.d.ts +14 -14
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +15 -13
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +59 -7
- package/dist/Model/Repository.d.ts +1 -0
- package/dist/Model/Repository.d.ts.map +1 -1
- package/dist/Model/Repository.js +2 -1
- package/dist/Model/query/dsl.js +43 -43
- package/dist/Model/query/new-kid-interpreter.js +1 -1
- package/dist/Model.d.ts +1 -0
- package/dist/Model.d.ts.map +1 -1
- package/dist/Model.js +2 -1
- package/dist/ids.js +1 -1
- package/package.json +1 -1
- package/src/Model/Repository/dependency.ts +32 -0
- package/src/Model/Repository/ext.ts +44 -45
- package/src/Model/Repository/internal/internal.ts +51 -11
- package/src/Model/Repository.ts +1 -0
- package/src/Model/query/dsl.ts +47 -47
- package/src/Model/query/new-kid-interpreter.ts +8 -8
- package/src/Model.ts +1 -0
- package/src/ids.ts +1 -1
- package/tsconfig.json +6 -1
|
@@ -5,7 +5,7 @@ import * as Request from "effect/Request"
|
|
|
5
5
|
import * as RequestResolver from "effect/RequestResolver"
|
|
6
6
|
import * as Array from "../../Array.ts"
|
|
7
7
|
import type { NonEmptyArray } from "../../Array.ts"
|
|
8
|
-
import { type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../../client/errors.ts"
|
|
8
|
+
import { type DatabaseError, type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../../client/errors.ts"
|
|
9
9
|
import * as Effect from "../../Effect.ts"
|
|
10
10
|
import * as Option from "../../Option.ts"
|
|
11
11
|
import { type FixEnv, type PureEnv, runTerm } from "../../Pure.ts"
|
|
@@ -89,7 +89,11 @@ export const extendRepo = <
|
|
|
89
89
|
A
|
|
90
90
|
>(
|
|
91
91
|
gen: Effect.Effect<readonly [Iterable<P>, Iterable<Evt>, A], E, R>
|
|
92
|
-
)
|
|
92
|
+
): Effect.Effect<
|
|
93
|
+
A,
|
|
94
|
+
E | InvalidStateError | OptimisticConcurrencyException | DatabaseError,
|
|
95
|
+
R | RSchema | RPublish
|
|
96
|
+
> {
|
|
93
97
|
return Effect.flatMap(gen, ([items, events, a]) => repo.saveAndPublish(items, events).pipe(Effect.map(() => a)))
|
|
94
98
|
}
|
|
95
99
|
|
|
@@ -113,6 +117,8 @@ export const extendRepo = <
|
|
|
113
117
|
)
|
|
114
118
|
}
|
|
115
119
|
|
|
120
|
+
type PureStoreError = InvalidStateError | OptimisticConcurrencyException | DatabaseError
|
|
121
|
+
|
|
116
122
|
const queryAndSavePure: {
|
|
117
123
|
<A, E2, R2, T2 extends T>(
|
|
118
124
|
q: (
|
|
@@ -121,8 +127,10 @@ export const extendRepo = <
|
|
|
121
127
|
pure: Effect.Effect<A, E2, FixEnv<R2, Evt, T, T2>>
|
|
122
128
|
): Effect.Effect<
|
|
123
129
|
A,
|
|
124
|
-
|
|
125
|
-
|
|
130
|
+
PureStoreError | NotFoundError<ItemType> | E2,
|
|
131
|
+
| RSchema
|
|
132
|
+
| RPublish
|
|
133
|
+
| Exclude<R2, {
|
|
126
134
|
env: PureEnv<Evt, T, T2>
|
|
127
135
|
}>
|
|
128
136
|
>
|
|
@@ -136,7 +144,7 @@ export const extendRepo = <
|
|
|
136
144
|
pure: Effect.Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>
|
|
137
145
|
): Effect.Effect<
|
|
138
146
|
A,
|
|
139
|
-
|
|
147
|
+
PureStoreError | E2,
|
|
140
148
|
| RSchema
|
|
141
149
|
| RPublish
|
|
142
150
|
| Exclude<R2, {
|
|
@@ -154,23 +162,25 @@ export const extendRepo = <
|
|
|
154
162
|
batch: "batched" | number
|
|
155
163
|
): Effect.Effect<
|
|
156
164
|
A[],
|
|
157
|
-
|
|
165
|
+
PureStoreError | E2,
|
|
158
166
|
| RSchema
|
|
159
167
|
| RPublish
|
|
160
168
|
| Exclude<R2, {
|
|
161
169
|
env: PureEnv<Evt, readonly T[], readonly T2[]>
|
|
162
170
|
}>
|
|
163
171
|
>
|
|
164
|
-
} = (q, pure, batch?: "batched" | number) =>
|
|
172
|
+
} = ((q: any, pure: any, batch?: "batched" | number) =>
|
|
173
|
+
// Overload dispatch: query returns T | T[]; pure helpers are generic on item shape.
|
|
174
|
+
// Runtime path is query → pure term → saveAndPublish (which raises DatabaseError).
|
|
165
175
|
repo.query(q).pipe(
|
|
166
176
|
Effect.andThen((_) =>
|
|
167
177
|
Array.isArray(_)
|
|
168
178
|
? batch === undefined
|
|
169
|
-
? saveManyWithPure_(_ as
|
|
170
|
-
: saveManyWithPureBatched_(_ as
|
|
171
|
-
: saveWithPure_(_ as
|
|
179
|
+
? saveManyWithPure_(_ as T[], pure)
|
|
180
|
+
: saveManyWithPureBatched_(_ as T[], pure, batch === "batched" ? 100 : batch)
|
|
181
|
+
: saveWithPure_(_ as T, pure)
|
|
172
182
|
)
|
|
173
|
-
) as
|
|
183
|
+
)) as typeof queryAndSavePure
|
|
174
184
|
|
|
175
185
|
const saveManyWithPure: {
|
|
176
186
|
<R, A, E, S1 extends T, S2 extends T>(
|
|
@@ -178,7 +188,7 @@ export const extendRepo = <
|
|
|
178
188
|
pure: Effect.Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>
|
|
179
189
|
): Effect.Effect<
|
|
180
190
|
A,
|
|
181
|
-
|
|
191
|
+
PureStoreError | E,
|
|
182
192
|
| RSchema
|
|
183
193
|
| RPublish
|
|
184
194
|
| Exclude<R, {
|
|
@@ -191,25 +201,25 @@ export const extendRepo = <
|
|
|
191
201
|
batch: "batched" | number
|
|
192
202
|
): Effect.Effect<
|
|
193
203
|
A[],
|
|
194
|
-
|
|
204
|
+
PureStoreError | E,
|
|
195
205
|
| RSchema
|
|
196
206
|
| RPublish
|
|
197
207
|
| Exclude<R, {
|
|
198
208
|
env: PureEnv<Evt, readonly S1[], readonly S2[]>
|
|
199
209
|
}>
|
|
200
210
|
>
|
|
201
|
-
} = (items
|
|
211
|
+
} = ((items: Iterable<T>, pure: any, batch?: "batched" | number) =>
|
|
202
212
|
batch
|
|
203
213
|
? Effect.forEach(
|
|
204
|
-
Array.chunksOf(items, batch === "batched" ? 100 : batch),
|
|
205
|
-
(
|
|
214
|
+
Array.chunksOf([...items], batch === "batched" ? 100 : batch),
|
|
215
|
+
(batchItems) =>
|
|
206
216
|
saveAllWithEffectInt(
|
|
207
|
-
runTerm(pure,
|
|
217
|
+
runTerm(pure, batchItems as any)
|
|
208
218
|
)
|
|
209
219
|
)
|
|
210
220
|
: saveAllWithEffectInt(
|
|
211
|
-
runTerm(pure, [...items])
|
|
212
|
-
)
|
|
221
|
+
runTerm(pure, [...items] as any)
|
|
222
|
+
)) as typeof saveManyWithPure
|
|
213
223
|
|
|
214
224
|
const byIdAndSaveWithPure: {
|
|
215
225
|
<R, A, E, S2 extends T>(
|
|
@@ -217,17 +227,19 @@ export const extendRepo = <
|
|
|
217
227
|
pure: Effect.Effect<A, E, FixEnv<R, Evt, T, S2>>
|
|
218
228
|
): Effect.Effect<
|
|
219
229
|
A,
|
|
220
|
-
|
|
230
|
+
PureStoreError | NotFoundError<ItemType> | E,
|
|
221
231
|
| RSchema
|
|
222
232
|
| RPublish
|
|
223
233
|
| Exclude<R, {
|
|
224
234
|
env: PureEnv<Evt, T, S2>
|
|
225
235
|
}>
|
|
226
236
|
>
|
|
227
|
-
} = (id, pure)
|
|
237
|
+
} = (id, pure) => get(id).pipe(Effect.flatMap((item) => saveWithPure_(item, pure)))
|
|
228
238
|
|
|
239
|
+
// query can raise DatabaseError; NotFound is completed per-entry. Dual package
|
|
240
|
+
// round-trips may still surface other store errors via failCause — keep channel honest.
|
|
229
241
|
type Req =
|
|
230
|
-
& Request.Request<T, NotFoundError<ItemType
|
|
242
|
+
& Request.Request<T, NotFoundError<ItemType> | DatabaseError>
|
|
231
243
|
& { _tag: `Get${ItemType}`; id: T[IdKey] }
|
|
232
244
|
const _request = Request.tagged<Req>(`Get${repo.itemType}`)
|
|
233
245
|
|
|
@@ -237,9 +249,9 @@ export const extendRepo = <
|
|
|
237
249
|
_key: unknown
|
|
238
250
|
) =>
|
|
239
251
|
(repo.query(Q.where(repo.idKey as any, "in" as any, entries.map((_) => _.request.id)) as any) as Effect.Effect<
|
|
240
|
-
readonly T[]
|
|
252
|
+
readonly T[],
|
|
253
|
+
DatabaseError
|
|
241
254
|
>)
|
|
242
|
-
// TODO
|
|
243
255
|
.pipe(
|
|
244
256
|
Effect.andThen((items) =>
|
|
245
257
|
Effect.forEach(entries, (entry) =>
|
|
@@ -270,7 +282,7 @@ export const extendRepo = <
|
|
|
270
282
|
* Enables chunked writes for large batches via `options.batch`.
|
|
271
283
|
* Note: batching breaks transactional properties because chunks are saved independently.
|
|
272
284
|
*/
|
|
273
|
-
save: (
|
|
285
|
+
save: (itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
|
|
274
286
|
const items = asReadonlyArray(itemOrItems)
|
|
275
287
|
if (!Array.isReadonlyArrayNonEmpty(items)) {
|
|
276
288
|
return Effect.void
|
|
@@ -284,23 +296,16 @@ export const extendRepo = <
|
|
|
284
296
|
(batch) => repo.saveAndPublish(batch),
|
|
285
297
|
{ discard: true }
|
|
286
298
|
)
|
|
287
|
-
}
|
|
288
|
-
itemOrItems: T | ReadonlyArray<T>,
|
|
289
|
-
options?: BatchOptions
|
|
290
|
-
) => Effect.Effect<
|
|
291
|
-
void,
|
|
292
|
-
InvalidStateError | OptimisticConcurrencyException,
|
|
293
|
-
RSchema | RPublish
|
|
294
|
-
>,
|
|
299
|
+
},
|
|
295
300
|
saveWithEvents: (events: Iterable<Evt>) => (...items: NonEmptyArray<T>) => repo.saveAndPublish(items, events),
|
|
296
301
|
/**
|
|
297
302
|
* Enables chunked deletes for large batches via `options.batch`.
|
|
298
303
|
* Note: batching breaks transactional properties because chunks are removed independently.
|
|
299
304
|
*/
|
|
300
|
-
remove: (
|
|
305
|
+
remove: (itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
|
|
301
306
|
const items = asReadonlyArray(itemOrItems)
|
|
302
307
|
if (!Array.isReadonlyArrayNonEmpty(items)) {
|
|
303
|
-
return Effect.void
|
|
308
|
+
return Effect.void as Effect.Effect<void, DatabaseError, RSchema | RPublish>
|
|
304
309
|
}
|
|
305
310
|
const batchSize = getBatchSize(options?.batch)
|
|
306
311
|
if (batchSize === undefined) {
|
|
@@ -311,18 +316,15 @@ export const extendRepo = <
|
|
|
311
316
|
(batch) => repo.removeAndPublish(batch),
|
|
312
317
|
{ discard: true }
|
|
313
318
|
)
|
|
314
|
-
}
|
|
315
|
-
itemOrItems: T | ReadonlyArray<T>,
|
|
316
|
-
options?: BatchOptions
|
|
317
|
-
) => Effect.Effect<void, never, RSchema | RPublish>,
|
|
319
|
+
},
|
|
318
320
|
/**
|
|
319
321
|
* Enables chunked deletes for large batches via `options.batch`.
|
|
320
322
|
* Note: batching breaks transactional properties because chunks are removed independently.
|
|
321
323
|
*/
|
|
322
|
-
removeById: (
|
|
324
|
+
removeById: (idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>, options?: BatchOptions) => {
|
|
323
325
|
const ids = asReadonlyArray(idOrIds)
|
|
324
326
|
if (!Array.isReadonlyArrayNonEmpty(ids)) {
|
|
325
|
-
return Effect.void
|
|
327
|
+
return Effect.void as Effect.Effect<void, DatabaseError, RSchema>
|
|
326
328
|
}
|
|
327
329
|
const batchSize = getBatchSize(options?.batch)
|
|
328
330
|
if (batchSize === undefined) {
|
|
@@ -333,10 +335,7 @@ export const extendRepo = <
|
|
|
333
335
|
(batch) => repo.removeById(batch),
|
|
334
336
|
{ discard: true }
|
|
335
337
|
)
|
|
336
|
-
}
|
|
337
|
-
idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>,
|
|
338
|
-
options?: BatchOptions
|
|
339
|
-
) => Effect.Effect<void, never, RSchema>,
|
|
338
|
+
},
|
|
340
339
|
queryAndSavePure,
|
|
341
340
|
saveManyWithPure,
|
|
342
341
|
byIdAndSaveWithPure,
|
|
@@ -25,8 +25,10 @@ import { type Codec, NonNegativeInt } from "../../../Schema.ts"
|
|
|
25
25
|
import * as SchemaAST from "../../../SchemaAST.ts"
|
|
26
26
|
import { setupRequestContextFromCurrent } from "../../../setupRequest.ts"
|
|
27
27
|
import { type FilterArgs, getContextMap, type PersistenceModelType, type StoreConfig, storeId, StoreMaker } from "../../../Store.ts"
|
|
28
|
+
import type { FilterResult } from "../../filter/filterApi.ts"
|
|
28
29
|
import type { FieldValues } from "../../filter/types.ts"
|
|
29
30
|
import * as Q from "../../query.ts"
|
|
31
|
+
import { repositoryDependencyPaths } from "../dependency.ts"
|
|
30
32
|
import type { ChangeFeed, ChangeFeedEvent, Repository } from "../service.ts"
|
|
31
33
|
import { ValidationError, ValidationResult } from "../validation.ts"
|
|
32
34
|
|
|
@@ -147,16 +149,55 @@ export function makeRepoInternal<
|
|
|
147
149
|
)
|
|
148
150
|
|
|
149
151
|
const store = yield* mkStore(args.makeInitial, args.config)
|
|
152
|
+
const dependencyPaths = repositoryDependencyPaths(schema)
|
|
150
153
|
const recordRead = DataDependencies.readRepo(name)
|
|
151
154
|
const entityDependency = (ids: NonEmptyReadonlyArray<T[IdKey]>) =>
|
|
152
155
|
DataDependencies.repo(name, [String(ids[0]), ...ids.slice(1).map(String)])
|
|
156
|
+
const valuesAtPath = (value: unknown, path: string): readonly unknown[] => {
|
|
157
|
+
if (path.length === 0) return [value]
|
|
158
|
+
const [head, ...tail] = path.split(".")
|
|
159
|
+
if (head === undefined) return [value]
|
|
160
|
+
if (head === "-1") {
|
|
161
|
+
return globalThis.Array.isArray(value)
|
|
162
|
+
? value.flatMap((item) => valuesAtPath(item, tail.join(".")))
|
|
163
|
+
: []
|
|
164
|
+
}
|
|
165
|
+
return typeof value === "object" && value !== null
|
|
166
|
+
? valuesAtPath((value as Record<string, unknown>)[head], tail.join("."))
|
|
167
|
+
: []
|
|
168
|
+
}
|
|
169
|
+
const dependencyIds = (item: T): NonEmptyReadonlyArray<string> => {
|
|
170
|
+
const configured = dependencyPaths
|
|
171
|
+
.flatMap((path) => valuesAtPath(item, String(path)))
|
|
172
|
+
.filter((value): value is string => typeof value === "string") ?? []
|
|
173
|
+
const ids = args.dependencyIds?.(item) ?? [String(item[idKey]), ...configured]
|
|
174
|
+
return [ids[0], ...ids.slice(1)]
|
|
175
|
+
}
|
|
153
176
|
const itemDependencies = (item: T) => {
|
|
154
|
-
const ids =
|
|
177
|
+
const ids = dependencyIds(item)
|
|
155
178
|
return [
|
|
156
179
|
DataDependencies.repo(name, ids),
|
|
157
180
|
...(args.additionalWriteDependencies?.(item) ?? [])
|
|
158
181
|
]
|
|
159
182
|
}
|
|
183
|
+
const queryDependencyIds = (filter: readonly FilterResult[] | undefined): readonly string[] => {
|
|
184
|
+
if (!filter) return []
|
|
185
|
+
const paths = new Set([String(idKey), ...dependencyPaths])
|
|
186
|
+
const visit = (items: readonly FilterResult[]): readonly string[] => {
|
|
187
|
+
if (items.some((item) => item.t === "or" || item.t === "or-scope")) return []
|
|
188
|
+
return items.flatMap((item) => {
|
|
189
|
+
if ("result" in item) return visit(item.result)
|
|
190
|
+
if (!paths.has(item.path)) return []
|
|
191
|
+
const value: unknown = item.value
|
|
192
|
+
if (item.op === "eq" && typeof value === "string") return [value]
|
|
193
|
+
if (item.op === "in" && globalThis.Array.isArray(value)) {
|
|
194
|
+
return value.filter((entry): entry is string => typeof entry === "string")
|
|
195
|
+
}
|
|
196
|
+
return []
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
return [...new Set(visit(filter))]
|
|
200
|
+
}
|
|
160
201
|
const recordEntityRead = (id: T[IdKey]) => DataDependencies.read(entityDependency([id]))
|
|
161
202
|
const recordEntityWrite = (ids: NonEmptyReadonlyArray<T[IdKey]>) =>
|
|
162
203
|
DataDependencies.write(entityDependency(ids))
|
|
@@ -166,12 +207,6 @@ export function makeRepoInternal<
|
|
|
166
207
|
DataDependencies.write,
|
|
167
208
|
{ discard: true }
|
|
168
209
|
)
|
|
169
|
-
const recordAdditionalItemWrites = (items: ReadonlyArray<T>) =>
|
|
170
|
-
Effect.forEach(
|
|
171
|
-
DataDependencies.merge(new Set(items.flatMap((item) => args.additionalWriteDependencies?.(item) ?? []))),
|
|
172
|
-
DataDependencies.write,
|
|
173
|
-
{ discard: true }
|
|
174
|
-
)
|
|
175
210
|
const cms = Effect.map(getContextMap.pipe(Effect.orDie), (_) => ({
|
|
176
211
|
get: (id: string) => _.get(`${name}.${id}`),
|
|
177
212
|
set: (id: string, etag: string | undefined) => _.set(`${name}.${id}`, etag)
|
|
@@ -353,7 +388,7 @@ export function makeRepoInternal<
|
|
|
353
388
|
const it = Chunk.fromIterable(items)
|
|
354
389
|
if (Chunk.isNonEmpty(it)) {
|
|
355
390
|
const values = Chunk.toReadonlyArray(it)
|
|
356
|
-
const previous = args.additionalWriteDependencies
|
|
391
|
+
const previous = args.additionalWriteDependencies || args.dependencyIds || dependencyPaths.length > 0
|
|
357
392
|
? yield* loadExistingItems(values.map((item) => item[idKey]))
|
|
358
393
|
: []
|
|
359
394
|
yield* recordItemWrite([values[0], ...values.slice(1), ...previous])
|
|
@@ -414,8 +449,9 @@ export function makeRepoInternal<
|
|
|
414
449
|
return
|
|
415
450
|
}
|
|
416
451
|
yield* recordEntityWrite(ids)
|
|
417
|
-
if (args.additionalWriteDependencies) {
|
|
418
|
-
yield* loadExistingItems(ids)
|
|
452
|
+
if (args.additionalWriteDependencies || args.dependencyIds || dependencyPaths.length > 0) {
|
|
453
|
+
const previous = yield* loadExistingItems(ids)
|
|
454
|
+
if (Array.isReadonlyArrayNonEmpty(previous)) yield* recordItemWrite(previous)
|
|
419
455
|
}
|
|
420
456
|
const { set } = yield* cms
|
|
421
457
|
const eids = yield* Effect.forEach(ids, (_) => encodeIdOnly(_ as any)).pipe(Effect.orDie)
|
|
@@ -485,6 +521,10 @@ export function makeRepoInternal<
|
|
|
485
521
|
): Effect.Effect<readonly A[], never, Exclude<R, RCtx>>
|
|
486
522
|
} = (<A, R, EncodedRefined extends Encoded = Encoded>(q: Q.QAll<Encoded, EncodedRefined, A, R>) => {
|
|
487
523
|
const a = Q.toFilter(q, schema)
|
|
524
|
+
const scopedIds = queryDependencyIds(a.filter)
|
|
525
|
+
const recordQueryRead = Array.isReadonlyArrayNonEmpty(scopedIds)
|
|
526
|
+
? DataDependencies.read(DataDependencies.repo(name, scopedIds))
|
|
527
|
+
: recordRead
|
|
488
528
|
// Mode dispatch — see `Q.project` JSDoc for the contract:
|
|
489
529
|
// aggregate: GROUP BY + aggregate functions at DB level; decode raw rows with schema; SchemaError surfaces.
|
|
490
530
|
// project : decode raw encoded rows with schema; no PM reverse-mapping; SchemaError surfaces.
|
|
@@ -563,7 +603,7 @@ export function makeRepoInternal<
|
|
|
563
603
|
"db.response.returned_rows": Array.isArray(r) ? r.length : 1
|
|
564
604
|
})
|
|
565
605
|
),
|
|
566
|
-
Effect.tap(() =>
|
|
606
|
+
Effect.tap(() => recordQueryRead),
|
|
567
607
|
Effect.withSpan("Repository.query", {
|
|
568
608
|
kind: "client",
|
|
569
609
|
attributes: { "app.entity": name }
|
package/src/Model/Repository.ts
CHANGED
package/src/Model/query/dsl.ts
CHANGED
|
@@ -707,7 +707,7 @@ export const relation = <
|
|
|
707
707
|
expr: {
|
|
708
708
|
field: (field: FieldPath<RelationElement<TFieldValues, P>>): ComputedProjectionMathExpression => ({
|
|
709
709
|
_tag: "field",
|
|
710
|
-
field
|
|
710
|
+
field
|
|
711
711
|
}),
|
|
712
712
|
mul: (
|
|
713
713
|
left: ComputedProjectionMathExpression,
|
|
@@ -716,33 +716,33 @@ export const relation = <
|
|
|
716
716
|
},
|
|
717
717
|
length: (): ComputedProjectionExpression<number> => ({
|
|
718
718
|
_tag: "relation-length",
|
|
719
|
-
path
|
|
719
|
+
path
|
|
720
720
|
}),
|
|
721
721
|
count: (operation?: ComputedProjectionOperation): ComputedProjectionExpression<number> =>
|
|
722
722
|
operation
|
|
723
723
|
? {
|
|
724
724
|
_tag: "relation-count",
|
|
725
|
-
path
|
|
725
|
+
path,
|
|
726
726
|
operation
|
|
727
727
|
}
|
|
728
728
|
: {
|
|
729
729
|
_tag: "relation-count",
|
|
730
|
-
path
|
|
730
|
+
path
|
|
731
731
|
},
|
|
732
732
|
any: (operation?: ComputedProjectionOperation): ComputedProjectionExpression<boolean> =>
|
|
733
733
|
operation
|
|
734
734
|
? {
|
|
735
735
|
_tag: "relation-any",
|
|
736
|
-
path
|
|
736
|
+
path,
|
|
737
737
|
operation
|
|
738
738
|
}
|
|
739
739
|
: {
|
|
740
740
|
_tag: "relation-any",
|
|
741
|
-
path
|
|
741
|
+
path
|
|
742
742
|
},
|
|
743
743
|
every: (operation: ComputedProjectionOperation): ComputedProjectionExpression<boolean> => ({
|
|
744
744
|
_tag: "relation-every",
|
|
745
|
-
path
|
|
745
|
+
path,
|
|
746
746
|
operation
|
|
747
747
|
}),
|
|
748
748
|
distinctCount: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
|
|
@@ -752,14 +752,14 @@ export const relation = <
|
|
|
752
752
|
operation
|
|
753
753
|
? {
|
|
754
754
|
_tag: "relation-distinct-count",
|
|
755
|
-
path
|
|
756
|
-
field
|
|
755
|
+
path,
|
|
756
|
+
field,
|
|
757
757
|
operation
|
|
758
758
|
}
|
|
759
759
|
: {
|
|
760
760
|
_tag: "relation-distinct-count",
|
|
761
|
-
path
|
|
762
|
-
field
|
|
761
|
+
path,
|
|
762
|
+
field
|
|
763
763
|
},
|
|
764
764
|
sum: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
|
|
765
765
|
field: F,
|
|
@@ -768,14 +768,14 @@ export const relation = <
|
|
|
768
768
|
operation
|
|
769
769
|
? {
|
|
770
770
|
_tag: "relation-sum",
|
|
771
|
-
path
|
|
772
|
-
field
|
|
771
|
+
path,
|
|
772
|
+
field,
|
|
773
773
|
operation
|
|
774
774
|
}
|
|
775
775
|
: {
|
|
776
776
|
_tag: "relation-sum",
|
|
777
|
-
path
|
|
778
|
-
field
|
|
777
|
+
path,
|
|
778
|
+
field
|
|
779
779
|
},
|
|
780
780
|
sumExpr: (
|
|
781
781
|
expression: ComputedProjectionMathExpression,
|
|
@@ -784,13 +784,13 @@ export const relation = <
|
|
|
784
784
|
operation
|
|
785
785
|
? {
|
|
786
786
|
_tag: "relation-sum-expr",
|
|
787
|
-
path
|
|
787
|
+
path,
|
|
788
788
|
expression,
|
|
789
789
|
operation
|
|
790
790
|
}
|
|
791
791
|
: {
|
|
792
792
|
_tag: "relation-sum-expr",
|
|
793
|
-
path
|
|
793
|
+
path,
|
|
794
794
|
expression
|
|
795
795
|
},
|
|
796
796
|
sumExprBy: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
|
|
@@ -803,16 +803,16 @@ export const relation = <
|
|
|
803
803
|
operation
|
|
804
804
|
? {
|
|
805
805
|
_tag: "relation-sum-expr-by",
|
|
806
|
-
path
|
|
806
|
+
path,
|
|
807
807
|
expression,
|
|
808
|
-
unit: options.unit
|
|
808
|
+
unit: options.unit,
|
|
809
809
|
operation
|
|
810
810
|
}
|
|
811
811
|
: {
|
|
812
812
|
_tag: "relation-sum-expr-by",
|
|
813
|
-
path
|
|
813
|
+
path,
|
|
814
814
|
expression,
|
|
815
|
-
unit: options.unit
|
|
815
|
+
unit: options.unit
|
|
816
816
|
},
|
|
817
817
|
sumExprNormalized: (
|
|
818
818
|
expression: ComputedProjectionMathExpression,
|
|
@@ -826,18 +826,18 @@ export const relation = <
|
|
|
826
826
|
operation
|
|
827
827
|
? {
|
|
828
828
|
_tag: "relation-sum-expr-normalized",
|
|
829
|
-
path
|
|
829
|
+
path,
|
|
830
830
|
expression,
|
|
831
|
-
unit: options.unit
|
|
831
|
+
unit: options.unit,
|
|
832
832
|
toBase: options.toBase,
|
|
833
833
|
factors: options.factors,
|
|
834
834
|
operation
|
|
835
835
|
}
|
|
836
836
|
: {
|
|
837
837
|
_tag: "relation-sum-expr-normalized",
|
|
838
|
-
path
|
|
838
|
+
path,
|
|
839
839
|
expression,
|
|
840
|
-
unit: options.unit
|
|
840
|
+
unit: options.unit,
|
|
841
841
|
toBase: options.toBase,
|
|
842
842
|
factors: options.factors
|
|
843
843
|
},
|
|
@@ -848,15 +848,15 @@ export const relation = <
|
|
|
848
848
|
operation
|
|
849
849
|
? {
|
|
850
850
|
_tag: "relation-collect",
|
|
851
|
-
path
|
|
852
|
-
field
|
|
851
|
+
path,
|
|
852
|
+
field,
|
|
853
853
|
distinct: false,
|
|
854
854
|
operation
|
|
855
855
|
}
|
|
856
856
|
: {
|
|
857
857
|
_tag: "relation-collect",
|
|
858
|
-
path
|
|
859
|
-
field
|
|
858
|
+
path,
|
|
859
|
+
field,
|
|
860
860
|
distinct: false
|
|
861
861
|
},
|
|
862
862
|
collectDistinct: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
|
|
@@ -866,15 +866,15 @@ export const relation = <
|
|
|
866
866
|
operation
|
|
867
867
|
? {
|
|
868
868
|
_tag: "relation-collect",
|
|
869
|
-
path
|
|
870
|
-
field
|
|
869
|
+
path,
|
|
870
|
+
field,
|
|
871
871
|
distinct: true,
|
|
872
872
|
operation
|
|
873
873
|
}
|
|
874
874
|
: {
|
|
875
875
|
_tag: "relation-collect",
|
|
876
|
-
path
|
|
877
|
-
field
|
|
876
|
+
path,
|
|
877
|
+
field,
|
|
878
878
|
distinct: true
|
|
879
879
|
},
|
|
880
880
|
collectFields: <const F extends readonly FieldPath<RelationElement<TFieldValues, P>>[]>(
|
|
@@ -886,15 +886,15 @@ export const relation = <
|
|
|
886
886
|
operation
|
|
887
887
|
? {
|
|
888
888
|
_tag: "relation-collect-fields",
|
|
889
|
-
path
|
|
890
|
-
fields
|
|
889
|
+
path,
|
|
890
|
+
fields,
|
|
891
891
|
distinct: false,
|
|
892
892
|
operation
|
|
893
893
|
}
|
|
894
894
|
: {
|
|
895
895
|
_tag: "relation-collect-fields",
|
|
896
|
-
path
|
|
897
|
-
fields
|
|
896
|
+
path,
|
|
897
|
+
fields,
|
|
898
898
|
distinct: false
|
|
899
899
|
},
|
|
900
900
|
collectDistinctFields: <const F extends readonly FieldPath<RelationElement<TFieldValues, P>>[]>(
|
|
@@ -906,15 +906,15 @@ export const relation = <
|
|
|
906
906
|
operation
|
|
907
907
|
? {
|
|
908
908
|
_tag: "relation-collect-fields",
|
|
909
|
-
path
|
|
910
|
-
fields
|
|
909
|
+
path,
|
|
910
|
+
fields,
|
|
911
911
|
distinct: true,
|
|
912
912
|
operation
|
|
913
913
|
}
|
|
914
914
|
: {
|
|
915
915
|
_tag: "relation-collect-fields",
|
|
916
|
-
path
|
|
917
|
-
fields
|
|
916
|
+
path,
|
|
917
|
+
fields,
|
|
918
918
|
distinct: true
|
|
919
919
|
}
|
|
920
920
|
})
|
|
@@ -930,7 +930,7 @@ export const relation = <
|
|
|
930
930
|
export const expr = {
|
|
931
931
|
field: <T extends FieldValues = FieldValues>(
|
|
932
932
|
field: FieldPath<T>
|
|
933
|
-
): ComputedProjectionMathExpression => ({ _tag: "field", field
|
|
933
|
+
): ComputedProjectionMathExpression => ({ _tag: "field", field }),
|
|
934
934
|
mul: (
|
|
935
935
|
left: ComputedProjectionMathExpression,
|
|
936
936
|
right: ComputedProjectionMathExpression
|
|
@@ -1059,7 +1059,7 @@ export const projectComputed: {
|
|
|
1059
1059
|
const computedProjection = typeof mapOrBuild === "function"
|
|
1060
1060
|
? mapOrBuild(makeComputedHelpers())
|
|
1061
1061
|
: mapOrBuild
|
|
1062
|
-
return new Project({ current, schema, mode, computed: computedProjection }
|
|
1062
|
+
return new Project({ current, schema, mode, computed: computedProjection })
|
|
1063
1063
|
}
|
|
1064
1064
|
|
|
1065
1065
|
/**
|
|
@@ -1077,12 +1077,12 @@ export interface AggBuilder<TFieldValues extends FieldValues> {
|
|
|
1077
1077
|
}
|
|
1078
1078
|
|
|
1079
1079
|
const makeAggBuilder = <TFieldValues extends FieldValues>(): AggBuilder<TFieldValues> => ({
|
|
1080
|
-
field: (path) => ({ _tag: "agg-field", path
|
|
1080
|
+
field: (path) => ({ _tag: "agg-field", path }),
|
|
1081
1081
|
count: () => ({ _tag: "agg-count" }),
|
|
1082
1082
|
countWhen: (operation) => ({ _tag: "agg-count-when", operation }),
|
|
1083
|
-
sum: (field) => ({ _tag: "agg-sum", field
|
|
1084
|
-
min: (field) => ({ _tag: "agg-min", field
|
|
1085
|
-
max: (field) => ({ _tag: "agg-max", field
|
|
1083
|
+
sum: (field) => ({ _tag: "agg-sum", field }),
|
|
1084
|
+
min: (field) => ({ _tag: "agg-min", field }),
|
|
1085
|
+
max: (field) => ({ _tag: "agg-max", field })
|
|
1086
1086
|
})
|
|
1087
1087
|
|
|
1088
1088
|
/**
|
|
@@ -316,17 +316,17 @@ const interpret = <
|
|
|
316
316
|
case "relation-count":
|
|
317
317
|
case "relation-any":
|
|
318
318
|
case "relation-every":
|
|
319
|
-
return [key, { _tag: e._tag, path: e.path, filter }
|
|
319
|
+
return [key, { _tag: e._tag, path: e.path, filter }]
|
|
320
320
|
case "relation-distinct-count":
|
|
321
321
|
case "relation-sum":
|
|
322
322
|
return [
|
|
323
323
|
key,
|
|
324
|
-
{ _tag: e._tag, path: e.path, field: e.field, filter }
|
|
324
|
+
{ _tag: e._tag, path: e.path, field: e.field, filter }
|
|
325
325
|
]
|
|
326
326
|
case "relation-sum-expr":
|
|
327
327
|
return [
|
|
328
328
|
key,
|
|
329
|
-
{ _tag: e._tag, path: e.path, expression: e.expression, filter }
|
|
329
|
+
{ _tag: e._tag, path: e.path, expression: e.expression, filter }
|
|
330
330
|
]
|
|
331
331
|
case "relation-sum-expr-by":
|
|
332
332
|
return [
|
|
@@ -337,7 +337,7 @@ const interpret = <
|
|
|
337
337
|
expression: e.expression,
|
|
338
338
|
unit: e.unit,
|
|
339
339
|
filter
|
|
340
|
-
}
|
|
340
|
+
}
|
|
341
341
|
]
|
|
342
342
|
case "relation-sum-expr-normalized":
|
|
343
343
|
return [
|
|
@@ -350,7 +350,7 @@ const interpret = <
|
|
|
350
350
|
toBase: e.toBase,
|
|
351
351
|
factors: e.factors,
|
|
352
352
|
filter
|
|
353
|
-
}
|
|
353
|
+
}
|
|
354
354
|
]
|
|
355
355
|
case "relation-collect":
|
|
356
356
|
return [
|
|
@@ -361,7 +361,7 @@ const interpret = <
|
|
|
361
361
|
field: e.field,
|
|
362
362
|
distinct: e.distinct,
|
|
363
363
|
filter
|
|
364
|
-
}
|
|
364
|
+
}
|
|
365
365
|
]
|
|
366
366
|
case "relation-collect-fields":
|
|
367
367
|
return [
|
|
@@ -372,10 +372,10 @@ const interpret = <
|
|
|
372
372
|
fields: e.fields,
|
|
373
373
|
distinct: e.distinct,
|
|
374
374
|
filter
|
|
375
|
-
}
|
|
375
|
+
}
|
|
376
376
|
]
|
|
377
377
|
case "relation-length":
|
|
378
|
-
return [key, { _tag: e._tag, path: e.path }
|
|
378
|
+
return [key, { _tag: e._tag, path: e.path }]
|
|
379
379
|
}
|
|
380
380
|
})
|
|
381
381
|
)
|
package/src/Model.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./Model/dsl.ts"
|
|
2
2
|
export * as Q from "./Model/query.ts"
|
|
3
3
|
export { makeRepo } from "./Model/Repository.ts"
|
|
4
|
+
export { repositoryDependency } from "./Model/Repository.ts"
|
|
4
5
|
export { type RegisteredRepository, RepositoryRegistry, RepositoryRegistryLive } from "./Model/Repository.ts"
|