agentlang 0.6.6 → 0.6.7
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/out/cli/main.d.ts +1 -1
- package/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +54 -3
- package/out/cli/main.js.map +1 -1
- package/out/runtime/api.d.ts +4 -5
- package/out/runtime/api.d.ts.map +1 -1
- package/out/runtime/api.js +10 -3
- package/out/runtime/api.js.map +1 -1
- package/out/runtime/defs.d.ts +12 -0
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +46 -0
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +16 -2
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts +1 -0
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +5 -0
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +1 -1
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +12 -10
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/core.d.ts +4 -0
- package/out/runtime/modules/core.d.ts.map +1 -1
- package/out/runtime/modules/core.js +72 -1
- package/out/runtime/modules/core.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +7 -0
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +61 -4
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/main.ts +70 -3
- package/src/runtime/api.ts +15 -3
- package/src/runtime/defs.ts +59 -0
- package/src/runtime/interpreter.ts +17 -2
- package/src/runtime/loader.ts +7 -0
- package/src/runtime/module.ts +14 -11
- package/src/runtime/modules/core.ts +96 -1
- package/src/runtime/resolvers/interface.ts +7 -0
- package/src/runtime/resolvers/sqldb/database.ts +64 -5
package/src/runtime/api.ts
CHANGED
|
@@ -4,6 +4,18 @@ import {
|
|
|
4
4
|
isInstanceOfType as al_isInstanceOfType,
|
|
5
5
|
} from './module.js';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
declare global {
|
|
8
|
+
var agentlang: any | undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let ApiInited = false;
|
|
12
|
+
|
|
13
|
+
export function initGlobalApi() {
|
|
14
|
+
if (!ApiInited) {
|
|
15
|
+
globalThis.agentlang = {};
|
|
16
|
+
globalThis.agentlang.makeInstance = al_makeInstance;
|
|
17
|
+
globalThis.agentlang.isInstanceOfType = al_isInstanceOfType;
|
|
18
|
+
globalThis.agentlang.fetchConfig = al_fetchConfig;
|
|
19
|
+
ApiInited = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/runtime/defs.ts
CHANGED
|
@@ -327,3 +327,62 @@ export type FkSpec = {
|
|
|
327
327
|
onDelete: 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | undefined;
|
|
328
328
|
onUpdate: 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | undefined;
|
|
329
329
|
};
|
|
330
|
+
|
|
331
|
+
enum RuntimeModeTag {
|
|
332
|
+
DEV,
|
|
333
|
+
PROD,
|
|
334
|
+
INIT_SCHEMA,
|
|
335
|
+
RUN_MIGRATION,
|
|
336
|
+
UNDO_MIGRATION,
|
|
337
|
+
GENERATE_MIGRATION,
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
let RuntimeMode: RuntimeModeTag = RuntimeModeTag.DEV;
|
|
341
|
+
|
|
342
|
+
export function setRuntimeMode_dev() {
|
|
343
|
+
RuntimeMode = RuntimeModeTag.DEV;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export function setRuntimeMode_prod() {
|
|
347
|
+
RuntimeMode = RuntimeModeTag.PROD;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function setRuntimeMode_init_schema() {
|
|
351
|
+
RuntimeMode = RuntimeModeTag.INIT_SCHEMA;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function setRuntimeMode_migration() {
|
|
355
|
+
RuntimeMode = RuntimeModeTag.RUN_MIGRATION;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export function setRuntimeMode_undo_migration() {
|
|
359
|
+
RuntimeMode = RuntimeModeTag.UNDO_MIGRATION;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export function setRuntimeMode_generate_migration() {
|
|
363
|
+
RuntimeMode = RuntimeModeTag.GENERATE_MIGRATION;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export function isRuntimeMode_dev(): boolean {
|
|
367
|
+
return RuntimeMode === RuntimeModeTag.DEV;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export function isRuntimeMode_prod(): boolean {
|
|
371
|
+
return RuntimeMode === RuntimeModeTag.PROD;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export function isRuntimeMode_init_schema(): boolean {
|
|
375
|
+
return RuntimeMode === RuntimeModeTag.INIT_SCHEMA;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export function isRuntimeMode_migration(): boolean {
|
|
379
|
+
return RuntimeMode === RuntimeModeTag.RUN_MIGRATION;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export function isRuntimeMode_generate_migration(): boolean {
|
|
383
|
+
return RuntimeMode === RuntimeModeTag.GENERATE_MIGRATION;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export function isRuntimeMode_undo_migration(): boolean {
|
|
387
|
+
return RuntimeMode === RuntimeModeTag.UNDO_MIGRATION;
|
|
388
|
+
}
|
|
@@ -1579,6 +1579,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
1579
1579
|
const res: Array<Instance> = new Array<Instance>();
|
|
1580
1580
|
for (let i = 0; i < lastRes.length; ++i) {
|
|
1581
1581
|
await computeExprAttributes(lastRes[i], crud.body?.attributes, attrs, env);
|
|
1582
|
+
env.attributes.set('__patch', attrs);
|
|
1582
1583
|
await runPreUpdateEvents(lastRes[i], env);
|
|
1583
1584
|
maybeSetMetaAttributes(attrs, env, true);
|
|
1584
1585
|
const finalInst: Instance = await resolver.updateInstance(lastRes[i], attrs);
|
|
@@ -2372,9 +2373,23 @@ export async function callPostEventOnSubscription(
|
|
|
2372
2373
|
inst: Instance,
|
|
2373
2374
|
env?: Environment
|
|
2374
2375
|
): Promise<any> {
|
|
2376
|
+
const localEnv = env === undefined;
|
|
2375
2377
|
const newEnv = env ? env : new Environment('onSubs.env');
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
+
try {
|
|
2379
|
+
await runPrePostEvents(crudType, false, inst, newEnv);
|
|
2380
|
+
if (localEnv) {
|
|
2381
|
+
await newEnv.commitAllTransactions();
|
|
2382
|
+
}
|
|
2383
|
+
return newEnv.getLastResult();
|
|
2384
|
+
} catch (reason: any) {
|
|
2385
|
+
if (localEnv) {
|
|
2386
|
+
await newEnv.rollbackAllTransactions();
|
|
2387
|
+
logger.error(
|
|
2388
|
+
`callPostEventOnSubscription failed for ${crudType} ${inst.getFqName()} - ${reason}`
|
|
2389
|
+
);
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
return undefined;
|
|
2378
2393
|
}
|
|
2379
2394
|
|
|
2380
2395
|
async function runPrePostEvents(
|
package/src/runtime/loader.ts
CHANGED
|
@@ -191,6 +191,12 @@ export const DefaultAppSpec: ApplicationSpec = {
|
|
|
191
191
|
version: '0.0.1',
|
|
192
192
|
};
|
|
193
193
|
|
|
194
|
+
let CurrentAppSpec: ApplicationSpec = DefaultAppSpec;
|
|
195
|
+
|
|
196
|
+
export function getAppSpec(): ApplicationSpec {
|
|
197
|
+
return CurrentAppSpec;
|
|
198
|
+
}
|
|
199
|
+
|
|
194
200
|
async function getAllModules(
|
|
195
201
|
dir: string,
|
|
196
202
|
fs: ExtendedFileSystem,
|
|
@@ -234,6 +240,7 @@ async function loadApp(appDir: string, fsOptions?: any, callback?: Function): Pr
|
|
|
234
240
|
const appJsonFile = `${appDir}${path.sep}package.json`;
|
|
235
241
|
const s: string = await fs.readFile(appJsonFile);
|
|
236
242
|
const appSpec: ApplicationSpec = JSON.parse(s);
|
|
243
|
+
CurrentAppSpec = appSpec;
|
|
237
244
|
if (dependenciesCallback !== undefined && appSpec.dependencies) {
|
|
238
245
|
const aldeps = new Array<DependencyInfo>();
|
|
239
246
|
for (const [k, v] of Object.entries(appSpec.dependencies)) {
|
package/src/runtime/module.ts
CHANGED
|
@@ -399,6 +399,15 @@ export class Record extends ModuleEntry {
|
|
|
399
399
|
this.compositeUqAttributes = findUqCompositeAttributes(scm);
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
+
protected addMetaAttributes(): Record {
|
|
403
|
+
this.schema
|
|
404
|
+
.set(SysAttr_Created, SysAttr_CreatedSpec)
|
|
405
|
+
.set(SysAttr_CreatedBy, SysAttr_CreatedBySpec)
|
|
406
|
+
.set(SysAttr_LastModified, SysAttr_LastModifiedSpec)
|
|
407
|
+
.set(SysAttr_LastModifiedBy, SysAttr_LastModifiedBySpec);
|
|
408
|
+
return this;
|
|
409
|
+
}
|
|
410
|
+
|
|
402
411
|
private addOneOfRefAttribute(s: string): Record {
|
|
403
412
|
if (this.oneOfRefAttributes === undefined) {
|
|
404
413
|
this.oneOfRefAttributes = [];
|
|
@@ -1152,15 +1161,6 @@ export class Entity extends Record {
|
|
|
1152
1161
|
this.addMetaAttributes();
|
|
1153
1162
|
}
|
|
1154
1163
|
|
|
1155
|
-
private addMetaAttributes(): Entity {
|
|
1156
|
-
this.schema
|
|
1157
|
-
.set(SysAttr_Created, SysAttr_CreatedSpec)
|
|
1158
|
-
.set(SysAttr_CreatedBy, SysAttr_CreatedBySpec)
|
|
1159
|
-
.set(SysAttr_LastModified, SysAttr_LastModifiedSpec)
|
|
1160
|
-
.set(SysAttr_LastModifiedBy, SysAttr_LastModifiedBySpec);
|
|
1161
|
-
return this;
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
1164
|
setRbacSpecifications(rbac: RbacSpecification[]): Entity {
|
|
1165
1165
|
this.rbac = rbac;
|
|
1166
1166
|
return this;
|
|
@@ -1254,7 +1254,10 @@ export class Relationship extends Record {
|
|
|
1254
1254
|
props?: Map<string, any>
|
|
1255
1255
|
) {
|
|
1256
1256
|
super(name, moduleName, scm);
|
|
1257
|
-
if (typ == 'between')
|
|
1257
|
+
if (typ == 'between') {
|
|
1258
|
+
this.relType = RelType.BETWEEN;
|
|
1259
|
+
this.addMetaAttributes();
|
|
1260
|
+
}
|
|
1258
1261
|
this.node1 = node1;
|
|
1259
1262
|
this.node2 = node2;
|
|
1260
1263
|
this.properties = props;
|
|
@@ -3261,7 +3264,7 @@ function checkOneOfValue(attrSpec: AttributeSpec, attrName: string, attrValue: a
|
|
|
3261
3264
|
const vals: Set<string> | undefined = getEnumValues(attrSpec);
|
|
3262
3265
|
if (vals) {
|
|
3263
3266
|
if (!vals.has(attrValue as string)) {
|
|
3264
|
-
throw new Error(`Value of ${attrName} must be one of ${vals}`);
|
|
3267
|
+
throw new Error(`Value of ${attrName} must be one of [${[...vals]}]`);
|
|
3265
3268
|
}
|
|
3266
3269
|
return true;
|
|
3267
3270
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { default as ai } from './ai.js';
|
|
2
2
|
import { default as auth } from './auth.js';
|
|
3
3
|
import { default as files } from './files.js';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
DefaultModuleName,
|
|
6
|
+
DefaultModules,
|
|
7
|
+
escapeSpecialChars,
|
|
8
|
+
isString,
|
|
9
|
+
restoreSpecialChars,
|
|
10
|
+
} from '../util.js';
|
|
5
11
|
import { Instance, isInstanceOfType, makeInstance, newInstanceAttributes } from '../module.js';
|
|
6
12
|
import {
|
|
7
13
|
Environment,
|
|
@@ -120,6 +126,12 @@ event validateModule extends ValidationRequest {
|
|
|
120
126
|
workflow validateModule {
|
|
121
127
|
await Core.validateModule(validateModule.data)
|
|
122
128
|
}
|
|
129
|
+
|
|
130
|
+
entity Migration {
|
|
131
|
+
appVersion String @id,
|
|
132
|
+
ups String @optional,
|
|
133
|
+
downs String @optional
|
|
134
|
+
}
|
|
123
135
|
`;
|
|
124
136
|
|
|
125
137
|
export const CoreModules: string[] = [];
|
|
@@ -404,3 +416,86 @@ export async function validateModule(moduleDef: any): Promise<Instance> {
|
|
|
404
416
|
);
|
|
405
417
|
}
|
|
406
418
|
}
|
|
419
|
+
|
|
420
|
+
const SqlSep = ';\n\n';
|
|
421
|
+
|
|
422
|
+
export async function saveMigration(
|
|
423
|
+
version: string,
|
|
424
|
+
ups: string[] | undefined,
|
|
425
|
+
downs: string[] | undefined
|
|
426
|
+
): Promise<boolean> {
|
|
427
|
+
try {
|
|
428
|
+
const env = new Environment(`migrations-${version}-env`);
|
|
429
|
+
await parseAndEvaluateStatement(
|
|
430
|
+
`purge {agentlang/Migration {appVersion? "${version}"}}`,
|
|
431
|
+
undefined,
|
|
432
|
+
env
|
|
433
|
+
);
|
|
434
|
+
let ups_str = '';
|
|
435
|
+
if (ups) {
|
|
436
|
+
ups_str = escapeSpecialChars(
|
|
437
|
+
ups
|
|
438
|
+
.map((s: string) => {
|
|
439
|
+
return s.trim();
|
|
440
|
+
})
|
|
441
|
+
.join(SqlSep)
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
let downs_str = '';
|
|
445
|
+
if (downs) {
|
|
446
|
+
downs_str = escapeSpecialChars(
|
|
447
|
+
downs
|
|
448
|
+
.map((s: string) => {
|
|
449
|
+
return s.trim();
|
|
450
|
+
})
|
|
451
|
+
.join(SqlSep)
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
const inst: Instance = await parseAndEvaluateStatement(`{agentlang/Migration {
|
|
455
|
+
appVersion "${version}",
|
|
456
|
+
ups "${ups_str}",
|
|
457
|
+
downs "${downs_str}"}}`);
|
|
458
|
+
if (isInstanceOfType(inst, 'agentlang/Migration') && inst.lookup('appVersion') === version) {
|
|
459
|
+
await env.commitAllTransactions();
|
|
460
|
+
return true;
|
|
461
|
+
} else {
|
|
462
|
+
logger.warn(`Failed to save migration for version ${version}`);
|
|
463
|
+
}
|
|
464
|
+
} catch (reason: any) {
|
|
465
|
+
logger.error(`Failed to save migration for version ${version} - ${reason}`);
|
|
466
|
+
}
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export async function loadMigration(version: string): Promise<Instance | undefined> {
|
|
471
|
+
try {
|
|
472
|
+
const env = new Environment(`migrations-${version}-env`);
|
|
473
|
+
const insts: Instance[] = await parseAndEvaluateStatement(
|
|
474
|
+
`{agentlang/Migration {appVersion? "${version}"}}`,
|
|
475
|
+
undefined,
|
|
476
|
+
env
|
|
477
|
+
);
|
|
478
|
+
if (insts && insts.length > 0) {
|
|
479
|
+
return insts[0];
|
|
480
|
+
}
|
|
481
|
+
} catch (reason: any) {
|
|
482
|
+
logger.error(`Failed to lookup migration for version ${version} - ${reason}`);
|
|
483
|
+
}
|
|
484
|
+
return undefined;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export function migrationUps(inst: Instance): string[] | undefined {
|
|
488
|
+
const ups: string | undefined = inst.lookup('ups');
|
|
489
|
+
if (ups) {
|
|
490
|
+
return restoreSpecialChars(ups).split(SqlSep);
|
|
491
|
+
}
|
|
492
|
+
return undefined;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export function migrationDowns(inst: Instance): string[] | undefined {
|
|
496
|
+
const downs: string | undefined = inst.lookup('downs');
|
|
497
|
+
if (downs) {
|
|
498
|
+
return restoreSpecialChars(downs).split(SqlSep);
|
|
499
|
+
}
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
@@ -329,6 +329,8 @@ export class GenericResolver extends Resolver {
|
|
|
329
329
|
}
|
|
330
330
|
|
|
331
331
|
override async subscribe() {
|
|
332
|
+
const MaxErrors = 3;
|
|
333
|
+
let errCount = 0;
|
|
332
334
|
while (true) {
|
|
333
335
|
try {
|
|
334
336
|
if (this.subs?.subscribe) {
|
|
@@ -338,6 +340,11 @@ export class GenericResolver extends Resolver {
|
|
|
338
340
|
return;
|
|
339
341
|
} catch (reason: any) {
|
|
340
342
|
logger.warn(`subscribe error in resolver ${this.name}: ${reason}`);
|
|
343
|
+
if (errCount >= MaxErrors) {
|
|
344
|
+
logger.warn(`exiting resolver subscription after ${errCount} retries`);
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
++errCount;
|
|
341
348
|
}
|
|
342
349
|
}
|
|
343
350
|
}
|
|
@@ -29,9 +29,16 @@ import { isString } from '../../util.js';
|
|
|
29
29
|
import {
|
|
30
30
|
DeletedFlagAttributeName,
|
|
31
31
|
ForceReadPermFlag,
|
|
32
|
+
isRuntimeMode_dev,
|
|
33
|
+
isRuntimeMode_generate_migration,
|
|
34
|
+
isRuntimeMode_init_schema,
|
|
35
|
+
isRuntimeMode_migration,
|
|
36
|
+
isRuntimeMode_undo_migration,
|
|
32
37
|
PathAttributeName,
|
|
33
38
|
UnauthorisedError,
|
|
34
39
|
} from '../../defs.js';
|
|
40
|
+
import { saveMigration } from '../../modules/core.js';
|
|
41
|
+
import { getAppSpec } from '../../loader.js';
|
|
35
42
|
|
|
36
43
|
export let defaultDataSource: DataSource | undefined;
|
|
37
44
|
|
|
@@ -165,9 +172,10 @@ function mkDbName(): string {
|
|
|
165
172
|
|
|
166
173
|
function makePostgresDataSource(
|
|
167
174
|
entities: EntitySchema[],
|
|
168
|
-
config: DatabaseConfig | undefined
|
|
169
|
-
synchronize: boolean = true
|
|
175
|
+
config: DatabaseConfig | undefined
|
|
170
176
|
): DataSource {
|
|
177
|
+
const synchronize = isRuntimeMode_dev() || isRuntimeMode_init_schema();
|
|
178
|
+
//const runMigrations = isRuntimeMode_migration() || isRuntimeMode_undo_migration() || !synchronize;
|
|
171
179
|
return new DataSource({
|
|
172
180
|
type: 'postgres',
|
|
173
181
|
host: process.env.POSTGRES_HOST || config?.host || 'localhost',
|
|
@@ -176,6 +184,8 @@ function makePostgresDataSource(
|
|
|
176
184
|
password: process.env.POSTGRES_PASSWORD || config?.password || 'postgres',
|
|
177
185
|
database: process.env.POSTGRES_DB || config?.dbname || 'postgres',
|
|
178
186
|
synchronize: synchronize,
|
|
187
|
+
migrationsRun: false,
|
|
188
|
+
dropSchema: false,
|
|
179
189
|
entities: entities,
|
|
180
190
|
invalidWhereValuesBehavior: {
|
|
181
191
|
null: 'sql-null',
|
|
@@ -195,14 +205,17 @@ function getPostgressEnvPort(): number | undefined {
|
|
|
195
205
|
|
|
196
206
|
function makeSqliteDataSource(
|
|
197
207
|
entities: EntitySchema[],
|
|
198
|
-
config: DatabaseConfig | undefined
|
|
199
|
-
synchronize: boolean = true
|
|
208
|
+
config: DatabaseConfig | undefined
|
|
200
209
|
): DataSource {
|
|
210
|
+
const synchronize = isRuntimeMode_dev() || isRuntimeMode_init_schema();
|
|
211
|
+
//const runMigrations = isRuntimeMode_migration() || isRuntimeMode_undo_migration() || !synchronize;
|
|
201
212
|
return new DataSource({
|
|
202
213
|
type: 'sqlite',
|
|
203
214
|
database: config?.dbname || mkDbName(),
|
|
204
215
|
synchronize: synchronize,
|
|
205
216
|
entities: entities,
|
|
217
|
+
migrationsRun: false,
|
|
218
|
+
dropSchema: false,
|
|
206
219
|
invalidWhereValuesBehavior: {
|
|
207
220
|
null: 'sql-null',
|
|
208
221
|
undefined: 'ignore',
|
|
@@ -210,6 +223,47 @@ function makeSqliteDataSource(
|
|
|
210
223
|
});
|
|
211
224
|
}
|
|
212
225
|
|
|
226
|
+
async function execMigrationSql(dataSource: DataSource, sql: string[]) {
|
|
227
|
+
const queryRunner = dataSource.createQueryRunner();
|
|
228
|
+
await queryRunner.startTransaction();
|
|
229
|
+
for (let i = 0; i < sql.length; ++i) {
|
|
230
|
+
await queryRunner.query(sql[i]);
|
|
231
|
+
}
|
|
232
|
+
await queryRunner.commitTransaction();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function maybeHandleMigrations(dataSource: DataSource) {
|
|
236
|
+
const is_migration = isRuntimeMode_migration();
|
|
237
|
+
const is_undo_migration = isRuntimeMode_undo_migration();
|
|
238
|
+
const is_gen_migration = isRuntimeMode_generate_migration();
|
|
239
|
+
if (is_migration || is_undo_migration || is_gen_migration) {
|
|
240
|
+
const sqlInMemory = await dataSource.driver.createSchemaBuilder().log();
|
|
241
|
+
let ups: string[] | undefined;
|
|
242
|
+
if (is_migration || is_gen_migration) {
|
|
243
|
+
ups = new Array<string>();
|
|
244
|
+
sqlInMemory.upQueries.forEach(upQuery => {
|
|
245
|
+
ups?.push(upQuery.query.replaceAll('`', '\\`'));
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
let downs: string[] | undefined;
|
|
249
|
+
if (is_undo_migration || is_gen_migration) {
|
|
250
|
+
downs = new Array<string>();
|
|
251
|
+
sqlInMemory.downQueries.forEach(downQuery => {
|
|
252
|
+
downs?.push(downQuery.query.replaceAll('`', '\\`'));
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
if (is_migration && ups?.length) {
|
|
256
|
+
await saveMigration(getAppSpec().version, ups, downs);
|
|
257
|
+
await execMigrationSql(dataSource, ups);
|
|
258
|
+
} else if (is_undo_migration && downs?.length) {
|
|
259
|
+
await saveMigration(getAppSpec().version, ups, downs);
|
|
260
|
+
await execMigrationSql(dataSource, downs);
|
|
261
|
+
} else if (is_gen_migration) {
|
|
262
|
+
await saveMigration(getAppSpec().version, ups, downs);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
213
267
|
function isBrowser(): boolean {
|
|
214
268
|
// window for DOM pages, self+importScripts for web workers
|
|
215
269
|
return (
|
|
@@ -305,6 +359,7 @@ export async function initDatabase(config: DatabaseConfig | undefined) {
|
|
|
305
359
|
const ormScm = modulesAsOrmSchema();
|
|
306
360
|
defaultDataSource = mkds(ormScm.entities, config) as DataSource;
|
|
307
361
|
await defaultDataSource.initialize();
|
|
362
|
+
await maybeHandleMigrations(defaultDataSource);
|
|
308
363
|
if (ormScm.fkSpecs.length > 0) {
|
|
309
364
|
const qr = defaultDataSource.createQueryRunner();
|
|
310
365
|
for (let i = 0; i < ormScm.fkSpecs.length; ++i) {
|
|
@@ -316,7 +371,11 @@ export async function initDatabase(config: DatabaseConfig | undefined) {
|
|
|
316
371
|
onDelete: fk.onDelete,
|
|
317
372
|
onUpdate: fk.onUpdate,
|
|
318
373
|
});
|
|
319
|
-
|
|
374
|
+
try {
|
|
375
|
+
await qr.createForeignKey(asTableReference(fk.moduleName, fk.entityName), fkobj);
|
|
376
|
+
} catch (reason: any) {
|
|
377
|
+
logger.warn(`initDatabase: ${reason}`);
|
|
378
|
+
}
|
|
320
379
|
}
|
|
321
380
|
}
|
|
322
381
|
const vectEnts = ormScm.vectorEntities.map((es: EntitySchema) => {
|