agentlang 0.7.8 → 0.7.11
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 +8 -1
- package/out/api/http.js.map +1 -1
- package/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +33 -2
- package/out/cli/main.js.map +1 -1
- package/out/extension/main.cjs +250 -250
- package/out/extension/main.cjs.map +2 -2
- package/out/language/agentlang-validator.d.ts +1 -2
- package/out/language/agentlang-validator.d.ts.map +1 -1
- package/out/language/agentlang-validator.js +0 -39
- package/out/language/agentlang-validator.js.map +1 -1
- package/out/language/generated/ast.d.ts +62 -11
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +75 -3
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.d.ts.map +1 -1
- package/out/language/generated/grammar.js +758 -239
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +1370 -824
- package/out/language/main.cjs.map +4 -4
- package/out/language/parser.d.ts +1 -0
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +44 -7
- package/out/language/parser.js.map +1 -1
- package/out/language/syntax.d.ts +1 -1
- package/out/language/syntax.d.ts.map +1 -1
- package/out/language/syntax.js +22 -13
- package/out/language/syntax.js.map +1 -1
- package/out/runtime/api.d.ts +4 -0
- package/out/runtime/api.d.ts.map +1 -1
- package/out/runtime/api.js +9 -0
- package/out/runtime/api.js.map +1 -1
- package/out/runtime/auth/cognito.d.ts.map +1 -1
- package/out/runtime/auth/cognito.js +4 -4
- package/out/runtime/auth/cognito.js.map +1 -1
- package/out/runtime/auth/defs.d.ts +9 -1
- package/out/runtime/auth/defs.d.ts.map +1 -1
- package/out/runtime/auth/defs.js +23 -2
- package/out/runtime/auth/defs.js.map +1 -1
- package/out/runtime/defs.d.ts +5 -0
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +16 -0
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/exec-graph.js +1 -1
- package/out/runtime/exec-graph.js.map +1 -1
- package/out/runtime/interpreter.d.ts +6 -1
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +144 -112
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +74 -27
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +41 -11
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +238 -50
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +13 -6
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/modules/auth.d.ts +2 -1
- package/out/runtime/modules/auth.d.ts.map +1 -1
- package/out/runtime/modules/auth.js +93 -3
- package/out/runtime/modules/auth.js.map +1 -1
- package/out/runtime/modules/core.d.ts +7 -5
- package/out/runtime/modules/core.d.ts.map +1 -1
- package/out/runtime/modules/core.js +93 -16
- package/out/runtime/modules/core.js.map +1 -1
- package/out/runtime/monitor.d.ts.map +1 -1
- package/out/runtime/monitor.js +1 -0
- package/out/runtime/monitor.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts +6 -1
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +2 -2
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts +19 -2
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +107 -21
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.d.ts +1 -0
- package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.js +25 -3
- package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +3 -2
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +80 -6
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/state.d.ts +58 -0
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +12 -0
- package/out/runtime/state.js.map +1 -1
- package/out/runtime/util.d.ts +1 -1
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +27 -13
- package/out/runtime/util.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +1 -1
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/out/utils/fs-utils.d.ts +10 -0
- package/out/utils/fs-utils.d.ts.map +1 -1
- package/out/utils/fs-utils.js +14 -0
- package/out/utils/fs-utils.js.map +1 -1
- package/package.json +2 -1
- package/src/api/http.ts +8 -0
- package/src/cli/main.ts +38 -2
- package/src/language/agentlang-validator.ts +1 -51
- package/src/language/agentlang.langium +17 -4
- package/src/language/generated/ast.ts +147 -13
- package/src/language/generated/grammar.ts +758 -239
- package/src/language/parser.ts +43 -8
- package/src/language/syntax.ts +25 -12
- package/src/runtime/api.ts +16 -0
- package/src/runtime/auth/defs.ts +25 -2
- package/src/runtime/defs.ts +8 -0
- package/src/runtime/interpreter.ts +104 -76
- package/src/runtime/loader.ts +75 -25
- package/src/runtime/module.ts +194 -32
- package/src/runtime/modules/ai.ts +10 -4
- package/src/runtime/modules/auth.ts +1 -0
- package/src/runtime/modules/core.ts +99 -23
- package/src/runtime/monitor.ts +1 -0
- package/src/runtime/resolvers/interface.ts +9 -2
- package/src/runtime/resolvers/sqldb/database.ts +68 -17
- package/src/runtime/resolvers/sqldb/dbutil.ts +28 -6
- package/src/runtime/resolvers/sqldb/impl.ts +86 -14
- package/src/runtime/state.ts +14 -0
- package/src/runtime/util.ts +25 -12
- package/src/syntaxes/agentlang.monarch.ts +1 -1
- package/src/utils/fs-utils.ts +16 -0
package/src/language/parser.ts
CHANGED
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
Statement,
|
|
34
34
|
WorkflowDefinition,
|
|
35
35
|
} from './generated/ast.js';
|
|
36
|
-
import { firstAliasSpec, firstCatchSpec, QuerySuffix } from '../runtime/util.js';
|
|
36
|
+
import { firstAliasSpec, firstCatchSpec, isString, QuerySuffix } from '../runtime/util.js';
|
|
37
37
|
import {
|
|
38
38
|
BasePattern,
|
|
39
39
|
CrudPattern,
|
|
@@ -291,7 +291,7 @@ function introspectPattern(pat: Pattern): BasePattern {
|
|
|
291
291
|
|
|
292
292
|
function introspectInto(intoSpec: SelectIntoSpec, p: CrudPattern): CrudPattern {
|
|
293
293
|
intoSpec.entries.forEach((se: SelectIntoEntry) => {
|
|
294
|
-
p.addInto(se.alias, se.attribute);
|
|
294
|
+
if (se.attribute) p.addInto(se.alias, se.attribute);
|
|
295
295
|
});
|
|
296
296
|
return p;
|
|
297
297
|
}
|
|
@@ -340,12 +340,14 @@ function introspectPrimExpr(expr: PrimExpr): BasePattern {
|
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
function introspectExpression(expr: Expr |
|
|
344
|
-
if (
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
343
|
+
function introspectExpression(expr: Expr | undefined): BasePattern {
|
|
344
|
+
if (expr !== undefined) {
|
|
345
|
+
if (isPrimExpr(expr)) {
|
|
346
|
+
return introspectPrimExpr(expr);
|
|
347
|
+
}
|
|
348
|
+
if (expr.$cstNode) {
|
|
349
|
+
return new ExpressionPattern(expr.$cstNode.text);
|
|
350
|
+
}
|
|
349
351
|
}
|
|
350
352
|
throw new Error('Failed to introspect expression - ' + expr);
|
|
351
353
|
}
|
|
@@ -507,3 +509,36 @@ export function canParse(s: string): boolean {
|
|
|
507
509
|
}
|
|
508
510
|
return false;
|
|
509
511
|
}
|
|
512
|
+
|
|
513
|
+
export function objectToQueryPattern(obj: any): string {
|
|
514
|
+
const strs = new Array<string>();
|
|
515
|
+
Object.keys(obj).forEach((k: string) => {
|
|
516
|
+
if (k.startsWith('@')) {
|
|
517
|
+
const xs: any = obj[k];
|
|
518
|
+
if (k.endsWith('join')) {
|
|
519
|
+
xs.forEach((x: any[]) => {
|
|
520
|
+
strs.push(`${k} ${x[0]} ${objectToQuerySpecPattern(x[1], true)}`);
|
|
521
|
+
});
|
|
522
|
+
} else if (k === '@groupBy' || k === '@orderBy') {
|
|
523
|
+
strs.push(`${k} ( ${xs.join(', ')} )`);
|
|
524
|
+
} else {
|
|
525
|
+
strs.push(`${k} ${objectToQuerySpecPattern(xs, true)}`);
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
strs.push(`${k} ${objectToQuerySpecPattern(obj[k])}`);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
return `{${strs.join(',\n')}}`;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
function objectToQuerySpecPattern(obj: any, refMode: boolean = false): string {
|
|
535
|
+
const strs = new Array<string>();
|
|
536
|
+
Object.keys(obj).forEach((k: string) => {
|
|
537
|
+
let v = obj[k];
|
|
538
|
+
if (!refMode && isString(v) && !v.startsWith('@')) {
|
|
539
|
+
v = `"${v}"`;
|
|
540
|
+
}
|
|
541
|
+
strs.push(`${k} ${v}`);
|
|
542
|
+
});
|
|
543
|
+
return `{${strs.join(', ')}}`;
|
|
544
|
+
}
|
package/src/language/syntax.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { parseHelper } from 'langium/test';
|
|
2
2
|
import { escapeQueryName, trimQuotes } from '../runtime/util.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
FlowEntry,
|
|
5
|
+
isDecisionDefinition,
|
|
6
|
+
isFlowDefinition,
|
|
7
|
+
ModuleDefinition,
|
|
8
|
+
} from './generated/ast.js';
|
|
4
9
|
import { createAgentlangServices } from './agentlang-module.js';
|
|
5
10
|
import { EmptyFileSystem } from 'langium';
|
|
6
11
|
import { introspect, parseModule } from './parser.js';
|
|
@@ -811,18 +816,26 @@ export class FlowStepPattern extends BasePattern {
|
|
|
811
816
|
this.condition = condition ? trimQuotes(condition) : undefined;
|
|
812
817
|
}
|
|
813
818
|
|
|
814
|
-
static Parse(s: string): FlowStepPattern {
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
819
|
+
static async Parse(s: string): Promise<FlowStepPattern> {
|
|
820
|
+
const p = await parseModule(`module Temp
|
|
821
|
+
flow tempFlow {
|
|
822
|
+
${s}
|
|
823
|
+
}`);
|
|
824
|
+
let result: FlowStepPattern | undefined;
|
|
825
|
+
const d = p.defs[0];
|
|
826
|
+
if (isFlowDefinition(d)) {
|
|
827
|
+
d.body?.entries.forEach((fe: FlowEntry) => {
|
|
828
|
+
if (fe.cond) {
|
|
829
|
+
result = new FlowStepPattern(fe.root, fe.cond.next.$cstNode?.text || '', fe.cond.expr);
|
|
830
|
+
} else {
|
|
831
|
+
result = new FlowStepPattern(fe.root, fe.next?.$cstNode?.text || '');
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
if (result !== undefined) {
|
|
836
|
+
return result;
|
|
825
837
|
}
|
|
838
|
+
throw new Error(`Failed to parse flow-step - ${s}`);
|
|
826
839
|
}
|
|
827
840
|
|
|
828
841
|
override toString(): string {
|
package/src/runtime/api.ts
CHANGED
|
@@ -3,9 +3,15 @@ import {
|
|
|
3
3
|
makeInstance as al_makeInstance,
|
|
4
4
|
isInstanceOfType as al_isInstanceOfType,
|
|
5
5
|
} from './module.js';
|
|
6
|
+
import { getLocalEnv as al_getLocalEnv, setLocalEnv as al_setLocalEnv } from './auth/defs.js';
|
|
7
|
+
import { now } from './util.js';
|
|
6
8
|
|
|
7
9
|
declare global {
|
|
8
10
|
var agentlang: any | undefined;
|
|
11
|
+
function getLocalEnv(k: string, defaultValue?: string): string | undefined;
|
|
12
|
+
function setLocalEnv(k: string, v: string): string;
|
|
13
|
+
function uuid(): string;
|
|
14
|
+
function now(): string;
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
let ApiInited = false;
|
|
@@ -16,6 +22,16 @@ export function initGlobalApi() {
|
|
|
16
22
|
globalThis.agentlang.makeInstance = al_makeInstance;
|
|
17
23
|
globalThis.agentlang.isInstanceOfType = al_isInstanceOfType;
|
|
18
24
|
globalThis.agentlang.fetchConfig = al_fetchConfig;
|
|
25
|
+
|
|
26
|
+
globalThis.uuid = () => {
|
|
27
|
+
return crypto.randomUUID();
|
|
28
|
+
};
|
|
29
|
+
globalThis.now = now;
|
|
30
|
+
|
|
31
|
+
// Expose environment variable functions globally (like readSecret pattern)
|
|
32
|
+
globalThis.getLocalEnv = al_getLocalEnv;
|
|
33
|
+
globalThis.setLocalEnv = al_setLocalEnv;
|
|
34
|
+
|
|
19
35
|
ApiInited = true;
|
|
20
36
|
}
|
|
21
37
|
}
|
package/src/runtime/auth/defs.ts
CHANGED
|
@@ -55,6 +55,29 @@ export function setLocalEnv(k: string, v: string): string {
|
|
|
55
55
|
return v;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Get environment variable with multi-source lookup
|
|
60
|
+
* Priority: 1) LocalEnv Map (explicit overrides), 2) process.env (Node.js), 3) defaultValue
|
|
61
|
+
*
|
|
62
|
+
* @param k - Environment variable key
|
|
63
|
+
* @param defaultValue - Optional default value if key not found
|
|
64
|
+
* @returns The value from highest priority source, or undefined
|
|
65
|
+
*/
|
|
66
|
+
export function getLocalEnv(k: string, defaultValue?: string): string | undefined {
|
|
67
|
+
// Priority 1: Explicitly set values in LocalEnv Map (highest priority)
|
|
68
|
+
const localValue = LocalEnv.get(k);
|
|
69
|
+
if (localValue !== undefined) {
|
|
70
|
+
return localValue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Priority 2: Node.js process.env (if in Node.js environment)
|
|
74
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
75
|
+
const envValue = process.env[k];
|
|
76
|
+
if (envValue !== undefined) {
|
|
77
|
+
return envValue;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Priority 3: Default value (if provided)
|
|
82
|
+
return defaultValue;
|
|
60
83
|
}
|
package/src/runtime/defs.ts
CHANGED
|
@@ -419,6 +419,7 @@ export function isRuntimeMode_undo_migration(): boolean {
|
|
|
419
419
|
|
|
420
420
|
let UpdateEventEndpoints: Function | undefined;
|
|
421
421
|
let UpdateEntityEndpoints: Function | undefined;
|
|
422
|
+
let UpdateRelationshipEndpoints: Function | undefined;
|
|
422
423
|
|
|
423
424
|
export function setEventEndpointsUpdater(f: Function) {
|
|
424
425
|
UpdateEventEndpoints = f;
|
|
@@ -428,6 +429,10 @@ export function setEntityEndpointsUpdater(f: Function) {
|
|
|
428
429
|
UpdateEntityEndpoints = f;
|
|
429
430
|
}
|
|
430
431
|
|
|
432
|
+
export function setRelationshipEndpointsUpdater(f: Function) {
|
|
433
|
+
UpdateRelationshipEndpoints = f;
|
|
434
|
+
}
|
|
435
|
+
|
|
431
436
|
export function updateEndpoints(moduleName: string) {
|
|
432
437
|
if (UpdateEventEndpoints !== undefined) {
|
|
433
438
|
UpdateEventEndpoints(moduleName);
|
|
@@ -435,6 +440,9 @@ export function updateEndpoints(moduleName: string) {
|
|
|
435
440
|
if (UpdateEntityEndpoints !== undefined) {
|
|
436
441
|
UpdateEntityEndpoints(moduleName);
|
|
437
442
|
}
|
|
443
|
+
if (UpdateRelationshipEndpoints !== undefined) {
|
|
444
|
+
UpdateRelationshipEndpoints(moduleName);
|
|
445
|
+
}
|
|
438
446
|
}
|
|
439
447
|
|
|
440
448
|
export let InternDynamicModule: Function | undefined;
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
SetAttribute,
|
|
29
29
|
Statement,
|
|
30
30
|
ThrowError,
|
|
31
|
+
WhereSpec,
|
|
31
32
|
} from '../language/generated/ast.js';
|
|
32
33
|
import {
|
|
33
34
|
maybeInstanceAsString,
|
|
@@ -52,7 +53,7 @@ import {
|
|
|
52
53
|
Workflow,
|
|
53
54
|
setMetaAttributes,
|
|
54
55
|
} from './module.js';
|
|
55
|
-
import { JoinInfo, Resolver } from './resolvers/interface.js';
|
|
56
|
+
import { JoinInfo, Resolver, WhereClause } from './resolvers/interface.js';
|
|
56
57
|
import { ResolverAuthInfo } from './resolvers/authinfo.js';
|
|
57
58
|
import { SqlDbResolver } from './resolvers/sqldb/impl.js';
|
|
58
59
|
import {
|
|
@@ -97,8 +98,7 @@ import {
|
|
|
97
98
|
addUpdateAudit,
|
|
98
99
|
createSuspension,
|
|
99
100
|
flushMonitoringData,
|
|
100
|
-
|
|
101
|
-
setTimerRunning,
|
|
101
|
+
triggerTimer,
|
|
102
102
|
} from './modules/core.js';
|
|
103
103
|
import { invokeModuleFn } from './jsmodules.js';
|
|
104
104
|
import { invokeOpenApiEvent, isOpenApiEventInstance } from './openapi.js';
|
|
@@ -106,6 +106,7 @@ import { fetchDoc } from './docs.js';
|
|
|
106
106
|
import { FlowSpec, FlowStep, getAgentFlow } from './agents/flows.js';
|
|
107
107
|
import { isMonitoringEnabled } from './state.js';
|
|
108
108
|
import { Monitor, MonitorEntry } from './monitor.js';
|
|
109
|
+
import { detailedDiff } from 'deep-object-diff';
|
|
109
110
|
|
|
110
111
|
export type Result = any;
|
|
111
112
|
|
|
@@ -1341,6 +1342,11 @@ async function lookupOneOfVals(fqName: string, env: Environment): Promise<Instan
|
|
|
1341
1342
|
return await parseAndEvaluateStatement(`{${fqName}? {}}`, undefined, env);
|
|
1342
1343
|
}
|
|
1343
1344
|
|
|
1345
|
+
export type AggregateFunctionCall = {
|
|
1346
|
+
name: string;
|
|
1347
|
+
args: string[];
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1344
1350
|
async function patternToInstance(
|
|
1345
1351
|
entryName: string,
|
|
1346
1352
|
attributes: SetAttribute[] | undefined,
|
|
@@ -1349,6 +1355,7 @@ async function patternToInstance(
|
|
|
1349
1355
|
const attrs: InstanceAttributes = newInstanceAttributes();
|
|
1350
1356
|
let qattrs: InstanceAttributes | undefined;
|
|
1351
1357
|
let qattrVals: InstanceAttributes | undefined;
|
|
1358
|
+
let aggregates: Map<string, AggregateFunctionCall> | undefined;
|
|
1352
1359
|
const isQueryAll: boolean = entryName.endsWith(QuerySuffix);
|
|
1353
1360
|
if (isQueryAll) {
|
|
1354
1361
|
entryName = entryName.slice(0, entryName.length - 1);
|
|
@@ -1356,20 +1363,25 @@ async function patternToInstance(
|
|
|
1356
1363
|
if (attributes) {
|
|
1357
1364
|
for (let i = 0; i < attributes.length; ++i) {
|
|
1358
1365
|
const a: SetAttribute = attributes[i];
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
if (
|
|
1364
|
-
|
|
1366
|
+
if (a.value !== undefined) {
|
|
1367
|
+
await evaluateExpression(a.value, env);
|
|
1368
|
+
const v: Result = env.getLastResult();
|
|
1369
|
+
let aname: string = a.name;
|
|
1370
|
+
if (aname.endsWith(QuerySuffix)) {
|
|
1371
|
+
if (isQueryAll) {
|
|
1372
|
+
throw new Error(`Cannot specifiy query attribute ${aname} here`);
|
|
1373
|
+
}
|
|
1374
|
+
if (qattrs === undefined) qattrs = newInstanceAttributes();
|
|
1375
|
+
if (qattrVals === undefined) qattrVals = newInstanceAttributes();
|
|
1376
|
+
aname = aname.slice(0, aname.length - 1);
|
|
1377
|
+
qattrs.set(aname, a.op === undefined ? '=' : a.op);
|
|
1378
|
+
qattrVals.set(aname, v);
|
|
1379
|
+
} else {
|
|
1380
|
+
attrs.set(aname, v);
|
|
1365
1381
|
}
|
|
1366
|
-
|
|
1367
|
-
if (
|
|
1368
|
-
|
|
1369
|
-
qattrs.set(aname, a.op === undefined ? '=' : a.op);
|
|
1370
|
-
qattrVals.set(aname, v);
|
|
1371
|
-
} else {
|
|
1372
|
-
attrs.set(aname, v);
|
|
1382
|
+
} else if (a.aggregate !== undefined) {
|
|
1383
|
+
if (aggregates === undefined) aggregates = new Map<string, AggregateFunctionCall>();
|
|
1384
|
+
aggregates.set(escapeQueryName(a.name), { name: a.aggregate.name, args: a.aggregate.args });
|
|
1373
1385
|
}
|
|
1374
1386
|
}
|
|
1375
1387
|
}
|
|
@@ -1379,7 +1391,11 @@ async function patternToInstance(
|
|
|
1379
1391
|
if (p.hasModule()) moduleName = p.getModuleName();
|
|
1380
1392
|
if (p.hasEntry()) entryName = p.getEntryName();
|
|
1381
1393
|
}
|
|
1382
|
-
|
|
1394
|
+
const inst = makeInstance(moduleName, entryName, attrs, qattrs, qattrVals, isQueryAll);
|
|
1395
|
+
if (aggregates !== undefined) {
|
|
1396
|
+
return inst.setAggregates(aggregates);
|
|
1397
|
+
}
|
|
1398
|
+
return inst;
|
|
1383
1399
|
}
|
|
1384
1400
|
|
|
1385
1401
|
async function instanceFromSource(crud: CrudMap, env: Environment): Promise<Instance> {
|
|
@@ -1431,6 +1447,15 @@ async function maybeValidateOneOfRefs(inst: Instance, env: Environment) {
|
|
|
1431
1447
|
}
|
|
1432
1448
|
}
|
|
1433
1449
|
|
|
1450
|
+
function maybeSetQueryClauses(inst: Instance, crud: CrudMap) {
|
|
1451
|
+
if (crud.groupByClause) {
|
|
1452
|
+
inst.setGroupBy(crud.groupByClause.colNames);
|
|
1453
|
+
}
|
|
1454
|
+
if (crud.orderByClause) {
|
|
1455
|
+
inst.setOrderBy(crud.orderByClause.colNames, crud.orderByClause.order === '@desc');
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1434
1459
|
async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
1435
1460
|
if (!env.isInUpsertMode() && crud.upsert.length > 0) {
|
|
1436
1461
|
return await evaluateUpsert(crud, env);
|
|
@@ -1442,8 +1467,10 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
1442
1467
|
const moduleName = inst.moduleName;
|
|
1443
1468
|
const attrs = inst.attributes;
|
|
1444
1469
|
const qattrs = inst.queryAttributes;
|
|
1445
|
-
const
|
|
1470
|
+
const onlyAggregates = inst.aggregates !== undefined && qattrs === undefined;
|
|
1471
|
+
const isQueryAll = onlyAggregates || crud.name.endsWith(QuerySuffix);
|
|
1446
1472
|
const distinct: boolean = crud.distinct.length > 0;
|
|
1473
|
+
maybeSetQueryClauses(inst, crud);
|
|
1447
1474
|
if (attrs.size > 0) {
|
|
1448
1475
|
await maybeValidateOneOfRefs(inst, env);
|
|
1449
1476
|
}
|
|
@@ -1456,8 +1483,8 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
1456
1483
|
if (qattrs === undefined && !isQueryAll) {
|
|
1457
1484
|
throw new Error(`Pattern for ${entryName} with 'into' clause must be a query`);
|
|
1458
1485
|
}
|
|
1459
|
-
if (crud.
|
|
1460
|
-
await evaluateJoinQuery(crud.
|
|
1486
|
+
if (crud.joins.length > 0) {
|
|
1487
|
+
await evaluateJoinQuery(crud.joins, crud.into, crud.where, inst, distinct, env);
|
|
1461
1488
|
} else {
|
|
1462
1489
|
await evaluateJoinQueryWithRelationships(crud.into, inst, crud.relationships, distinct, env);
|
|
1463
1490
|
}
|
|
@@ -1671,51 +1698,6 @@ async function handleDocEvent(inst: Instance, env: Environment): Promise<void> {
|
|
|
1671
1698
|
}
|
|
1672
1699
|
}
|
|
1673
1700
|
|
|
1674
|
-
function triggerTimer(timerInst: Instance): Instance {
|
|
1675
|
-
const dur = timerInst.lookup('duration');
|
|
1676
|
-
const unit = timerInst.lookup('unit');
|
|
1677
|
-
let millisecs = 0;
|
|
1678
|
-
switch (unit) {
|
|
1679
|
-
case 'millisecond': {
|
|
1680
|
-
millisecs = dur;
|
|
1681
|
-
break;
|
|
1682
|
-
}
|
|
1683
|
-
case 'second': {
|
|
1684
|
-
millisecs = dur * 1000;
|
|
1685
|
-
break;
|
|
1686
|
-
}
|
|
1687
|
-
case 'minute': {
|
|
1688
|
-
millisecs = dur * 60 * 1000;
|
|
1689
|
-
break;
|
|
1690
|
-
}
|
|
1691
|
-
case 'hour': {
|
|
1692
|
-
millisecs = dur * 60 * 60 * 1000;
|
|
1693
|
-
break;
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
const eventName = nameToPath(timerInst.lookup('trigger'));
|
|
1697
|
-
const m = eventName.hasModule() ? eventName.getModuleName() : timerInst.moduleName;
|
|
1698
|
-
const n = eventName.getEntryName();
|
|
1699
|
-
const inst = makeInstance(m, n, newInstanceAttributes());
|
|
1700
|
-
const name = timerInst.lookup('name');
|
|
1701
|
-
const timer = setInterval(async () => {
|
|
1702
|
-
const env = new Environment();
|
|
1703
|
-
try {
|
|
1704
|
-
await evaluate(
|
|
1705
|
-
inst,
|
|
1706
|
-
(result: Result) => logger.debug(`Timer ${name} ran with result ${result}`),
|
|
1707
|
-
env
|
|
1708
|
-
);
|
|
1709
|
-
await env.commitAllTransactions();
|
|
1710
|
-
await maybeCancelTimer(name, timer, env);
|
|
1711
|
-
} catch (reason: any) {
|
|
1712
|
-
logger.error(`Timer ${name} raised error: ${reason}`);
|
|
1713
|
-
}
|
|
1714
|
-
}, millisecs);
|
|
1715
|
-
setTimerRunning(timerInst);
|
|
1716
|
-
return timerInst;
|
|
1717
|
-
}
|
|
1718
|
-
|
|
1719
1701
|
async function computeExprAttributes(
|
|
1720
1702
|
inst: Instance,
|
|
1721
1703
|
origAttrs: SetAttribute[] | undefined,
|
|
@@ -1749,7 +1731,7 @@ async function computeExprAttributes(
|
|
|
1749
1731
|
for (let i = 0; i < origAttrs.length; ++i) {
|
|
1750
1732
|
const a: SetAttribute = origAttrs[i];
|
|
1751
1733
|
const n = a.name;
|
|
1752
|
-
if (!n.endsWith(QuerySuffix) && updatedAttrs.has(n)) {
|
|
1734
|
+
if (!n.endsWith(QuerySuffix) && updatedAttrs.has(n) && a.value !== undefined) {
|
|
1753
1735
|
await evaluateExpression(a.value, newEnv);
|
|
1754
1736
|
const v: Result = newEnv.getLastResult();
|
|
1755
1737
|
updatedAttrs.set(n, v);
|
|
@@ -1760,19 +1742,51 @@ async function computeExprAttributes(
|
|
|
1760
1742
|
}
|
|
1761
1743
|
}
|
|
1762
1744
|
|
|
1745
|
+
async function evalWhereClauses(whereSpec: WhereSpec, env: Environment): Promise<WhereClause[]> {
|
|
1746
|
+
const result = new Array<WhereClause>();
|
|
1747
|
+
const e = new Environment(undefined, env);
|
|
1748
|
+
for (let i = 0; i < whereSpec.clauses.length; ++i) {
|
|
1749
|
+
const c = whereSpec.clauses[i];
|
|
1750
|
+
await evaluateExpression(c.rhs, e);
|
|
1751
|
+
result.push({
|
|
1752
|
+
attrName: escapeQueryName(c.lhs),
|
|
1753
|
+
op: c.op === undefined ? '=' : c.op,
|
|
1754
|
+
qval: e.getLastResult(),
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
return result;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1763
1760
|
async function evaluateJoinQuery(
|
|
1764
|
-
joinSpec: JoinSpec,
|
|
1761
|
+
joinSpec: JoinSpec[],
|
|
1765
1762
|
intoSpec: SelectIntoSpec,
|
|
1763
|
+
whereSpec: WhereSpec | undefined,
|
|
1766
1764
|
inst: Instance,
|
|
1767
1765
|
distinct: boolean,
|
|
1768
1766
|
env: Environment
|
|
1769
1767
|
): Promise<void> {
|
|
1770
1768
|
const normIntoSpec = new Map<string, string>();
|
|
1769
|
+
let aggregates: Map<string, AggregateFunctionCall> | undefined;
|
|
1771
1770
|
intoSpec.entries.forEach((entry: SelectIntoEntry) => {
|
|
1772
|
-
normIntoSpec.set(entry.alias, entry.attribute);
|
|
1771
|
+
if (entry.attribute !== undefined) normIntoSpec.set(entry.alias, entry.attribute);
|
|
1772
|
+
else {
|
|
1773
|
+
if (aggregates === undefined) aggregates = new Map<string, AggregateFunctionCall>();
|
|
1774
|
+
if (entry.aggregate !== undefined) aggregates?.set(entry.alias, entry.aggregate);
|
|
1775
|
+
}
|
|
1773
1776
|
});
|
|
1777
|
+
if (aggregates !== undefined) {
|
|
1778
|
+
inst.setAggregates(aggregates);
|
|
1779
|
+
}
|
|
1780
|
+
const clauses = whereSpec ? await evalWhereClauses(whereSpec, env) : undefined;
|
|
1774
1781
|
const resolver = await getResolverForPath(inst.name, inst.moduleName, env);
|
|
1775
|
-
const result: Result = await resolver.queryByJoin(
|
|
1782
|
+
const result: Result = await resolver.queryByJoin(
|
|
1783
|
+
inst,
|
|
1784
|
+
[],
|
|
1785
|
+
normIntoSpec,
|
|
1786
|
+
distinct,
|
|
1787
|
+
joinSpec,
|
|
1788
|
+
clauses
|
|
1789
|
+
);
|
|
1776
1790
|
|
|
1777
1791
|
const transformedResult = transformDateFieldsInJoinResult(result);
|
|
1778
1792
|
|
|
@@ -1787,9 +1801,17 @@ async function evaluateJoinQueryWithRelationships(
|
|
|
1787
1801
|
env: Environment
|
|
1788
1802
|
): Promise<void> {
|
|
1789
1803
|
const normIntoSpec = new Map<string, string>();
|
|
1804
|
+
let aggregates: Map<string, AggregateFunctionCall> | undefined;
|
|
1790
1805
|
intoSpec.entries.forEach((entry: SelectIntoEntry) => {
|
|
1791
|
-
normIntoSpec.set(entry.alias, entry.attribute);
|
|
1806
|
+
if (entry.attribute !== undefined) normIntoSpec.set(entry.alias, entry.attribute);
|
|
1807
|
+
else {
|
|
1808
|
+
if (aggregates === undefined) aggregates = new Map<string, AggregateFunctionCall>();
|
|
1809
|
+
if (entry.aggregate !== undefined) aggregates?.set(entry.alias, entry.aggregate);
|
|
1810
|
+
}
|
|
1792
1811
|
});
|
|
1812
|
+
if (aggregates !== undefined) {
|
|
1813
|
+
inst.setAggregates(aggregates);
|
|
1814
|
+
}
|
|
1793
1815
|
const moduleName = inst.moduleName;
|
|
1794
1816
|
let joinsSpec = new Array<JoinInfo>();
|
|
1795
1817
|
for (let i = 0; i < relationships.length; ++i) {
|
|
@@ -2126,7 +2148,7 @@ async function preprocessStep(spec: string, env: Environment): Promise<string> {
|
|
|
2126
2148
|
const step = crudMap.name;
|
|
2127
2149
|
if (crudMap.body) {
|
|
2128
2150
|
crudMap.body.attributes.forEach((sa: SetAttribute) => {
|
|
2129
|
-
const v = sa.value
|
|
2151
|
+
const v = sa.value?.$cstNode?.text;
|
|
2130
2152
|
if (v) env.setTemplateMapping(sa.name, v);
|
|
2131
2153
|
});
|
|
2132
2154
|
}
|
|
@@ -2202,7 +2224,7 @@ export async function maybeDeleteQueriedInstances(
|
|
|
2202
2224
|
const inst: Instance[] | Instance = queryEnv.getLastResult();
|
|
2203
2225
|
let resolver: Resolver = Resolver.Default;
|
|
2204
2226
|
if (inst instanceof Array) {
|
|
2205
|
-
if (inst.length > 0
|
|
2227
|
+
if (inst.length > 0) {
|
|
2206
2228
|
resolver = await getResolverForPath(inst[0].name, inst[0].moduleName, queryEnv);
|
|
2207
2229
|
const finalResult: Array<any> = new Array<any>();
|
|
2208
2230
|
for (let i = 0; i < inst.length; ++i) {
|
|
@@ -2215,7 +2237,7 @@ export async function maybeDeleteQueriedInstances(
|
|
|
2215
2237
|
} else {
|
|
2216
2238
|
queryEnv.setLastResult(inst);
|
|
2217
2239
|
}
|
|
2218
|
-
} else
|
|
2240
|
+
} else {
|
|
2219
2241
|
resolver = await getResolverForPath(inst.name, inst.moduleName, queryEnv);
|
|
2220
2242
|
await runPreDeleteEvents(inst, env);
|
|
2221
2243
|
const r: Instance | null = await resolver.deleteInstance(inst, purge);
|
|
@@ -2479,7 +2501,7 @@ async function runPreCreateEvents(inst: Instance, env: Environment) {
|
|
|
2479
2501
|
|
|
2480
2502
|
export async function runPostCreateEvents(inst: Instance, env: Environment) {
|
|
2481
2503
|
if (inst.requireAudit()) {
|
|
2482
|
-
await addCreateAudit(inst.getPath(), env);
|
|
2504
|
+
await addCreateAudit(inst.getPath(), env, { original: inst.userAttributesAsObject() });
|
|
2483
2505
|
}
|
|
2484
2506
|
await runPrePostEvents(CrudType.CREATE, false, inst, env);
|
|
2485
2507
|
}
|
|
@@ -2494,7 +2516,13 @@ export async function runPostUpdateEvents(
|
|
|
2494
2516
|
env: Environment
|
|
2495
2517
|
) {
|
|
2496
2518
|
if (inst.requireAudit()) {
|
|
2497
|
-
|
|
2519
|
+
let diff: object | undefined;
|
|
2520
|
+
if (oldInst !== undefined) {
|
|
2521
|
+
const oldAttrs = oldInst.userAttributesAsObject();
|
|
2522
|
+
const d = detailedDiff(oldAttrs, inst.userAttributesAsObject());
|
|
2523
|
+
diff = { original: oldAttrs, updated: d.updated };
|
|
2524
|
+
}
|
|
2525
|
+
await addUpdateAudit(inst.getPath(), diff, env);
|
|
2498
2526
|
}
|
|
2499
2527
|
await runPrePostEvents(CrudType.UPDATE, false, inst, env);
|
|
2500
2528
|
}
|
|
@@ -2505,7 +2533,7 @@ async function runPreDeleteEvents(inst: Instance, env: Environment) {
|
|
|
2505
2533
|
|
|
2506
2534
|
export async function runPostDeleteEvents(inst: Instance, env: Environment) {
|
|
2507
2535
|
if (inst.requireAudit()) {
|
|
2508
|
-
await addDeleteAudit(inst.getPath(), inst, env);
|
|
2536
|
+
await addDeleteAudit(inst.getPath(), { deleted: inst.userAttributesAsObject() }, env);
|
|
2509
2537
|
}
|
|
2510
2538
|
await runPrePostEvents(CrudType.DELETE, false, inst, env);
|
|
2511
2539
|
}
|