@open-mercato/shared 0.5.1-develop.2691.d8a0934b37 → 0.5.1-develop.2694.732417c5ec
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/dist/lib/api/crud.js +1 -1
- package/dist/lib/api/crud.js.map +2 -2
- package/dist/lib/auth/server.js +1 -1
- package/dist/lib/auth/server.js.map +2 -2
- package/dist/lib/data/engine.js +68 -27
- package/dist/lib/data/engine.js.map +2 -2
- package/dist/lib/db/mikro.js +18 -22
- package/dist/lib/db/mikro.js.map +2 -2
- package/dist/lib/indexers/error-log.js +10 -12
- package/dist/lib/indexers/error-log.js.map +2 -2
- package/dist/lib/indexers/status-log.js +14 -16
- package/dist/lib/indexers/status-log.js.map +2 -2
- package/dist/lib/query/engine.js +220 -228
- package/dist/lib/query/engine.js.map +3 -3
- package/dist/lib/query/join-utils.js +28 -23
- package/dist/lib/query/join-utils.js.map +2 -2
- package/dist/lib/version.js +1 -1
- package/dist/lib/version.js.map +1 -1
- package/jest.config.cjs +4 -2
- package/package.json +1 -1
- package/src/lib/api/__tests__/crud.test.ts +5 -3
- package/src/lib/api/crud.ts +1 -1
- package/src/lib/auth/__tests__/server.apiKeyCache.test.ts +10 -4
- package/src/lib/auth/server.ts +1 -1
- package/src/lib/bootstrap/types.ts +2 -2
- package/src/lib/crud/__tests__/crud-factory.test.ts +27 -17
- package/src/lib/data/engine.ts +95 -47
- package/src/lib/db/mikro.ts +26 -25
- package/src/lib/indexers/error-log.ts +23 -23
- package/src/lib/indexers/status-log.ts +36 -33
- package/src/lib/query/__tests__/engine.scope-and-or.test.ts +253 -114
- package/src/lib/query/__tests__/engine.test.ts +206 -139
- package/src/lib/query/engine.ts +306 -263
- package/src/lib/query/join-utils.ts +38 -30
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Kysely } from 'kysely'
|
|
2
|
+
import { sql } from 'kysely'
|
|
2
3
|
import type { QueryOptions, QueryJoinEdge } from './types'
|
|
3
4
|
import type { FilterOp } from './types'
|
|
4
5
|
|
|
6
|
+
type AnyBuilder = any
|
|
7
|
+
|
|
5
8
|
export type NormalizedFilter = { field: string; op: FilterOp; value?: unknown; orGroup?: string; qualified?: string | null }
|
|
6
9
|
|
|
7
10
|
export function normalizeFilters(filters?: QueryOptions['filters']): NormalizedFilter[] {
|
|
@@ -195,21 +198,21 @@ export function partitionFilters(
|
|
|
195
198
|
}
|
|
196
199
|
|
|
197
200
|
type ApplyJoinFiltersOptions = {
|
|
198
|
-
|
|
201
|
+
db: Kysely<any>
|
|
199
202
|
baseTable: string
|
|
200
|
-
builder:
|
|
203
|
+
builder: AnyBuilder
|
|
201
204
|
joinMap: Map<string, ResolvedJoin>
|
|
202
205
|
joinFilters: Map<string, JoinFilter[]>
|
|
203
206
|
aliasTables: Map<string, string>
|
|
204
207
|
qualifyBase: (column: string) => string
|
|
205
|
-
applyAliasScope: (builder:
|
|
206
|
-
applyFilterOp: (builder:
|
|
207
|
-
applyJoinFilterOp?: (builder:
|
|
208
|
+
applyAliasScope: (builder: AnyBuilder, alias: string, table: string) => Promise<AnyBuilder> | AnyBuilder
|
|
209
|
+
applyFilterOp: (builder: AnyBuilder, column: string, op: FilterOp, value?: unknown) => AnyBuilder
|
|
210
|
+
applyJoinFilterOp?: (builder: AnyBuilder, filter: JoinFilter, qualified: string, join: ResolvedJoin, table: string) => Promise<{ applied: boolean; builder: AnyBuilder }> | { applied: boolean; builder: AnyBuilder }
|
|
208
211
|
columnExists?: (table: string, column: string) => Promise<boolean> | boolean
|
|
209
212
|
}
|
|
210
213
|
|
|
211
214
|
export async function applyJoinFilters({
|
|
212
|
-
|
|
215
|
+
db,
|
|
213
216
|
baseTable,
|
|
214
217
|
builder,
|
|
215
218
|
joinMap,
|
|
@@ -220,35 +223,29 @@ export async function applyJoinFilters({
|
|
|
220
223
|
applyFilterOp,
|
|
221
224
|
applyJoinFilterOp,
|
|
222
225
|
columnExists,
|
|
223
|
-
}: ApplyJoinFiltersOptions): Promise<
|
|
226
|
+
}: ApplyJoinFiltersOptions): Promise<AnyBuilder> {
|
|
224
227
|
const resolveAliasName = (aliasName?: string | null) => {
|
|
225
228
|
if (!aliasName || aliasName === 'base') return baseTable
|
|
226
229
|
return aliasName
|
|
227
230
|
}
|
|
228
231
|
|
|
232
|
+
let nextBuilder = builder
|
|
229
233
|
for (const [alias, filtersForAlias] of joinFilters.entries()) {
|
|
230
234
|
const chain = buildJoinChain(alias, joinMap, baseTable)
|
|
231
235
|
if (!chain.length) continue
|
|
232
236
|
const first = chain[0]
|
|
233
|
-
|
|
234
|
-
await applyAliasScope(sub, first.alias, first.table)
|
|
237
|
+
let sub: AnyBuilder = db.selectFrom(`${first.table} as ${first.alias}` as any).select(sql`1`.as('one'))
|
|
238
|
+
sub = await applyAliasScope(sub, first.alias, first.table)
|
|
235
239
|
const parentAlias = resolveAliasName(first.fromAlias)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
} else {
|
|
239
|
-
sub.whereRaw('?? = ??', [`${first.alias}.${first.toField}`, `${parentAlias}.${first.fromField}`])
|
|
240
|
-
}
|
|
240
|
+
const parentRef = parentAlias === baseTable ? qualifyBase(first.fromField) : `${parentAlias}.${first.fromField}`
|
|
241
|
+
sub = sub.whereRef(`${first.alias}.${first.toField}`, '=', parentRef)
|
|
241
242
|
for (const cfg of chain.slice(1)) {
|
|
242
|
-
const joinArgs = { [cfg.alias]: cfg.table }
|
|
243
243
|
const parent = resolveAliasName(cfg.fromAlias)
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (cfg.type === 'inner') sub.join(joinArgs, joinFn)
|
|
250
|
-
else sub.leftJoin(joinArgs, joinFn)
|
|
251
|
-
await applyAliasScope(sub, cfg.alias, cfg.table)
|
|
244
|
+
const rightRef = parent === baseTable ? qualifyBase(cfg.fromField) : `${parent}.${cfg.fromField}`
|
|
245
|
+
const joinFn = cfg.type === 'inner' ? 'innerJoin' : 'leftJoin'
|
|
246
|
+
sub = (sub as any)[joinFn](`${cfg.table} as ${cfg.alias}`, (jb: any) =>
|
|
247
|
+
jb.onRef(`${cfg.alias}.${cfg.toField}`, '=', rightRef))
|
|
248
|
+
sub = await applyAliasScope(sub, cfg.alias, cfg.table)
|
|
252
249
|
}
|
|
253
250
|
let existsDirective: boolean | null = null
|
|
254
251
|
for (const filter of filtersForAlias) {
|
|
@@ -267,13 +264,24 @@ export async function applyJoinFilters({
|
|
|
267
264
|
}
|
|
268
265
|
const qualified = `${filter.alias}.${filter.column}`
|
|
269
266
|
if (applyJoinFilterOp) {
|
|
270
|
-
const
|
|
271
|
-
if (
|
|
267
|
+
const result = await applyJoinFilterOp(sub, filter, qualified, join, targetTable)
|
|
268
|
+
if (result && result.applied) {
|
|
269
|
+
sub = result.builder
|
|
270
|
+
continue
|
|
271
|
+
}
|
|
272
|
+
if (result && result.builder) {
|
|
273
|
+
sub = result.builder
|
|
274
|
+
}
|
|
272
275
|
}
|
|
273
|
-
applyFilterOp(sub, qualified, filter.op, filter.value)
|
|
276
|
+
sub = applyFilterOp(sub, qualified, filter.op, filter.value)
|
|
277
|
+
}
|
|
278
|
+
if (existsDirective === false) {
|
|
279
|
+
const capturedSub = sub
|
|
280
|
+
nextBuilder = nextBuilder.where((eb: any) => eb.not(eb.exists(capturedSub)))
|
|
281
|
+
} else {
|
|
282
|
+
const capturedSub = sub
|
|
283
|
+
nextBuilder = nextBuilder.where((eb: any) => eb.exists(capturedSub))
|
|
274
284
|
}
|
|
275
|
-
if (existsDirective === false) builder = builder.whereNotExists(sub)
|
|
276
|
-
else builder = builder.whereExists(sub)
|
|
277
285
|
}
|
|
278
|
-
return
|
|
286
|
+
return nextBuilder
|
|
279
287
|
}
|