@effect-app/infra 0.200.1 → 0.200.3

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 (32) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/_cjs/services/RepositoryBase.cjs +3 -0
  3. package/_cjs/services/RepositoryBase.cjs.map +1 -1
  4. package/_cjs/services/query/dsl.cjs +79 -0
  5. package/_cjs/services/query/dsl.cjs.map +1 -0
  6. package/_cjs/services/query/new-kid-interpreter.cjs +129 -0
  7. package/_cjs/services/query/new-kid-interpreter.cjs.map +1 -0
  8. package/_cjs/services/query.cjs +20 -200
  9. package/_cjs/services/query.cjs.map +1 -1
  10. package/_cjs/services/query.test.cjs +34 -0
  11. package/_cjs/services/query.test.cjs.map +1 -0
  12. package/dist/services/QueueMaker/memQueue.d.ts +1 -1
  13. package/dist/services/QueueMaker/sbqueue.d.ts +1 -1
  14. package/dist/services/RepositoryBase.d.ts +10 -10
  15. package/dist/services/RepositoryBase.d.ts.map +1 -1
  16. package/dist/services/RepositoryBase.js +4 -1
  17. package/dist/services/query/dsl.d.ts +127 -0
  18. package/dist/services/query/dsl.d.ts.map +1 -0
  19. package/dist/services/query/dsl.js +38 -0
  20. package/dist/services/query/new-kid-interpreter.d.ts +15 -0
  21. package/dist/services/query/new-kid-interpreter.d.ts.map +1 -0
  22. package/dist/services/query/new-kid-interpreter.js +110 -0
  23. package/dist/services/query.d.ts +2 -163
  24. package/dist/services/query.d.ts.map +1 -1
  25. package/dist/services/query.js +3 -157
  26. package/dist/services/query.test.d.ts.map +1 -0
  27. package/package.json +23 -3
  28. package/src/services/RepositoryBase.ts +13 -10
  29. package/src/services/query/dsl.ts +290 -0
  30. package/src/services/query/new-kid-interpreter.ts +169 -0
  31. package/src/services/query.test.ts +37 -0
  32. package/src/services/query.ts +2 -462
@@ -1,462 +1,2 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { toNonEmptyArray } from "@effect-app/core/Array"
3
- import type { FieldValues } from "@effect-app/infra/filter/types"
4
- import type { FieldPath, FieldPathValue } from "@effect-app/infra/filter/types/path/eager"
5
- import type { Repository } from "@effect-app/infra/services/Repository"
6
- import type { PersistenceModelType } from "@effect-app/infra/services/Store"
7
- import type { Ops } from "@effect-app/infra/services/Store/filterApi/proxy"
8
- import type { FilterResult, QueryBuilder } from "@effect-app/infra/services/Store/filterApi/query"
9
- import { Data, Effect, Match, Option, pipe, S, Unify } from "effect-app"
10
- import type { NoInfer } from "effect/Types"
11
-
12
- export type QAll<TFieldValues extends FieldValues, A = TFieldValues, R = never> =
13
- | Query<TFieldValues>
14
- | QueryWhere<TFieldValues>
15
- | QueryEnd<TFieldValues>
16
- | QueryProjection<TFieldValues, A, R>
17
-
18
- export interface Query<TFieldValues extends FieldValues> {
19
- readonly args: { TFieldValues: TFieldValues }
20
- readonly _id: unique symbol
21
- }
22
- export interface QueryWhere<TFieldValues extends FieldValues> {
23
- readonly args: { TFieldValues: TFieldValues }
24
- readonly _id2: unique symbol
25
- }
26
-
27
- export interface QueryEnd<TFieldValues extends FieldValues> {
28
- readonly args: { TFieldValues: TFieldValues }
29
- readonly _id3: unique symbol
30
- }
31
-
32
- export interface QueryProjection<TFieldValues extends FieldValues, A = TFieldValues, R = never> {
33
- readonly args: { TFieldValues: TFieldValues; A: A; R: R }
34
- readonly _id4: unique symbol
35
- }
36
-
37
- // Impl, later
38
- export type Q<TFieldValues extends FieldValues> =
39
- | Initial<TFieldValues>
40
- | Where<TFieldValues>
41
- | And<TFieldValues>
42
- | Or<TFieldValues>
43
- | Order<TFieldValues, any>
44
- | Page<TFieldValues>
45
- | Project<any, TFieldValues, any>
46
-
47
- export class Initial<TFieldValues extends FieldValues> extends Data.TaggedClass("value")<{ value: "initial" }>
48
- implements Query<TFieldValues>
49
- {
50
- readonly _id: any
51
- readonly args: any
52
- constructor() {
53
- super({ value: "initial" as const })
54
- }
55
- }
56
-
57
- export class Where<TFieldValues extends FieldValues> extends Data.TaggedClass("where")<{
58
- current: Query<TFieldValues>
59
- operation: [string, Ops, any] | [string, any]
60
- }> implements QueryWhere<TFieldValues> {
61
- _id2!: any
62
- _id: any
63
- readonly args: any
64
- }
65
-
66
- export class And<TFieldValues extends FieldValues> extends Data.TaggedClass("and")<{
67
- current: Query<TFieldValues>
68
- operation: [string, Ops, any] | [string, any] | ((q: Query<TFieldValues>) => QueryWhere<TFieldValues>)
69
- }> implements QueryWhere<TFieldValues> {
70
- _id2!: any
71
- _id: any
72
- readonly args: any
73
- }
74
-
75
- export class Or<TFieldValues extends FieldValues> extends Data.TaggedClass("or")<{
76
- current: Query<TFieldValues>
77
- operation: [string, Ops, any] | [string, any] | ((q: Query<TFieldValues>) => QueryWhere<TFieldValues>)
78
- }> implements QueryWhere<TFieldValues> {
79
- _id2!: any
80
- _id: any
81
- readonly args: any
82
- }
83
-
84
- export class Page<TFieldValues extends FieldValues> extends Data.TaggedClass("page")<{
85
- current: Query<TFieldValues> | QueryWhere<TFieldValues> | QueryEnd<TFieldValues>
86
- limit?: number | undefined
87
- skip?: number | undefined
88
- }> implements QueryEnd<TFieldValues> {
89
- _id3!: any
90
- readonly args: any
91
- }
92
-
93
- export class Order<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>>
94
- extends Data.TaggedClass("order")<{
95
- current: Query<TFieldValues> | QueryWhere<TFieldValues> | QueryEnd<TFieldValues>
96
- field: TFieldName
97
- direction: "ASC" | "DESC"
98
- }>
99
- implements QueryEnd<TFieldValues>
100
- {
101
- _id3!: any
102
- readonly args: any
103
- }
104
-
105
- export class Project<A, TFieldValues extends FieldValues, R> extends Data.TaggedClass("project")<{
106
- current: Query<TFieldValues> | QueryWhere<TFieldValues> | QueryEnd<TFieldValues>
107
- schema: S.Schema<A, TFieldValues, R>
108
- }> implements QueryProjection<TFieldValues, A, R> {
109
- _id4!: any
110
- readonly args: any
111
- }
112
-
113
- const wh: any = (...operation: any[]) => (current: any[]) => new Where({ current, operation } as any)
114
- export const where: FilterWhere = wh
115
-
116
- export const and: FilterContinuation = (...operation: any[]) => (current: any) =>
117
- new And({ current, operation: typeof operation[0] === "function" ? operation[0] : operation } as any)
118
-
119
- export const or: FilterContinuation = (...operation: any[]) => (current: any) =>
120
- new Or({ current, operation: typeof operation[0] === "function" ? operation[0] : operation } as any)
121
-
122
- export const order: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>>(
123
- field: TFieldName,
124
- desc?: boolean
125
- ) => (current: Query<TFieldValues> | QueryWhere<TFieldValues> | QueryEnd<TFieldValues>) => QueryEnd<TFieldValues> =
126
- (field, desc) => (current) => new Order({ current, field, direction: desc ? "DESC" : "ASC" })
127
-
128
- export const page: <TFieldValues extends FieldValues>(
129
- page: { limit?: number; skip?: number }
130
- ) => (current: Query<TFieldValues> | QueryWhere<TFieldValues> | QueryEnd<TFieldValues>) => QueryEnd<TFieldValues> =
131
- ({ limit, skip }) => (current) =>
132
- new Page({
133
- current,
134
- limit,
135
- skip
136
- })
137
-
138
- export const project: <TFieldValues extends FieldValues, A, R>(
139
- schema: S.Schema<A, TFieldValues, R>
140
- // TODO: should be able to use a subset of FieldValues and use select
141
- ) => (
142
- current: Query<TFieldValues> | QueryWhere<TFieldValues> | QueryEnd<TFieldValues>
143
- ) => QueryProjection<TFieldValues, A, R> = (schema) => (current) => new Project({ current, schema })
144
-
145
- // TODO: able to switch to Order and Limit/Take, which are "enders"
146
- export type FilterWheres = {
147
- <
148
- TFieldValues extends FieldValues,
149
- TFieldName extends FieldPath<TFieldValues>,
150
- V extends FieldPathValue<TFieldValues, TFieldName>
151
- >(
152
- path: TFieldName,
153
- value: V
154
- ): (
155
- current: Query<TFieldValues>
156
- ) => QueryWhere<TFieldValues>
157
- <
158
- TFieldValues extends FieldValues,
159
- TFieldName extends FieldPath<TFieldValues>,
160
- V extends FieldPathValue<TFieldValues, TFieldName>
161
- >(
162
- path: TFieldName,
163
- op: "neq",
164
- value: V
165
- ): (
166
- current: Query<TFieldValues>
167
- ) => QueryWhere<TFieldValues>
168
- <
169
- TFieldValues extends FieldValues,
170
- TFieldName extends FieldPath<TFieldValues>,
171
- V extends FieldPathValue<TFieldValues, TFieldName>
172
- >(
173
- path: TFieldName,
174
- op: "gt" | "gte" | "lt" | "lte",
175
- value: V // only numbers?
176
- ): (
177
- current: Query<TFieldValues>
178
- ) => QueryWhere<TFieldValues>
179
- <
180
- TFieldValues extends FieldValues,
181
- TFieldName extends FieldPath<TFieldValues>,
182
- V extends FieldPathValue<TFieldValues, TFieldName>
183
- >(
184
- path: TFieldName,
185
- op: "startsWith" | "endsWith" | "contains" | "notContains" | "notStartsWith" | "notEndsWith",
186
- value: V // only strings?
187
- ): (
188
- current: Query<TFieldValues>
189
- ) => QueryWhere<TFieldValues>
190
- <
191
- TFieldValues extends FieldValues,
192
- TFieldName extends FieldPath<TFieldValues>,
193
- V extends FieldPathValue<TFieldValues, TFieldName>
194
- >(
195
- path: TFieldName,
196
- op: "in" | "notIn",
197
- value: readonly V[]
198
- ): (
199
- current: Query<TFieldValues>
200
- ) => QueryWhere<TFieldValues>
201
- }
202
-
203
- export type FilterWhere = {
204
- <
205
- TFieldValues extends FieldValues,
206
- TFieldName extends FieldPath<TFieldValues>,
207
- V extends FieldPathValue<TFieldValues, TFieldName>
208
- >(f: {
209
- path: TFieldName
210
- op: Ops
211
- value: V
212
- }): (
213
- current: Query<TFieldValues>
214
- ) => QueryWhere<TFieldValues>
215
- } & FilterWheres
216
-
217
- export type FilterContinuations = {
218
- <
219
- TFieldValues extends FieldValues,
220
- TFieldName extends FieldPath<TFieldValues>,
221
- V extends FieldPathValue<TFieldValues, TFieldName>
222
- >(
223
- path: TFieldName,
224
- value: V
225
- ): (
226
- current: QueryWhere<TFieldValues>
227
- ) => QueryWhere<TFieldValues>
228
- <
229
- TFieldValues extends FieldValues,
230
- TFieldName extends FieldPath<TFieldValues>,
231
- V extends FieldPathValue<TFieldValues, TFieldName>
232
- >(
233
- path: TFieldName,
234
- op: "neq",
235
- value: V
236
- ): (
237
- current: QueryWhere<TFieldValues>
238
- ) => QueryWhere<TFieldValues>
239
- <
240
- TFieldValues extends FieldValues,
241
- TFieldName extends FieldPath<TFieldValues>,
242
- V extends FieldPathValue<TFieldValues, TFieldName>
243
- >(
244
- path: TFieldName,
245
- op: "gt" | "gte" | "lt" | "lte",
246
- value: V // only numbers?
247
- ): (
248
- current: QueryWhere<TFieldValues>
249
- ) => QueryWhere<TFieldValues>
250
- <
251
- TFieldValues extends FieldValues,
252
- TFieldName extends FieldPath<TFieldValues>,
253
- V extends FieldPathValue<TFieldValues, TFieldName>
254
- >(
255
- path: TFieldName,
256
- op: "startsWith" | "endsWith" | "contains" | "notContains" | "notStartsWith" | "notEndsWith",
257
- value: V // only strings?
258
- ): (
259
- current: QueryWhere<TFieldValues>
260
- ) => QueryWhere<TFieldValues>
261
- <
262
- TFieldValues extends FieldValues,
263
- TFieldName extends FieldPath<TFieldValues>,
264
- V extends FieldPathValue<TFieldValues, TFieldName>
265
- >(
266
- path: TFieldName,
267
- op: "in" | "notIn",
268
- value: readonly V[]
269
- ): (
270
- current: QueryWhere<TFieldValues>
271
- ) => QueryWhere<TFieldValues>
272
- }
273
-
274
- export type FilterContinuation = {
275
- <TFieldValues extends FieldValues>(
276
- fb: (
277
- current: Query<TFieldValues>
278
- ) => QueryWhere<TFieldValues>
279
- ): (
280
- current: QueryWhere<TFieldValues>
281
- ) => QueryWhere<TFieldValues>
282
- <
283
- TFieldValues extends FieldValues,
284
- TFieldName extends FieldPath<TFieldValues>,
285
- V extends FieldPathValue<TFieldValues, TFieldName>
286
- >(f: {
287
- path: TFieldName
288
- op: Ops
289
- value: V
290
- }): (
291
- current: QueryWhere<TFieldValues>
292
- ) => QueryWhere<TFieldValues>
293
- } & FilterContinuations
294
-
295
- export const make: <TFieldValues extends FieldValues>() => Query<TFieldValues> = () => new Initial()
296
- export interface A {
297
- a: string
298
- b: number
299
- c: boolean
300
- }
301
-
302
- const interpret = <TFieldValues extends FieldValues, A = TFieldValues, R = never>(_: QAll<TFieldValues, A, R>) => {
303
- const values: FilterResult[] = []
304
- const a = _ as Q<TFieldValues>
305
-
306
- let schema: S.Schema<A, TFieldValues, R> | undefined = undefined as any
307
- let limit: number | undefined = undefined as any
308
- let skip: number | undefined = undefined as any
309
- const order: { field: FieldPath<TFieldValues>; direction: "ASC" | "DESC" }[] = []
310
-
311
- const upd = (v: { schema: any; limit: any; skip: any; filter: readonly FilterResult[]; order: any[] }) => {
312
- values.push(...v.filter)
313
- order.push(...v.order)
314
- limit = v.limit
315
- skip = v.skip
316
- schema = v.schema
317
- }
318
-
319
- pipe(
320
- a,
321
- Match.valueTags({
322
- value: () => {
323
- // values.push(value)
324
- },
325
- where: ({ current, operation }) => {
326
- upd(interpret(current))
327
- values.push(
328
- {
329
- t: "where",
330
- path: operation[0],
331
- op: operation.length === 2 ? "eq" : operation[1],
332
- value: operation.length === 2 ? operation[1] : operation[2]
333
- }
334
- )
335
- },
336
- and: ({ current, operation }) => {
337
- upd(interpret(current))
338
- if (typeof operation === "function") {
339
- values.push(
340
- { t: "and-scope", result: interpret(operation(make())).filter }
341
- )
342
- } else {
343
- values.push(
344
- {
345
- t: "and",
346
- path: operation[0],
347
- op: operation.length === 2 ? "eq" : operation[1],
348
- value: operation.length === 2 ? operation[1] : operation[2]
349
- }
350
- )
351
- }
352
- },
353
- or: ({ current, operation }) => {
354
- upd(interpret(current))
355
- if (typeof operation === "function") {
356
- values.push(
357
- { t: "or-scope", result: interpret(operation(make())).filter }
358
- )
359
- } else {
360
- values.push(
361
- {
362
- t: "or",
363
- path: operation[0],
364
- op: operation.length === 2 ? "eq" : operation[1],
365
- value: operation.length === 2 ? operation[1] : operation[2]
366
- }
367
- )
368
- }
369
- },
370
- order: ({ current }) => {
371
- upd(interpret(current))
372
- },
373
- page: (v) => {
374
- upd(interpret(v.current))
375
- limit = v.limit
376
- skip = v.skip
377
- },
378
- project: (v) => {
379
- upd(interpret(v.current))
380
- schema = v.schema
381
- }
382
- })
383
- )
384
-
385
- // TODO
386
- return {
387
- filter: values,
388
- limit,
389
- skip,
390
- schema,
391
- order
392
- }
393
- }
394
-
395
- export const query: {
396
- <
397
- T extends { id: unknown },
398
- PM extends PersistenceModelType<string>,
399
- Evt,
400
- ItemType extends string,
401
- A,
402
- R,
403
- From extends FieldValues
404
- >(
405
- repo: Repository<T, PM, Evt, ItemType>,
406
- q: QueryProjection<PM extends From ? From : never, A, R>
407
- ): Effect.Effect<readonly A[], S.ParseResult.ParseError, R>
408
- <
409
- T extends { id: unknown },
410
- PM extends PersistenceModelType<string>,
411
- Evt,
412
- ItemType extends string,
413
- A,
414
- R
415
- >(
416
- repo: Repository<T, PM, Evt, ItemType>,
417
- q: QAll<NoInfer<PM>, A, R>
418
- ): Effect.Effect<readonly T[], never, R>
419
- } = (<
420
- T extends { id: unknown },
421
- PM extends PersistenceModelType<string>,
422
- Evt,
423
- ItemType extends string,
424
- A,
425
- R
426
- >(repo: Repository<T, PM, Evt, ItemType>, q: QAll<PM, A, R>) => {
427
- // TODO: Native interpreter for each db adapter, instead of the intermediate "new-kid" format
428
- const a = interpret(q)
429
- const schema = a.schema
430
- let select: (keyof PM)[] = []
431
- if (schema) {
432
- let t = schema.ast
433
- if (S.AST.isTransform(t)) {
434
- t = t.from
435
- }
436
- if (S.AST.isTypeLiteral(t)) {
437
- select = t.propertySignatures.map((_) => _.name) as any
438
- }
439
- }
440
- return pipe(
441
- a.filter.length === 0
442
- ? repo.utils.all
443
- : repo.utils.filter({
444
- limit: a.limit,
445
- skip: a.skip,
446
- select: Option.getOrUndefined(toNonEmptyArray(select)),
447
- filter: a.filter.length
448
- ? {
449
- type: "new-kid" as const,
450
- build: () => a.filter
451
- } as any as QueryBuilder<any>
452
- : undefined
453
- }),
454
- Effect.flatMap((_) =>
455
- Unify.unify(
456
- schema
457
- ? repo.utils.parseMany2(_, schema as any)
458
- : repo.utils.parseMany(_)
459
- )
460
- )
461
- )
462
- }) as any
1
+ export * from "./query/dsl.js"
2
+ export * from "./query/new-kid-interpreter.js"