agentlang 0.0.26 → 0.0.29
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/language/generated/ast.d.ts +16 -18
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +17 -20
- 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 +231 -181
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +239 -196
- package/out/language/main.cjs.map +2 -2
- package/out/runtime/interpreter.d.ts +3 -1
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +15 -7
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.js +1 -1
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/logger.js +1 -2
- package/out/runtime/logger.js.map +1 -1
- package/out/runtime/module.d.ts +8 -4
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +70 -13
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/core.js +2 -2
- package/out/runtime/modules/core.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts +1 -1
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +14 -8
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +1 -1
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +1 -1
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/package.json +1 -1
- package/src/language/agentlang.langium +5 -3
- package/src/language/generated/ast.ts +31 -37
- package/src/language/generated/grammar.ts +231 -181
- package/src/runtime/interpreter.ts +24 -7
- package/src/runtime/loader.ts +1 -1
- package/src/runtime/logger.ts +1 -3
- package/src/runtime/module.ts +89 -16
- package/src/runtime/modules/core.ts +2 -2
- package/src/runtime/resolvers/interface.ts +17 -11
- package/src/runtime/resolvers/sqldb/impl.ts +1 -1
- package/src/syntaxes/agentlang.monarch.ts +1 -1
|
@@ -1062,7 +1062,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
1062
1062
|
if (env.isInUpsertMode()) {
|
|
1063
1063
|
await runPreUpdateEvents(inst, env);
|
|
1064
1064
|
r = await res.upsertInstance(inst);
|
|
1065
|
-
await runPostUpdateEvents(inst, env);
|
|
1065
|
+
await runPostUpdateEvents(inst, undefined, env);
|
|
1066
1066
|
} else {
|
|
1067
1067
|
await runPreCreateEvents(inst, env);
|
|
1068
1068
|
if (isTimer(inst)) triggerTimer(inst);
|
|
@@ -1178,7 +1178,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
1178
1178
|
await computeExprAttributes(lastRes[i], env);
|
|
1179
1179
|
await runPreUpdateEvents(lastRes[i], env);
|
|
1180
1180
|
const finalInst: Instance = await resolver.updateInstance(lastRes[i], attrs);
|
|
1181
|
-
await runPostUpdateEvents(finalInst, env);
|
|
1181
|
+
await runPostUpdateEvents(finalInst, lastRes[i], env);
|
|
1182
1182
|
res.push(finalInst);
|
|
1183
1183
|
}
|
|
1184
1184
|
env.setLastResult(res);
|
|
@@ -1190,7 +1190,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
1190
1190
|
await computeExprAttributes(lastRes, env);
|
|
1191
1191
|
await runPreUpdateEvents(lastRes, env);
|
|
1192
1192
|
const finalInst: Instance = await res.updateInstance(lastRes, attrs);
|
|
1193
|
-
await runPostUpdateEvents(finalInst, env);
|
|
1193
|
+
await runPostUpdateEvents(finalInst, lastRes, env);
|
|
1194
1194
|
env.setLastResult(finalInst);
|
|
1195
1195
|
}
|
|
1196
1196
|
}
|
|
@@ -1699,6 +1699,16 @@ async function realizeMap(mapLiteral: MapLiteral, env: Environment): Promise<voi
|
|
|
1699
1699
|
env.setLastResult(Object.fromEntries(result.entries()));
|
|
1700
1700
|
}
|
|
1701
1701
|
|
|
1702
|
+
export async function callPostEventOnSubscription(
|
|
1703
|
+
crudType: CrudType,
|
|
1704
|
+
inst: Instance,
|
|
1705
|
+
env?: Environment
|
|
1706
|
+
): Promise<any> {
|
|
1707
|
+
const newEnv = env ? env : new Environment('onSubs.env');
|
|
1708
|
+
await runPrePostEvents(crudType, false, inst, newEnv);
|
|
1709
|
+
return newEnv.getLastResult();
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1702
1712
|
async function runPrePostEvents(
|
|
1703
1713
|
crudType: CrudType,
|
|
1704
1714
|
pre: boolean,
|
|
@@ -1730,8 +1740,11 @@ async function runPrePostEvents(
|
|
|
1730
1740
|
}
|
|
1731
1741
|
};
|
|
1732
1742
|
if (trigInfo.async) {
|
|
1733
|
-
|
|
1743
|
+
const newEnv = new Environment('async.prepost.env');
|
|
1744
|
+
newEnv.bind('this', inst);
|
|
1745
|
+
evaluate(eventInst, callback, newEnv).catch(catchHandler);
|
|
1734
1746
|
} else {
|
|
1747
|
+
env.bind('this', inst);
|
|
1735
1748
|
await evaluate(eventInst, callback, env).catch(catchHandler);
|
|
1736
1749
|
}
|
|
1737
1750
|
}
|
|
@@ -1752,9 +1765,13 @@ async function runPreUpdateEvents(inst: Instance, env: Environment) {
|
|
|
1752
1765
|
await runPrePostEvents(CrudType.UPDATE, true, inst, env);
|
|
1753
1766
|
}
|
|
1754
1767
|
|
|
1755
|
-
export async function runPostUpdateEvents(
|
|
1768
|
+
export async function runPostUpdateEvents(
|
|
1769
|
+
inst: Instance,
|
|
1770
|
+
oldInst: Instance | undefined,
|
|
1771
|
+
env: Environment
|
|
1772
|
+
) {
|
|
1756
1773
|
if (inst.requireAudit()) {
|
|
1757
|
-
await addUpdateAudit(inst.getPath(),
|
|
1774
|
+
await addUpdateAudit(inst.getPath(), oldInst, env);
|
|
1758
1775
|
}
|
|
1759
1776
|
await runPrePostEvents(CrudType.UPDATE, false, inst, env);
|
|
1760
1777
|
}
|
|
@@ -1765,7 +1782,7 @@ async function runPreDeleteEvents(inst: Instance, env: Environment) {
|
|
|
1765
1782
|
|
|
1766
1783
|
export async function runPostDeleteEvents(inst: Instance, env: Environment) {
|
|
1767
1784
|
if (inst.requireAudit()) {
|
|
1768
|
-
await addDeleteAudit(inst.getPath(),
|
|
1785
|
+
await addDeleteAudit(inst.getPath(), inst, env);
|
|
1769
1786
|
}
|
|
1770
1787
|
await runPrePostEvents(CrudType.DELETE, false, inst, env);
|
|
1771
1788
|
}
|
package/src/runtime/loader.ts
CHANGED
|
@@ -413,7 +413,7 @@ export function addRelationshipFromDef(
|
|
|
413
413
|
}
|
|
414
414
|
|
|
415
415
|
export function addWorkflowFromDef(def: WorkflowDefinition, moduleName: string): Workflow {
|
|
416
|
-
return addWorkflow(def.name, moduleName, def.statements, def.
|
|
416
|
+
return addWorkflow(def.name || '', moduleName, def.statements, def.header);
|
|
417
417
|
}
|
|
418
418
|
|
|
419
419
|
const StandaloneStatements = new Map<string, Statement[]>();
|
package/src/runtime/logger.ts
CHANGED
|
@@ -25,8 +25,6 @@ if (isNodeEnv) {
|
|
|
25
25
|
maxFiles: '7d',
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
const consoleTransport = new winston.transports.Console();
|
|
29
|
-
|
|
30
28
|
logger = winston.createLogger({
|
|
31
29
|
format: winston.format.combine(
|
|
32
30
|
winston.format.timestamp(),
|
|
@@ -34,7 +32,7 @@ if (isNodeEnv) {
|
|
|
34
32
|
return `[${timestamp}] ${level}: ${message}`;
|
|
35
33
|
})
|
|
36
34
|
),
|
|
37
|
-
transports: [fileTransport
|
|
35
|
+
transports: [fileTransport],
|
|
38
36
|
});
|
|
39
37
|
} else {
|
|
40
38
|
function mkLogger(tag: string): Function {
|
package/src/runtime/module.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
RbacSpecEntry,
|
|
20
20
|
RbacSpecEntries,
|
|
21
21
|
RbacOpr,
|
|
22
|
-
|
|
22
|
+
WorkflowHeader,
|
|
23
23
|
} from '../language/generated/ast.js';
|
|
24
24
|
import {
|
|
25
25
|
Path,
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
} from './util.js';
|
|
46
46
|
import { parseStatement } from '../language/parser.js';
|
|
47
47
|
import { ActiveSessionInfo, AdminSession } from './auth/defs.js';
|
|
48
|
-
import { FetchModuleFn, PathAttributeName
|
|
48
|
+
import { FetchModuleFn, PathAttributeName } from './defs.js';
|
|
49
49
|
import { logger } from './logger.js';
|
|
50
50
|
|
|
51
51
|
export class ModuleEntry {
|
|
@@ -200,7 +200,7 @@ export type TriggerInfo = {
|
|
|
200
200
|
async: boolean;
|
|
201
201
|
};
|
|
202
202
|
|
|
203
|
-
function asTriggerInfo(te:
|
|
203
|
+
function asTriggerInfo(te: any): TriggerInfo {
|
|
204
204
|
return {
|
|
205
205
|
eventName: te.event,
|
|
206
206
|
async: te.async ? true : false,
|
|
@@ -338,6 +338,22 @@ export class Record extends ModuleEntry {
|
|
|
338
338
|
return this;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
public addAfterTrigger(te: any): Record {
|
|
342
|
+
if (this.afterTriggers == undefined) {
|
|
343
|
+
this.afterTriggers = new Map();
|
|
344
|
+
}
|
|
345
|
+
this.afterTriggers?.set(asCrudType(te.on), asTriggerInfo(te));
|
|
346
|
+
return this;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
public addBeforeTrigger(te: any): Record {
|
|
350
|
+
if (this.beforeTriggers == undefined) {
|
|
351
|
+
this.beforeTriggers = new Map();
|
|
352
|
+
}
|
|
353
|
+
this.beforeTriggers?.set(asCrudType(te.on), asTriggerInfo(te));
|
|
354
|
+
return this;
|
|
355
|
+
}
|
|
356
|
+
|
|
341
357
|
getCompositeUniqueAttributes(): Array<string> | undefined {
|
|
342
358
|
return this.compositeUqAttributes;
|
|
343
359
|
}
|
|
@@ -1141,10 +1157,17 @@ export class Relationship extends Record {
|
|
|
1141
1157
|
|
|
1142
1158
|
export class Workflow extends ModuleEntry {
|
|
1143
1159
|
statements: Statement[];
|
|
1160
|
+
generatedName: boolean;
|
|
1144
1161
|
|
|
1145
|
-
constructor(
|
|
1162
|
+
constructor(
|
|
1163
|
+
name: string,
|
|
1164
|
+
patterns: Statement[],
|
|
1165
|
+
moduleName: string,
|
|
1166
|
+
generatedName: boolean = false
|
|
1167
|
+
) {
|
|
1146
1168
|
super(name, moduleName);
|
|
1147
1169
|
this.statements = patterns;
|
|
1170
|
+
this.generatedName = generatedName;
|
|
1148
1171
|
}
|
|
1149
1172
|
|
|
1150
1173
|
async addStatement(stmtCode: string): Promise<Workflow> {
|
|
@@ -1262,7 +1285,8 @@ export class Workflow extends ModuleEntry {
|
|
|
1262
1285
|
}
|
|
1263
1286
|
|
|
1264
1287
|
override toString() {
|
|
1265
|
-
|
|
1288
|
+
const n = this.generatedName ? untangleWorkflowName(this.name) : this.name;
|
|
1289
|
+
let s: string = `workflow ${normalizeWorkflowName(n)} {\n`;
|
|
1266
1290
|
const ss = this.statementsToStringsHelper(this.statements);
|
|
1267
1291
|
s = s.concat(joinStatements(ss));
|
|
1268
1292
|
return s.concat('\n}');
|
|
@@ -1871,8 +1895,11 @@ export function addWorkflow(
|
|
|
1871
1895
|
name: string,
|
|
1872
1896
|
moduleName = activeModule,
|
|
1873
1897
|
statements?: Statement[],
|
|
1874
|
-
|
|
1898
|
+
hdr?: WorkflowHeader
|
|
1875
1899
|
): Workflow {
|
|
1900
|
+
if (hdr) {
|
|
1901
|
+
name = prePostWorkflowName(hdr.tag, hdr.prefix, hdr.name, moduleName);
|
|
1902
|
+
}
|
|
1876
1903
|
const module: Module = fetchModule(moduleName);
|
|
1877
1904
|
if (module.hasEntry(name)) {
|
|
1878
1905
|
const entry: ModuleEntry = module.getEntry(name);
|
|
@@ -1884,14 +1911,51 @@ export function addWorkflow(
|
|
|
1884
1911
|
event.addMeta(SystemDefinedEvent, 'true');
|
|
1885
1912
|
}
|
|
1886
1913
|
if (!statements) statements = new Array<Statement>();
|
|
1887
|
-
if (
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1914
|
+
if (hdr) {
|
|
1915
|
+
const eventFqName = makeFqName(moduleName, name);
|
|
1916
|
+
const entityDef = getEntityDef(hdr.name, moduleName);
|
|
1917
|
+
if (hdr.tag == '@after') {
|
|
1918
|
+
entityDef?.addAfterTrigger({
|
|
1919
|
+
on: hdr.prefix,
|
|
1920
|
+
event: eventFqName,
|
|
1921
|
+
async: false,
|
|
1922
|
+
});
|
|
1923
|
+
} else {
|
|
1924
|
+
entityDef?.addBeforeTrigger({
|
|
1925
|
+
on: hdr.prefix,
|
|
1926
|
+
event: eventFqName,
|
|
1927
|
+
async: false,
|
|
1928
|
+
});
|
|
1929
|
+
}
|
|
1893
1930
|
}
|
|
1894
|
-
return module.addEntry(
|
|
1931
|
+
return module.addEntry(
|
|
1932
|
+
new Workflow(asWorkflowName(name), statements, moduleName, hdr ? true : false)
|
|
1933
|
+
) as Workflow;
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
function prePostWorkflowName(
|
|
1937
|
+
tag: '@after' | '@before',
|
|
1938
|
+
opr: 'create' | 'update' | 'delete',
|
|
1939
|
+
entityName: string,
|
|
1940
|
+
moduleName?: string
|
|
1941
|
+
): string {
|
|
1942
|
+
const parts = splitFqName(entityName);
|
|
1943
|
+
const mname = parts.hasModule() ? parts.getModuleName() : moduleName;
|
|
1944
|
+
if (!mname) {
|
|
1945
|
+
throw new Error(`Cannot infer module name for ${entityName}`);
|
|
1946
|
+
}
|
|
1947
|
+
return `${tag.substring(1)}_${opr}_${mname}_${parts.getEntryName()}`;
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
function untangleWorkflowName(name: string): string {
|
|
1951
|
+
const parts = name.split('_');
|
|
1952
|
+
return `@${parts[0]} ${parts[1]}:${parts[2]}/${parts[3]}`;
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
function getEntityDef(entityName: string, moduleName: string): Entity | undefined {
|
|
1956
|
+
const parts = splitFqName(entityName);
|
|
1957
|
+
const mname = parts.hasModule() ? parts.getModuleName() : moduleName;
|
|
1958
|
+
return getEntity(parts.getEntryName(), mname);
|
|
1895
1959
|
}
|
|
1896
1960
|
|
|
1897
1961
|
export function getWorkflow(eventInstance: Instance): Workflow {
|
|
@@ -1905,12 +1969,13 @@ export function getWorkflow(eventInstance: Instance): Workflow {
|
|
|
1905
1969
|
return EmptyWorkflow;
|
|
1906
1970
|
}
|
|
1907
1971
|
|
|
1908
|
-
export function getEntity(name: string, moduleName: string): Entity {
|
|
1972
|
+
export function getEntity(name: string, moduleName: string): Entity | undefined {
|
|
1909
1973
|
const fr: FetchModuleByEntryNameResult = fetchModuleByEntryName(name, moduleName);
|
|
1910
1974
|
if (fr.module.isEntity(fr.entryName)) {
|
|
1911
1975
|
return fr.module.getEntry(fr.entryName) as Entity;
|
|
1912
1976
|
}
|
|
1913
|
-
|
|
1977
|
+
logger.error(`Entity ${fr.entryName} not found in module ${fr.moduleName}`);
|
|
1978
|
+
return undefined;
|
|
1914
1979
|
}
|
|
1915
1980
|
|
|
1916
1981
|
function isEntryOfType(t: RecordType, fqName: string): boolean {
|
|
@@ -2225,6 +2290,14 @@ export class Instance {
|
|
|
2225
2290
|
);
|
|
2226
2291
|
}
|
|
2227
2292
|
|
|
2293
|
+
static clone(inst: Instance): Instance {
|
|
2294
|
+
const attrs = newInstanceAttributes();
|
|
2295
|
+
inst.attributes.forEach((v: any, k: string) => {
|
|
2296
|
+
attrs.set(k, v);
|
|
2297
|
+
});
|
|
2298
|
+
return Instance.newWithAttributes(inst, attrs);
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2228
2301
|
normalizeAttributes(attrs: InstanceAttributes): InstanceAttributes {
|
|
2229
2302
|
attrs.forEach((v: any, k: string) => {
|
|
2230
2303
|
const attrSpec = this.record.schema.get(k);
|
|
@@ -2730,7 +2803,7 @@ export function getEntityRbacRules(entityFqName: string): RbacSpecification[] |
|
|
|
2730
2803
|
const m = isModule(mn) && fetchModule(mn);
|
|
2731
2804
|
if (m && m.isEntity(en)) {
|
|
2732
2805
|
const entity = getEntity(en, mn);
|
|
2733
|
-
return entity
|
|
2806
|
+
return entity?.getRbacSpecifications()?.filter((spec: RbacSpecification) => {
|
|
2734
2807
|
return spec.expression != undefined;
|
|
2735
2808
|
});
|
|
2736
2809
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { default as ai } from './ai.js';
|
|
2
2
|
import { default as auth } from './auth.js';
|
|
3
|
-
import { DefaultModuleName, DefaultModules } from '../util.js';
|
|
3
|
+
import { DefaultModuleName, DefaultModules, escapeSpecialChars } from '../util.js';
|
|
4
4
|
import { Instance, isInstanceOfType, makeInstance, newInstanceAttributes } from '../module.js';
|
|
5
5
|
import {
|
|
6
6
|
Environment,
|
|
@@ -103,7 +103,7 @@ async function addAudit(
|
|
|
103
103
|
`{agentlang/auditlog {
|
|
104
104
|
action "${action}",
|
|
105
105
|
resource "${resource}",
|
|
106
|
-
previous_value "${previuos_value ? JSON.stringify(previuos_value.asObject()) : ''}",
|
|
106
|
+
previous_value "${previuos_value ? escapeSpecialChars(JSON.stringify(previuos_value.asObject())) : ''}",
|
|
107
107
|
user "${user}",
|
|
108
108
|
token "${token ? token : ''}"
|
|
109
109
|
}}`,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
callPostEventOnSubscription,
|
|
2
3
|
Environment,
|
|
3
4
|
evaluate,
|
|
4
5
|
runPostCreateEvents,
|
|
@@ -206,7 +207,7 @@ export class Resolver {
|
|
|
206
207
|
case CrudType.CREATE:
|
|
207
208
|
return await runPostCreateEvents(inst, env);
|
|
208
209
|
case CrudType.UPDATE:
|
|
209
|
-
return await runPostUpdateEvents(inst, env);
|
|
210
|
+
return await runPostUpdateEvents(inst, undefined, env);
|
|
210
211
|
case CrudType.DELETE:
|
|
211
212
|
return await runPostDeleteEvents(inst, env);
|
|
212
213
|
default:
|
|
@@ -226,18 +227,23 @@ export class Resolver {
|
|
|
226
227
|
return this.onOutOfBandCrud(inst, CrudType.DELETE, env);
|
|
227
228
|
}
|
|
228
229
|
|
|
229
|
-
public async onSubscription(result: any): Promise<any> {
|
|
230
|
+
public async onSubscription(result: any, callPostCrudEvent: boolean = false): Promise<any> {
|
|
230
231
|
if (result != undefined) {
|
|
231
232
|
try {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
233
|
+
if (callPostCrudEvent) {
|
|
234
|
+
const inst = result as Instance;
|
|
235
|
+
return await callPostEventOnSubscription(CrudType.CREATE, inst);
|
|
236
|
+
} else {
|
|
237
|
+
const eventName = getSubscriptionEvent(this.name);
|
|
238
|
+
if (eventName) {
|
|
239
|
+
const path = splitFqName(eventName);
|
|
240
|
+
const inst = makeInstance(
|
|
241
|
+
path.getModuleName(),
|
|
242
|
+
path.getEntryName(),
|
|
243
|
+
newInstanceAttributes().set('data', result)
|
|
244
|
+
);
|
|
245
|
+
return await evaluate(inst);
|
|
246
|
+
}
|
|
241
247
|
}
|
|
242
248
|
} catch (err: any) {
|
|
243
249
|
logger.error(`Resolver ${this.name} raised error in onSubscription handler: ${err}`);
|
|
@@ -146,7 +146,7 @@ export class SqlDbResolver extends Resolver {
|
|
|
146
146
|
updateObj,
|
|
147
147
|
this.getDbContext(inst.getFqName())
|
|
148
148
|
);
|
|
149
|
-
return inst.mergeAttributes(newAttrs);
|
|
149
|
+
return Instance.clone(inst).mergeAttributes(newAttrs);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
static EmptyResultSet: Array<Instance> = new Array<Instance>();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Monarch syntax highlighting for the agentlang language.
|
|
2
2
|
export default {
|
|
3
3
|
keywords: [
|
|
4
|
-
'@actions','@after','@as','@async','@before','@catch','@distinct','@enum','@expr','@from','@into','@meta','@oneof','@rbac','@ref','@
|
|
4
|
+
'@actions','@after','@as','@async','@before','@catch','@distinct','@enum','@expr','@from','@into','@meta','@oneof','@rbac','@ref','@then','@upsert','@with_unique','agent','allow','and','await','between','contains','create','delete','else','entity','error','event','extends','false','for','if','import','in','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','subscribe','true','update','upsert','where','workflow'
|
|
5
5
|
],
|
|
6
6
|
operators: [
|
|
7
7
|
'!=','*','+',',','-','.','/',':',';','<','<=','<>','=','>','>=','?','@'
|