agentlang 0.7.2 → 0.7.4
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/api/http.d.ts.map +1 -1
- package/out/api/http.js +63 -1
- package/out/api/http.js.map +1 -1
- package/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +10 -3
- package/out/cli/main.js.map +1 -1
- package/out/runtime/defs.d.ts +2 -0
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +11 -4
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/interpreter.js +3 -3
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts +0 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +61 -34
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/logger.d.ts +2 -0
- package/out/runtime/logger.d.ts.map +1 -1
- package/out/runtime/logger.js +46 -24
- package/out/runtime/logger.js.map +1 -1
- package/out/runtime/module.d.ts +3 -2
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +7 -3
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/core.d.ts +2 -1
- package/out/runtime/modules/core.d.ts.map +1 -1
- package/out/runtime/modules/core.js +69 -9
- 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 +49 -8
- 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 +8 -4
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +3 -2
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/state.d.ts +13 -0
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +5 -0
- package/out/runtime/state.js.map +1 -1
- package/out/runtime/util.d.ts +2 -0
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +11 -0
- package/out/runtime/util.js.map +1 -1
- package/package.json +185 -186
- package/src/api/http.ts +72 -0
- package/src/cli/main.ts +12 -1
- package/src/runtime/defs.ts +9 -0
- package/src/runtime/interpreter.ts +3 -3
- package/src/runtime/loader.ts +60 -31
- package/src/runtime/logger.ts +52 -27
- package/src/runtime/module.ts +12 -3
- package/src/runtime/modules/core.ts +78 -9
- package/src/runtime/resolvers/interface.ts +55 -7
- package/src/runtime/resolvers/sqldb/database.ts +9 -2
- package/src/runtime/resolvers/sqldb/impl.ts +3 -10
- package/src/runtime/state.ts +5 -0
- package/src/runtime/util.ts +13 -0
- package/out/setupClassic.d.ts +0 -98
- package/out/setupClassic.d.ts.map +0 -1
- package/out/setupClassic.js +0 -38
- package/out/setupClassic.js.map +0 -1
- package/out/setupCommon.d.ts +0 -2
- package/out/setupCommon.d.ts.map +0 -1
- package/out/setupCommon.js +0 -33
- package/out/setupCommon.js.map +0 -1
- package/out/setupExtended.d.ts +0 -40
- package/out/setupExtended.d.ts.map +0 -1
- package/out/setupExtended.js +0 -67
- package/out/setupExtended.js.map +0 -1
package/src/runtime/loader.ts
CHANGED
|
@@ -77,6 +77,7 @@ import {
|
|
|
77
77
|
isFqName,
|
|
78
78
|
makeFqName,
|
|
79
79
|
maybeExtends,
|
|
80
|
+
objectAsString,
|
|
80
81
|
preprocessRawConfig,
|
|
81
82
|
registerInitFunction,
|
|
82
83
|
rootRef,
|
|
@@ -342,6 +343,40 @@ export async function flushAllAndLoad(
|
|
|
342
343
|
return await load(fileName, fsOptions, callback);
|
|
343
344
|
}
|
|
344
345
|
|
|
346
|
+
async function evaluateConfigPatterns(cfgPats: string): Promise<any> {
|
|
347
|
+
const cfgWf = `workflow createConfig{\n${cfgPats}}`;
|
|
348
|
+
const wf = await parseWorkflow(cfgWf);
|
|
349
|
+
const cfgStmts = new Array<Statement>();
|
|
350
|
+
const initInsts = new Array<Statement>();
|
|
351
|
+
for (let i = 0; i < wf.statements.length; ++i) {
|
|
352
|
+
const stmt: Statement = wf.statements[i];
|
|
353
|
+
if (stmt.pattern.crudMap) {
|
|
354
|
+
initInsts.push(await makeDeleteAllConfigStatement(stmt.pattern.crudMap));
|
|
355
|
+
initInsts.push(stmt);
|
|
356
|
+
} else {
|
|
357
|
+
cfgStmts.push(stmt);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (initInsts.length > 0) {
|
|
361
|
+
registerInitFunction(async () => {
|
|
362
|
+
const env = new Environment('config.insts.env');
|
|
363
|
+
try {
|
|
364
|
+
await evaluateStatements(initInsts, env);
|
|
365
|
+
await env.commitAllTransactions();
|
|
366
|
+
} catch (reason: any) {
|
|
367
|
+
await env.rollbackAllTransactions();
|
|
368
|
+
console.error(`Failed to initialize config instances: ${reason}`);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
if (cfgStmts.length > 0) {
|
|
373
|
+
const env = new Environment('config.env');
|
|
374
|
+
await evaluateStatements(cfgStmts, env);
|
|
375
|
+
return env.getLastResult();
|
|
376
|
+
}
|
|
377
|
+
return undefined;
|
|
378
|
+
}
|
|
379
|
+
|
|
345
380
|
export async function loadAppConfig(configDir: string): Promise<Config> {
|
|
346
381
|
let cfgObj: any = undefined;
|
|
347
382
|
const fs = await getFileSystem();
|
|
@@ -349,39 +384,12 @@ export async function loadAppConfig(configDir: string): Promise<Config> {
|
|
|
349
384
|
if (await fs.exists(alCfgFile)) {
|
|
350
385
|
const cfgPats = await fs.readFile(alCfgFile);
|
|
351
386
|
if (canParse(cfgPats)) {
|
|
352
|
-
|
|
353
|
-
const wf = await parseWorkflow(cfgWf);
|
|
354
|
-
const env = new Environment('config.env');
|
|
355
|
-
const cfgStmts = new Array<Statement>();
|
|
356
|
-
const initInsts = new Array<Statement>();
|
|
357
|
-
for (let i = 0; i < wf.statements.length; ++i) {
|
|
358
|
-
const stmt: Statement = wf.statements[i];
|
|
359
|
-
if (stmt.pattern.crudMap) {
|
|
360
|
-
initInsts.push(await makeDeleteAllConfigStatement(stmt.pattern.crudMap));
|
|
361
|
-
initInsts.push(stmt);
|
|
362
|
-
} else {
|
|
363
|
-
cfgStmts.push(stmt);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
if (initInsts.length > 0) {
|
|
367
|
-
registerInitFunction(async () => {
|
|
368
|
-
const env = new Environment('config.insts.env');
|
|
369
|
-
try {
|
|
370
|
-
await evaluateStatements(initInsts, env);
|
|
371
|
-
await env.commitAllTransactions();
|
|
372
|
-
} catch (reason: any) {
|
|
373
|
-
await env.rollbackAllTransactions();
|
|
374
|
-
console.error(`Failed to initialize config instances: ${reason}`);
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
await evaluateStatements(cfgStmts, env);
|
|
379
|
-
cfgObj = env.getLastResult();
|
|
387
|
+
cfgObj = await evaluateConfigPatterns(cfgPats);
|
|
380
388
|
}
|
|
381
389
|
}
|
|
382
390
|
try {
|
|
383
391
|
const cfg = cfgObj
|
|
384
|
-
? configFromObject(cfgObj)
|
|
392
|
+
? await configFromObject(cfgObj)
|
|
385
393
|
: await loadRawConfig(`${configDir}${path.sep}app.config.json`);
|
|
386
394
|
return setAppConfig(cfg);
|
|
387
395
|
} catch (err: any) {
|
|
@@ -1178,10 +1186,31 @@ export async function loadRawConfig(
|
|
|
1178
1186
|
}
|
|
1179
1187
|
}
|
|
1180
1188
|
|
|
1181
|
-
|
|
1189
|
+
function filterConfigEntityInstances(rawConfig: any): [any, Map<string, any>] {
|
|
1190
|
+
const cfg = new Map<string, any>();
|
|
1191
|
+
const insts = new Map<string, any>();
|
|
1192
|
+
Object.entries(rawConfig).forEach(([key, value]: [string, any]) => {
|
|
1193
|
+
if (isFqName(key)) {
|
|
1194
|
+
insts.set(key, value);
|
|
1195
|
+
} else {
|
|
1196
|
+
cfg.set(key, value);
|
|
1197
|
+
}
|
|
1198
|
+
});
|
|
1199
|
+
return [Object.fromEntries(cfg), insts];
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
async function configFromObject(cfgObj: any, validate: boolean = true): Promise<any> {
|
|
1182
1203
|
const rawConfig = preprocessRawConfig(cfgObj);
|
|
1183
1204
|
if (validate) {
|
|
1184
|
-
|
|
1205
|
+
const [cfg, insts] = filterConfigEntityInstances(rawConfig);
|
|
1206
|
+
const pats = new Array<string>();
|
|
1207
|
+
insts.forEach((v: any, k: string) => {
|
|
1208
|
+
pats.push(`{${k} ${objectAsString(v)}}`);
|
|
1209
|
+
});
|
|
1210
|
+
if (pats.length > 0) {
|
|
1211
|
+
await evaluateConfigPatterns(pats.join('\n'));
|
|
1212
|
+
}
|
|
1213
|
+
return ConfigSchema.parse(cfg);
|
|
1185
1214
|
}
|
|
1186
1215
|
return rawConfig;
|
|
1187
1216
|
}
|
package/src/runtime/logger.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isNodeEnv } from '../utils/runtime.js';
|
|
2
|
+
import { AppConfig } from './state.js';
|
|
2
3
|
|
|
3
4
|
let DailyRotateFile: any;
|
|
4
5
|
let winston: any;
|
|
@@ -16,34 +17,58 @@ if (isNodeEnv) {
|
|
|
16
17
|
|
|
17
18
|
export let logger: any;
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
maxFiles: '7d',
|
|
26
|
-
});
|
|
20
|
+
function getLogLevel(): string {
|
|
21
|
+
if (isNodeEnv && process.env && process.env.DEBUG) {
|
|
22
|
+
return 'debug';
|
|
23
|
+
}
|
|
24
|
+
return AppConfig?.logging?.level || 'info';
|
|
25
|
+
}
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
27
|
+
export function initializeLogger() {
|
|
28
|
+
const logLevel = getLogLevel();
|
|
29
|
+
|
|
30
|
+
if (isNodeEnv) {
|
|
31
|
+
const fileTransport = new DailyRotateFile({
|
|
32
|
+
level: logLevel,
|
|
33
|
+
filename: 'logs/app-%DATE%.log',
|
|
34
|
+
datePattern: 'YYYY-MM-DD',
|
|
35
|
+
maxSize: '20m',
|
|
36
|
+
maxFiles: '7d',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
logger = winston.createLogger({
|
|
40
|
+
level: logLevel,
|
|
41
|
+
format: winston.format.combine(
|
|
42
|
+
winston.format.timestamp(),
|
|
43
|
+
winston.format.printf(({ timestamp, level, message }: any) => {
|
|
44
|
+
return `[${timestamp}] ${level}: ${message}`;
|
|
45
|
+
})
|
|
46
|
+
),
|
|
47
|
+
transports: [fileTransport],
|
|
48
|
+
});
|
|
49
|
+
} else {
|
|
50
|
+
function mkLogger(tag: string): Function {
|
|
51
|
+
return (msg: string) => {
|
|
52
|
+
console.log(`${tag}: ${msg}`);
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
logger = {
|
|
56
|
+
debug: mkLogger('DEBUG'),
|
|
57
|
+
info: mkLogger('INFO'),
|
|
58
|
+
warn: mkLogger('WARN'),
|
|
59
|
+
error: mkLogger('ERROR'),
|
|
41
60
|
};
|
|
42
61
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
initializeLogger();
|
|
65
|
+
|
|
66
|
+
export function updateLoggerFromConfig() {
|
|
67
|
+
if (isNodeEnv && logger) {
|
|
68
|
+
const logLevel = getLogLevel();
|
|
69
|
+
logger.level = logLevel;
|
|
70
|
+
if (logger.transports && logger.transports.length > 0) {
|
|
71
|
+
logger.transports[0].level = logLevel;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
49
74
|
}
|
package/src/runtime/module.ts
CHANGED
|
@@ -1248,7 +1248,7 @@ export class Relationship extends Record {
|
|
|
1248
1248
|
|
|
1249
1249
|
constructor(
|
|
1250
1250
|
name: string,
|
|
1251
|
-
|
|
1251
|
+
type: string,
|
|
1252
1252
|
node1: RelationshipNode,
|
|
1253
1253
|
node2: RelationshipNode,
|
|
1254
1254
|
moduleName: string,
|
|
@@ -1256,7 +1256,7 @@ export class Relationship extends Record {
|
|
|
1256
1256
|
props?: Map<string, any>
|
|
1257
1257
|
) {
|
|
1258
1258
|
super(name, moduleName, scm);
|
|
1259
|
-
if (
|
|
1259
|
+
if (type == 'between') {
|
|
1260
1260
|
this.relType = RelType.BETWEEN;
|
|
1261
1261
|
this.addMetaAttributes();
|
|
1262
1262
|
}
|
|
@@ -3999,7 +3999,7 @@ export function getAttributeNames(entityFqName: string): Array<string> {
|
|
|
3999
3999
|
return [...scm.keys()];
|
|
4000
4000
|
}
|
|
4001
4001
|
|
|
4002
|
-
export function
|
|
4002
|
+
export function setMetaAttributes(
|
|
4003
4003
|
attrs: InstanceAttributes,
|
|
4004
4004
|
env: Environment,
|
|
4005
4005
|
inUpdateMode: boolean = false
|
|
@@ -4010,3 +4010,12 @@ export function maybeSetMetaAttributes(
|
|
|
4010
4010
|
attrs.set(SysAttr_CreatedBy, user);
|
|
4011
4011
|
}
|
|
4012
4012
|
}
|
|
4013
|
+
|
|
4014
|
+
export function setAllMetaAttributes(
|
|
4015
|
+
attrs: InstanceAttributes,
|
|
4016
|
+
env: Environment,
|
|
4017
|
+
inUpdateMode: boolean = false
|
|
4018
|
+
) {
|
|
4019
|
+
attrs.set(SysAttr_Created, now());
|
|
4020
|
+
setMetaAttributes(attrs, env, inUpdateMode);
|
|
4021
|
+
}
|
|
@@ -28,14 +28,16 @@ import {
|
|
|
28
28
|
import { logger } from '../logger.js';
|
|
29
29
|
import { Statement } from '../../language/generated/ast.js';
|
|
30
30
|
import { parseModule, parseStatements } from '../../language/parser.js';
|
|
31
|
-
import { Resolver } from '../resolvers/interface.js';
|
|
31
|
+
import { GenericResolver, Resolver } from '../resolvers/interface.js';
|
|
32
32
|
import {
|
|
33
33
|
FlowSuspensionTag,
|
|
34
34
|
ForceReadPermFlag,
|
|
35
35
|
InternDynamicModule,
|
|
36
|
+
isRuntimeMode_dev,
|
|
36
37
|
PathAttributeName,
|
|
37
38
|
} from '../defs.js';
|
|
38
39
|
import { getMonitor, getMonitorsForEvent, Monitor } from '../monitor.js';
|
|
40
|
+
import { registerResolver, setResolver } from '../resolvers/registry.js';
|
|
39
41
|
|
|
40
42
|
const CoreModuleDefinition = `module ${DefaultModuleName}
|
|
41
43
|
|
|
@@ -146,11 +148,12 @@ entity Module {
|
|
|
146
148
|
definition String
|
|
147
149
|
}
|
|
148
150
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
entity PersistentModule extends Module {
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
workflow savePersistentModule {
|
|
155
|
+
purge {PersistentModule {name? savePersistentModule.name}}
|
|
156
|
+
{PersistentModule {name savePersistentModule.name, definition savePersistentModule.definition}}
|
|
154
157
|
}
|
|
155
158
|
|
|
156
159
|
entity Migration {
|
|
@@ -464,7 +467,21 @@ export async function internModuleHelper(
|
|
|
464
467
|
}
|
|
465
468
|
|
|
466
469
|
export async function createModule(_: Resolver, inst: Instance) {
|
|
467
|
-
|
|
470
|
+
const n = inst.lookup('name');
|
|
471
|
+
const d = inst.lookup('definition');
|
|
472
|
+
const env = new Environment('module-env');
|
|
473
|
+
try {
|
|
474
|
+
await parseAndEvaluateStatement(
|
|
475
|
+
`{agentlang/savePersistentModule {name "${n}", definition "${d}"}}`,
|
|
476
|
+
undefined,
|
|
477
|
+
env
|
|
478
|
+
);
|
|
479
|
+
await env.commitAllTransactions();
|
|
480
|
+
} catch (reason: any) {
|
|
481
|
+
await env.rollbackAllTransactions();
|
|
482
|
+
logger.error(`Failed to persist module ${n} - ${reason}`);
|
|
483
|
+
}
|
|
484
|
+
await internModuleHelper(n, d);
|
|
468
485
|
return inst;
|
|
469
486
|
}
|
|
470
487
|
|
|
@@ -473,7 +490,20 @@ export async function updateModule(r: Resolver, inst: Instance) {
|
|
|
473
490
|
}
|
|
474
491
|
|
|
475
492
|
export async function deleteModule(_: Resolver, inst: Instance) {
|
|
476
|
-
|
|
493
|
+
const n = inst.lookup('name');
|
|
494
|
+
const env = new Environment('module-env');
|
|
495
|
+
try {
|
|
496
|
+
await parseAndEvaluateStatement(
|
|
497
|
+
`purge {agentlang/PersistentModule {name? "${n}"}}`,
|
|
498
|
+
undefined,
|
|
499
|
+
env
|
|
500
|
+
);
|
|
501
|
+
await env.commitAllTransactions();
|
|
502
|
+
} catch (reason: any) {
|
|
503
|
+
await env.rollbackAllTransactions();
|
|
504
|
+
logger.error(`Failed to purge persistent module ${n} - ${reason}`);
|
|
505
|
+
}
|
|
506
|
+
removeModule(n);
|
|
477
507
|
return inst;
|
|
478
508
|
}
|
|
479
509
|
|
|
@@ -489,7 +519,46 @@ export async function getModule(_: Resolver, inst: Instance) {
|
|
|
489
519
|
return [makeInstance('agentlang', 'Module', attrs)];
|
|
490
520
|
}
|
|
491
521
|
}
|
|
492
|
-
return
|
|
522
|
+
return [];
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
async function internPersistentModules() {
|
|
526
|
+
try {
|
|
527
|
+
const insts: Instance[] = await parseAndEvaluateStatement(`{agentlang/PersistentModule? {}}`);
|
|
528
|
+
for (let i = 0; i < insts.length; ++i) {
|
|
529
|
+
const inst = insts[i];
|
|
530
|
+
const n = inst.lookup('name');
|
|
531
|
+
if (!isModule(n)) await internModuleHelper(n, inst.lookup('definition'));
|
|
532
|
+
}
|
|
533
|
+
} catch (reason: any) {
|
|
534
|
+
logger.warn(`Failed to intern persistent modules: ${reason}`);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export function initCoreModuleManager() {
|
|
539
|
+
const ModuleResolverName = 'agentlang/moduleResolver';
|
|
540
|
+
const ModuleResolver = new GenericResolver(ModuleResolverName, {
|
|
541
|
+
create: createModule,
|
|
542
|
+
upsert: createModule,
|
|
543
|
+
update: updateModule,
|
|
544
|
+
query: getModule,
|
|
545
|
+
delete: deleteModule,
|
|
546
|
+
startTransaction: undefined,
|
|
547
|
+
commitTransaction: undefined,
|
|
548
|
+
rollbackTransaction: undefined,
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
registerResolver(ModuleResolverName, () => {
|
|
552
|
+
return ModuleResolver;
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
setResolver('agentlang/Module', ModuleResolverName);
|
|
556
|
+
|
|
557
|
+
if (isRuntimeMode_dev()) {
|
|
558
|
+
setInterval(() => {
|
|
559
|
+
internPersistentModules();
|
|
560
|
+
}, 10000);
|
|
561
|
+
}
|
|
493
562
|
}
|
|
494
563
|
|
|
495
564
|
const SqlSep = ';\n\n';
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
newInstanceAttributes,
|
|
15
15
|
Relationship,
|
|
16
16
|
} from '../module.js';
|
|
17
|
-
import { CrudType, nameToPath } from '../util.js';
|
|
17
|
+
import { CrudType, nameToPath, generateLoggerCallId } from '../util.js';
|
|
18
18
|
import { DefaultAuthInfo, ResolverAuthInfo } from './authinfo.js';
|
|
19
19
|
|
|
20
20
|
export type JoinInfo = {
|
|
@@ -272,11 +272,22 @@ export class GenericResolver extends Resolver {
|
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
public override async createInstance(inst: Instance): Promise<any> {
|
|
275
|
+
const callId = generateLoggerCallId();
|
|
276
|
+
let attrVals;
|
|
277
|
+
if (inst.attributes) {
|
|
278
|
+
attrVals = JSON.stringify(Object.fromEntries(inst.attributes));
|
|
279
|
+
}
|
|
280
|
+
logger.debug(
|
|
281
|
+
`${callId}: Resolver createInstance called for ${inst.moduleName + '/' + inst.name} with values ${attrVals}`
|
|
282
|
+
);
|
|
283
|
+
let result;
|
|
275
284
|
if (this.implementation?.create) {
|
|
276
|
-
|
|
285
|
+
result = await this.implementation.create(this, inst);
|
|
277
286
|
} else {
|
|
278
|
-
|
|
287
|
+
result = await super.createInstance(inst);
|
|
279
288
|
}
|
|
289
|
+
logger.debug(`${callId}: Resolver createInstance response: ${JSON.stringify(result)}`);
|
|
290
|
+
return result;
|
|
280
291
|
}
|
|
281
292
|
|
|
282
293
|
public override async upsertInstance(inst: Instance): Promise<any> {
|
|
@@ -287,20 +298,57 @@ export class GenericResolver extends Resolver {
|
|
|
287
298
|
}
|
|
288
299
|
|
|
289
300
|
public override async updateInstance(inst: Instance, newAttrs: InstanceAttributes): Promise<any> {
|
|
301
|
+
const callId = generateLoggerCallId();
|
|
302
|
+
|
|
303
|
+
const newAttrsVals = JSON.stringify(Object.fromEntries(newAttrs));
|
|
304
|
+
logger.debug(
|
|
305
|
+
`${callId} Resolver updateInstance called for ${inst.moduleName + '/' + inst.name} with values ${newAttrsVals}`
|
|
306
|
+
);
|
|
307
|
+
if (inst.queryAttributes && inst.queryAttributeValues) {
|
|
308
|
+
const qattr = JSON.stringify(Object.fromEntries(inst.queryAttributes));
|
|
309
|
+
const qattrValues = JSON.stringify(Object.fromEntries(inst.queryAttributeValues));
|
|
310
|
+
logger.debug(`${callId}: Query attributes: ${qattr}, values ${qattrValues}`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
let result;
|
|
290
314
|
if (this.implementation?.update) {
|
|
291
|
-
|
|
315
|
+
result = await this.implementation.update(this, inst, newAttrs);
|
|
316
|
+
} else {
|
|
317
|
+
result = await super.updateInstance(inst, newAttrs);
|
|
292
318
|
}
|
|
293
|
-
|
|
319
|
+
logger.debug(`${callId}: Resolver updateInstance response: ${JSON.stringify(result)}`);
|
|
320
|
+
return result;
|
|
294
321
|
}
|
|
295
322
|
|
|
296
323
|
public override async queryInstances(inst: Instance, queryAll: boolean): Promise<any> {
|
|
324
|
+
const callId = generateLoggerCallId();
|
|
325
|
+
logger.debug(
|
|
326
|
+
`${callId}: Resolver queryInstances called for ${inst.moduleName + '/' + inst.name}`
|
|
327
|
+
);
|
|
328
|
+
if (inst.queryAttributes && inst.queryAttributeValues) {
|
|
329
|
+
const qattr = JSON.stringify(Object.fromEntries(inst.queryAttributes));
|
|
330
|
+
const qattrValues = JSON.stringify(Object.fromEntries(inst.queryAttributeValues));
|
|
331
|
+
logger.debug(`${callId}: Query attributes: ${qattr}, values ${qattrValues}`);
|
|
332
|
+
}
|
|
333
|
+
let result;
|
|
297
334
|
if (this.implementation?.query) {
|
|
298
|
-
|
|
335
|
+
result = await this.implementation.query(this, inst, queryAll);
|
|
336
|
+
} else {
|
|
337
|
+
result = await super.queryInstances(inst, queryAll);
|
|
299
338
|
}
|
|
300
|
-
|
|
339
|
+
logger.debug(`${callId}: Resolver queryInstances response: ${JSON.stringify(result)}`);
|
|
340
|
+
return result;
|
|
301
341
|
}
|
|
302
342
|
|
|
303
343
|
public override async deleteInstance(inst: Instance | Instance[], purge: boolean): Promise<any> {
|
|
344
|
+
if (inst instanceof Instance) {
|
|
345
|
+
if (inst.queryAttributes)
|
|
346
|
+
logger.debug(`Resolver deleteInstance called for ${inst.moduleName + '/' + inst.name}`);
|
|
347
|
+
} else {
|
|
348
|
+
logger.debug(
|
|
349
|
+
`Resolver deleteInstance called for ${inst.map(i => i.moduleName + '/' + i.name).join(', ')}`
|
|
350
|
+
);
|
|
351
|
+
}
|
|
304
352
|
if (this.implementation?.delete) {
|
|
305
353
|
return await this.implementation.delete(this, inst, purge);
|
|
306
354
|
}
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
RbacPermissionFlag,
|
|
25
25
|
RbacSpecification,
|
|
26
26
|
Relationship,
|
|
27
|
+
setAllMetaAttributes,
|
|
27
28
|
} from '../../module.js';
|
|
28
29
|
import { isString } from '../../util.js';
|
|
29
30
|
import {
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
isRuntimeMode_generate_migration,
|
|
34
35
|
isRuntimeMode_init_schema,
|
|
35
36
|
isRuntimeMode_migration,
|
|
37
|
+
isRuntimeMode_test,
|
|
36
38
|
isRuntimeMode_undo_migration,
|
|
37
39
|
PathAttributeName,
|
|
38
40
|
UnauthorisedError,
|
|
@@ -170,11 +172,15 @@ function mkDbName(): string {
|
|
|
170
172
|
return process.env.AGENTLANG_DB_NAME || `db-${Date.now()}`;
|
|
171
173
|
}
|
|
172
174
|
|
|
175
|
+
function needSync(): boolean {
|
|
176
|
+
return isRuntimeMode_dev() || isRuntimeMode_test() || isRuntimeMode_init_schema();
|
|
177
|
+
}
|
|
178
|
+
|
|
173
179
|
function makePostgresDataSource(
|
|
174
180
|
entities: EntitySchema[],
|
|
175
181
|
config: DatabaseConfig | undefined
|
|
176
182
|
): DataSource {
|
|
177
|
-
const synchronize =
|
|
183
|
+
const synchronize = needSync();
|
|
178
184
|
//const runMigrations = isRuntimeMode_migration() || isRuntimeMode_undo_migration() || !synchronize;
|
|
179
185
|
return new DataSource({
|
|
180
186
|
type: 'postgres',
|
|
@@ -207,7 +213,7 @@ function makeSqliteDataSource(
|
|
|
207
213
|
entities: EntitySchema[],
|
|
208
214
|
config: DatabaseConfig | undefined
|
|
209
215
|
): DataSource {
|
|
210
|
-
const synchronize =
|
|
216
|
+
const synchronize = needSync();
|
|
211
217
|
//const runMigrations = isRuntimeMode_migration() || isRuntimeMode_undo_migration() || !synchronize;
|
|
212
218
|
return new DataSource({
|
|
213
219
|
type: 'sqlite',
|
|
@@ -646,6 +652,7 @@ export async function insertBetweenRow(
|
|
|
646
652
|
if (relEntry.isOneToMany()) {
|
|
647
653
|
attrs.set(relEntry.joinNodesAttributeName(), `${p1}_${p2}`);
|
|
648
654
|
}
|
|
655
|
+
setAllMetaAttributes(attrs, ctx.activeEnv);
|
|
649
656
|
const row = Object.fromEntries(attrs);
|
|
650
657
|
await insertRow(n, row, ctx.clone().setNeedAuthCheck(false), false);
|
|
651
658
|
} else {
|
|
@@ -435,6 +435,7 @@ export class SqlDbResolver extends Resolver {
|
|
|
435
435
|
const a1: string = relEntry.node1.alias;
|
|
436
436
|
const a2: string = relEntry.node2.alias;
|
|
437
437
|
const n1path: any = orUpdate ? firstNode.lookup(PathAttributeName) : undefined;
|
|
438
|
+
const ctx = this.getDbContext(relEntry.getFqName());
|
|
438
439
|
if (relEntry.isOneToOne()) {
|
|
439
440
|
await this.updateInstance(
|
|
440
441
|
node1,
|
|
@@ -452,18 +453,10 @@ export class SqlDbResolver extends Resolver {
|
|
|
452
453
|
[a1, n1path],
|
|
453
454
|
[a2, secondNode.lookup(PathAttributeName)],
|
|
454
455
|
],
|
|
455
|
-
|
|
456
|
+
ctx
|
|
456
457
|
);
|
|
457
458
|
}
|
|
458
|
-
await insertBetweenRow(
|
|
459
|
-
n,
|
|
460
|
-
a1,
|
|
461
|
-
a2,
|
|
462
|
-
firstNode,
|
|
463
|
-
secondNode,
|
|
464
|
-
relEntry,
|
|
465
|
-
this.getDbContext(relEntry.getFqName())
|
|
466
|
-
);
|
|
459
|
+
await insertBetweenRow(n, a1, a2, firstNode, secondNode, relEntry, ctx);
|
|
467
460
|
}
|
|
468
461
|
}
|
|
469
462
|
|
package/src/runtime/state.ts
CHANGED
|
@@ -111,6 +111,11 @@ export const ConfigSchema = z.object({
|
|
|
111
111
|
})
|
|
112
112
|
)
|
|
113
113
|
.optional(),
|
|
114
|
+
logging: z
|
|
115
|
+
.object({
|
|
116
|
+
level: z.enum(['error', 'warn', 'info', 'debug']).default('info'),
|
|
117
|
+
})
|
|
118
|
+
.optional(),
|
|
114
119
|
});
|
|
115
120
|
|
|
116
121
|
export type Config = z.infer<typeof ConfigSchema>;
|
package/src/runtime/util.ts
CHANGED
|
@@ -612,6 +612,10 @@ export function generateUrlSafePassword(length: number = 8): string {
|
|
|
612
612
|
return chars.join('');
|
|
613
613
|
}
|
|
614
614
|
|
|
615
|
+
export function generateLoggerCallId() {
|
|
616
|
+
return Math.floor(10000 + Math.random() * 90000);
|
|
617
|
+
}
|
|
618
|
+
|
|
615
619
|
const JS_PREFIX = '#js';
|
|
616
620
|
|
|
617
621
|
export function preprocessRawConfig(rawConfig: any): any {
|
|
@@ -637,3 +641,12 @@ declare global {
|
|
|
637
641
|
export function setScecretReader(f: ReadSecret) {
|
|
638
642
|
globalThis.readSecret = f;
|
|
639
643
|
}
|
|
644
|
+
|
|
645
|
+
export function objectAsString(obj: any) {
|
|
646
|
+
const entries = new Array<string>();
|
|
647
|
+
Object.entries(obj).forEach(([k, v]) => {
|
|
648
|
+
const vv = typeof v === 'string' ? `"${v}"` : v;
|
|
649
|
+
entries.push(`${k}: ${vv}`);
|
|
650
|
+
});
|
|
651
|
+
return `{${entries.join(', ')}}`;
|
|
652
|
+
}
|