@aeriajs/compiler 0.0.14 → 0.0.16

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/dist/ast.d.ts CHANGED
@@ -9,6 +9,7 @@ export declare const PropertyType: {
9
9
  readonly enum: "enum";
10
10
  readonly date: "string";
11
11
  readonly datetime: "string";
12
+ readonly const: "const";
12
13
  };
13
14
  export declare const PropertyModifiers: Record<'Error' | 'Result', ExportSymbol>;
14
15
  export type ExportSymbol = {
@@ -22,6 +23,7 @@ export type PropertyNode = NodeBase<'property'> & {
22
23
  modifier?: keyof typeof PropertyModifiers;
23
24
  property: Property & {
24
25
  [LOCATION_SYMBOL]?: {
26
+ type: symbol;
25
27
  attributes: Record<string, symbol>;
26
28
  arrays: {
27
29
  [P in ArrayProperties<Extract<Property, {
package/dist/ast.js CHANGED
@@ -10,6 +10,7 @@ exports.PropertyType = {
10
10
  enum: 'enum',
11
11
  date: 'string',
12
12
  datetime: 'string',
13
+ const: 'const',
13
14
  };
14
15
  exports.PropertyModifiers = {
15
16
  Error: {
package/dist/ast.mjs CHANGED
@@ -7,7 +7,8 @@ export const PropertyType = {
7
7
  bool: "boolean",
8
8
  enum: "enum",
9
9
  date: "string",
10
- datetime: "string"
10
+ datetime: "string",
11
+ const: "const"
11
12
  };
12
13
  export const PropertyModifiers = {
13
14
  Error: {
@@ -1,5 +1,5 @@
1
1
  import type * as AST from '../ast.js';
2
2
  export declare const generateContracts: (ast: AST.Node[]) => false | {
3
3
  js: string;
4
- dTs: string;
4
+ dts: string;
5
5
  };
@@ -10,7 +10,7 @@ const generateContracts = (ast) => {
10
10
  }
11
11
  return {
12
12
  js: makeJSContractsCode(contractNodes),
13
- dTs: makeTSContractsCode(contractNodes),
13
+ dts: makeTSContractsCode(contractNodes),
14
14
  };
15
15
  };
16
16
  exports.generateContracts = generateContracts;
@@ -8,7 +8,7 @@ export const generateContracts = (ast) => {
8
8
  }
9
9
  return {
10
10
  js: makeJSContractsCode(contractNodes),
11
- dTs: makeTSContractsCode(contractNodes)
11
+ dts: makeTSContractsCode(contractNodes)
12
12
  };
13
13
  };
14
14
  const makeJSContractsCode = (contractAst) => {
@@ -2,14 +2,14 @@ import type * as AST from '../ast.js';
2
2
  export declare const generateExports: (ast: AST.ProgramNode, hasContracts?: boolean) => {
3
3
  main: {
4
4
  js: string;
5
- dTs: string;
5
+ dts: string;
6
6
  };
7
7
  collections: {
8
8
  js: string;
9
- dTs: string;
9
+ dts: string;
10
10
  };
11
11
  contracts?: {
12
12
  js: string;
13
- dTs: string;
13
+ dts: string;
14
14
  };
15
15
  };
@@ -15,7 +15,7 @@ const generateExports = (ast, hasContracts = false) => {
15
15
  const exports = {
16
16
  collections: {
17
17
  js: `export { ${symbolsToExport.map((symbol) => `${symbol.id}`).join(', ')} } from './collections.js'`,
18
- dTs: `export { ${symbolsToExport.map((symbol) => `${symbol.id}`).join(', ')} } from './collections.js'`,
18
+ dts: `export { ${symbolsToExport.map((symbol) => `${symbol.id}`).join(', ')} } from './collections.js'`,
19
19
  },
20
20
  main: {
21
21
  js: (hasContracts
@@ -23,7 +23,7 @@ const generateExports = (ast, hasContracts = false) => {
23
23
  : '') +
24
24
  'export * as collections from \'./collections/index.js\'\n' +
25
25
  `export { ${symbolsToExport.map((symbol) => symbol.extend).join(', ')} } from './collections/collections.js'`,
26
- dTs: (hasContracts
26
+ dts: (hasContracts
27
27
  ? 'export * as contracts from \'./contracts/index.js\'\n'
28
28
  : '') +
29
29
  'export * as collections from \'./collections/index.js\'\n' +
@@ -33,7 +33,7 @@ const generateExports = (ast, hasContracts = false) => {
33
33
  if (hasContracts) {
34
34
  exports.contracts = {
35
35
  js: 'export * from \'./contracts.js\'',
36
- dTs: 'export * from \'./contracts.js\'',
36
+ dts: 'export * from \'./contracts.js\'',
37
37
  };
38
38
  }
39
39
  return exports;
@@ -13,19 +13,19 @@ export const generateExports = (ast, hasContracts = false) => {
13
13
  const exports = {
14
14
  collections: {
15
15
  js: `export { ${symbolsToExport.map((symbol) => `${symbol.id}`).join(", ")} } from './collections.mjs'`,
16
- dTs: `export { ${symbolsToExport.map((symbol) => `${symbol.id}`).join(", ")} } from './collections.mjs'`
16
+ dts: `export { ${symbolsToExport.map((symbol) => `${symbol.id}`).join(", ")} } from './collections.mjs'`
17
17
  },
18
18
  main: {
19
19
  js: (hasContracts ? "export * as contracts from './contracts/index.mjs'\n" : "") + `export * as collections from './collections/index.mjs'
20
20
  export { ${symbolsToExport.map((symbol) => symbol.extend).join(", ")} } from './collections/collections.mjs'`,
21
- dTs: (hasContracts ? "export * as contracts from './contracts/index.mjs'\n" : "") + `export * as collections from './collections/index.mjs'
21
+ dts: (hasContracts ? "export * as contracts from './contracts/index.mjs'\n" : "") + `export * as collections from './collections/index.mjs'
22
22
  export { ${symbolsToExport.map((symbol) => `${symbol.extend}, ${symbol.schema}`).join(", ")} } from './collections/collections.mjs'`
23
23
  }
24
24
  };
25
25
  if (hasContracts) {
26
26
  exports.contracts = {
27
27
  js: "export * from './contracts.mjs'",
28
- dTs: "export * from './contracts.mjs'"
28
+ dts: "export * from './contracts.mjs'"
29
29
  };
30
30
  }
31
31
  return exports;
@@ -47,10 +47,10 @@ const makeJSCollectionSchema = (collectionNode, collectionId) => {
47
47
  }
48
48
  switch (key) {
49
49
  case 'properties':
50
- collectionSchema.description.properties = (0, utils_js_1.getProperties)(collectionNode[key]);
50
+ collectionSchema.description[key] = (0, utils_js_1.getProperties)(collectionNode[key]);
51
51
  break;
52
52
  case 'owned':
53
- collectionSchema.description.owned = collectionNode[key];
53
+ collectionSchema.description[key] = collectionNode[key];
54
54
  break;
55
55
  case 'functions':
56
56
  collectionSchema.functions = {
@@ -40,10 +40,10 @@ const makeJSCollectionSchema = (collectionNode, collectionId) => {
40
40
  }
41
41
  switch (key) {
42
42
  case "properties":
43
- collectionSchema.description.properties = getProperties(collectionNode[key]);
43
+ collectionSchema.description[key] = getProperties(collectionNode[key]);
44
44
  break;
45
45
  case "owned":
46
- collectionSchema.description.owned = collectionNode[key];
46
+ collectionSchema.description[key] = collectionNode[key];
47
47
  break;
48
48
  case "functions":
49
49
  collectionSchema.functions = {
@@ -15,7 +15,7 @@ export declare const makeASTImports: (ast: AST.Node[], initialImports?: Record<s
15
15
  };
16
16
  export declare const propertyToSchema: ({ property, nestedProperties }: Pick<AST.PropertyNode, "property" | "nestedProperties">) => Property;
17
17
  /** Transforms the AST properties to the format of aeria schema properties */
18
- export declare const getProperties: <TProperties extends Record<string, AST.PropertyNode | AST.PropertyNode[]>, TReturnType = TProperties[keyof TProperties] extends unknown[] ? Record<string, Property[]> : Record<string, Property>>(properties: TProperties) => TReturnType;
18
+ export declare const getProperties: <TProperties extends Record<string, AST.PropertyNode | AST.PropertyNode[]>, TReturnType = TProperties[keyof TProperties] extends Array<unknown> ? Record<string, Property[]> : Record<string, Property>>(properties: TProperties) => TReturnType;
19
19
  export declare const UnquotedSymbol: unique symbol;
20
20
  /** Serves to know if the value must be unquoted on strinfigy function */
21
21
  export type StringifyProperty = unknown | {
package/dist/codegen.js CHANGED
@@ -77,17 +77,17 @@ const generateCode = async (ast, options) => {
77
77
  ['collections']: {
78
78
  ['collections.d.ts']: (0, index_js_1.generateTSCollections)(ast.collections),
79
79
  ['collections.js']: (0, index_js_1.generateJSCollections)(ast.collections),
80
- ['index.d.ts']: exports.collections.dTs,
80
+ ['index.d.ts']: exports.collections.dts,
81
81
  ['index.js']: exports.collections.js,
82
82
  },
83
- ['index.d.ts']: exports.main.dTs,
83
+ ['index.d.ts']: exports.main.dts,
84
84
  ['index.js']: exports.main.js,
85
85
  };
86
86
  if (contracts) {
87
87
  fileTree.contracts = {
88
88
  ['contracts.js']: contracts.js,
89
- ['contracts.d.ts']: contracts.dTs,
90
- ['index.d.ts']: exports.contracts.dTs,
89
+ ['contracts.d.ts']: contracts.dts,
90
+ ['index.d.ts']: exports.contracts.dts,
91
91
  ['index.js']: exports.contracts.js,
92
92
  };
93
93
  }
package/dist/codegen.mjs CHANGED
@@ -28,17 +28,17 @@ export const generateCode = async (ast, options) => {
28
28
  ["collections"]: {
29
29
  ["collections.d.ts"]: generateTSCollections(ast.collections),
30
30
  ["collections.mjs"]: generateJSCollections(ast.collections),
31
- ["index.d.ts"]: exports.collections.dTs,
31
+ ["index.d.ts"]: exports.collections.dts,
32
32
  ["index.mjs"]: exports.collections.js
33
33
  },
34
- ["index.d.ts"]: exports.main.dTs,
34
+ ["index.d.ts"]: exports.main.dts,
35
35
  ["index.mjs"]: exports.main.js
36
36
  };
37
37
  if (contracts) {
38
38
  fileTree.contracts = {
39
39
  ["contracts.mjs"]: contracts.js,
40
- ["contracts.d.ts"]: contracts.dTs,
41
- ["index.d.ts"]: exports.contracts.dTs,
40
+ ["contracts.d.ts"]: contracts.dts,
41
+ ["index.d.ts"]: exports.contracts.dts,
42
42
  ["index.mjs"]: exports.contracts.js
43
43
  };
44
44
  }
package/dist/compile.d.ts CHANGED
@@ -3,7 +3,7 @@ import { Diagnostic } from './diagnostic.js';
3
3
  export declare const FILE_PRECEDENCE: string[];
4
4
  export declare const parseAndCheck: (sources: Record<string, string>, options?: Pick<CompilationOptions, "languageServer">) => Promise<CompilationResult>;
5
5
  export declare const generateScaffolding: (options: CompilationOptions) => Promise<string[]>;
6
- export declare const compileFromFiles: (schemaDir: string, options: CompilationOptions) => Promise<CompilationResult | {
6
+ export declare const compileFromFiles: (globPattern: string, options: CompilationOptions) => Promise<CompilationResult | {
7
7
  emittedFiles: Record<string, string>;
8
8
  success: boolean;
9
9
  ast?: import("./ast.js").ProgramNode;
package/dist/compile.js CHANGED
@@ -44,28 +44,23 @@ const fs = __importStar(require("node:fs"));
44
44
  exports.FILE_PRECEDENCE = ['contract'];
45
45
  const parseAndCheck = async (sources, options = {}) => {
46
46
  const errors = [];
47
- let errorCount = 0;
48
47
  let ast;
48
+ const allTokens = [];
49
49
  for (const fileName in sources) {
50
50
  diagnostic_js_1.Diagnostic.currentFile = fileName;
51
51
  const { errors: lexerErrors, tokens } = (0, lexer_js_1.tokenize)(sources[fileName]);
52
- const { errors: parserErrors, ast: currentAst } = (0, parser_js_1.parse)(Array.from(tokens));
53
- const { errors: semanticErrors } = await (0, semantic_js_1.analyze)(currentAst, options);
54
- errors.push(...lexerErrors.concat(parserErrors, semanticErrors));
55
- errorCount += errors.length;
56
- if (!ast) {
57
- ast = currentAst;
58
- }
59
- else {
60
- ast.collections.push(...currentAst.collections);
61
- ast.contracts.push(...currentAst.contracts);
62
- ast.functionsets.push(...currentAst.functionsets);
52
+ if (lexerErrors.length > 0) {
53
+ errors.push(...lexerErrors);
63
54
  }
55
+ allTokens.push(...tokens);
64
56
  }
57
+ const { errors: parserErrors, ast: currentAst } = (0, parser_js_1.parse)(allTokens);
58
+ const { errors: semanticErrors } = await (0, semantic_js_1.analyze)(currentAst, options);
59
+ errors.push(...parserErrors.concat(semanticErrors));
65
60
  return {
66
- success: errorCount === 0,
61
+ success: errors.length === 0,
67
62
  errors,
68
- errorCount,
63
+ errorCount: errors.length,
69
64
  ast,
70
65
  };
71
66
  };
@@ -80,8 +75,8 @@ const generateScaffolding = async (options) => {
80
75
  return directories;
81
76
  };
82
77
  exports.generateScaffolding = generateScaffolding;
83
- const compileFromFiles = async (schemaDir, options) => {
84
- const fileList = await Array.fromAsync(fs.promises.glob(`${schemaDir}/*.aeria`));
78
+ const compileFromFiles = async (globPattern, options) => {
79
+ const fileList = await Array.fromAsync(fs.promises.glob(globPattern));
85
80
  const sortedFileList = fileList.sort((a, b) => {
86
81
  const aIndex = exports.FILE_PRECEDENCE.findIndex((file) => a.split('/').at(-1).startsWith(file));
87
82
  const bIndex = exports.FILE_PRECEDENCE.findIndex((file) => b.split('/').at(-1).startsWith(file));
package/dist/compile.mjs CHANGED
@@ -9,27 +9,23 @@ import * as fs from "node:fs";
9
9
  export const FILE_PRECEDENCE = ["contract"];
10
10
  export const parseAndCheck = async (sources, options = {}) => {
11
11
  const errors = [];
12
- let errorCount = 0;
13
12
  let ast;
13
+ const allTokens = [];
14
14
  for (const fileName in sources) {
15
15
  Diagnostic.currentFile = fileName;
16
16
  const { errors: lexerErrors, tokens } = tokenize(sources[fileName]);
17
- const { errors: parserErrors, ast: currentAst } = parse(Array.from(tokens));
18
- const { errors: semanticErrors } = await analyze(currentAst, options);
19
- errors.push(...lexerErrors.concat(parserErrors, semanticErrors));
20
- errorCount += errors.length;
21
- if (!ast) {
22
- ast = currentAst;
23
- } else {
24
- ast.collections.push(...currentAst.collections);
25
- ast.contracts.push(...currentAst.contracts);
26
- ast.functionsets.push(...currentAst.functionsets);
17
+ if (lexerErrors.length > 0) {
18
+ errors.push(...lexerErrors);
27
19
  }
20
+ allTokens.push(...tokens);
28
21
  }
22
+ const { errors: parserErrors, ast: currentAst } = parse(allTokens);
23
+ const { errors: semanticErrors } = await analyze(currentAst, options);
24
+ errors.push(...parserErrors.concat(semanticErrors));
29
25
  return {
30
- success: errorCount === 0,
26
+ success: errors.length === 0,
31
27
  errors,
32
- errorCount,
28
+ errorCount: errors.length,
33
29
  ast
34
30
  };
35
31
  };
@@ -42,8 +38,8 @@ export const generateScaffolding = async (options) => {
42
38
  }
43
39
  return directories;
44
40
  };
45
- export const compileFromFiles = async (schemaDir, options) => {
46
- const fileList = await Array.fromAsync(fs.promises.glob(`${schemaDir}/*.aeria`));
41
+ export const compileFromFiles = async (globPattern, options) => {
42
+ const fileList = await Array.fromAsync(fs.promises.glob(globPattern));
47
43
  const sortedFileList = fileList.sort((a, b) => {
48
44
  const aIndex = FILE_PRECEDENCE.findIndex((file) => a.split("/").at(-1).startsWith(file));
49
45
  const bIndex = FILE_PRECEDENCE.findIndex((file) => b.split("/").at(-1).startsWith(file));
package/dist/parser.js CHANGED
@@ -179,6 +179,9 @@ const parse = (tokens) => {
179
179
  array.push(identifier);
180
180
  symbols.push(elemSymbol);
181
181
  exports.locationMap.set(elemSymbol, location);
182
+ if (match(token_js_1.TokenType.Comma)) {
183
+ consume(token_js_1.TokenType.Comma);
184
+ }
182
185
  }
183
186
  consume(token_js_1.TokenType.RightBracket);
184
187
  return {
@@ -225,6 +228,22 @@ const parse = (tokens) => {
225
228
  ]).value;
226
229
  return;
227
230
  }
231
+ if ('const' in property && attributeName === 'value') {
232
+ const token = current();
233
+ advance();
234
+ switch (token.type) {
235
+ case token_js_1.TokenType.Number:
236
+ case token_js_1.TokenType.Boolean:
237
+ case token_js_1.TokenType.Null:
238
+ case token_js_1.TokenType.QuotedString: {
239
+ property.const = token.value;
240
+ return;
241
+ }
242
+ default: {
243
+ throw new diagnostic_js_1.Diagnostic(`const received invalid value: "${token.value}"`, location);
244
+ }
245
+ }
246
+ }
228
247
  switch (attributeName) {
229
248
  case 'icon': {
230
249
  const { value } = consume(token_js_1.TokenType.QuotedString, ICON_NAMES);
@@ -360,6 +379,8 @@ const parse = (tokens) => {
360
379
  let property;
361
380
  let nestedProperties;
362
381
  let modifierToken;
382
+ const typeSymbol = Symbol();
383
+ exports.locationMap.set(typeSymbol, next().location);
363
384
  if (match(token_js_1.TokenType.LeftSquareBracket)) {
364
385
  consume(token_js_1.TokenType.LeftSquareBracket);
365
386
  const arrayProperty = {
@@ -368,6 +389,7 @@ const parse = (tokens) => {
368
389
  while (!match(token_js_1.TokenType.RightSquareBracket)) {
369
390
  const attributeSymbol = Symbol();
370
391
  arrayProperty[AST.LOCATION_SYMBOL] ??= {
392
+ type: typeSymbol,
371
393
  attributes: {},
372
394
  arrays: {},
373
395
  };
@@ -425,6 +447,7 @@ const parse = (tokens) => {
425
447
  type: 'object',
426
448
  properties: {},
427
449
  [AST.LOCATION_SYMBOL]: {
450
+ type: typeSymbol,
428
451
  attributes: {},
429
452
  arrays: {},
430
453
  },
@@ -452,7 +475,7 @@ const parse = (tokens) => {
452
475
  consume(token_js_1.TokenType.RightBracket);
453
476
  }
454
477
  else {
455
- const { value: identifier, location } = consume(token_js_1.TokenType.Identifier);
478
+ const { value: identifier } = consume(token_js_1.TokenType.Identifier);
456
479
  if (guards.isNativePropertyType(identifier)) {
457
480
  switch (identifier) {
458
481
  case 'enum': {
@@ -461,6 +484,12 @@ const parse = (tokens) => {
461
484
  };
462
485
  break;
463
486
  }
487
+ case 'const': {
488
+ property = {
489
+ const: null,
490
+ };
491
+ break;
492
+ }
464
493
  case 'date': {
465
494
  property = {
466
495
  type: 'string',
@@ -482,12 +511,13 @@ const parse = (tokens) => {
482
511
  }
483
512
  }
484
513
  else {
485
- const collection = ast.collections.find((node) => node.name === identifier);
486
- if (!collection) {
487
- throw new diagnostic_js_1.Diagnostic(`invalid reference "${identifier}"`, location);
488
- }
489
514
  property = {
490
515
  $ref: identifier,
516
+ [AST.LOCATION_SYMBOL]: {
517
+ type: typeSymbol,
518
+ attributes: {},
519
+ arrays: {},
520
+ },
491
521
  };
492
522
  }
493
523
  }
@@ -498,6 +528,7 @@ const parse = (tokens) => {
498
528
  const attributeSymbol = Symbol();
499
529
  exports.locationMap.set(attributeSymbol, next().location);
500
530
  property[AST.LOCATION_SYMBOL] ??= {
531
+ type: typeSymbol,
501
532
  attributes: {},
502
533
  arrays: {},
503
534
  };
package/dist/parser.mjs CHANGED
@@ -141,6 +141,9 @@ export const parse = (tokens) => {
141
141
  array.push(identifier);
142
142
  symbols.push(elemSymbol);
143
143
  locationMap.set(elemSymbol, location);
144
+ if (match(TokenType.Comma)) {
145
+ consume(TokenType.Comma);
146
+ }
144
147
  }
145
148
  consume(TokenType.RightBracket);
146
149
  return {
@@ -184,6 +187,22 @@ export const parse = (tokens) => {
184
187
  ]).value;
185
188
  return;
186
189
  }
190
+ if ("const" in property && attributeName === "value") {
191
+ const token = current();
192
+ advance();
193
+ switch (token.type) {
194
+ case TokenType.Number:
195
+ case TokenType.Boolean:
196
+ case TokenType.Null:
197
+ case TokenType.QuotedString: {
198
+ property.const = token.value;
199
+ return;
200
+ }
201
+ default: {
202
+ throw new Diagnostic(`const received invalid value: "${token.value}"`, location);
203
+ }
204
+ }
205
+ }
187
206
  switch (attributeName) {
188
207
  case "icon": {
189
208
  const { value } = consume(TokenType.QuotedString, ICON_NAMES);
@@ -318,6 +337,8 @@ export const parse = (tokens) => {
318
337
  let property;
319
338
  let nestedProperties;
320
339
  let modifierToken;
340
+ const typeSymbol = Symbol();
341
+ locationMap.set(typeSymbol, next().location);
321
342
  if (match(TokenType.LeftSquareBracket)) {
322
343
  consume(TokenType.LeftSquareBracket);
323
344
  const arrayProperty = {
@@ -326,6 +347,7 @@ export const parse = (tokens) => {
326
347
  while (!match(TokenType.RightSquareBracket)) {
327
348
  const attributeSymbol = Symbol();
328
349
  arrayProperty[AST.LOCATION_SYMBOL] ??= {
350
+ type: typeSymbol,
329
351
  attributes: {},
330
352
  arrays: {}
331
353
  };
@@ -381,6 +403,7 @@ export const parse = (tokens) => {
381
403
  type: "object",
382
404
  properties: {},
383
405
  [AST.LOCATION_SYMBOL]: {
406
+ type: typeSymbol,
384
407
  attributes: {},
385
408
  arrays: {}
386
409
  }
@@ -407,7 +430,7 @@ export const parse = (tokens) => {
407
430
  }
408
431
  consume(TokenType.RightBracket);
409
432
  } else {
410
- const { value: identifier, location } = consume(TokenType.Identifier);
433
+ const { value: identifier } = consume(TokenType.Identifier);
411
434
  if (guards.isNativePropertyType(identifier)) {
412
435
  switch (identifier) {
413
436
  case "enum": {
@@ -416,6 +439,12 @@ export const parse = (tokens) => {
416
439
  };
417
440
  break;
418
441
  }
442
+ case "const": {
443
+ property = {
444
+ const: null
445
+ };
446
+ break;
447
+ }
419
448
  case "date": {
420
449
  property = {
421
450
  type: "string",
@@ -436,12 +465,13 @@ export const parse = (tokens) => {
436
465
  };
437
466
  }
438
467
  } else {
439
- const collection = ast.collections.find((node2) => node2.name === identifier);
440
- if (!collection) {
441
- throw new Diagnostic(`invalid reference "${identifier}"`, location);
442
- }
443
468
  property = {
444
- $ref: identifier
469
+ $ref: identifier,
470
+ [AST.LOCATION_SYMBOL]: {
471
+ type: typeSymbol,
472
+ attributes: {},
473
+ arrays: {}
474
+ }
445
475
  };
446
476
  }
447
477
  }
@@ -452,6 +482,7 @@ export const parse = (tokens) => {
452
482
  const attributeSymbol = Symbol();
453
483
  locationMap.set(attributeSymbol, next().location);
454
484
  property[AST.LOCATION_SYMBOL] ??= {
485
+ type: typeSymbol,
455
486
  attributes: {},
456
487
  arrays: {}
457
488
  };
package/dist/semantic.js CHANGED
@@ -110,7 +110,9 @@ const analyze = async (ast, options, errors = []) => {
110
110
  const refName = node.property.$ref;
111
111
  const foreignCollection = ast.collections.find(({ name }) => name === refName);
112
112
  if (!foreignCollection) {
113
- throw new Error;
113
+ const location = parser_js_1.locationMap.get(node.property[AST.LOCATION_SYMBOL].type);
114
+ errors.push(new diagnostic_js_1.Diagnostic(`invalid reference "${refName}"`, location));
115
+ return;
114
116
  }
115
117
  await checkCollectionForeignProperties(foreignCollection, node.property, 'indexes');
116
118
  await checkCollectionForeignProperties(foreignCollection, node.property, 'populate');
package/dist/semantic.mjs CHANGED
@@ -74,7 +74,9 @@ export const analyze = async (ast, options, errors = []) => {
74
74
  const refName = node.property.$ref;
75
75
  const foreignCollection = ast.collections.find(({ name }) => name === refName);
76
76
  if (!foreignCollection) {
77
- throw new Error();
77
+ const location = locationMap.get(node.property[AST.LOCATION_SYMBOL].type);
78
+ errors.push(new Diagnostic(`invalid reference "${refName}"`, location));
79
+ return;
78
80
  }
79
81
  await checkCollectionForeignProperties(foreignCollection, node.property, "indexes");
80
82
  await checkCollectionForeignProperties(foreignCollection, node.property, "populate");
package/dist/token.d.ts CHANGED
@@ -12,6 +12,7 @@ export declare const TokenType: {
12
12
  readonly Dot: "DOT";
13
13
  readonly Number: "NUMBER";
14
14
  readonly Boolean: "BOOLEAN";
15
+ readonly Null: "NULL";
15
16
  readonly Keyword: "KEYWORD";
16
17
  readonly Identifier: "IDENTIFIER";
17
18
  readonly QuotedString: "QUOTED_STRING";
@@ -23,6 +24,7 @@ export type TokenType = typeof TokenType[keyof typeof TokenType];
23
24
  export type TypeMap = {
24
25
  [TokenType.Number]: number;
25
26
  [TokenType.Boolean]: boolean;
27
+ [TokenType.Null]: null;
26
28
  [TokenType.Range]: readonly [number, number];
27
29
  };
28
30
  export type Location = {
package/dist/token.js CHANGED
@@ -15,6 +15,7 @@ exports.TokenType = {
15
15
  Dot: 'DOT',
16
16
  Number: 'NUMBER',
17
17
  Boolean: 'BOOLEAN',
18
+ Null: 'NULL',
18
19
  Keyword: 'KEYWORD',
19
20
  Identifier: 'IDENTIFIER',
20
21
  QuotedString: 'QUOTED_STRING',
package/dist/token.mjs CHANGED
@@ -13,6 +13,7 @@ export const TokenType = {
13
13
  Dot: "DOT",
14
14
  Number: "NUMBER",
15
15
  Boolean: "BOOLEAN",
16
+ Null: "NULL",
16
17
  Keyword: "KEYWORD",
17
18
  Identifier: "IDENTIFIER",
18
19
  QuotedString: "QUOTED_STRING",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeriajs/compiler",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",