@aeriajs/compiler 0.0.10 → 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.
@@ -31,8 +31,9 @@ const makeJSContractsCode = (contractAst) => {
31
31
  };
32
32
  const declarations = contractAst.map((contractNode) => {
33
33
  const { name, kind, roles, response, ...contractProperty } = contractNode;
34
- let responseString = '';
34
+ let responseString;
35
35
  if (response) {
36
+ responseString = '';
36
37
  if (Array.isArray(response)) {
37
38
  const responseArray = [];
38
39
  for (const responseElement of response) {
@@ -47,10 +48,15 @@ const makeJSContractsCode = (contractAst) => {
47
48
  }
48
49
  }
49
50
  const contractSchema = (0, utils_js_1.getProperties)(contractProperty);
50
- contractSchema.response = {
51
- [utils_js_1.UnquotedSymbol]: responseString,
52
- };
53
- return `export const ${name}Contract = defineContract(${(0, utils_js_1.stringify)(contractSchema)})`;
51
+ if (responseString) {
52
+ contractSchema.response = {
53
+ [utils_js_1.UnquotedSymbol]: responseString,
54
+ };
55
+ }
56
+ if (roles) {
57
+ contractSchema.roles = roles;
58
+ }
59
+ return `export const ${name} = defineContract(${(0, utils_js_1.stringify)(contractSchema)})`;
54
60
  }).join('\n\n');
55
61
  return `import { ${Array.from(imports).join(', ')} } from \'aeria\'\n\n` + declarations;
56
62
  };
@@ -76,9 +82,12 @@ const makeTSContractsCode = (contractAst) => {
76
82
  }
77
83
  }
78
84
  const contractProperties = (0, utils_js_1.getProperties)(contractSchema);
79
- return `export declare const ${contractNode.name}Contract: ${(0, utils_js_1.stringify)({
80
- ...contractProperties,
81
- response: responseSchema,
82
- })}`;
85
+ if (responseSchema) {
86
+ contractProperties.response = responseSchema;
87
+ }
88
+ if (roles) {
89
+ contractProperties.roles = roles;
90
+ }
91
+ return `export declare const ${contractNode.name}: ${(0, utils_js_1.stringify)(contractProperties)}`;
83
92
  }).join('\n\n');
84
93
  };
@@ -26,8 +26,9 @@ const makeJSContractsCode = (contractAst) => {
26
26
  };
27
27
  const declarations = contractAst.map((contractNode) => {
28
28
  const { name, kind, roles, response, ...contractProperty } = contractNode;
29
- let responseString = "";
29
+ let responseString;
30
30
  if (response) {
31
+ responseString = "";
31
32
  if (Array.isArray(response)) {
32
33
  const responseArray = [];
33
34
  for (const responseElement of response) {
@@ -41,10 +42,15 @@ const makeJSContractsCode = (contractAst) => {
41
42
  }
42
43
  }
43
44
  const contractSchema = getProperties(contractProperty);
44
- contractSchema.response = {
45
- [UnquotedSymbol]: responseString
46
- };
47
- return `export const ${name}Contract = defineContract(${stringify(contractSchema)})`;
45
+ if (responseString) {
46
+ contractSchema.response = {
47
+ [UnquotedSymbol]: responseString
48
+ };
49
+ }
50
+ if (roles) {
51
+ contractSchema.roles = roles;
52
+ }
53
+ return `export const ${name} = defineContract(${stringify(contractSchema)})`;
48
54
  }).join("\n\n");
49
55
  return `import { ${Array.from(imports).join(", ")} } from 'aeria'
50
56
 
@@ -69,9 +75,12 @@ const makeTSContractsCode = (contractAst) => {
69
75
  }
70
76
  }
71
77
  const contractProperties = getProperties(contractSchema);
72
- return `export declare const ${contractNode.name}Contract: ${stringify({
73
- ...contractProperties,
74
- response: responseSchema
75
- })}`;
78
+ if (responseSchema) {
79
+ contractProperties.response = responseSchema;
80
+ }
81
+ if (roles) {
82
+ contractProperties.roles = roles;
83
+ }
84
+ return `export declare const ${contractNode.name}: ${stringify(contractProperties)}`;
76
85
  }).join("\n\n");
77
86
  };
@@ -13,7 +13,7 @@ export declare const makeASTImports: (ast: AST.Node[], initialImports?: Record<s
13
13
  code: string[];
14
14
  modifiedSymbols: Record<string, string>;
15
15
  };
16
- export declare const propertyToSchema: (propertyNode: AST.PropertyNode) => Property;
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
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;
19
19
  export declare const UnquotedSymbol: unique symbol;
@@ -14,8 +14,7 @@ exports.DEFAULT_FUNCTIONS = [
14
14
  ];
15
15
  exports.ArraySymbol = Symbol('array');
16
16
  const getExposedFunctions = (astFunctions) => {
17
- return Object.fromEntries(Object.entries(astFunctions)
18
- .map(([key, value]) => [
17
+ return Object.fromEntries(Object.entries(astFunctions).map(([key, value]) => [
19
18
  key,
20
19
  value.accessCondition,
21
20
  ]));
@@ -56,22 +55,22 @@ const makeASTImports = (ast, initialImports) => {
56
55
  };
57
56
  };
58
57
  exports.makeASTImports = makeASTImports;
59
- const propertyToSchema = (propertyNode) => {
60
- const propertySchema = propertyNode.property;
58
+ const propertyToSchema = ({ property, nestedProperties }) => {
59
+ const propertySchema = property;
61
60
  if ('$ref' in propertySchema) {
62
61
  propertySchema.$ref = (0, exports.getCollectionId)(propertySchema.$ref);
63
62
  }
64
63
  else if ('items' in propertySchema && '$ref' in propertySchema.items) {
65
64
  propertySchema.items.$ref = (0, exports.getCollectionId)(propertySchema.items.$ref);
66
65
  }
67
- if (propertyNode.nestedProperties && 'type' in propertySchema) {
66
+ if (nestedProperties && 'type' in propertySchema) {
68
67
  if (propertySchema.type === 'object' && 'properties' in propertySchema) {
69
- propertySchema.properties = (0, exports.getProperties)(propertyNode.nestedProperties);
68
+ propertySchema.properties = (0, exports.getProperties)(nestedProperties);
70
69
  }
71
70
  else if (propertySchema.type === 'array') {
72
71
  propertySchema.items = {
73
72
  type: 'object',
74
- properties: (0, exports.getProperties)(propertyNode.nestedProperties),
73
+ properties: (0, exports.getProperties)(nestedProperties),
75
74
  };
76
75
  }
77
76
  }
@@ -48,20 +48,20 @@ export const makeASTImports = (ast, initialImports) => {
48
48
  modifiedSymbols
49
49
  };
50
50
  };
51
- export const propertyToSchema = (propertyNode) => {
52
- const propertySchema = propertyNode.property;
51
+ export const propertyToSchema = ({ property, nestedProperties }) => {
52
+ const propertySchema = property;
53
53
  if ("$ref" in propertySchema) {
54
54
  propertySchema.$ref = getCollectionId(propertySchema.$ref);
55
55
  } else if ("items" in propertySchema && "$ref" in propertySchema.items) {
56
56
  propertySchema.items.$ref = getCollectionId(propertySchema.items.$ref);
57
57
  }
58
- if (propertyNode.nestedProperties && "type" in propertySchema) {
58
+ if (nestedProperties && "type" in propertySchema) {
59
59
  if (propertySchema.type === "object" && "properties" in propertySchema) {
60
- propertySchema.properties = getProperties(propertyNode.nestedProperties);
60
+ propertySchema.properties = getProperties(nestedProperties);
61
61
  } else if (propertySchema.type === "array") {
62
62
  propertySchema.items = {
63
63
  type: "object",
64
- properties: getProperties(propertyNode.nestedProperties)
64
+ properties: getProperties(nestedProperties)
65
65
  };
66
66
  }
67
67
  }
package/dist/compile.js CHANGED
@@ -99,7 +99,7 @@ const compileFromFiles = async (schemaDir, options) => {
99
99
  });
100
100
  }
101
101
  const result = await (0, exports.parseAndCheck)(sources, options);
102
- if (!result.ast) {
102
+ if (!result.ast || result.errorCount > 0) {
103
103
  return result;
104
104
  }
105
105
  const emittedFiles = await (0, codegen_js_1.generateCode)(result.ast, options);
package/dist/compile.mjs CHANGED
@@ -59,7 +59,7 @@ export const compileFromFiles = async (schemaDir, options) => {
59
59
  });
60
60
  }
61
61
  const result = await parseAndCheck(sources, options);
62
- if (!result.ast) {
62
+ if (!result.ast || result.errorCount > 0) {
63
63
  return result;
64
64
  }
65
65
  const emittedFiles = await generateCode(result.ast, options);
package/dist/lexer.d.ts CHANGED
@@ -4,7 +4,7 @@ export type Keyword = typeof COLLECTION_KEYWORDS[number] | typeof COLLECTION_ACT
4
4
  export declare const COLLECTION_KEYWORDS: readonly ["actions", "filters", "form", "functions", "icon", "indexes", "individualActions", "owned", "presets", "properties", "required", "search", "table"];
5
5
  export declare const COLLECTION_ACTIONS_KEYWORDS: readonly ["ask", "button", "clearItem", "effect", "event", "fetchItem", "function", "icon", "label", "params", "query", "requires", "roles", "route", "selection", "setItem", "translate"];
6
6
  export declare const COLLECTION_SEARCH_KEYWORDS: readonly ["indexes", "placeholder", "exactMatches"];
7
- export declare const CONTRACT_KEYWORDS: readonly ["payload", "query", "response"];
7
+ export declare const CONTRACT_KEYWORDS: readonly ["roles", "payload", "query", "response"];
8
8
  export declare const TOPLEVEL_KEYWORDS: readonly ["collection", "contract", "functionset"];
9
9
  export declare const MISC_KEYWORDS: readonly ["extends"];
10
10
  export declare const KEYWORDS: Keyword[];
package/dist/lexer.js CHANGED
@@ -43,6 +43,7 @@ exports.COLLECTION_SEARCH_KEYWORDS = [
43
43
  'exactMatches',
44
44
  ];
45
45
  exports.CONTRACT_KEYWORDS = [
46
+ 'roles',
46
47
  'payload',
47
48
  'query',
48
49
  'response',
package/dist/lexer.mjs CHANGED
@@ -41,6 +41,7 @@ export const COLLECTION_SEARCH_KEYWORDS = [
41
41
  "exactMatches"
42
42
  ];
43
43
  export const CONTRACT_KEYWORDS = [
44
+ "roles",
44
45
  "payload",
45
46
  "query",
46
47
  "response"
package/dist/parser.d.ts CHANGED
@@ -2,6 +2,9 @@ import { type Token, type Location } from './token.js';
2
2
  import { Diagnostic } from './diagnostic.js';
3
3
  import * as AST from './ast.js';
4
4
  export declare const locationMap: WeakMap<symbol, Location>;
5
+ export declare const memoTable: {
6
+ roles?: string[];
7
+ };
5
8
  export declare const parse: (tokens: (Token | undefined)[]) => {
6
9
  ast: AST.ProgramNode;
7
10
  errors: Diagnostic[];
package/dist/parser.js CHANGED
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.parse = exports.locationMap = void 0;
36
+ exports.parse = exports.memoTable = exports.locationMap = void 0;
37
37
  const token_js_1 = require("./token.js");
38
38
  const types_1 = require("@aeriajs/types");
39
39
  const core_1 = require("@phosphor-icons/core");
@@ -44,9 +44,22 @@ const lexer = __importStar(require("./lexer.js"));
44
44
  const MAX_ERROR_MESSAGE_ITEMS = 20;
45
45
  const ICON_NAMES = core_1.icons.map((icon) => icon.name);
46
46
  exports.locationMap = new WeakMap();
47
+ exports.memoTable = {};
47
48
  const isFileProperty = (property) => {
48
49
  return property.$ref === 'File';
49
50
  };
51
+ const checkForValidRoles = (roles, symbols) => {
52
+ if (exports.memoTable.roles) {
53
+ for (const [i, role] of roles.entries()) {
54
+ const symbol = symbols[i];
55
+ if (!exports.memoTable.roles.includes(role)) {
56
+ const location = exports.locationMap.get(symbol);
57
+ throw new diagnostic_js_1.Diagnostic(`invalid role "${role}"`, location);
58
+ }
59
+ }
60
+ }
61
+ return roles;
62
+ };
50
63
  const parse = (tokens) => {
51
64
  let index = 0;
52
65
  const ast = {
@@ -126,18 +139,35 @@ const parse = (tokens) => {
126
139
  }
127
140
  }
128
141
  };
129
- const parseArray = (type) => {
130
- consume(token_js_1.TokenType.LeftSquareBracket);
142
+ const parseArray = (types) => {
143
+ const { location: openingLocation } = consume(token_js_1.TokenType.LeftSquareBracket);
131
144
  const array = [];
145
+ const symbols = [];
146
+ let type;
147
+ for (const typeCandidate of types) {
148
+ if (match(typeCandidate)) {
149
+ type = typeCandidate;
150
+ break;
151
+ }
152
+ }
153
+ if (!type) {
154
+ throw new diagnostic_js_1.Diagnostic(`array got an invalid type, accepted ones are: ${types.join(' | ')}`, openingLocation);
155
+ }
132
156
  while (!match(token_js_1.TokenType.RightSquareBracket)) {
133
- const { value } = consume(type);
157
+ const { value, location } = consume(type);
158
+ const elemSymbol = Symbol();
134
159
  array.push(value);
160
+ symbols.push(elemSymbol);
161
+ exports.locationMap.set(elemSymbol, location);
135
162
  if (match(token_js_1.TokenType.Comma)) {
136
163
  consume(token_js_1.TokenType.Comma);
137
164
  }
138
165
  }
139
166
  consume(token_js_1.TokenType.RightSquareBracket);
140
- return array;
167
+ return {
168
+ value: array,
169
+ symbols,
170
+ };
141
171
  };
142
172
  const parseArrayBlock = (value) => {
143
173
  const array = [];
@@ -189,7 +219,10 @@ const parse = (tokens) => {
189
219
  return true;
190
220
  };
191
221
  if ('enum' in property && attributeName === 'values') {
192
- property.enum = parseArray(token_js_1.TokenType.QuotedString);
222
+ property.enum = parseArray([
223
+ token_js_1.TokenType.QuotedString,
224
+ token_js_1.TokenType.Number,
225
+ ]).value;
193
226
  return;
194
227
  }
195
228
  switch (attributeName) {
@@ -216,7 +249,7 @@ const parse = (tokens) => {
216
249
  case 'form':
217
250
  case 'populate':
218
251
  case 'indexes': {
219
- property[attributeName] = parseArray(token_js_1.TokenType.Identifier);
252
+ property[attributeName] = parseArray([token_js_1.TokenType.Identifier]).value;
220
253
  return;
221
254
  }
222
255
  case 'populateDepth': {
@@ -229,7 +262,7 @@ const parse = (tokens) => {
229
262
  switch (attributeName) {
230
263
  case 'extensions':
231
264
  case 'accept': {
232
- property[attributeName] = parseArray(token_js_1.TokenType.QuotedString);
265
+ property[attributeName] = parseArray([token_js_1.TokenType.QuotedString]).value;
233
266
  return;
234
267
  }
235
268
  }
@@ -246,7 +279,7 @@ const parse = (tokens) => {
246
279
  }
247
280
  case 'mask': {
248
281
  if (match(token_js_1.TokenType.LeftSquareBracket)) {
249
- property[attributeName] = parseArray(token_js_1.TokenType.QuotedString);
282
+ property[attributeName] = parseArray([token_js_1.TokenType.QuotedString]).value;
250
283
  return;
251
284
  }
252
285
  else {
@@ -584,15 +617,15 @@ const parse = (tokens) => {
584
617
  }
585
618
  case 'icon': {
586
619
  const { value } = consume(token_js_1.TokenType.QuotedString, ICON_NAMES);
587
- node.icon = value;
620
+ node[keyword] = value;
588
621
  break;
589
622
  }
590
623
  case 'properties': {
591
- node.properties = parsePropertiesBlock();
624
+ node[keyword] = parsePropertiesBlock();
592
625
  break;
593
626
  }
594
627
  case 'functions': {
595
- node.functions = parseFunctionsBlock(ast);
628
+ node[keyword] = parseFunctionsBlock(ast);
596
629
  break;
597
630
  }
598
631
  case 'individualActions':
@@ -647,6 +680,26 @@ const parse = (tokens) => {
647
680
  while (!match(token_js_1.TokenType.RightBracket)) {
648
681
  const { value: keyword } = consume(token_js_1.TokenType.Keyword, lexer.CONTRACT_KEYWORDS);
649
682
  switch (keyword) {
683
+ case 'roles': {
684
+ if (match(token_js_1.TokenType.Boolean)) {
685
+ const { value: boolean } = consume(token_js_1.TokenType.Boolean);
686
+ node.roles = boolean;
687
+ }
688
+ else if (match(token_js_1.TokenType.QuotedString, 'unauthenticated')) {
689
+ consume(token_js_1.TokenType.QuotedString);
690
+ node.roles = 'unauthenticated';
691
+ }
692
+ else if (match(token_js_1.TokenType.QuotedString, 'unauthenticated-only')) {
693
+ consume(token_js_1.TokenType.QuotedString);
694
+ node.roles = 'unauthenticated-only';
695
+ }
696
+ else {
697
+ const { value, symbols } = parseArrayBlock();
698
+ const roles = checkForValidRoles(value, symbols);
699
+ node.roles = roles;
700
+ }
701
+ break;
702
+ }
650
703
  case 'payload': {
651
704
  node.payload = parsePropertyType({
652
705
  allowModifiers: true,
@@ -716,9 +769,10 @@ const parse = (tokens) => {
716
769
  };
717
770
  }
718
771
  else {
719
- const value = parseArray(token_js_1.TokenType.QuotedString);
772
+ const { value, symbols } = parseArray([token_js_1.TokenType.QuotedString]);
773
+ const roles = checkForValidRoles(value, symbols);
720
774
  functions[functionName] = {
721
- accessCondition: value,
775
+ accessCondition: roles,
722
776
  };
723
777
  }
724
778
  consume(token_js_1.TokenType.RightParens);
@@ -780,9 +834,14 @@ const parse = (tokens) => {
780
834
  baseSlots[keyword] = value;
781
835
  break;
782
836
  }
783
- case 'roles':
837
+ case 'roles': {
838
+ const { value, symbols } = parseArray([token_js_1.TokenType.Identifier]);
839
+ const roles = checkForValidRoles(value, symbols);
840
+ baseSlots[keyword] = roles;
841
+ break;
842
+ }
784
843
  case 'requires': {
785
- const value = parseArray(token_js_1.TokenType.Identifier);
844
+ const { value } = parseArray([token_js_1.TokenType.Identifier]);
786
845
  baseSlots[keyword] = value;
787
846
  break;
788
847
  }
@@ -875,7 +934,14 @@ const parse = (tokens) => {
875
934
  try {
876
935
  switch (declType) {
877
936
  case 'collection': {
878
- ast.collections.push(parseCollection(ast));
937
+ const collection = parseCollection(ast);
938
+ if (collection.name === 'User') {
939
+ const { properties } = collection;
940
+ if ('roles' in properties && 'items' in properties.roles.property && 'enum' in properties.roles.property.items) {
941
+ exports.memoTable.roles = properties.roles.property.items.enum;
942
+ }
943
+ }
944
+ ast.collections.push(collection);
879
945
  break;
880
946
  }
881
947
  case 'contract': {
package/dist/parser.mjs CHANGED
@@ -9,9 +9,22 @@ import * as lexer from "./lexer.mjs";
9
9
  const MAX_ERROR_MESSAGE_ITEMS = 20;
10
10
  const ICON_NAMES = icons.map((icon) => icon.name);
11
11
  export const locationMap = /* @__PURE__ */ new WeakMap();
12
+ export const memoTable = {};
12
13
  const isFileProperty = (property) => {
13
14
  return property.$ref === "File";
14
15
  };
16
+ const checkForValidRoles = (roles, symbols) => {
17
+ if (memoTable.roles) {
18
+ for (const [i, role] of roles.entries()) {
19
+ const symbol = symbols[i];
20
+ if (!memoTable.roles.includes(role)) {
21
+ const location = locationMap.get(symbol);
22
+ throw new Diagnostic(`invalid role "${role}"`, location);
23
+ }
24
+ }
25
+ }
26
+ return roles;
27
+ };
15
28
  export const parse = (tokens) => {
16
29
  let index = 0;
17
30
  const ast = {
@@ -88,18 +101,35 @@ export const parse = (tokens) => {
88
101
  }
89
102
  }
90
103
  };
91
- const parseArray = (type) => {
92
- consume(TokenType.LeftSquareBracket);
104
+ const parseArray = (types) => {
105
+ const { location: openingLocation } = consume(TokenType.LeftSquareBracket);
93
106
  const array = [];
107
+ const symbols = [];
108
+ let type;
109
+ for (const typeCandidate of types) {
110
+ if (match(typeCandidate)) {
111
+ type = typeCandidate;
112
+ break;
113
+ }
114
+ }
115
+ if (!type) {
116
+ throw new Diagnostic(`array got an invalid type, accepted ones are: ${types.join(" | ")}`, openingLocation);
117
+ }
94
118
  while (!match(TokenType.RightSquareBracket)) {
95
- const { value } = consume(type);
119
+ const { value, location } = consume(type);
120
+ const elemSymbol = Symbol();
96
121
  array.push(value);
122
+ symbols.push(elemSymbol);
123
+ locationMap.set(elemSymbol, location);
97
124
  if (match(TokenType.Comma)) {
98
125
  consume(TokenType.Comma);
99
126
  }
100
127
  }
101
128
  consume(TokenType.RightSquareBracket);
102
- return array;
129
+ return {
130
+ value: array,
131
+ symbols
132
+ };
103
133
  };
104
134
  const parseArrayBlock = (value) => {
105
135
  const array = [];
@@ -148,7 +178,10 @@ export const parse = (tokens) => {
148
178
  return true;
149
179
  };
150
180
  if ("enum" in property && attributeName === "values") {
151
- property.enum = parseArray(TokenType.QuotedString);
181
+ property.enum = parseArray([
182
+ TokenType.QuotedString,
183
+ TokenType.Number
184
+ ]).value;
152
185
  return;
153
186
  }
154
187
  switch (attributeName) {
@@ -175,7 +208,7 @@ export const parse = (tokens) => {
175
208
  case "form":
176
209
  case "populate":
177
210
  case "indexes": {
178
- property[attributeName] = parseArray(TokenType.Identifier);
211
+ property[attributeName] = parseArray([TokenType.Identifier]).value;
179
212
  return;
180
213
  }
181
214
  case "populateDepth": {
@@ -188,7 +221,7 @@ export const parse = (tokens) => {
188
221
  switch (attributeName) {
189
222
  case "extensions":
190
223
  case "accept": {
191
- property[attributeName] = parseArray(TokenType.QuotedString);
224
+ property[attributeName] = parseArray([TokenType.QuotedString]).value;
192
225
  return;
193
226
  }
194
227
  }
@@ -205,7 +238,7 @@ export const parse = (tokens) => {
205
238
  }
206
239
  case "mask": {
207
240
  if (match(TokenType.LeftSquareBracket)) {
208
- property[attributeName] = parseArray(TokenType.QuotedString);
241
+ property[attributeName] = parseArray([TokenType.QuotedString]).value;
209
242
  return;
210
243
  } else {
211
244
  const { value } = consume(TokenType.QuotedString);
@@ -535,15 +568,15 @@ export const parse = (tokens) => {
535
568
  }
536
569
  case "icon": {
537
570
  const { value } = consume(TokenType.QuotedString, ICON_NAMES);
538
- node.icon = value;
571
+ node[keyword] = value;
539
572
  break;
540
573
  }
541
574
  case "properties": {
542
- node.properties = parsePropertiesBlock();
575
+ node[keyword] = parsePropertiesBlock();
543
576
  break;
544
577
  }
545
578
  case "functions": {
546
- node.functions = parseFunctionsBlock(ast2);
579
+ node[keyword] = parseFunctionsBlock(ast2);
547
580
  break;
548
581
  }
549
582
  case "individualActions":
@@ -597,6 +630,23 @@ export const parse = (tokens) => {
597
630
  while (!match(TokenType.RightBracket)) {
598
631
  const { value: keyword } = consume(TokenType.Keyword, lexer.CONTRACT_KEYWORDS);
599
632
  switch (keyword) {
633
+ case "roles": {
634
+ if (match(TokenType.Boolean)) {
635
+ const { value: boolean } = consume(TokenType.Boolean);
636
+ node.roles = boolean;
637
+ } else if (match(TokenType.QuotedString, "unauthenticated")) {
638
+ consume(TokenType.QuotedString);
639
+ node.roles = "unauthenticated";
640
+ } else if (match(TokenType.QuotedString, "unauthenticated-only")) {
641
+ consume(TokenType.QuotedString);
642
+ node.roles = "unauthenticated-only";
643
+ } else {
644
+ const { value, symbols } = parseArrayBlock();
645
+ const roles = checkForValidRoles(value, symbols);
646
+ node.roles = roles;
647
+ }
648
+ break;
649
+ }
600
650
  case "payload": {
601
651
  node.payload = parsePropertyType({
602
652
  allowModifiers: true
@@ -664,9 +714,10 @@ export const parse = (tokens) => {
664
714
  accessCondition: value
665
715
  };
666
716
  } else {
667
- const value = parseArray(TokenType.QuotedString);
717
+ const { value, symbols } = parseArray([TokenType.QuotedString]);
718
+ const roles = checkForValidRoles(value, symbols);
668
719
  functions[functionName] = {
669
- accessCondition: value
720
+ accessCondition: roles
670
721
  };
671
722
  }
672
723
  consume(TokenType.RightParens);
@@ -727,9 +778,14 @@ export const parse = (tokens) => {
727
778
  baseSlots[keyword] = value;
728
779
  break;
729
780
  }
730
- case "roles":
781
+ case "roles": {
782
+ const { value, symbols } = parseArray([TokenType.Identifier]);
783
+ const roles = checkForValidRoles(value, symbols);
784
+ baseSlots[keyword] = roles;
785
+ break;
786
+ }
731
787
  case "requires": {
732
- const value = parseArray(TokenType.Identifier);
788
+ const { value } = parseArray([TokenType.Identifier]);
733
789
  baseSlots[keyword] = value;
734
790
  break;
735
791
  }
@@ -821,7 +877,14 @@ export const parse = (tokens) => {
821
877
  try {
822
878
  switch (declType) {
823
879
  case "collection": {
824
- ast.collections.push(parseCollection(ast));
880
+ const collection = parseCollection(ast);
881
+ if (collection.name === "User") {
882
+ const { properties } = collection;
883
+ if ("roles" in properties && "items" in properties.roles.property && "enum" in properties.roles.property.items) {
884
+ memoTable.roles = properties.roles.property.items.enum;
885
+ }
886
+ }
887
+ ast.collections.push(collection);
825
888
  break;
826
889
  }
827
890
  case "contract": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeriajs/compiler",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",