@aeriajs/compiler 0.0.31 → 0.0.33

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
@@ -1,4 +1,4 @@
1
- import type { Property, AccessCondition, CollectionActions, SearchOptions, DescriptionPreset, Icon, OwnershipMode, Layout, LayoutOptions, FormLayout, Description, FormLayoutField } from '@aeriajs/types';
1
+ import type { Property, AccessCondition, CollectionActions, SearchOptions, DescriptionPreset, Icon, OwnershipMode, Layout, LayoutOptions, FormLayout, Description, FormLayoutField, RequiredProperties } from '@aeriajs/types';
2
2
  import type { ArrayProperties } from './utils.js';
3
3
  export declare const LOCATION_SYMBOL: unique symbol;
4
4
  export declare const PropertyType: {
@@ -34,7 +34,7 @@ export type FormLayoutNode = NodeBase<'formLayout'> & FormLayout<Description> &
34
34
  field: FormLayoutField<Description>;
35
35
  };
36
36
  };
37
- terms?: [string, symbol][];
37
+ terms?: readonly [string, symbol][];
38
38
  };
39
39
  };
40
40
  export type PropertyNode = NodeBase<'property'> & {
@@ -56,6 +56,7 @@ export type PropertyNode = NodeBase<'property'> & {
56
56
  export type CollectionNode = NodeBase<'collection'> & {
57
57
  name: string;
58
58
  extends?: ExportSymbol;
59
+ middlewares?: readonly string[];
59
60
  owned?: OwnershipMode;
60
61
  icon?: Icon;
61
62
  actions?: CollectionActions;
@@ -64,13 +65,13 @@ export type CollectionNode = NodeBase<'collection'> & {
64
65
  functions?: Record<string, {
65
66
  accessCondition: AccessCondition;
66
67
  }>;
67
- required?: Record<string, unknown> | string[];
68
- indexes?: string[];
68
+ required?: RequiredProperties;
69
+ indexes?: readonly string[];
69
70
  presets?: DescriptionPreset[];
70
- form?: string[];
71
- table?: string[];
72
- tableMeta?: string[];
73
- filters?: string[];
71
+ form?: readonly string[];
72
+ table?: readonly string[];
73
+ tableMeta?: readonly string[];
74
+ filters?: readonly string[];
74
75
  search?: SearchOptions<any>;
75
76
  layout?: LayoutNode;
76
77
  formLayout?: FormLayoutNode;
@@ -78,6 +79,7 @@ export type CollectionNode = NodeBase<'collection'> & {
78
79
  arrays: {
79
80
  [P in ArrayProperties<CollectionNode>]?: symbol[];
80
81
  };
82
+ requiredTerms?: readonly [string, symbol][];
81
83
  };
82
84
  };
83
85
  export type ContractNode = NodeBase<'contract'> & {
@@ -10,8 +10,10 @@ const generateJSCollections = (ast) => {
10
10
  let javascriptCode = '';
11
11
  const importsResult = (0, utils_js_1.makeASTImports)(ast, {
12
12
  [utils_js_1.PACKAGE_NAME]: new Set(initialImportedFunctions),
13
+ }, {
14
+ includeRuntimeOnlyImports: true,
13
15
  });
14
- javascriptCode += importsResult.code + '\n\n';
16
+ javascriptCode += importsResult.code.join('\n') + '\n\n';
15
17
  javascriptCode += makeJSCollections(ast, importsResult.modifiedSymbols) + '\n\n';
16
18
  return javascriptCode;
17
19
  };
@@ -37,8 +39,10 @@ const makeJSCollections = (ast, modifiedSymbols) => {
37
39
  };
38
40
  const makeJSCollectionSchema = (collectionNode, collectionId) => {
39
41
  const collectionSchema = {
42
+ item: {},
40
43
  description: {
41
44
  $id: collectionId,
45
+ properties: {},
42
46
  },
43
47
  };
44
48
  for (const key of Object.keys(collectionNode)) {
@@ -52,6 +56,11 @@ const makeJSCollectionSchema = (collectionNode, collectionId) => {
52
56
  case 'owned':
53
57
  collectionSchema.description[key] = collectionNode[key];
54
58
  break;
59
+ case 'middlewares':
60
+ collectionSchema.middlewares = {
61
+ [utils_js_1.UnquotedSymbol]: `[ ${collectionNode[key].join(', ')} ]`,
62
+ };
63
+ break;
55
64
  case 'functions':
56
65
  collectionSchema.functions = {
57
66
  [utils_js_1.UnquotedSymbol]: `{ ${makeJSFunctions(collectionNode[key])} }`,
@@ -8,8 +8,10 @@ export const generateJSCollections = (ast) => {
8
8
  let javascriptCode = "";
9
9
  const importsResult = makeASTImports(ast, {
10
10
  [PACKAGE_NAME]: new Set(initialImportedFunctions)
11
+ }, {
12
+ includeRuntimeOnlyImports: true
11
13
  });
12
- javascriptCode += importsResult.code + "\n\n";
14
+ javascriptCode += importsResult.code.join("\n") + "\n\n";
13
15
  javascriptCode += makeJSCollections(ast, importsResult.modifiedSymbols) + "\n\n";
14
16
  return javascriptCode;
15
17
  };
@@ -30,8 +32,10 @@ const makeJSCollections = (ast, modifiedSymbols) => {
30
32
  };
31
33
  const makeJSCollectionSchema = (collectionNode, collectionId) => {
32
34
  const collectionSchema = {
35
+ item: {},
33
36
  description: {
34
- $id: collectionId
37
+ $id: collectionId,
38
+ properties: {}
35
39
  }
36
40
  };
37
41
  for (const key of Object.keys(collectionNode)) {
@@ -45,6 +49,11 @@ const makeJSCollectionSchema = (collectionNode, collectionId) => {
45
49
  case "owned":
46
50
  collectionSchema.description[key] = collectionNode[key];
47
51
  break;
52
+ case "middlewares":
53
+ collectionSchema.middlewares = {
54
+ [UnquotedSymbol]: `[ ${collectionNode[key].join(", ")} ]`
55
+ };
56
+ break;
48
57
  case "functions":
49
58
  collectionSchema.functions = {
50
59
  [UnquotedSymbol]: `{ ${makeJSFunctions(collectionNode[key])} }`
@@ -12,7 +12,7 @@ const generateTSCollections = (ast) => {
12
12
  let code = '';
13
13
  code += `import type { ${initialImportedTypes.join(', ')} } from '${utils_js_1.PACKAGE_NAME}'\n`; //Used types
14
14
  const importsResult = (0, utils_js_1.makeASTImports)(ast);
15
- code += importsResult.code + '\n\n';
15
+ code += importsResult.code.join('\n') + '\n\n';
16
16
  code += makeTSCollections(ast, importsResult.modifiedSymbols) + '\n';
17
17
  return code;
18
18
  };
@@ -49,8 +49,10 @@ const makeTSCollections = (ast, modifiedSymbols) => {
49
49
  };
50
50
  const makeTSCollectionSchema = (collectionNode, collectionId) => {
51
51
  const collectionSchema = {
52
+ item: {},
52
53
  description: {
53
54
  $id: collectionId,
55
+ properties: {},
54
56
  },
55
57
  };
56
58
  for (const key of Object.keys(collectionNode)) {
@@ -64,6 +66,11 @@ const makeTSCollectionSchema = (collectionNode, collectionId) => {
64
66
  case 'owned':
65
67
  collectionSchema.description.owned = collectionNode[key];
66
68
  break;
69
+ case 'middlewares':
70
+ collectionSchema.middlewares = {
71
+ [utils_js_1.UnquotedSymbol]: 'import(\'@aeriajs/types\').CollectionMiddleware<unknown>[]',
72
+ };
73
+ break;
67
74
  case 'functions':
68
75
  collectionSchema.functions = makeTSFunctions(collectionNode[key]);
69
76
  collectionSchema.exposedFunctions = (0, utils_js_1.getExposedFunctions)(collectionNode[key]);
@@ -11,7 +11,7 @@ export const generateTSCollections = (ast) => {
11
11
  code += `import type { ${initialImportedTypes.join(", ")} } from '${PACKAGE_NAME}'
12
12
  `;
13
13
  const importsResult = makeASTImports(ast);
14
- code += importsResult.code + "\n\n";
14
+ code += importsResult.code.join("\n") + "\n\n";
15
15
  code += makeTSCollections(ast, importsResult.modifiedSymbols) + "\n";
16
16
  return code;
17
17
  };
@@ -44,8 +44,10 @@ const makeTSCollections = (ast, modifiedSymbols) => {
44
44
  };
45
45
  const makeTSCollectionSchema = (collectionNode, collectionId) => {
46
46
  const collectionSchema = {
47
+ item: {},
47
48
  description: {
48
- $id: collectionId
49
+ $id: collectionId,
50
+ properties: {}
49
51
  }
50
52
  };
51
53
  for (const key of Object.keys(collectionNode)) {
@@ -59,6 +61,11 @@ const makeTSCollectionSchema = (collectionNode, collectionId) => {
59
61
  case "owned":
60
62
  collectionSchema.description.owned = collectionNode[key];
61
63
  break;
64
+ case "middlewares":
65
+ collectionSchema.middlewares = {
66
+ [UnquotedSymbol]: "import('@aeriajs/types').CollectionMiddleware<unknown>[]"
67
+ };
68
+ break;
62
69
  case "functions":
63
70
  collectionSchema.functions = makeTSFunctions(collectionNode[key]);
64
71
  collectionSchema.exposedFunctions = getExposedFunctions(collectionNode[key]);
@@ -1,6 +1,7 @@
1
1
  import type * as AST from '../ast.js';
2
2
  import type { Property } from '@aeriajs/types';
3
3
  export declare const PACKAGE_NAME = "aeria";
4
+ export declare const MIDDLEWARES_RUNTIME_PATH = "../../../dist/middlewares/index.js";
4
5
  export declare const DEFAULT_FUNCTIONS: string[];
5
6
  export declare const ArraySymbol: unique symbol;
6
7
  export declare const getExposedFunctions: (astFunctions: NonNullable<AST.CollectionNode["functions"]>) => {
@@ -9,7 +10,9 @@ export declare const getExposedFunctions: (astFunctions: NonNullable<AST.Collect
9
10
  /**
10
11
  * Obs: It will save and return any modified symbols to avoid name duplication later
11
12
  */
12
- export declare const makeASTImports: (ast: AST.Node[], initialImports?: Record<string, Set<string>>) => {
13
+ export declare const makeASTImports: (ast: AST.Node[], initialImports?: Record<string, Set<string>>, options?: {
14
+ includeRuntimeOnlyImports: boolean;
15
+ }) => {
13
16
  code: string[];
14
17
  modifiedSymbols: Record<string, string>;
15
18
  };
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getExtendName = exports.getCollectionId = exports.resizeFirstChar = exports.stringify = exports.UnquotedSymbol = exports.recursivelyUnwrapPropertyNodes = exports.unwrapPropertyNode = exports.unwrapNode = exports.makeASTImports = exports.getExposedFunctions = exports.ArraySymbol = exports.DEFAULT_FUNCTIONS = exports.PACKAGE_NAME = void 0;
3
+ exports.getExtendName = exports.getCollectionId = exports.resizeFirstChar = exports.stringify = exports.UnquotedSymbol = exports.recursivelyUnwrapPropertyNodes = exports.unwrapPropertyNode = exports.unwrapNode = exports.makeASTImports = exports.getExposedFunctions = exports.ArraySymbol = exports.DEFAULT_FUNCTIONS = exports.MIDDLEWARES_RUNTIME_PATH = exports.PACKAGE_NAME = void 0;
4
4
  exports.PACKAGE_NAME = 'aeria';
5
+ exports.MIDDLEWARES_RUNTIME_PATH = '../../../dist/middlewares/index.js';
5
6
  exports.DEFAULT_FUNCTIONS = [
6
7
  'count',
7
8
  'get',
@@ -24,7 +25,9 @@ exports.getExposedFunctions = getExposedFunctions;
24
25
  /**
25
26
  * Obs: It will save and return any modified symbols to avoid name duplication later
26
27
  */
27
- const makeASTImports = (ast, initialImports) => {
28
+ const makeASTImports = (ast, initialImports, options = {
29
+ includeRuntimeOnlyImports: false,
30
+ }) => {
28
31
  const modifiedSymbols = {};
29
32
  const toImport = ast.reduce((imports, node) => {
30
33
  if (node.kind === 'collection') {
@@ -39,14 +42,20 @@ const makeASTImports = (ast, initialImports) => {
39
42
  if (node.functions) {
40
43
  const functionsToImport = Object.keys(node.functions).filter((key) => exports.DEFAULT_FUNCTIONS.includes(key));
41
44
  if (functionsToImport.length > 0) {
42
- if (!(exports.PACKAGE_NAME in imports)) {
43
- imports[exports.PACKAGE_NAME] = new Set();
44
- }
45
+ imports[exports.PACKAGE_NAME] ??= new Set();
45
46
  for (const key of functionsToImport) {
46
47
  imports[exports.PACKAGE_NAME].add(key);
47
48
  }
48
49
  }
49
50
  }
51
+ if (options.includeRuntimeOnlyImports) {
52
+ if (node.middlewares) {
53
+ imports[exports.MIDDLEWARES_RUNTIME_PATH] ??= new Set();
54
+ for (const middleware of node.middlewares) {
55
+ imports[exports.MIDDLEWARES_RUNTIME_PATH].add(middleware);
56
+ }
57
+ }
58
+ }
50
59
  }
51
60
  return imports;
52
61
  }, initialImports ?? {});
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  export const PACKAGE_NAME = "aeria";
3
+ export const MIDDLEWARES_RUNTIME_PATH = "../../../dist/middlewares/index.mjs";
3
4
  export const DEFAULT_FUNCTIONS = [
4
5
  "count",
5
6
  "get",
@@ -18,7 +19,9 @@ export const getExposedFunctions = (astFunctions) => {
18
19
  value.accessCondition
19
20
  ]));
20
21
  };
21
- export const makeASTImports = (ast, initialImports) => {
22
+ export const makeASTImports = (ast, initialImports, options = {
23
+ includeRuntimeOnlyImports: false
24
+ }) => {
22
25
  const modifiedSymbols = {};
23
26
  const toImport = ast.reduce((imports, node) => {
24
27
  if (node.kind === "collection") {
@@ -33,14 +36,20 @@ export const makeASTImports = (ast, initialImports) => {
33
36
  if (node.functions) {
34
37
  const functionsToImport = Object.keys(node.functions).filter((key) => DEFAULT_FUNCTIONS.includes(key));
35
38
  if (functionsToImport.length > 0) {
36
- if (!(PACKAGE_NAME in imports)) {
37
- imports[PACKAGE_NAME] = /* @__PURE__ */ new Set();
38
- }
39
+ imports[PACKAGE_NAME] ??= /* @__PURE__ */ new Set();
39
40
  for (const key of functionsToImport) {
40
41
  imports[PACKAGE_NAME].add(key);
41
42
  }
42
43
  }
43
44
  }
45
+ if (options.includeRuntimeOnlyImports) {
46
+ if (node.middlewares) {
47
+ imports[MIDDLEWARES_RUNTIME_PATH] ??= /* @__PURE__ */ new Set();
48
+ for (const middleware of node.middlewares) {
49
+ imports[MIDDLEWARES_RUNTIME_PATH].add(middleware);
50
+ }
51
+ }
52
+ }
44
53
  }
45
54
  return imports;
46
55
  }, initialImports ?? {});
package/dist/lexer.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type Token } from './token.js';
2
2
  import { Diagnostic } from './diagnostic.js';
3
- export declare const COLLECTION_KEYWORDS: readonly ["actions", "additionalProperties", "filters", "form", "formLayout", "functions", "icon", "indexes", "individualActions", "layout", "owned", "presets", "properties", "required", "search", "table", "tableMeta"];
3
+ export declare const COLLECTION_KEYWORDS: readonly ["actions", "additionalProperties", "filters", "form", "formLayout", "functions", "icon", "indexes", "individualActions", "layout", "middlewares", "owned", "presets", "properties", "required", "search", "table", "tableMeta"];
4
4
  export declare const COLLECTION_ACTIONS_KEYWORDS: readonly ["ask", "button", "clearItem", "effect", "event", "fetchItem", "function", "icon", "label", "params", "query", "requires", "roles", "route", "selection", "setItem", "translate"];
5
5
  export declare const COLLECTION_SEARCH_KEYWORDS: readonly ["indexes", "placeholder", "exactMatches"];
6
6
  export declare const COLLECTION_LAYOUT_KEYWORDS: readonly ["name", "options"];
package/dist/lexer.js CHANGED
@@ -14,6 +14,7 @@ exports.COLLECTION_KEYWORDS = [
14
14
  'indexes',
15
15
  'individualActions',
16
16
  'layout',
17
+ 'middlewares',
17
18
  'owned',
18
19
  'presets',
19
20
  'properties',
@@ -338,7 +339,7 @@ const tokenize = function (rawInput) {
338
339
  break;
339
340
  }
340
341
  case token_js_1.TokenType.RightParens: {
341
- if (state.variableScopeStack.length > 0) {
342
+ if (state.variableExpressionStack.length > 0) {
342
343
  state.variableExpressionStack.pop();
343
344
  }
344
345
  break;
package/dist/lexer.mjs CHANGED
@@ -12,6 +12,7 @@ export const COLLECTION_KEYWORDS = [
12
12
  "indexes",
13
13
  "individualActions",
14
14
  "layout",
15
+ "middlewares",
15
16
  "owned",
16
17
  "presets",
17
18
  "properties",
@@ -341,7 +342,7 @@ export const tokenize = function(rawInput) {
341
342
  break;
342
343
  }
343
344
  case TokenType.RightParens: {
344
- if (state.variableScopeStack.length > 0) {
345
+ if (state.variableExpressionStack.length > 0) {
345
346
  state.variableExpressionStack.pop();
346
347
  }
347
348
  break;
package/dist/parser.d.ts CHANGED
@@ -3,7 +3,7 @@ import { Diagnostic } from './diagnostic.js';
3
3
  import * as AST from './ast.js';
4
4
  export declare const locationMap: WeakMap<symbol, Location>;
5
5
  export declare const memoTable: {
6
- roles?: string[];
6
+ roles?: readonly string[];
7
7
  };
8
8
  export declare const parse: (tokens: (Token | undefined)[]) => {
9
9
  ast: AST.ProgramNode;
package/dist/parser.js CHANGED
@@ -189,23 +189,20 @@ const parse = (tokens) => {
189
189
  symbols,
190
190
  };
191
191
  };
192
- const parseArrayBlockWithAttributes = () => {
192
+ const parseArrayBlockWithAttributes = (allowedAttributes, cb) => {
193
193
  const array = {};
194
194
  let hasAttributes = false;
195
195
  consume(token_js_1.TokenType.LeftBracket);
196
196
  while (!match(token_js_1.TokenType.RightBracket)) {
197
197
  const { value: identifier } = consume(token_js_1.TokenType.Identifier);
198
- array[identifier] = {};
199
- while (match(token_js_1.TokenType.AttributeName)) {
198
+ array[identifier] = true;
199
+ if (match(token_js_1.TokenType.AttributeName)) {
200
200
  hasAttributes = true;
201
- const { value: attributeName } = consume(token_js_1.TokenType.AttributeName);
202
- if (match(token_js_1.TokenType.LeftParens)) {
203
- consume(token_js_1.TokenType.LeftParens);
204
- consume(token_js_1.TokenType.RightParens);
205
- }
206
- else {
207
- array[identifier][attributeName] = true;
208
- }
201
+ }
202
+ while (match(token_js_1.TokenType.AttributeName)) {
203
+ array[identifier] = {};
204
+ const { value: attributeName } = consume(token_js_1.TokenType.AttributeName, allowedAttributes);
205
+ cb(attributeName, array, identifier);
209
206
  }
210
207
  }
211
208
  consume(token_js_1.TokenType.RightBracket);
@@ -679,6 +676,10 @@ const parse = (tokens) => {
679
676
  const { value: keyword } = consume(token_js_1.TokenType.Keyword, lexer.COLLECTION_KEYWORDS);
680
677
  try {
681
678
  switch (keyword) {
679
+ case 'middlewares': {
680
+ node.middlewares = parseArrayBlock().value;
681
+ break;
682
+ }
682
683
  case 'owned': {
683
684
  if (match(token_js_1.TokenType.Boolean)) {
684
685
  node.owned = consume(token_js_1.TokenType.Boolean).value;
@@ -710,7 +711,16 @@ const parse = (tokens) => {
710
711
  break;
711
712
  }
712
713
  case 'required': {
713
- node.required = parseArrayBlockWithAttributes();
714
+ node.required = parseArrayBlockWithAttributes(['if'], (attributeName, array, identifier) => {
715
+ switch (attributeName) {
716
+ case 'if': {
717
+ const ifTerms = [];
718
+ array[identifier] = parseCondition(ifTerms);
719
+ node[AST.LOCATION_SYMBOL].requiredTerms = ifTerms;
720
+ break;
721
+ }
722
+ }
723
+ });
714
724
  break;
715
725
  }
716
726
  case 'presets': {
@@ -803,7 +813,6 @@ const parse = (tokens) => {
803
813
  if (match(token_js_1.TokenType.MacroName)) {
804
814
  const { value: macroName } = consume(token_js_1.TokenType.MacroName, ['include']);
805
815
  switch (macroName) {
806
- /* eslint-disable-next-line */
807
816
  case 'include': {
808
817
  const { value: functionSetName, location } = consume(token_js_1.TokenType.Identifier);
809
818
  const functionset = ast.functionsets.find((node) => node.name === functionSetName);
@@ -812,6 +821,7 @@ const parse = (tokens) => {
812
821
  }
813
822
  Object.assign(functions, functionset.functions);
814
823
  consume(token_js_1.TokenType.RightParens);
824
+ break;
815
825
  }
816
826
  }
817
827
  continue;
@@ -1223,7 +1233,7 @@ const parse = (tokens) => {
1223
1233
  operator = 'lt';
1224
1234
  break;
1225
1235
  default: {
1226
- throw new diagnostic_js_1.Diagnostic(`unsuported operator: "${operatorSymbol}"`, location);
1236
+ throw new diagnostic_js_1.Diagnostic(`unsupported operator: "${operatorSymbol}"`, location);
1227
1237
  }
1228
1238
  }
1229
1239
  return {
package/dist/parser.mjs CHANGED
@@ -151,22 +151,20 @@ export const parse = (tokens) => {
151
151
  symbols
152
152
  };
153
153
  };
154
- const parseArrayBlockWithAttributes = () => {
154
+ const parseArrayBlockWithAttributes = (allowedAttributes, cb) => {
155
155
  const array = {};
156
156
  let hasAttributes = false;
157
157
  consume(TokenType.LeftBracket);
158
158
  while (!match(TokenType.RightBracket)) {
159
159
  const { value: identifier } = consume(TokenType.Identifier);
160
- array[identifier] = {};
161
- while (match(TokenType.AttributeName)) {
160
+ array[identifier] = true;
161
+ if (match(TokenType.AttributeName)) {
162
162
  hasAttributes = true;
163
- const { value: attributeName } = consume(TokenType.AttributeName);
164
- if (match(TokenType.LeftParens)) {
165
- consume(TokenType.LeftParens);
166
- consume(TokenType.RightParens);
167
- } else {
168
- array[identifier][attributeName] = true;
169
- }
163
+ }
164
+ while (match(TokenType.AttributeName)) {
165
+ array[identifier] = {};
166
+ const { value: attributeName } = consume(TokenType.AttributeName, allowedAttributes);
167
+ cb(attributeName, array, identifier);
170
168
  }
171
169
  }
172
170
  consume(TokenType.RightBracket);
@@ -625,6 +623,10 @@ export const parse = (tokens) => {
625
623
  const { value: keyword } = consume(TokenType.Keyword, lexer.COLLECTION_KEYWORDS);
626
624
  try {
627
625
  switch (keyword) {
626
+ case "middlewares": {
627
+ node.middlewares = parseArrayBlock().value;
628
+ break;
629
+ }
628
630
  case "owned": {
629
631
  if (match(TokenType.Boolean)) {
630
632
  node.owned = consume(TokenType.Boolean).value;
@@ -655,7 +657,16 @@ export const parse = (tokens) => {
655
657
  break;
656
658
  }
657
659
  case "required": {
658
- node.required = parseArrayBlockWithAttributes();
660
+ node.required = parseArrayBlockWithAttributes(["if"], (attributeName, array, identifier) => {
661
+ switch (attributeName) {
662
+ case "if": {
663
+ const ifTerms = [];
664
+ array[identifier] = parseCondition(ifTerms);
665
+ node[AST.LOCATION_SYMBOL].requiredTerms = ifTerms;
666
+ break;
667
+ }
668
+ }
669
+ });
659
670
  break;
660
671
  }
661
672
  case "presets": {
@@ -755,6 +766,7 @@ export const parse = (tokens) => {
755
766
  }
756
767
  Object.assign(functions, functionset.functions);
757
768
  consume(TokenType.RightParens);
769
+ break;
758
770
  }
759
771
  }
760
772
  continue;
@@ -1159,7 +1171,7 @@ export const parse = (tokens) => {
1159
1171
  operator = "lt";
1160
1172
  break;
1161
1173
  default: {
1162
- throw new Diagnostic(`unsuported operator: "${operatorSymbol}"`, location);
1174
+ throw new Diagnostic(`unsupported operator: "${operatorSymbol}"`, location);
1163
1175
  }
1164
1176
  }
1165
1177
  return {
package/dist/semantic.js CHANGED
@@ -140,6 +140,14 @@ const analyze = async (ast, options, errors = []) => {
140
140
  const subNode = node.properties[propName];
141
141
  await recurseProperty(subNode);
142
142
  }
143
+ if (node[AST.LOCATION_SYMBOL].requiredTerms) {
144
+ for (const [name, symbol] of node[AST.LOCATION_SYMBOL].requiredTerms) {
145
+ if (!(name in node.properties)) {
146
+ const location = parser_js_1.locationMap.get(symbol);
147
+ errors.push(new diagnostic_js_1.Diagnostic(`invalid left operand "${name}"`, location));
148
+ }
149
+ }
150
+ }
143
151
  if (node.layout) {
144
152
  if (node.layout.options) {
145
153
  for (const [name, value] of Object.entries(node.layout[AST.LOCATION_SYMBOL].options)) {
package/dist/semantic.mjs CHANGED
@@ -103,6 +103,14 @@ export const analyze = async (ast, options, errors = []) => {
103
103
  const subNode = node.properties[propName];
104
104
  await recurseProperty(subNode);
105
105
  }
106
+ if (node[AST.LOCATION_SYMBOL].requiredTerms) {
107
+ for (const [name, symbol] of node[AST.LOCATION_SYMBOL].requiredTerms) {
108
+ if (!(name in node.properties)) {
109
+ const location = locationMap.get(symbol);
110
+ errors.push(new Diagnostic(`invalid left operand "${name}"`, location));
111
+ }
112
+ }
113
+ }
106
114
  if (node.layout) {
107
115
  if (node.layout.options) {
108
116
  for (const [name, value] of Object.entries(node.layout[AST.LOCATION_SYMBOL].options)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeriajs/compiler",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -21,8 +21,8 @@
21
21
  "dist"
22
22
  ],
23
23
  "peerDependencies": {
24
- "@aeriajs/common": "^0.0.142",
25
- "@aeriajs/types": "^0.0.124"
24
+ "@aeriajs/common": "^0.0.143",
25
+ "@aeriajs/types": "^0.0.125"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@aeriajs/common": "link:../common",