agentlang 0.0.11 → 0.0.12

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.
Files changed (46) hide show
  1. package/out/extension/main.cjs +250 -250
  2. package/out/extension/main.cjs.map +2 -2
  3. package/out/language/generated/ast.d.ts +2 -1
  4. package/out/language/generated/ast.d.ts.map +1 -1
  5. package/out/language/generated/ast.js +1 -0
  6. package/out/language/generated/ast.js.map +1 -1
  7. package/out/language/generated/grammar.d.ts.map +1 -1
  8. package/out/language/generated/grammar.js +20 -1
  9. package/out/language/generated/grammar.js.map +1 -1
  10. package/out/language/main.cjs +805 -505
  11. package/out/language/main.cjs.map +4 -4
  12. package/out/language/syntax.js +1 -1
  13. package/out/language/syntax.js.map +1 -1
  14. package/out/runtime/interpreter.d.ts +1 -0
  15. package/out/runtime/interpreter.d.ts.map +1 -1
  16. package/out/runtime/interpreter.js +13 -7
  17. package/out/runtime/interpreter.js.map +1 -1
  18. package/out/runtime/resolvers/interface.d.ts +2 -2
  19. package/out/runtime/resolvers/interface.d.ts.map +1 -1
  20. package/out/runtime/resolvers/interface.js +4 -4
  21. package/out/runtime/resolvers/interface.js.map +1 -1
  22. package/out/runtime/resolvers/sqldb/database.d.ts +3 -3
  23. package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
  24. package/out/runtime/resolvers/sqldb/database.js +19 -10
  25. package/out/runtime/resolvers/sqldb/database.js.map +1 -1
  26. package/out/runtime/resolvers/sqldb/dbutil.d.ts +1 -1
  27. package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
  28. package/out/runtime/resolvers/sqldb/dbutil.js +12 -4
  29. package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
  30. package/out/runtime/resolvers/sqldb/impl.d.ts +2 -2
  31. package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
  32. package/out/runtime/resolvers/sqldb/impl.js +17 -17
  33. package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
  34. package/out/syntaxes/agentlang.monarch.js +1 -1
  35. package/out/syntaxes/agentlang.monarch.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/language/agentlang.langium +2 -1
  38. package/src/language/generated/ast.ts +4 -1
  39. package/src/language/generated/grammar.ts +20 -1
  40. package/src/language/syntax.ts +1 -1
  41. package/src/runtime/interpreter.ts +14 -6
  42. package/src/runtime/resolvers/interface.ts +9 -4
  43. package/src/runtime/resolvers/sqldb/database.ts +21 -8
  44. package/src/runtime/resolvers/sqldb/dbutil.ts +11 -4
  45. package/src/runtime/resolvers/sqldb/impl.ts +19 -16
  46. package/src/syntaxes/agentlang.monarch.ts +1 -1
@@ -3244,6 +3244,25 @@ export const AgentlangGrammar = (): Grammar => loadedAgentlangGrammar ?? (loaded
3244
3244
  ],
3245
3245
  "cardinality": "?"
3246
3246
  },
3247
+ {
3248
+ "$type": "Group",
3249
+ "elements": [
3250
+ {
3251
+ "$type": "Keyword",
3252
+ "value": ","
3253
+ },
3254
+ {
3255
+ "$type": "Assignment",
3256
+ "feature": "distinct",
3257
+ "operator": "+=",
3258
+ "terminal": {
3259
+ "$type": "Keyword",
3260
+ "value": "@distinct"
3261
+ }
3262
+ }
3263
+ ],
3264
+ "cardinality": "?"
3265
+ },
3247
3266
  {
3248
3267
  "$type": "Keyword",
3249
3268
  "value": "}"
@@ -3341,7 +3360,7 @@ export const AgentlangGrammar = (): Grammar => loadedAgentlangGrammar ?? (loaded
3341
3360
  "elements": [
3342
3361
  {
3343
3362
  "$type": "Keyword",
3344
- "value": "into"
3363
+ "value": "@into"
3345
3364
  },
3346
3365
  {
3347
3366
  "$type": "Keyword",
@@ -473,7 +473,7 @@ export class CrudPattern extends BasePattern {
473
473
  this.into.forEach((attr: string, alias: string) => {
474
474
  ss.push(`${alias} ${attr}`);
475
475
  });
476
- return `into { ${ss.join(',\n')} }`;
476
+ return `@into { ${ss.join(',\n')} }`;
477
477
  }
478
478
  return undefined;
479
479
  }
@@ -408,15 +408,21 @@ export class Environment extends Instance {
408
408
  return this.activeTransactions;
409
409
  }
410
410
 
411
+ async resetActiveTransactions(commit: boolean): Promise<Environment> {
412
+ await this.endAllTransactions(commit);
413
+ this.activeTransactions = new Map<string, string>();
414
+ return this;
415
+ }
416
+
411
417
  async getTransactionForResolver(resolver: Resolver): Promise<string> {
412
418
  const n: string = resolver.getName();
413
- let txnId: string | undefined = this.getActiveTransactions().get(n);
419
+ let txnId: string | undefined = this.activeTransactions.get(n);
414
420
  if (txnId) {
415
421
  return txnId;
416
422
  } else {
417
423
  txnId = await resolver.startTransaction();
418
424
  if (txnId) {
419
- this.getActiveTransactions().set(n, txnId);
425
+ this.activeTransactions.set(n, txnId);
420
426
  return txnId;
421
427
  } else {
422
428
  throw new Error(`Failed to start transaction for ${n}`);
@@ -430,7 +436,7 @@ export class Environment extends Instance {
430
436
  }
431
437
 
432
438
  private async endAllTransactions(commit: boolean): Promise<void> {
433
- const txns: Map<string, string> = this.getActiveTransactions();
439
+ const txns: Map<string, string> = this.activeTransactions;
434
440
  for (const n of txns.keys()) {
435
441
  const txnId: string | undefined = txns.get(n);
436
442
  if (txnId) {
@@ -952,6 +958,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
952
958
  const attrs = inst.attributes;
953
959
  const qattrs = inst.queryAttributes;
954
960
  const isQueryAll = crud.name.endsWith(QuerySuffix);
961
+ const distinct: boolean = crud.distinct.length > 0;
955
962
  if (attrs.size > 0) {
956
963
  await maybeValidateOneOfRefs(inst, env);
957
964
  }
@@ -964,7 +971,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
964
971
  if (qattrs == undefined && !isQueryAll) {
965
972
  throw new Error(`Pattern for ${entryName} with 'into' clause must be a query`);
966
973
  }
967
- await evaluateJoinQuery(crud.into, inst, crud.relationships, env);
974
+ await evaluateJoinQuery(crud.into, inst, crud.relationships, distinct, env);
968
975
  return;
969
976
  }
970
977
  if (isEntityInstance(inst) || isBetweenRelationship(inst.name, inst.moduleName)) {
@@ -1051,7 +1058,7 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
1051
1058
  isReadForUpdate,
1052
1059
  env.isInDeleteMode()
1053
1060
  );
1054
- const insts: Instance[] = await res.queryInstances(inst, isQueryAll);
1061
+ const insts: Instance[] = await res.queryInstances(inst, isQueryAll, distinct);
1055
1062
  env.setLastResult(insts);
1056
1063
  }
1057
1064
  if (crud.relationships != undefined) {
@@ -1184,6 +1191,7 @@ async function evaluateJoinQuery(
1184
1191
  intoSpec: SelectIntoSpec,
1185
1192
  inst: Instance,
1186
1193
  relationships: RelationshipPattern[],
1194
+ distinct: boolean,
1187
1195
  env: Environment
1188
1196
  ): Promise<void> {
1189
1197
  const normIntoSpec = new Map<string, string>();
@@ -1196,7 +1204,7 @@ async function evaluateJoinQuery(
1196
1204
  joinsSpec = await walkJoinQueryPattern(relationships[i], joinsSpec, env);
1197
1205
  }
1198
1206
  const resolver = await getResolverForPath(inst.name, moduleName, env);
1199
- const result: Result = await resolver.queryByJoin(inst, joinsSpec, normIntoSpec);
1207
+ const result: Result = await resolver.queryByJoin(inst, joinsSpec, normIntoSpec, distinct);
1200
1208
  env.setLastResult(result);
1201
1209
  }
1202
1210
 
@@ -100,8 +100,12 @@ export class Resolver {
100
100
  * @param {Instance} inst - an Instance with query attributes
101
101
  * @param {boolean} queryAll - if this flag is set, fetch all instances
102
102
  */
103
- public async queryInstances(inst: Instance, queryAll: boolean): Promise<any> {
104
- return this.notImpl(`queryInstances(${inst}, ${queryAll})`);
103
+ public async queryInstances(
104
+ inst: Instance,
105
+ queryAll: boolean,
106
+ distinct: boolean = false
107
+ ): Promise<any> {
108
+ return this.notImpl(`queryInstances(${inst}, ${queryAll}, ${distinct})`);
105
109
  }
106
110
 
107
111
  /**
@@ -130,9 +134,10 @@ export class Resolver {
130
134
  public async queryByJoin(
131
135
  inst: Instance,
132
136
  joinsSpec: JoinInfo[],
133
- intoSpec: Map<string, string>
137
+ intoSpec: Map<string, string>,
138
+ distinct: boolean = false
134
139
  ): Promise<any> {
135
- return this.notImpl(`queryByJoin(${inst}, ${joinsSpec}, ${intoSpec})`);
140
+ return this.notImpl(`queryByJoin(${inst}, ${joinsSpec}, ${intoSpec}, ${distinct})`);
136
141
  }
137
142
 
138
143
  /**
@@ -185,7 +185,11 @@ function makeSqliteDataSource(
185
185
  });
186
186
  }
187
187
 
188
- export const DbType = 'sqlite';
188
+ const DbType = 'sqlite';
189
+
190
+ function getDbType(config?: DatabaseConfig): string {
191
+ return process.env.AL_DB_TYPE || config?.type || DbType;
192
+ }
189
193
 
190
194
  function getDsFunction(
191
195
  config: DatabaseConfig | undefined
@@ -194,7 +198,7 @@ function getDsFunction(
194
198
  config: DatabaseConfig | undefined,
195
199
  synchronize?: boolean | undefined
196
200
  ) => DataSource {
197
- switch (process.env.AL_DB_TYPE || config?.type || DbType) {
201
+ switch (getDbType(config)) {
198
202
  case 'sqlite':
199
203
  return makeSqliteDataSource;
200
204
  case 'postgres':
@@ -204,6 +208,10 @@ function getDsFunction(
204
208
  }
205
209
  }
206
210
 
211
+ export function isUsingSqlite(): boolean {
212
+ return getDbType() == 'sqlite';
213
+ }
214
+
207
215
  export async function initDatabase(config: DatabaseConfig | undefined) {
208
216
  if (defaultDataSource == undefined) {
209
217
  const mkds = getDsFunction(config);
@@ -602,8 +610,8 @@ function mkBetweenClause(tableName: string | undefined, k: string, queryVals: an
602
610
  const v1 = isstr ? `'${ov[0]}'` : ov[0];
603
611
  const v2 = isstr ? `'${ov[1]}'` : ov[1];
604
612
  const s = tableName
605
- ? `${tableName}.${k} BETWEEN ${v1} AND ${v2}`
606
- : `${k} BETWEEN ${v1} AND ${v2}`;
613
+ ? `"${tableName}"."${k}" BETWEEN ${v1} AND ${v2}`
614
+ : `"${k}" BETWEEN ${v1} AND ${v2}`;
607
615
  delete queryVals[k];
608
616
  return s;
609
617
  } else {
@@ -619,8 +627,8 @@ function objectToWhereClause(queryObj: object, queryVals: any, tableName?: strin
619
627
  op == 'between'
620
628
  ? mkBetweenClause(tableName, value[0], queryVals)
621
629
  : tableName
622
- ? `${tableName}.${value[0]} ${op} :${value[0]}`
623
- : `${value[0]} ${op} :${value[0]}`;
630
+ ? `"${tableName}"."${value[0]}" ${op} :${value[0]}`
631
+ : `"${value[0]}" ${op} :${value[0]}`;
624
632
  clauses.push(clause);
625
633
  });
626
634
  return clauses.join(' AND ');
@@ -637,7 +645,7 @@ function objectToRawWhereClause(queryObj: object, queryVals: any, tableName?: st
637
645
  } else {
638
646
  const ov: any = queryVals[k];
639
647
  const v = isString(ov) ? `'${ov}'` : ov;
640
- clause = tableName ? `${tableName}.${k} ${op} ${v}` : `${k} ${op} ${v}`;
648
+ clause = tableName ? `"${tableName}"."${k}" ${op} ${v}` : `"${k}" ${op} ${v}`;
641
649
  }
642
650
  clauses.push(clause);
643
651
  });
@@ -652,6 +660,7 @@ export async function getMany(
652
660
  tableName: string,
653
661
  queryObj: object | undefined,
654
662
  queryVals: object | undefined,
663
+ distinct: boolean,
655
664
  ctx: DbContext
656
665
  ): Promise<any> {
657
666
  const alias: string = tableName.toLowerCase();
@@ -697,6 +706,9 @@ export async function getMany(
697
706
  if (ownersJoinCond) {
698
707
  qb.innerJoin(ot, otAlias, ownersJoinCond.join(' AND '));
699
708
  }
709
+ if (distinct) {
710
+ qb.distinct(true);
711
+ }
700
712
  qb.where(queryStr, queryVals);
701
713
  return await qb.getMany();
702
714
  }
@@ -707,6 +719,7 @@ export async function getManyByJoin(
707
719
  queryVals: object | undefined,
708
720
  joinClauses: JoinClause[],
709
721
  intoSpec: Map<string, string>,
722
+ distinct: boolean,
710
723
  ctx: DbContext
711
724
  ): Promise<any> {
712
725
  const alias: string = tableName.toLowerCase();
@@ -746,7 +759,7 @@ export async function getManyByJoin(
746
759
  }
747
760
  }
748
761
  });
749
- const sql = `SELECT ${intoSpecToSql(intoSpec)} FROM ${tableName} ${joinSql.join('\n')} WHERE ${queryStr}`;
762
+ const sql = `SELECT ${distinct ? 'DISTINCT' : ''} ${intoSpecToSql(intoSpec)} FROM ${tableName} ${joinSql.join('\n')} WHERE ${queryStr}`;
750
763
  logger.debug(`Join Query: ${sql}`);
751
764
  const qb = getDatasourceForTransaction(ctx.txnId).getRepository(tableName).manager;
752
765
  return await qb.query(sql);
@@ -30,8 +30,15 @@ export type TableSchema = {
30
30
  columns: TableSpec;
31
31
  };
32
32
 
33
- export function asTableName(moduleName: string, entityName: string): string {
34
- return `${moduleName}_${entityName}`.toLowerCase();
33
+ export function asTableReference(moduleName: string, ref: string): string {
34
+ if (ref.indexOf('.') > 0) {
35
+ const parts = ref.split('.')
36
+ const r = `${moduleName}_${parts[0]}`.toLowerCase()
37
+ const colref = parts.slice(1).join('.')
38
+ return `"${r}"."${colref}"`;
39
+ } else {
40
+ return `${moduleName}_${ref}`.toLowerCase()
41
+ }
35
42
  }
36
43
 
37
44
  export function modulesAsDbSchema(): TableSchema[] {
@@ -46,7 +53,7 @@ export function modulesAsDbSchema(): TableSchema[] {
46
53
  const allEntries: Record[] = entities.concat(betRels) as Record[];
47
54
  allEntries.forEach((ent: Record) => {
48
55
  const tspec: TableSchema = {
49
- name: asTableName(n, ent.name),
56
+ name: asTableReference(n, ent.name),
50
57
  columns: entitySchemaToTable(ent.schema),
51
58
  };
52
59
  result.push(tspec);
@@ -85,7 +92,7 @@ function ormSchemaFromRecordSchema(moduleName: string, entry: Record, hasOwnPk?:
85
92
  const entityName = entry.name
86
93
  const scm: RecordSchema = entry.schema
87
94
  const result = new EntitySchemaOptions<any>()
88
- result.tableName = asTableName(moduleName, entityName)
95
+ result.tableName = asTableReference(moduleName, entityName)
89
96
  result.name = result.tableName
90
97
  const cols = new Map<string, any>()
91
98
  const indices = new Array<any>()
@@ -15,7 +15,7 @@ import {
15
15
  } from '../../module.js';
16
16
  import { escapeFqName, makeFqName, splitFqName } from '../../util.js';
17
17
  import { JoinInfo, Resolver } from '../interface.js';
18
- import { asTableName } from './dbutil.js';
18
+ import { asTableReference } from './dbutil.js';
19
19
  import {
20
20
  getMany,
21
21
  insertRow,
@@ -103,7 +103,7 @@ export class SqlDbResolver extends Resolver {
103
103
  else p = `${n.replace('/', '$')}/${idAttrVal}`;
104
104
  attrs.set(PathAttributeName, p);
105
105
  }
106
- const n: string = asTableName(inst.moduleName, inst.name);
106
+ const n: string = asTableReference(inst.moduleName, inst.name);
107
107
  const rowObj: object = inst.attributesWithStringifiedObjects();
108
108
  const ctx = this.getDbContext(inst.getFqName());
109
109
  await insertRow(n, rowObj, ctx, orUpdate);
@@ -140,7 +140,7 @@ export class SqlDbResolver extends Resolver {
140
140
  );
141
141
  const updateObj: object = Object.fromEntries(newAttrs);
142
142
  await updateRow(
143
- asTableName(inst.moduleName, inst.name),
143
+ asTableReference(inst.moduleName, inst.name),
144
144
  queryObj,
145
145
  queryVals,
146
146
  updateObj,
@@ -153,16 +153,17 @@ export class SqlDbResolver extends Resolver {
153
153
 
154
154
  public override async queryInstances(
155
155
  inst: Instance,
156
- queryAll: boolean = false
156
+ queryAll: boolean = false,
157
+ distinct: boolean = false
157
158
  ): Promise<Instance[]> {
158
159
  let result = SqlDbResolver.EmptyResultSet;
159
160
 
160
- const tableName = asTableName(inst.moduleName, inst.name);
161
+ const tableName = asTableReference(inst.moduleName, inst.name);
161
162
  const fqName = inst.getFqName();
162
163
  const ctx = this.getDbContext(fqName);
163
164
  const qattrs: any = queryAll ? undefined : inst.queryAttributesAsObject();
164
165
  const qvals: any = queryAll ? undefined : inst.queryAttributeValuesAsObject();
165
- const rslt: any = await getMany(tableName, qattrs, qvals, ctx);
166
+ const rslt: any = await getMany(tableName, qattrs, qvals, distinct, ctx);
166
167
  if (rslt instanceof Array) {
167
168
  result = new Array<Instance>();
168
169
  rslt.forEach((r: object) => {
@@ -217,11 +218,11 @@ export class SqlDbResolver extends Resolver {
217
218
  return await this.queryInstances(inst, false);
218
219
  } else {
219
220
  await getAllConnected(
220
- asTableName(inst.moduleName, inst.name),
221
+ asTableReference(inst.moduleName, inst.name),
221
222
  inst.queryAttributesAsObject(),
222
223
  inst.queryAttributeValuesAsObject(),
223
224
  {
224
- connectionTable: asTableName(inst.moduleName, relationship.name),
225
+ connectionTable: asTableReference(inst.moduleName, relationship.name),
225
226
  fromColumn: relationship.node1.alias,
226
227
  fromValue: `'${connectedInstance.lookup(PathAttributeName)}'`,
227
228
  toColumn: relationship.node2.alias,
@@ -249,15 +250,16 @@ export class SqlDbResolver extends Resolver {
249
250
  public override async queryByJoin(
250
251
  inst: Instance,
251
252
  joinsSpec: JoinInfo[],
252
- intoSpec: Map<string, string>
253
+ intoSpec: Map<string, string>,
254
+ distinct: boolean = false
253
255
  ): Promise<any> {
254
- const tableName = asTableName(inst.moduleName, inst.name);
256
+ const tableName = asTableReference(inst.moduleName, inst.name);
255
257
  const joinClauses: JoinClause[] = [];
256
258
  this.processJoinInfo(tableName, inst, joinsSpec, joinClauses);
257
259
  intoSpec.forEach((v: string, k: string) => {
258
260
  const p = splitFqName(v);
259
261
  const mn = p.hasModule() ? p.getModuleName() : inst.moduleName;
260
- intoSpec.set(k, asTableName(mn, p.getEntryName()));
262
+ intoSpec.set(k, asTableReference(mn, p.getEntryName()));
261
263
  });
262
264
  const rslt: any = await getManyByJoin(
263
265
  tableName,
@@ -265,6 +267,7 @@ export class SqlDbResolver extends Resolver {
265
267
  inst.queryAttributeValuesAsObject(),
266
268
  joinClauses,
267
269
  intoSpec,
270
+ distinct,
268
271
  this.getDbContext(inst.getFqName())
269
272
  );
270
273
  return rslt;
@@ -278,7 +281,7 @@ export class SqlDbResolver extends Resolver {
278
281
  ) {
279
282
  joinsSpec.forEach((ji: JoinInfo) => {
280
283
  const rel: Relationship = ji.relationship;
281
- const joinTableName = asTableName(ji.queryInstance.moduleName, ji.queryInstance.name);
284
+ const joinTableName = asTableReference(ji.queryInstance.moduleName, ji.queryInstance.name);
282
285
  let joinOn: JoinOn | JoinOn[] | undefined;
283
286
  if (rel.isContains()) {
284
287
  const walkDown = rel.isParent(joinInst);
@@ -295,7 +298,7 @@ export class SqlDbResolver extends Resolver {
295
298
  pathRef
296
299
  );
297
300
  } else {
298
- const relTableName = asTableName(rel.moduleName, rel.name);
301
+ const relTableName = asTableReference(rel.moduleName, rel.name);
299
302
  const jPathRef = `"${joinTableName}"."${PathAttributeName}"`;
300
303
  const fqn = ji.queryInstance.getFqName();
301
304
  const n1 = rel.getAliasForName(fqn);
@@ -333,7 +336,7 @@ export class SqlDbResolver extends Resolver {
333
336
  const queryVals: object = Object.fromEntries(
334
337
  newInstanceAttributes().set(PathAttributeName, target.attributes.get(PathAttributeName))
335
338
  );
336
- const tableName = asTableName(target.moduleName, target.name);
339
+ const tableName = asTableReference(target.moduleName, target.name);
337
340
  const ctx = this.getDbContext(target.getFqName());
338
341
  if (purge) {
339
342
  await hardDeleteRow(tableName, [[PathAttributeName, target.lookup(PathAttributeName)]], ctx);
@@ -374,7 +377,7 @@ export class SqlDbResolver extends Resolver {
374
377
  relEntry: Relationship,
375
378
  orUpdate: boolean
376
379
  ): Promise<void> {
377
- const n: string = asTableName(relEntry.moduleName, relEntry.name);
380
+ const n: string = asTableReference(relEntry.moduleName, relEntry.name);
378
381
  const [firstNode, secondNode] = relEntry.isFirstNode(node1) ? [node1, node2] : [node2, node1];
379
382
  const a1: string = relEntry.node1.alias;
380
383
  const a2: string = relEntry.node2.alias;
@@ -423,7 +426,7 @@ export class SqlDbResolver extends Resolver {
423
426
  if (options && options.has('limit')) {
424
427
  limit = options.get('limit') as number;
425
428
  }
426
- return await vectorStoreSearch(asTableName(moduleName, entryName), queryVec, limit, ctx);
429
+ return await vectorStoreSearch(asTableReference(moduleName, entryName), queryVec, limit, ctx);
427
430
  }
428
431
 
429
432
  public override async startTransaction(): Promise<string> {
@@ -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','@enum','@expr','@from','@meta','@oneof','@rbac','@ref','@upsert','@with_unique','agent','allow','and','await','between','contains','create','delete','else','entity','error','event','extends','false','for','if','import','in','into','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','subscribe','true','update','upsert','where','workflow'
4
+ '@actions','@after','@as','@async','@before','@catch','@distinct','@enum','@expr','@from','@into','@meta','@oneof','@rbac','@ref','@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
  '*','+',',','-','.','/',':',';','<','<=','<>','=','>','>=','?','@'