vona-module-a-orm 5.1.39 → 5.1.41
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/.metadata/index.d.ts +18 -18
- package/dist/.metadata/index.d.ts.map +1 -1
- package/dist/index.js +459 -58
- package/dist/index.js.map +1 -1
- package/dist/lib/aggregateResult.d.ts +7 -0
- package/dist/lib/aggregateResult.d.ts.map +1 -0
- package/dist/lib/analysis/controls.d.ts +27 -0
- package/dist/lib/analysis/controls.d.ts.map +1 -0
- package/dist/lib/analysis/execute.d.ts +6 -0
- package/dist/lib/analysis/execute.d.ts.map +1 -0
- package/dist/lib/analysis/index.d.ts +4 -0
- package/dist/lib/analysis/index.d.ts.map +1 -0
- package/dist/lib/analysis/policy.d.ts +6 -0
- package/dist/lib/analysis/policy.d.ts.map +1 -0
- package/dist/lib/bean.model/bean.model_cache.d.ts +4 -1
- package/dist/lib/bean.model/bean.model_cache.d.ts.map +1 -1
- package/dist/lib/bean.model/bean.model_crud_inner.d.ts +1 -1
- package/dist/lib/bean.model/bean.model_crud_inner.d.ts.map +1 -1
- package/dist/lib/dto/dto.d.ts +3 -0
- package/dist/lib/dto/dto.d.ts.map +1 -1
- package/dist/lib/dto/dtoAggregate.d.ts.map +1 -1
- package/dist/lib/dto/dtoAnalysis.d.ts +6 -0
- package/dist/lib/dto/dtoAnalysis.d.ts.map +1 -0
- package/dist/lib/dto/dtoCreate.d.ts +2 -2
- package/dist/lib/dto/dtoCreate.d.ts.map +1 -1
- package/dist/lib/dto/dtoGet.d.ts.map +1 -1
- package/dist/lib/dto/dtoMutate.d.ts +2 -2
- package/dist/lib/dto/dtoMutate.d.ts.map +1 -1
- package/dist/lib/dto/dtoUpdate.d.ts +2 -2
- package/dist/lib/dto/dtoUpdate.d.ts.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/types/analysis.d.ts +105 -0
- package/dist/types/analysis.d.ts.map +1 -0
- package/dist/types/dto/dtoMutate.d.ts +28 -11
- package/dist/types/dto/dtoMutate.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/relationsAggr.d.ts +1 -1
- package/dist/types/relationsAggr.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/.metadata/index.ts +26 -26
- package/src/lib/aggregateResult.ts +53 -0
- package/src/lib/analysis/controls.ts +163 -0
- package/src/lib/analysis/execute.ts +49 -0
- package/src/lib/analysis/index.ts +3 -0
- package/src/lib/analysis/policy.ts +140 -0
- package/src/lib/bean.model/bean.model_cache.ts +96 -12
- package/src/lib/bean.model/bean.model_crud_inner.ts +8 -3
- package/src/lib/dto/dto.ts +3 -0
- package/src/lib/dto/dtoAggregate.ts +4 -1
- package/src/lib/dto/dtoAnalysis.ts +34 -0
- package/src/lib/dto/dtoCreate.ts +7 -9
- package/src/lib/dto/dtoGet.ts +27 -3
- package/src/lib/dto/dtoMutate.ts +2 -2
- package/src/lib/dto/dtoUpdate.ts +7 -9
- package/src/lib/index.ts +1 -0
- package/src/types/analysis.ts +137 -0
- package/src/types/dto/dtoMutate.ts +124 -87
- package/src/types/index.ts +1 -0
- package/src/types/relationsAggr.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
|
-
import { BeanInfo,
|
|
2
|
+
import { BeanInfo, BeanBase, BeanAopMethodBase, deepExtend, appResource, assertIsolatedTestDatabaseClient, assertTestClaimDatabaseClient, beanFullNameFromOnionName, cast, useApp, $makeLocaleMagic, Virtual, registerTestClaimDatabaseCreation, BeanSimple, combineConfigDefault, BeanScopeBase, createBeanDecorator, PickClassInner, $Class, registerMappedClassMetadataKey, appMetadata, disposeInstance } from 'vona';
|
|
3
3
|
import { __decorate, __metadata } from 'tslib';
|
|
4
|
+
import { Schedule } from 'vona-module-a-schedule';
|
|
4
5
|
import { AopMethod } from 'vona-module-a-aspect';
|
|
5
6
|
import { Service, Bean, Scope } from 'vona-module-a-bean';
|
|
6
7
|
import { AsyncLocalStorage, AsyncResource } from 'node:async_hooks';
|
|
@@ -9,18 +10,58 @@ import knex from 'knex';
|
|
|
9
10
|
import { BeanMutateBase } from 'vona-module-a-beanmutate';
|
|
10
11
|
import { swapDeps } from '@cabloy/deps';
|
|
11
12
|
import { $tableNameFromEntity, $tableDefaults, $columnsAll } from 'vona-module-a-ormutils';
|
|
12
|
-
import { prepareClassType, Api, v, schemaRenderVisible, getSchemaDynamic, SymbolSchemaDynamicRefId, addSchemaDynamic, getTargetDecoratorRuleColumns, mergeTargetDecoratorDtoOpenapi, mergeDtoFieldsOpenapiMetadata } from 'vona-module-a-openapiutils';
|
|
13
|
+
import { prepareClassType, Api, v, getTargetDecoratorRules, schemaRenderVisible, getSchemaDynamic, SymbolSchemaDynamicRefId, addSchemaDynamic, getTargetDecoratorRuleColumns, mergeTargetDecoratorDtoOpenapi, mergeDtoFieldsOpenapiMetadata } from 'vona-module-a-openapiutils';
|
|
13
14
|
import z from 'zod';
|
|
14
15
|
import { Broadcast, BeanBroadcastBase } from 'vona-module-a-broadcast';
|
|
15
16
|
import { Event, BeanEventBase } from 'vona-module-a-event';
|
|
16
17
|
import { Hmr } from 'vona-module-a-hmrbase';
|
|
17
18
|
import { Queue, BeanQueueBase } from 'vona-module-a-queue';
|
|
18
|
-
import { Schedule } from 'vona-module-a-schedule';
|
|
19
19
|
import { configAll, configRedis } from 'vona-module-a-summer';
|
|
20
20
|
import { ServiceDatabaseAsyncLocalStorage as ServiceDatabaseAsyncLocalStorage$1, ServiceTransactionConsistency as ServiceTransactionConsistency_ } from 'vona-module-a-orm';
|
|
21
|
+
import { ZodMetadata } from '@cabloy/zod-openapi';
|
|
21
22
|
import { mutate } from 'mutate-on-copy';
|
|
22
23
|
import { parseFirstWord, toLowerCaseFirstChar } from '@cabloy/word-utils';
|
|
23
24
|
|
|
25
|
+
let ScheduleSoftDeletionPrune = class ScheduleSoftDeletionPrune extends BeanBase {
|
|
26
|
+
async execute() {
|
|
27
|
+
const onionSlices = this.bean.onion.model.getOnionsEnabledCached();
|
|
28
|
+
for (const onionSlice of onionSlices) {
|
|
29
|
+
if (onionSlice.beanOptions.options?.disableDeleted) continue;
|
|
30
|
+
let softDeletionPrune = onionSlice.beanOptions.options?.softDeletionPrune ?? this.scope.config.softDeletionPrune.enable;
|
|
31
|
+
if (!softDeletionPrune) continue;
|
|
32
|
+
if (softDeletionPrune === true) softDeletionPrune = {};
|
|
33
|
+
await this._modulePrune(onionSlice, softDeletionPrune);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async _modulePrune(onionSlice, softDeletionPrune) {
|
|
37
|
+
const handler = softDeletionPrune.handler;
|
|
38
|
+
const expired = softDeletionPrune.expired ?? this.scope.config.softDeletionPrune.expired;
|
|
39
|
+
const modelTarget = this.bean._getBean(onionSlice.beanOptions.beanFullName);
|
|
40
|
+
if (handler) {
|
|
41
|
+
await handler(this.ctx, modelTarget, {
|
|
42
|
+
expired
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
const expiredTime = new Date(Date.now() - expired);
|
|
46
|
+
await modelTarget.delete({
|
|
47
|
+
deleted: true,
|
|
48
|
+
updatedAt: {
|
|
49
|
+
_lt_: expiredTime
|
|
50
|
+
}
|
|
51
|
+
}, {
|
|
52
|
+
disableDeleted: true
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
ScheduleSoftDeletionPrune = __decorate([Schedule({
|
|
58
|
+
repeat: {
|
|
59
|
+
every: 24 * 3600 * 1000
|
|
60
|
+
}
|
|
61
|
+
}), BeanInfo({
|
|
62
|
+
module: "a-orm"
|
|
63
|
+
})], ScheduleSoftDeletionPrune);
|
|
64
|
+
|
|
24
65
|
let AopMethodTransaction = class AopMethodTransaction extends BeanAopMethodBase {
|
|
25
66
|
execute(options, _args, next, _receiver, _prop) {
|
|
26
67
|
return this.bean.database.current.transaction.begin(() => {
|
|
@@ -781,6 +822,50 @@ BeanDatabase = __decorate([Bean(), BeanInfo({
|
|
|
781
822
|
module: "a-orm"
|
|
782
823
|
})], BeanDatabase);
|
|
783
824
|
|
|
825
|
+
function normalizeAggregateValue(value, fn) {
|
|
826
|
+
if (value === undefined) return value;
|
|
827
|
+
if (value === null && fn !== 'count') return value;
|
|
828
|
+
if (typeof value === 'string') {
|
|
829
|
+
if (fn !== 'count' || /^(0|[1-9]\d*)$/.test(value)) return value;
|
|
830
|
+
} else if (typeof value === 'number') {
|
|
831
|
+
if (Number.isFinite(value) && (fn !== 'count' || Number.isSafeInteger(value) && value >= 0)) {
|
|
832
|
+
return String(value);
|
|
833
|
+
}
|
|
834
|
+
} else if (typeof value === 'bigint' && (fn !== 'count' || value >= 0n)) {
|
|
835
|
+
return String(value);
|
|
836
|
+
}
|
|
837
|
+
throw new TypeError(`Invalid ORM ${fn} aggregate result`);
|
|
838
|
+
}
|
|
839
|
+
function normalizeAggregateRows(rows, aggrs) {
|
|
840
|
+
if (!aggrs || rows.length === 0) return rows;
|
|
841
|
+
const aliases = [];
|
|
842
|
+
for (const fn of ['count', 'sum', 'avg', 'min', 'max']) {
|
|
843
|
+
const columns = aggrs[fn];
|
|
844
|
+
if (columns === undefined) continue;
|
|
845
|
+
for (const column of typeof columns === 'object' ? columns : [columns]) {
|
|
846
|
+
aliases.push([`${fn}_${column === '*' ? 'all' : String(column)}`, fn]);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
let result = rows;
|
|
850
|
+
for (const [index, row] of rows.entries()) {
|
|
851
|
+
let target = row;
|
|
852
|
+
for (const [alias, fn] of aliases) {
|
|
853
|
+
if (!Object.hasOwn(row, alias)) continue;
|
|
854
|
+
const value = row[alias];
|
|
855
|
+
const normalized = normalizeAggregateValue(value, fn);
|
|
856
|
+
if (value === normalized) continue;
|
|
857
|
+
if (target === row) target = {
|
|
858
|
+
...row
|
|
859
|
+
};
|
|
860
|
+
target[alias] = normalized;
|
|
861
|
+
}
|
|
862
|
+
if (target === row) continue;
|
|
863
|
+
if (result === rows) result = [...rows];
|
|
864
|
+
result[index] = target;
|
|
865
|
+
}
|
|
866
|
+
return result;
|
|
867
|
+
}
|
|
868
|
+
|
|
784
869
|
const OpAggrs = ['count', 'sum', 'avg', 'max', 'min'];
|
|
785
870
|
const OpJoint = {
|
|
786
871
|
and: '_and_',
|
|
@@ -1068,6 +1153,8 @@ function _safeColumn(column) {
|
|
|
1068
1153
|
return column.replace(/[\\.#%'"`;,() ]/g, '');
|
|
1069
1154
|
}
|
|
1070
1155
|
|
|
1156
|
+
const SymbolDtoMutateRelations = Symbol('SymbolDtoMutateRelations');
|
|
1157
|
+
|
|
1071
1158
|
const app$1 = useApp();
|
|
1072
1159
|
const ormConfig$1 = app$1.util.getModuleConfigRaw('a-orm');
|
|
1073
1160
|
const ordersDefault = ormConfig$1?.rest?.query?.orders?.default ?? 'createdAt,desc';
|
|
@@ -1764,7 +1851,8 @@ class BeanModelCrudInner extends BeanModelView {
|
|
|
1764
1851
|
}
|
|
1765
1852
|
return `model.select: ${tip}, ${builder.toQuery()}`;
|
|
1766
1853
|
});
|
|
1767
|
-
|
|
1854
|
+
const rows = await this.dialect.select(builder, datas, () => this.columns(table));
|
|
1855
|
+
return normalizeAggregateRows(rows, params?.aggrs);
|
|
1768
1856
|
}
|
|
1769
1857
|
_select_buildParams(table, params, options) {
|
|
1770
1858
|
// builder
|
|
@@ -1827,7 +1915,7 @@ class BeanModelCrudInner extends BeanModelView {
|
|
|
1827
1915
|
// ready
|
|
1828
1916
|
this.$loggerChild('model').debug(() => `model.count: ${builder.toQuery()}`);
|
|
1829
1917
|
const res = await builder;
|
|
1830
|
-
return this.
|
|
1918
|
+
return normalizeAggregateValue(this.extractFirstValue(res), 'count');
|
|
1831
1919
|
}
|
|
1832
1920
|
async _increment(table, params, options) {
|
|
1833
1921
|
// table
|
|
@@ -3080,46 +3168,6 @@ QueueDoubleDelete = __decorate([Queue({
|
|
|
3080
3168
|
module: "a-orm"
|
|
3081
3169
|
})], QueueDoubleDelete);
|
|
3082
3170
|
|
|
3083
|
-
let ScheduleSoftDeletionPrune = class ScheduleSoftDeletionPrune extends BeanBase {
|
|
3084
|
-
async execute() {
|
|
3085
|
-
const onionSlices = this.bean.onion.model.getOnionsEnabledCached();
|
|
3086
|
-
for (const onionSlice of onionSlices) {
|
|
3087
|
-
if (onionSlice.beanOptions.options?.disableDeleted) continue;
|
|
3088
|
-
let softDeletionPrune = onionSlice.beanOptions.options?.softDeletionPrune ?? this.scope.config.softDeletionPrune.enable;
|
|
3089
|
-
if (!softDeletionPrune) continue;
|
|
3090
|
-
if (softDeletionPrune === true) softDeletionPrune = {};
|
|
3091
|
-
await this._modulePrune(onionSlice, softDeletionPrune);
|
|
3092
|
-
}
|
|
3093
|
-
}
|
|
3094
|
-
async _modulePrune(onionSlice, softDeletionPrune) {
|
|
3095
|
-
const handler = softDeletionPrune.handler;
|
|
3096
|
-
const expired = softDeletionPrune.expired ?? this.scope.config.softDeletionPrune.expired;
|
|
3097
|
-
const modelTarget = this.bean._getBean(onionSlice.beanOptions.beanFullName);
|
|
3098
|
-
if (handler) {
|
|
3099
|
-
await handler(this.ctx, modelTarget, {
|
|
3100
|
-
expired
|
|
3101
|
-
});
|
|
3102
|
-
} else {
|
|
3103
|
-
const expiredTime = new Date(Date.now() - expired);
|
|
3104
|
-
await modelTarget.delete({
|
|
3105
|
-
deleted: true,
|
|
3106
|
-
updatedAt: {
|
|
3107
|
-
_lt_: expiredTime
|
|
3108
|
-
}
|
|
3109
|
-
}, {
|
|
3110
|
-
disableDeleted: true
|
|
3111
|
-
});
|
|
3112
|
-
}
|
|
3113
|
-
}
|
|
3114
|
-
};
|
|
3115
|
-
ScheduleSoftDeletionPrune = __decorate([Schedule({
|
|
3116
|
-
repeat: {
|
|
3117
|
-
every: 24 * 3600 * 1000
|
|
3118
|
-
}
|
|
3119
|
-
}), BeanInfo({
|
|
3120
|
-
module: "a-orm"
|
|
3121
|
-
})], ScheduleSoftDeletionPrune);
|
|
3122
|
-
|
|
3123
3171
|
function config(_app) {
|
|
3124
3172
|
return {
|
|
3125
3173
|
sharding: {
|
|
@@ -3332,6 +3380,255 @@ ScopeModuleAOrm = __decorate([Scope(), BeanInfo({
|
|
|
3332
3380
|
})], ScopeModuleAOrm);
|
|
3333
3381
|
/** scope: end */
|
|
3334
3382
|
|
|
3383
|
+
const analysisFunctions = ['count', 'sum', 'avg', 'min', 'max'];
|
|
3384
|
+
const analysisReservedFields = new Set(['groups', 'aggrs', 'where', 'joins', 'having', 'columns', 'orders', 'limit', 'offset', 'pageNo', 'pageSize', 'distinct', 'include', 'with']);
|
|
3385
|
+
/** A deliberate validation/resource-bound error, also usable without an application context. */
|
|
3386
|
+
class AnalysisError extends Error {
|
|
3387
|
+
constructor(...args) {
|
|
3388
|
+
super(...args);
|
|
3389
|
+
this.code = 422;
|
|
3390
|
+
this.status = 422;
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
function analysisFailure(message) {
|
|
3394
|
+
throw new AnalysisError(message);
|
|
3395
|
+
}
|
|
3396
|
+
function actionDefaults(policy, mode) {
|
|
3397
|
+
if (mode !== 'group' && mode !== 'aggregate') analysisFailure('Unknown analysis action');
|
|
3398
|
+
const defaults = policy.defaults[mode];
|
|
3399
|
+
if (!defaults) analysisFailure(`Analysis ${mode} action is not enabled`);
|
|
3400
|
+
return defaults;
|
|
3401
|
+
}
|
|
3402
|
+
function columnArray(columns, max) {
|
|
3403
|
+
return z.array(z.enum([...columns])).min(1).max(max).superRefine((value, ctx) => {
|
|
3404
|
+
if (new Set(value).size !== value.length) {
|
|
3405
|
+
ctx.addIssue({
|
|
3406
|
+
code: 'custom',
|
|
3407
|
+
message: 'Duplicate analysis columns are not allowed'
|
|
3408
|
+
});
|
|
3409
|
+
}
|
|
3410
|
+
});
|
|
3411
|
+
}
|
|
3412
|
+
/** Native array/object schemas preserve finite enums for query coercion and OpenAPI. */
|
|
3413
|
+
function analysisControlSchemas(policy, mode) {
|
|
3414
|
+
const defaults = actionDefaults(policy, mode);
|
|
3415
|
+
const shape = {};
|
|
3416
|
+
for (const fn of analysisFunctions) {
|
|
3417
|
+
const columns = policy.aggrs[fn];
|
|
3418
|
+
if (columns) shape[fn] = columnArray(columns, policy.limits.maxMetrics).optional();
|
|
3419
|
+
}
|
|
3420
|
+
const aggrs = z.strictObject(shape).superRefine((value, ctx) => {
|
|
3421
|
+
const count = Object.values(value).reduce((total, columns) => total + (Array.isArray(columns) ? columns.length : 0), 0);
|
|
3422
|
+
if (count === 0 || count > policy.limits.maxMetrics) {
|
|
3423
|
+
ctx.addIssue({
|
|
3424
|
+
code: 'custom',
|
|
3425
|
+
message: `Analysis requires 1 to ${policy.limits.maxMetrics} metrics`
|
|
3426
|
+
});
|
|
3427
|
+
}
|
|
3428
|
+
}).default(() => Object.fromEntries(Object.entries(defaults.aggrs).map(([fn, columns]) => [fn, [...columns]])));
|
|
3429
|
+
const groups = mode === 'group' ? columnArray(policy.groups, policy.limits.maxGroups).default(() => [...defaults.groups]) : undefined;
|
|
3430
|
+
const selection = z.strictObject({
|
|
3431
|
+
groups: groups ?? z.never().optional(),
|
|
3432
|
+
aggrs
|
|
3433
|
+
});
|
|
3434
|
+
return {
|
|
3435
|
+
groups,
|
|
3436
|
+
aggrs,
|
|
3437
|
+
selection
|
|
3438
|
+
};
|
|
3439
|
+
}
|
|
3440
|
+
/** Validate controls independently of row filters and ignored list controls. */
|
|
3441
|
+
function resolveAnalysis(policy, mode, input) {
|
|
3442
|
+
if (input !== undefined && (!input || typeof input !== 'object' || Array.isArray(input))) {
|
|
3443
|
+
analysisFailure('Analysis parameters must be an object');
|
|
3444
|
+
}
|
|
3445
|
+
const params = input ?? {};
|
|
3446
|
+
for (const key of ['joins', 'having', 'distinct', 'include', 'with']) {
|
|
3447
|
+
if (Object.hasOwn(params, key) && params[key] !== undefined) {
|
|
3448
|
+
analysisFailure(`Analysis does not support ${key}`);
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3451
|
+
if (mode === 'aggregate' && Object.hasOwn(params, 'groups')) {
|
|
3452
|
+
analysisFailure('Aggregate analysis does not support groups');
|
|
3453
|
+
}
|
|
3454
|
+
// The request context can enable generic query coercion. Direct service calls must
|
|
3455
|
+
// still supply native arrays/objects, never JSON strings or coerced scalar items.
|
|
3456
|
+
const assertNativeColumns = columns => {
|
|
3457
|
+
if (!Array.isArray(columns) || columns.some(column => typeof column !== 'string')) {
|
|
3458
|
+
analysisFailure('Analysis columns must be arrays of strings');
|
|
3459
|
+
}
|
|
3460
|
+
};
|
|
3461
|
+
if (params.groups !== undefined) assertNativeColumns(params.groups);
|
|
3462
|
+
if (params.aggrs !== undefined) {
|
|
3463
|
+
if (!params.aggrs || typeof params.aggrs !== 'object' || Array.isArray(params.aggrs)) {
|
|
3464
|
+
analysisFailure('Analysis metrics must be an object of column arrays');
|
|
3465
|
+
}
|
|
3466
|
+
for (const columns of Object.values(params.aggrs)) assertNativeColumns(columns);
|
|
3467
|
+
}
|
|
3468
|
+
const parsed = analysisControlSchemas(policy, mode).selection.safeParse({
|
|
3469
|
+
...(mode === 'group' ? {
|
|
3470
|
+
groups: params.groups
|
|
3471
|
+
} : {}),
|
|
3472
|
+
aggrs: params.aggrs
|
|
3473
|
+
});
|
|
3474
|
+
if (!parsed.success) analysisFailure(parsed.error.message);
|
|
3475
|
+
const result = {
|
|
3476
|
+
aggrs: {}
|
|
3477
|
+
};
|
|
3478
|
+
if (mode === 'group') {
|
|
3479
|
+
// Canonical policy order also stabilizes SQL/cache keys for equivalent selections.
|
|
3480
|
+
const selected = parsed.data.groups;
|
|
3481
|
+
result.groups = policy.groups.filter(column => selected.includes(column));
|
|
3482
|
+
}
|
|
3483
|
+
for (const fn of analysisFunctions) {
|
|
3484
|
+
const selected = parsed.data.aggrs[fn];
|
|
3485
|
+
if (selected) result.aggrs[fn] = policy.aggrs[fn].filter(column => selected.includes(column));
|
|
3486
|
+
}
|
|
3487
|
+
return result;
|
|
3488
|
+
}
|
|
3489
|
+
function analysisCapabilities(policy, mode) {
|
|
3490
|
+
const defaults = actionDefaults(policy, mode);
|
|
3491
|
+
return {
|
|
3492
|
+
mode,
|
|
3493
|
+
groups: mode === 'group' ? [...policy.groups] : [],
|
|
3494
|
+
aggrs: Object.fromEntries(Object.entries(policy.aggrs).map(([fn, columns]) => [fn, [...columns]])),
|
|
3495
|
+
defaults: {
|
|
3496
|
+
...(mode === 'group' ? {
|
|
3497
|
+
groups: [...defaults.groups]
|
|
3498
|
+
} : {}),
|
|
3499
|
+
aggrs: Object.fromEntries(Object.entries(defaults.aggrs).map(([fn, columns]) => [fn, [...columns]]))
|
|
3500
|
+
},
|
|
3501
|
+
limits: {
|
|
3502
|
+
...policy.limits
|
|
3503
|
+
}
|
|
3504
|
+
};
|
|
3505
|
+
}
|
|
3506
|
+
|
|
3507
|
+
function assertModel(model, policy) {
|
|
3508
|
+
if (!(model instanceof policy.modelClass)) analysisFailure('Analysis policy does not belong to this model');
|
|
3509
|
+
}
|
|
3510
|
+
/** Keep instance/soft-delete scope, caching and scalar normalization owned by the ORM. */
|
|
3511
|
+
async function $executeAnalysisGroup(model, policy, params) {
|
|
3512
|
+
assertModel(model, policy);
|
|
3513
|
+
const {
|
|
3514
|
+
groups,
|
|
3515
|
+
aggrs
|
|
3516
|
+
} = resolveAnalysis(policy, 'group', params);
|
|
3517
|
+
const rows = await model.group({
|
|
3518
|
+
where: params?.where,
|
|
3519
|
+
groups: groups,
|
|
3520
|
+
aggrs,
|
|
3521
|
+
orders: groups.map(column => [column, 'asc']),
|
|
3522
|
+
limit: policy.limits.maxGroupRows + 1
|
|
3523
|
+
});
|
|
3524
|
+
if (rows.length > policy.limits.maxGroupRows) analysisFailure(`Analysis exceeds ${policy.limits.maxGroupRows} group rows`);
|
|
3525
|
+
return rows;
|
|
3526
|
+
}
|
|
3527
|
+
async function $executeAnalysisAggregate(model, policy, params) {
|
|
3528
|
+
assertModel(model, policy);
|
|
3529
|
+
const {
|
|
3530
|
+
aggrs
|
|
3531
|
+
} = resolveAnalysis(policy, 'aggregate', params);
|
|
3532
|
+
return await model.aggregate({
|
|
3533
|
+
where: params?.where,
|
|
3534
|
+
aggrs
|
|
3535
|
+
});
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3538
|
+
function invalid(message) {
|
|
3539
|
+
throw new TypeError(`Invalid analysis policy: ${message}`);
|
|
3540
|
+
}
|
|
3541
|
+
function assertColumns(columns, label, allowEmpty = false) {
|
|
3542
|
+
if (!Array.isArray(columns) || !allowEmpty && columns.length === 0) invalid(`${label} must be a nonempty column array`);
|
|
3543
|
+
if (columns.some(column => typeof column !== 'string')) invalid(`${label} columns must be strings`);
|
|
3544
|
+
if (new Set(columns).size !== columns.length) invalid(`${label} contains duplicate columns`);
|
|
3545
|
+
}
|
|
3546
|
+
function copyAggrs(aggrs) {
|
|
3547
|
+
return Object.freeze(Object.fromEntries(Object.entries(aggrs).map(([fn, columns]) => [fn, Object.freeze([...columns])])));
|
|
3548
|
+
}
|
|
3549
|
+
/** Static model/entity metadata only: safe while DTO classes are being evaluated. */
|
|
3550
|
+
function $defineAnalysis(modelLike, config) {
|
|
3551
|
+
const modelClass = prepareClassModel(modelLike);
|
|
3552
|
+
const entityClass = getClassEntityFromClassModel(modelClass);
|
|
3553
|
+
const rules = getTargetDecoratorRules(entityClass.prototype, true);
|
|
3554
|
+
assertColumns(config.groups, 'groups', true);
|
|
3555
|
+
const validateField = (column, numeric) => {
|
|
3556
|
+
if (!/^[A-Z_]\w*$/i.test(column) || analysisReservedFields.has(column)) invalid(`unsupported column ${column}`);
|
|
3557
|
+
if (!Object.hasOwn(rules, column)) invalid(`unknown entity column ${column}`);
|
|
3558
|
+
const schema = ZodMetadata.unwrapChained(ZodMetadata.resolveLazySchema(rules[column]));
|
|
3559
|
+
if (numeric && (column === 'id' || column === 'iid' || schema.def.type !== 'number')) invalid(`non-count metrics require numeric columns: ${column}`);
|
|
3560
|
+
};
|
|
3561
|
+
for (const column of config.groups) validateField(column, false);
|
|
3562
|
+
if (!config.aggrs || typeof config.aggrs !== 'object' || Array.isArray(config.aggrs)) invalid('aggrs must be an object');
|
|
3563
|
+
const aliases = new Set(config.groups);
|
|
3564
|
+
let metricCount = 0;
|
|
3565
|
+
for (const [fn, columns] of Object.entries(config.aggrs)) {
|
|
3566
|
+
if (!analysisFunctions.includes(fn)) invalid(`unsupported function ${fn}`);
|
|
3567
|
+
assertColumns(columns, fn);
|
|
3568
|
+
for (const column of columns) {
|
|
3569
|
+
if (column !== '*' || fn !== 'count') validateField(column, fn !== 'count');
|
|
3570
|
+
const alias = `${fn}_${column === '*' ? 'all' : column}`;
|
|
3571
|
+
if (aliases.has(alias) || analysisReservedFields.has(alias)) invalid(`alias collision: ${alias}`);
|
|
3572
|
+
aliases.add(alias);
|
|
3573
|
+
metricCount++;
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
if (metricCount === 0) invalid('at least one allowed metric is required');
|
|
3577
|
+
const limits = {
|
|
3578
|
+
maxGroups: 3,
|
|
3579
|
+
maxMetrics: 10,
|
|
3580
|
+
maxGroupRows: 1000,
|
|
3581
|
+
...config.limits
|
|
3582
|
+
};
|
|
3583
|
+
for (const [key, value] of Object.entries(limits)) {
|
|
3584
|
+
if (!['maxGroups', 'maxMetrics', 'maxGroupRows'].includes(key) || !Number.isSafeInteger(value) || value < 1 || value >= Number.MAX_SAFE_INTEGER) {
|
|
3585
|
+
invalid(`invalid limit ${key}`);
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
if (!config.defaults || Object.keys(config.defaults).some(key => key !== 'group' && key !== 'aggregate')) {
|
|
3589
|
+
invalid('unknown or missing action defaults');
|
|
3590
|
+
}
|
|
3591
|
+
if (!config.defaults.group && !config.defaults.aggregate) invalid('at least one action default is required');
|
|
3592
|
+
const policy = {
|
|
3593
|
+
modelLike,
|
|
3594
|
+
modelClass,
|
|
3595
|
+
groups: Object.freeze([...config.groups]),
|
|
3596
|
+
aggrs: copyAggrs(config.aggrs),
|
|
3597
|
+
defaults: {},
|
|
3598
|
+
limits: Object.freeze(limits)
|
|
3599
|
+
};
|
|
3600
|
+
const defaults = {};
|
|
3601
|
+
for (const mode of ['group', 'aggregate']) {
|
|
3602
|
+
const input = config.defaults[mode];
|
|
3603
|
+
if (!input) continue;
|
|
3604
|
+
// Do not allow omitted defaults to expand authorization implicitly.
|
|
3605
|
+
if (!Object.hasOwn(input, 'aggrs') || mode === 'group' && !Object.hasOwn(input, 'groups')) invalid(`incomplete ${mode} defaults`);
|
|
3606
|
+
if (Object.keys(input).some(key => key !== 'aggrs' && !(mode === 'group' && key === 'groups'))) invalid(`unsupported ${mode} default control`);
|
|
3607
|
+
const forValidation = {
|
|
3608
|
+
...policy,
|
|
3609
|
+
defaults: {
|
|
3610
|
+
[mode]: input
|
|
3611
|
+
}
|
|
3612
|
+
};
|
|
3613
|
+
try {
|
|
3614
|
+
const resolved = resolveAnalysis(forValidation, mode, input);
|
|
3615
|
+
const aggrs = copyAggrs(resolved.aggrs);
|
|
3616
|
+
if (mode === 'group') defaults.group = Object.freeze({
|
|
3617
|
+
groups: Object.freeze(resolved.groups),
|
|
3618
|
+
aggrs
|
|
3619
|
+
});else defaults.aggregate = Object.freeze({
|
|
3620
|
+
aggrs
|
|
3621
|
+
});
|
|
3622
|
+
} catch (error) {
|
|
3623
|
+
invalid(`${mode} defaults: ${error.message}`);
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
return Object.freeze({
|
|
3627
|
+
...policy,
|
|
3628
|
+
defaults: Object.freeze(defaults)
|
|
3629
|
+
});
|
|
3630
|
+
}
|
|
3631
|
+
|
|
3335
3632
|
function DatabaseDialect(options) {
|
|
3336
3633
|
return createBeanDecorator('databaseDialect', options);
|
|
3337
3634
|
}
|
|
@@ -3349,7 +3646,7 @@ function _DtoAggregate_inner(classTarget, _modelLike, aggrs) {
|
|
|
3349
3646
|
if (!columns) continue;
|
|
3350
3647
|
for (const column of columns) {
|
|
3351
3648
|
const column2 = `${key}_${column === '*' ? 'all' : column}`;
|
|
3352
|
-
Api.field(v.optional(), z.string())(classTarget.prototype, column2);
|
|
3649
|
+
Api.field(v.optional(), key === 'count' ? z.string() : z.string().nullable())(classTarget.prototype, column2);
|
|
3353
3650
|
}
|
|
3354
3651
|
}
|
|
3355
3652
|
return classTarget;
|
|
@@ -3377,6 +3674,19 @@ function _DtoGroup_raw(modelLike, groups, aggrs, columns) {
|
|
|
3377
3674
|
return TargetClass;
|
|
3378
3675
|
}
|
|
3379
3676
|
|
|
3677
|
+
/** A finite optional superset: absent fields are unrequested, null retains SQL meaning. */
|
|
3678
|
+
function DtoAnalysisGroup(policy) {
|
|
3679
|
+
if (!policy.defaults.group) throw new TypeError('Analysis group action is not enabled');
|
|
3680
|
+
const base = DtoGroup(policy.modelLike, [...policy.groups], policy.aggrs);
|
|
3681
|
+
return $Class.partial(base);
|
|
3682
|
+
}
|
|
3683
|
+
function DtoAnalysisAggregate(policy) {
|
|
3684
|
+
if (!policy.defaults.aggregate) throw new TypeError('Analysis aggregate action is not enabled');
|
|
3685
|
+
class TargetClass {}
|
|
3686
|
+
// Aggregate aliases deliberately do not copy field validators/renderers from source columns.
|
|
3687
|
+
return _DtoAggregate_inner(TargetClass, policy.modelLike, policy.aggrs);
|
|
3688
|
+
}
|
|
3689
|
+
|
|
3380
3690
|
function DtoGet(modelLike, params) {
|
|
3381
3691
|
return _DtoGet_raw(modelLike, params);
|
|
3382
3692
|
}
|
|
@@ -3394,10 +3704,25 @@ function _DtoGet_raw(modelLike, params) {
|
|
|
3394
3704
|
return entityClass;
|
|
3395
3705
|
}
|
|
3396
3706
|
function _DtoGet_relations(modelClass, entityClass, includeWrapper, mutateTypeTopLevel) {
|
|
3397
|
-
// relations
|
|
3398
3707
|
const relations = _DtoGet_relations_collection(modelClass, includeWrapper);
|
|
3399
|
-
|
|
3708
|
+
// Mapped-class metadata follows the dtoClass field projection, including pick/omit.
|
|
3709
|
+
registerMappedClassMetadataKey(entityClass.prototype, SymbolDtoMutateRelations, {});
|
|
3710
|
+
const retained = appMetadata.getOwnMetadataMap(true, SymbolDtoMutateRelations, entityClass.prototype);
|
|
3711
|
+
if (mutateTypeTopLevel) {
|
|
3712
|
+
const overridden = new Set(relations.map(relation => relation[0]));
|
|
3713
|
+
for (const name in retained) {
|
|
3714
|
+
if (!overridden.has(name)) {
|
|
3715
|
+
_DtoGet_relation_handle(entityClass, retained[name], mutateTypeTopLevel);
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3400
3719
|
for (const relation of relations) {
|
|
3720
|
+
const [name, definition] = relation;
|
|
3721
|
+
if (mutateTypeTopLevel && definition !== false && (definition.type === 'hasOne' || definition.type === 'hasMany')) {
|
|
3722
|
+
retained[name] = relation;
|
|
3723
|
+
} else {
|
|
3724
|
+
delete retained[name];
|
|
3725
|
+
}
|
|
3401
3726
|
_DtoGet_relation_handle(entityClass, relation, mutateTypeTopLevel);
|
|
3402
3727
|
}
|
|
3403
3728
|
}
|
|
@@ -3623,6 +3948,8 @@ const $Dto = {
|
|
|
3623
3948
|
mutate: DtoMutate,
|
|
3624
3949
|
get: DtoGet,
|
|
3625
3950
|
aggregate: DtoAggregate,
|
|
3951
|
+
analysisGroup: DtoAnalysisGroup,
|
|
3952
|
+
analysisAggregate: DtoAnalysisAggregate,
|
|
3626
3953
|
group: DtoGroup,
|
|
3627
3954
|
query: DtoQuery,
|
|
3628
3955
|
queryPage: DtoQueryPage,
|
|
@@ -3757,7 +4084,7 @@ class BeanModelCache extends BeanModelCrud {
|
|
|
3757
4084
|
}
|
|
3758
4085
|
// insert/update
|
|
3759
4086
|
const itemsInsertNew = await this.__insertBulk_raw(table, itemsInsert, options);
|
|
3760
|
-
await this.__updateBulk_raw(table, itemsUpdate, options);
|
|
4087
|
+
const idsUpdate = await this.__updateBulk_raw(table, itemsUpdate, options);
|
|
3761
4088
|
const itemsMutate = itemsInsert.map((item, index) => {
|
|
3762
4089
|
return Object.assign({}, item, {
|
|
3763
4090
|
id: cast(itemsInsertNew[index]).id
|
|
@@ -3765,7 +4092,7 @@ class BeanModelCache extends BeanModelCrud {
|
|
|
3765
4092
|
}).concat(itemsUpdate);
|
|
3766
4093
|
let itemsMutateResult = itemsInsertNew.concat(itemsUpdate);
|
|
3767
4094
|
const indexesMutate = indexesInsert.concat(indexesUpdate);
|
|
3768
|
-
itemsMutateResult = await this.
|
|
4095
|
+
itemsMutateResult = await this.__handleRelationsMutateAdmitted(itemsMutateResult, itemsMutate, [...itemsInsertNew.map(item => [cast(item).id]), ...idsUpdate], options);
|
|
3769
4096
|
let result = [];
|
|
3770
4097
|
for (let index = 0; index < indexesMutate.length; index++) {
|
|
3771
4098
|
result[indexesMutate[index]] = itemsMutateResult[index];
|
|
@@ -3997,7 +4324,7 @@ class BeanModelCache extends BeanModelCrud {
|
|
|
3997
4324
|
},
|
|
3998
4325
|
db: this.db
|
|
3999
4326
|
});
|
|
4000
|
-
return items;
|
|
4327
|
+
return normalizeAggregateRows(items, params?.aggrs);
|
|
4001
4328
|
}
|
|
4002
4329
|
async get(where, options) {
|
|
4003
4330
|
const relations = this.relations.handleRelationsCollection(options);
|
|
@@ -4106,19 +4433,80 @@ class BeanModelCache extends BeanModelCrud {
|
|
|
4106
4433
|
return items[0];
|
|
4107
4434
|
}
|
|
4108
4435
|
async updateBulk(items, options) {
|
|
4109
|
-
await this.__updateBulk_raw(undefined, items, options);
|
|
4110
|
-
return await this.
|
|
4436
|
+
const ids = await this.__updateBulk_raw(undefined, items, options);
|
|
4437
|
+
return await this.__handleRelationsMutateAdmitted(items, items, ids, options);
|
|
4111
4438
|
}
|
|
4112
4439
|
async __updateBulk_raw(table, items, options) {
|
|
4113
|
-
|
|
4440
|
+
const ids = [];
|
|
4114
4441
|
for (const item of items) {
|
|
4115
|
-
await this.__update_raw(table, item, options);
|
|
4442
|
+
ids.push(await this.__update_raw(table, item, options));
|
|
4116
4443
|
}
|
|
4444
|
+
return ids;
|
|
4445
|
+
}
|
|
4446
|
+
async __handleRelationsMutateAdmitted(results, items, ids, options) {
|
|
4447
|
+
const indexes = [];
|
|
4448
|
+
const itemsAdmitted = [];
|
|
4449
|
+
const resultsAdmitted = [];
|
|
4450
|
+
for (let index = 0; index < items.length; index++) {
|
|
4451
|
+
const idsItem = ids[index];
|
|
4452
|
+
if (!idsItem || idsItem.length !== 1) continue;
|
|
4453
|
+
indexes.push(index);
|
|
4454
|
+
itemsAdmitted.push(Object.assign({}, items[index], {
|
|
4455
|
+
id: idsItem[0]
|
|
4456
|
+
}));
|
|
4457
|
+
resultsAdmitted.push(results[index]);
|
|
4458
|
+
}
|
|
4459
|
+
const resultsMutated = await this.relations.handleRelationsMutate(resultsAdmitted, itemsAdmitted, options, options);
|
|
4460
|
+
const result = results.concat();
|
|
4461
|
+
for (let index = 0; index < indexes.length; index++) {
|
|
4462
|
+
result[indexes[index]] = resultsMutated[index];
|
|
4463
|
+
}
|
|
4464
|
+
return result;
|
|
4465
|
+
}
|
|
4466
|
+
__hasWritableRelations(options) {
|
|
4467
|
+
return this.relations.handleRelationsCollection(options).some(([, relation]) => {
|
|
4468
|
+
return relation !== false && relation.type !== 'belongsTo';
|
|
4469
|
+
});
|
|
4470
|
+
}
|
|
4471
|
+
async __selectMutationIds(table, where, options) {
|
|
4472
|
+
// Admission must use current scoped rows, not cached entities or changed-row counts.
|
|
4473
|
+
const items = await super._select(table, {
|
|
4474
|
+
where,
|
|
4475
|
+
columns: ['id']
|
|
4476
|
+
}, options);
|
|
4477
|
+
return items.map(item => cast(item).id);
|
|
4117
4478
|
}
|
|
4118
4479
|
async __update_raw(table, data, options) {
|
|
4119
4480
|
// table
|
|
4120
4481
|
table = table || this.getTable(data);
|
|
4121
4482
|
if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
|
|
4483
|
+
if (this.__hasWritableRelations(options)) {
|
|
4484
|
+
const where = Object.assign({}, options?.where);
|
|
4485
|
+
const dataNew = Object.assign({}, data);
|
|
4486
|
+
let hasId = false;
|
|
4487
|
+
for (const key of ['id', `${table}.id`]) {
|
|
4488
|
+
if (!isNil(dataNew[key])) {
|
|
4489
|
+
cast(where).id = dataNew[key];
|
|
4490
|
+
delete dataNew[key];
|
|
4491
|
+
hasId = true;
|
|
4492
|
+
}
|
|
4493
|
+
}
|
|
4494
|
+
if (!hasId && !options?.where) {
|
|
4495
|
+
throw new Error('id should be specified for update method');
|
|
4496
|
+
}
|
|
4497
|
+
const ids = await this.__selectMutationIds(table, where, options);
|
|
4498
|
+
if (ids.length === 0) return [];
|
|
4499
|
+
await super._update(table, dataNew, {
|
|
4500
|
+
...options,
|
|
4501
|
+
where: Object.assign({}, where, {
|
|
4502
|
+
id: ids
|
|
4503
|
+
})
|
|
4504
|
+
});
|
|
4505
|
+
if (!this._checkDisableCacheEntityByOptions(options)) {
|
|
4506
|
+
await this.cacheEntityDel(ids, table);
|
|
4507
|
+
}
|
|
4508
|
+
return ids;
|
|
4509
|
+
}
|
|
4122
4510
|
// check if cache
|
|
4123
4511
|
if (this._checkDisableCacheEntityByOptions(options)) {
|
|
4124
4512
|
await super._update(table, data, options);
|
|
@@ -4185,15 +4573,28 @@ class BeanModelCache extends BeanModelCrud {
|
|
|
4185
4573
|
}
|
|
4186
4574
|
async __deleteBulk_raw_with_relations(table, ids, options) {
|
|
4187
4575
|
if (ids.length === 0) return;
|
|
4188
|
-
await this.__delete_raw(table, {
|
|
4576
|
+
const idsDeleted = await this.__delete_raw(table, {
|
|
4189
4577
|
id: ids
|
|
4190
4578
|
}, options);
|
|
4191
|
-
|
|
4579
|
+
if (idsDeleted) {
|
|
4580
|
+
await this.relations.handleRelationsDelete(idsDeleted, options, options);
|
|
4581
|
+
}
|
|
4192
4582
|
}
|
|
4193
4583
|
async __delete_raw(table, where, options) {
|
|
4194
4584
|
// table
|
|
4195
4585
|
table = table || this.getTable(where);
|
|
4196
4586
|
if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
|
|
4587
|
+
if (this.__hasWritableRelations(options)) {
|
|
4588
|
+
const ids = await this.__selectMutationIds(table, where, options);
|
|
4589
|
+
if (ids.length === 0) return [];
|
|
4590
|
+
await super._delete(table, Object.assign({}, where, {
|
|
4591
|
+
id: ids
|
|
4592
|
+
}), options);
|
|
4593
|
+
if (!this._checkDisableCacheEntityByOptions(options)) {
|
|
4594
|
+
await this.cacheEntityDel(ids, table);
|
|
4595
|
+
}
|
|
4596
|
+
return ids;
|
|
4597
|
+
}
|
|
4197
4598
|
// check if cache
|
|
4198
4599
|
if (this._checkDisableCacheEntityByOptions(options)) {
|
|
4199
4600
|
return await super._delete(table, where, options);
|
|
@@ -4623,5 +5024,5 @@ const $relationMutate = {
|
|
|
4623
5024
|
belongsToMany
|
|
4624
5025
|
};
|
|
4625
5026
|
|
|
4626
|
-
export { $Dto, $locale, $relation, $relationDynamic, $relationMutate, AopMethodTransaction, BeanDatabase, BeanModel, BeanModelBase, BeanModelMeta, BroadcastColumnsClear, DatabaseDialect, DtoQueryBase, DtoQueryPageBase, Entity, EntityBase, EntityBaseEmpty, EntityBaseInner, EntityBaseSimple, EventClientNameReal, EventColumnsClear, ExtendKnex, ExtendSchemaBuilder, ExtendTableBuilder, HmrEntity, HmrModel, Main, Model, Op, OpAggrs, OpJoint, OpJointValues, OpNormal, OpNormalValues, OpValues, QueueDoubleDelete, ScheduleSoftDeletionPrune, ScopeModuleAOrm, ServiceCacheEntity, ServiceCacheQuery, ServiceColumns, ServiceColumnsCache, ServiceDatabase, ServiceDatabaseAsyncLocalStorage, ServiceDatabaseClient, ServiceDatabaseDialectBase, ServiceDb, ServiceEntityResolver, ServiceModelResolver, ServiceRelations, ServiceTransaction, ServiceTransactionAsyncLocalStorage, ServiceTransactionConsistency, ServiceTransactionFiber, ServiceTransactionState, SymbolCacheModelCacheInstances, SymbolCacheModelsClear, SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyFieldsMore, SymbolKeyModelOptions, TransactionIsolationLevelsMap, buildWhere, clearAllCacheModelsClear, clearCacheModelCacheInstance, config, configDefault, errors, getCacheModelCacheInstances, getCacheModelsClear, getClassEntityFromClassModel, getTableOrTableAlias, getTargetColumnName, isRaw, isRef, locales, prepareClassModel, prepareColumns };
|
|
5027
|
+
export { $Dto, $defineAnalysis, $executeAnalysisAggregate, $executeAnalysisGroup, $locale, $relation, $relationDynamic, $relationMutate, AnalysisError, AopMethodTransaction, BeanDatabase, BeanModel, BeanModelBase, BeanModelMeta, BroadcastColumnsClear, DatabaseDialect, DtoQueryBase, DtoQueryPageBase, Entity, EntityBase, EntityBaseEmpty, EntityBaseInner, EntityBaseSimple, EventClientNameReal, EventColumnsClear, ExtendKnex, ExtendSchemaBuilder, ExtendTableBuilder, HmrEntity, HmrModel, Main, Model, Op, OpAggrs, OpJoint, OpJointValues, OpNormal, OpNormalValues, OpValues, QueueDoubleDelete, ScheduleSoftDeletionPrune, ScopeModuleAOrm, ServiceCacheEntity, ServiceCacheQuery, ServiceColumns, ServiceColumnsCache, ServiceDatabase, ServiceDatabaseAsyncLocalStorage, ServiceDatabaseClient, ServiceDatabaseDialectBase, ServiceDb, ServiceEntityResolver, ServiceModelResolver, ServiceRelations, ServiceTransaction, ServiceTransactionAsyncLocalStorage, ServiceTransactionConsistency, ServiceTransactionFiber, ServiceTransactionState, SymbolCacheModelCacheInstances, SymbolCacheModelsClear, SymbolDtoMutateRelations, SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyFieldsMore, SymbolKeyModelOptions, TransactionIsolationLevelsMap, analysisCapabilities, analysisControlSchemas, analysisFailure, analysisFunctions, analysisReservedFields, buildWhere, clearAllCacheModelsClear, clearCacheModelCacheInstance, config, configDefault, errors, getCacheModelCacheInstances, getCacheModelsClear, getClassEntityFromClassModel, getTableOrTableAlias, getTargetColumnName, isRaw, isRef, locales, prepareClassModel, prepareColumns, resolveAnalysis };
|
|
4627
5028
|
//# sourceMappingURL=index.js.map
|