@aeriajs/compiler 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.
@@ -53,6 +53,9 @@ const makeJSContractsCode = (contractAst) => {
53
53
  [utils_js_1.UnquotedSymbol]: responseString,
54
54
  };
55
55
  }
56
+ if (roles) {
57
+ contractSchema.roles = roles;
58
+ }
56
59
  return `export const ${name} = defineContract(${(0, utils_js_1.stringify)(contractSchema)})`;
57
60
  }).join('\n\n');
58
61
  return `import { ${Array.from(imports).join(', ')} } from \'aeria\'\n\n` + declarations;
@@ -79,11 +82,12 @@ const makeTSContractsCode = (contractAst) => {
79
82
  }
80
83
  }
81
84
  const contractProperties = (0, utils_js_1.getProperties)(contractSchema);
82
- return `export declare const ${contractNode.name}: ${(0, utils_js_1.stringify)({
83
- ...contractProperties,
84
- ...(responseSchema && {
85
- response: responseSchema,
86
- }),
87
- })}`;
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)}`;
88
92
  }).join('\n\n');
89
93
  };
@@ -47,6 +47,9 @@ const makeJSContractsCode = (contractAst) => {
47
47
  [UnquotedSymbol]: responseString
48
48
  };
49
49
  }
50
+ if (roles) {
51
+ contractSchema.roles = roles;
52
+ }
50
53
  return `export const ${name} = defineContract(${stringify(contractSchema)})`;
51
54
  }).join("\n\n");
52
55
  return `import { ${Array.from(imports).join(", ")} } from 'aeria'
@@ -72,11 +75,12 @@ const makeTSContractsCode = (contractAst) => {
72
75
  }
73
76
  }
74
77
  const contractProperties = getProperties(contractSchema);
75
- return `export declare const ${contractNode.name}: ${stringify({
76
- ...contractProperties,
77
- ...responseSchema && {
78
- response: responseSchema
79
- }
80
- })}`;
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)}`;
81
85
  }).join("\n\n");
82
86
  };
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 = {
@@ -127,8 +140,9 @@ const parse = (tokens) => {
127
140
  }
128
141
  };
129
142
  const parseArray = (types) => {
130
- const { location } = consume(token_js_1.TokenType.LeftSquareBracket);
143
+ const { location: openingLocation } = consume(token_js_1.TokenType.LeftSquareBracket);
131
144
  const array = [];
145
+ const symbols = [];
132
146
  let type;
133
147
  for (const typeCandidate of types) {
134
148
  if (match(typeCandidate)) {
@@ -137,17 +151,23 @@ const parse = (tokens) => {
137
151
  }
138
152
  }
139
153
  if (!type) {
140
- throw new diagnostic_js_1.Diagnostic(`array got an invalid type, accepted ones are: ${types.join(' | ')}`, location);
154
+ throw new diagnostic_js_1.Diagnostic(`array got an invalid type, accepted ones are: ${types.join(' | ')}`, openingLocation);
141
155
  }
142
156
  while (!match(token_js_1.TokenType.RightSquareBracket)) {
143
- const { value } = consume(type);
157
+ const { value, location } = consume(type);
158
+ const elemSymbol = Symbol();
144
159
  array.push(value);
160
+ symbols.push(elemSymbol);
161
+ exports.locationMap.set(elemSymbol, location);
145
162
  if (match(token_js_1.TokenType.Comma)) {
146
163
  consume(token_js_1.TokenType.Comma);
147
164
  }
148
165
  }
149
166
  consume(token_js_1.TokenType.RightSquareBracket);
150
- return array;
167
+ return {
168
+ value: array,
169
+ symbols,
170
+ };
151
171
  };
152
172
  const parseArrayBlock = (value) => {
153
173
  const array = [];
@@ -202,7 +222,7 @@ const parse = (tokens) => {
202
222
  property.enum = parseArray([
203
223
  token_js_1.TokenType.QuotedString,
204
224
  token_js_1.TokenType.Number,
205
- ]);
225
+ ]).value;
206
226
  return;
207
227
  }
208
228
  switch (attributeName) {
@@ -229,7 +249,7 @@ const parse = (tokens) => {
229
249
  case 'form':
230
250
  case 'populate':
231
251
  case 'indexes': {
232
- property[attributeName] = parseArray([token_js_1.TokenType.Identifier]);
252
+ property[attributeName] = parseArray([token_js_1.TokenType.Identifier]).value;
233
253
  return;
234
254
  }
235
255
  case 'populateDepth': {
@@ -242,7 +262,7 @@ const parse = (tokens) => {
242
262
  switch (attributeName) {
243
263
  case 'extensions':
244
264
  case 'accept': {
245
- property[attributeName] = parseArray([token_js_1.TokenType.QuotedString]);
265
+ property[attributeName] = parseArray([token_js_1.TokenType.QuotedString]).value;
246
266
  return;
247
267
  }
248
268
  }
@@ -259,7 +279,7 @@ const parse = (tokens) => {
259
279
  }
260
280
  case 'mask': {
261
281
  if (match(token_js_1.TokenType.LeftSquareBracket)) {
262
- property[attributeName] = parseArray([token_js_1.TokenType.QuotedString]);
282
+ property[attributeName] = parseArray([token_js_1.TokenType.QuotedString]).value;
263
283
  return;
264
284
  }
265
285
  else {
@@ -597,15 +617,15 @@ const parse = (tokens) => {
597
617
  }
598
618
  case 'icon': {
599
619
  const { value } = consume(token_js_1.TokenType.QuotedString, ICON_NAMES);
600
- node.icon = value;
620
+ node[keyword] = value;
601
621
  break;
602
622
  }
603
623
  case 'properties': {
604
- node.properties = parsePropertiesBlock();
624
+ node[keyword] = parsePropertiesBlock();
605
625
  break;
606
626
  }
607
627
  case 'functions': {
608
- node.functions = parseFunctionsBlock(ast);
628
+ node[keyword] = parseFunctionsBlock(ast);
609
629
  break;
610
630
  }
611
631
  case 'individualActions':
@@ -660,6 +680,26 @@ const parse = (tokens) => {
660
680
  while (!match(token_js_1.TokenType.RightBracket)) {
661
681
  const { value: keyword } = consume(token_js_1.TokenType.Keyword, lexer.CONTRACT_KEYWORDS);
662
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
+ }
663
703
  case 'payload': {
664
704
  node.payload = parsePropertyType({
665
705
  allowModifiers: true,
@@ -729,9 +769,10 @@ const parse = (tokens) => {
729
769
  };
730
770
  }
731
771
  else {
732
- const value = parseArray([token_js_1.TokenType.QuotedString]);
772
+ const { value, symbols } = parseArray([token_js_1.TokenType.QuotedString]);
773
+ const roles = checkForValidRoles(value, symbols);
733
774
  functions[functionName] = {
734
- accessCondition: value,
775
+ accessCondition: roles,
735
776
  };
736
777
  }
737
778
  consume(token_js_1.TokenType.RightParens);
@@ -793,9 +834,14 @@ const parse = (tokens) => {
793
834
  baseSlots[keyword] = value;
794
835
  break;
795
836
  }
796
- 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
+ }
797
843
  case 'requires': {
798
- const value = parseArray([token_js_1.TokenType.Identifier]);
844
+ const { value } = parseArray([token_js_1.TokenType.Identifier]);
799
845
  baseSlots[keyword] = value;
800
846
  break;
801
847
  }
@@ -888,7 +934,14 @@ const parse = (tokens) => {
888
934
  try {
889
935
  switch (declType) {
890
936
  case 'collection': {
891
- 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);
892
945
  break;
893
946
  }
894
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 = {
@@ -89,8 +102,9 @@ export const parse = (tokens) => {
89
102
  }
90
103
  };
91
104
  const parseArray = (types) => {
92
- const { location } = consume(TokenType.LeftSquareBracket);
105
+ const { location: openingLocation } = consume(TokenType.LeftSquareBracket);
93
106
  const array = [];
107
+ const symbols = [];
94
108
  let type;
95
109
  for (const typeCandidate of types) {
96
110
  if (match(typeCandidate)) {
@@ -99,17 +113,23 @@ export const parse = (tokens) => {
99
113
  }
100
114
  }
101
115
  if (!type) {
102
- throw new Diagnostic(`array got an invalid type, accepted ones are: ${types.join(" | ")}`, location);
116
+ throw new Diagnostic(`array got an invalid type, accepted ones are: ${types.join(" | ")}`, openingLocation);
103
117
  }
104
118
  while (!match(TokenType.RightSquareBracket)) {
105
- const { value } = consume(type);
119
+ const { value, location } = consume(type);
120
+ const elemSymbol = Symbol();
106
121
  array.push(value);
122
+ symbols.push(elemSymbol);
123
+ locationMap.set(elemSymbol, location);
107
124
  if (match(TokenType.Comma)) {
108
125
  consume(TokenType.Comma);
109
126
  }
110
127
  }
111
128
  consume(TokenType.RightSquareBracket);
112
- return array;
129
+ return {
130
+ value: array,
131
+ symbols
132
+ };
113
133
  };
114
134
  const parseArrayBlock = (value) => {
115
135
  const array = [];
@@ -161,7 +181,7 @@ export const parse = (tokens) => {
161
181
  property.enum = parseArray([
162
182
  TokenType.QuotedString,
163
183
  TokenType.Number
164
- ]);
184
+ ]).value;
165
185
  return;
166
186
  }
167
187
  switch (attributeName) {
@@ -188,7 +208,7 @@ export const parse = (tokens) => {
188
208
  case "form":
189
209
  case "populate":
190
210
  case "indexes": {
191
- property[attributeName] = parseArray([TokenType.Identifier]);
211
+ property[attributeName] = parseArray([TokenType.Identifier]).value;
192
212
  return;
193
213
  }
194
214
  case "populateDepth": {
@@ -201,7 +221,7 @@ export const parse = (tokens) => {
201
221
  switch (attributeName) {
202
222
  case "extensions":
203
223
  case "accept": {
204
- property[attributeName] = parseArray([TokenType.QuotedString]);
224
+ property[attributeName] = parseArray([TokenType.QuotedString]).value;
205
225
  return;
206
226
  }
207
227
  }
@@ -218,7 +238,7 @@ export const parse = (tokens) => {
218
238
  }
219
239
  case "mask": {
220
240
  if (match(TokenType.LeftSquareBracket)) {
221
- property[attributeName] = parseArray([TokenType.QuotedString]);
241
+ property[attributeName] = parseArray([TokenType.QuotedString]).value;
222
242
  return;
223
243
  } else {
224
244
  const { value } = consume(TokenType.QuotedString);
@@ -548,15 +568,15 @@ export const parse = (tokens) => {
548
568
  }
549
569
  case "icon": {
550
570
  const { value } = consume(TokenType.QuotedString, ICON_NAMES);
551
- node.icon = value;
571
+ node[keyword] = value;
552
572
  break;
553
573
  }
554
574
  case "properties": {
555
- node.properties = parsePropertiesBlock();
575
+ node[keyword] = parsePropertiesBlock();
556
576
  break;
557
577
  }
558
578
  case "functions": {
559
- node.functions = parseFunctionsBlock(ast2);
579
+ node[keyword] = parseFunctionsBlock(ast2);
560
580
  break;
561
581
  }
562
582
  case "individualActions":
@@ -610,6 +630,23 @@ export const parse = (tokens) => {
610
630
  while (!match(TokenType.RightBracket)) {
611
631
  const { value: keyword } = consume(TokenType.Keyword, lexer.CONTRACT_KEYWORDS);
612
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
+ }
613
650
  case "payload": {
614
651
  node.payload = parsePropertyType({
615
652
  allowModifiers: true
@@ -677,9 +714,10 @@ export const parse = (tokens) => {
677
714
  accessCondition: value
678
715
  };
679
716
  } else {
680
- const value = parseArray([TokenType.QuotedString]);
717
+ const { value, symbols } = parseArray([TokenType.QuotedString]);
718
+ const roles = checkForValidRoles(value, symbols);
681
719
  functions[functionName] = {
682
- accessCondition: value
720
+ accessCondition: roles
683
721
  };
684
722
  }
685
723
  consume(TokenType.RightParens);
@@ -740,9 +778,14 @@ export const parse = (tokens) => {
740
778
  baseSlots[keyword] = value;
741
779
  break;
742
780
  }
743
- 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
+ }
744
787
  case "requires": {
745
- const value = parseArray([TokenType.Identifier]);
788
+ const { value } = parseArray([TokenType.Identifier]);
746
789
  baseSlots[keyword] = value;
747
790
  break;
748
791
  }
@@ -834,7 +877,14 @@ export const parse = (tokens) => {
834
877
  try {
835
878
  switch (declType) {
836
879
  case "collection": {
837
- 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);
838
888
  break;
839
889
  }
840
890
  case "contract": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeriajs/compiler",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",