@aeriajs/compiler 0.0.40 → 0.0.42

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
@@ -66,6 +66,7 @@ export type CollectionNode = NodeBase<'collection'> & {
66
66
  functions?: Record<string, {
67
67
  accessCondition: AccessCondition;
68
68
  }>;
69
+ functionSets?: [string, symbol][];
69
70
  required?: RequiredProperties;
70
71
  indexes?: readonly string[];
71
72
  presets?: DescriptionPreset[];
@@ -97,6 +98,7 @@ export type FunctionSetNode = NodeBase<'functionset'> & {
97
98
  accessCondition: AccessCondition;
98
99
  fromFunctionSet?: true;
99
100
  }>;
101
+ functionSets: [string, symbol][];
100
102
  };
101
103
  export type ProgramNode = NodeBase<'program'> & {
102
104
  collections: CollectionNode[];
@@ -1,5 +1,5 @@
1
1
  import type * as AST from '../ast.js';
2
- export declare const generateContracts: (ast: AST.Node[]) => false | {
2
+ export declare const generateContracts: (ast: AST.ProgramNode) => false | {
3
3
  js: string;
4
4
  dts: string;
5
5
  };
@@ -4,17 +4,16 @@ exports.generateContracts = void 0;
4
4
  const types_1 = require("@aeriajs/types");
5
5
  const utils_js_1 = require("./utils.js");
6
6
  const generateContracts = (ast) => {
7
- const contractNodes = ast.filter((node) => node.kind === 'contract');
8
- if (contractNodes.length === 0) {
7
+ if (ast.contracts.length === 0) {
9
8
  return false;
10
9
  }
11
10
  return {
12
- js: makeJSContractsCode(contractNodes),
13
- dts: makeTSContractsCode(contractNodes),
11
+ js: makeJSContractsCode(ast),
12
+ dts: makeTSContractsCode(ast),
14
13
  };
15
14
  };
16
15
  exports.generateContracts = generateContracts;
17
- const makeJSContractsCode = (contractAst) => {
16
+ const makeJSContractsCode = (ast) => {
18
17
  const imports = new Set(['defineContract']);
19
18
  const getCodeForResponse = (responseProperty) => {
20
19
  const { kind, modifier, ...propertyNode } = responseProperty;
@@ -29,8 +28,8 @@ const makeJSContractsCode = (contractAst) => {
29
28
  }
30
29
  return `${modifierSymbol}(${(0, utils_js_1.stringify)((0, utils_js_1.unwrapPropertyNode)(propertyNode))})`;
31
30
  };
32
- const declarations = contractAst.map((contractNode) => {
33
- const { name, kind, roles, response, ...contractProperty } = contractNode;
31
+ const declarations = ast.contracts.map((node) => {
32
+ const { name, kind, roles, response, ...contractProperty } = node;
34
33
  let responseString;
35
34
  if (response) {
36
35
  responseString = '';
@@ -69,9 +68,9 @@ const getResponseSchema = (response) => {
69
68
  (0, types_1.resultSchema)(responseSchema) :
70
69
  (0, types_1.errorSchema)(responseSchema);
71
70
  };
72
- const makeTSContractsCode = (contractAst) => {
73
- return contractAst.map((contractNode) => {
74
- const { name, kind, roles, ...contractSchema } = contractNode;
71
+ const makeTSContractsCode = (ast) => {
72
+ return ast.contracts.map((node) => {
73
+ const { name, kind, roles, ...contractSchema } = node;
75
74
  let responseSchema = null;
76
75
  if (contractSchema.response) {
77
76
  if (Array.isArray(contractSchema.response)) {
@@ -88,6 +87,6 @@ const makeTSContractsCode = (contractAst) => {
88
87
  if (roles) {
89
88
  contractProperties.roles = roles;
90
89
  }
91
- return `export declare const ${contractNode.name}: ${(0, utils_js_1.stringify)(contractProperties)}`;
90
+ return `export declare const ${node.name}: ${(0, utils_js_1.stringify)(contractProperties)}`;
92
91
  }).join('\n\n');
93
92
  };
@@ -2,16 +2,15 @@
2
2
  import { errorSchema, resultSchema } from "@aeriajs/types";
3
3
  import { recursivelyUnwrapPropertyNodes, unwrapPropertyNode, stringify, UnquotedSymbol } from "./utils.mjs";
4
4
  export const generateContracts = (ast) => {
5
- const contractNodes = ast.filter((node) => node.kind === "contract");
6
- if (contractNodes.length === 0) {
5
+ if (ast.contracts.length === 0) {
7
6
  return false;
8
7
  }
9
8
  return {
10
- js: makeJSContractsCode(contractNodes),
11
- dts: makeTSContractsCode(contractNodes)
9
+ js: makeJSContractsCode(ast),
10
+ dts: makeTSContractsCode(ast)
12
11
  };
13
12
  };
14
- const makeJSContractsCode = (contractAst) => {
13
+ const makeJSContractsCode = (ast) => {
15
14
  const imports = /* @__PURE__ */ new Set(["defineContract"]);
16
15
  const getCodeForResponse = (responseProperty) => {
17
16
  const { kind, modifier, ...propertyNode } = responseProperty;
@@ -24,8 +23,8 @@ const makeJSContractsCode = (contractAst) => {
24
23
  }
25
24
  return `${modifierSymbol}(${stringify(unwrapPropertyNode(propertyNode))})`;
26
25
  };
27
- const declarations = contractAst.map((contractNode) => {
28
- const { name, kind, roles, response, ...contractProperty } = contractNode;
26
+ const declarations = ast.contracts.map((node) => {
27
+ const { name, kind, roles, response, ...contractProperty } = node;
29
28
  let responseString;
30
29
  if (response) {
31
30
  responseString = "";
@@ -63,9 +62,9 @@ const getResponseSchema = (response) => {
63
62
  }
64
63
  return response.modifier === "Result" ? resultSchema(responseSchema) : errorSchema(responseSchema);
65
64
  };
66
- const makeTSContractsCode = (contractAst) => {
67
- return contractAst.map((contractNode) => {
68
- const { name, kind, roles, ...contractSchema } = contractNode;
65
+ const makeTSContractsCode = (ast) => {
66
+ return ast.contracts.map((node) => {
67
+ const { name, kind, roles, ...contractSchema } = node;
69
68
  let responseSchema = null;
70
69
  if (contractSchema.response) {
71
70
  if (Array.isArray(contractSchema.response)) {
@@ -81,6 +80,6 @@ const makeTSContractsCode = (contractAst) => {
81
80
  if (roles) {
82
81
  contractProperties.roles = roles;
83
82
  }
84
- return `export declare const ${contractNode.name}: ${stringify(contractProperties)}`;
83
+ return `export declare const ${node.name}: ${stringify(contractProperties)}`;
85
84
  }).join("\n\n");
86
85
  };
@@ -1,2 +1,2 @@
1
1
  import type * as AST from '../ast.js';
2
- export declare const generateJSCollections: (ast: AST.CollectionNode[]) => string;
2
+ export declare const generateJSCollections: (ast: AST.ProgramNode) => string;
@@ -8,7 +8,7 @@ const initialImportedFunctions = [
8
8
  ];
9
9
  const generateJSCollections = (ast) => {
10
10
  let javascriptCode = '';
11
- const importsResult = (0, utils_js_1.makeASTImports)(ast, {
11
+ const importsResult = (0, utils_js_1.makeASTImports)(ast.collections, {
12
12
  [utils_js_1.PACKAGE_NAME]: new Set(initialImportedFunctions),
13
13
  }, {
14
14
  includeRuntimeOnlyImports: true,
@@ -20,14 +20,14 @@ const generateJSCollections = (ast) => {
20
20
  exports.generateJSCollections = generateJSCollections;
21
21
  const makeJSCollections = (ast, modifiedSymbols) => {
22
22
  const collectionCodes = {};
23
- for (const collectionNode of ast) {
23
+ for (const collectionNode of ast.collections) {
24
24
  const id = (0, utils_js_1.getCollectionId)(collectionNode.name); // CollectionName -> collectionName
25
25
  const extendCollectionName = (0, utils_js_1.getExtendName)(collectionNode.name);
26
26
  const collectionDefinition = `export const ${id} = ${collectionNode.extends
27
27
  ? `extendCollection(${id in modifiedSymbols
28
28
  ? modifiedSymbols[id]
29
- : id}, ${makeJSCollectionSchema(collectionNode, id)})`
30
- : `defineCollection(${makeJSCollectionSchema(collectionNode, id)})`}`;
29
+ : id}, ${makeJSCollectionSchema(ast, collectionNode, id)})`
30
+ : `defineCollection(${makeJSCollectionSchema(ast, collectionNode, id)})`}`;
31
31
  const collectionDeclaration = `export const ${extendCollectionName} = (collection) => extendCollection(${id}, collection)`;
32
32
  collectionCodes[collectionNode.name] = [
33
33
  '//' + collectionNode.name,
@@ -37,7 +37,7 @@ const makeJSCollections = (ast, modifiedSymbols) => {
37
37
  }
38
38
  return Object.values(collectionCodes).join('\n\n');
39
39
  };
40
- const makeJSCollectionSchema = (collectionNode, collectionId) => {
40
+ const makeJSCollectionSchema = (ast, collectionNode, collectionId) => {
41
41
  const collectionSchema = {
42
42
  item: {},
43
43
  description: {
@@ -6,7 +6,7 @@ const initialImportedFunctions = [
6
6
  ];
7
7
  export const generateJSCollections = (ast) => {
8
8
  let javascriptCode = "";
9
- const importsResult = makeASTImports(ast, {
9
+ const importsResult = makeASTImports(ast.collections, {
10
10
  [PACKAGE_NAME]: new Set(initialImportedFunctions)
11
11
  }, {
12
12
  includeRuntimeOnlyImports: true
@@ -17,10 +17,10 @@ export const generateJSCollections = (ast) => {
17
17
  };
18
18
  const makeJSCollections = (ast, modifiedSymbols) => {
19
19
  const collectionCodes = {};
20
- for (const collectionNode of ast) {
20
+ for (const collectionNode of ast.collections) {
21
21
  const id = getCollectionId(collectionNode.name);
22
22
  const extendCollectionName = getExtendName(collectionNode.name);
23
- const collectionDefinition = `export const ${id} = ${collectionNode.extends ? `extendCollection(${id in modifiedSymbols ? modifiedSymbols[id] : id}, ${makeJSCollectionSchema(collectionNode, id)})` : `defineCollection(${makeJSCollectionSchema(collectionNode, id)})`}`;
23
+ const collectionDefinition = `export const ${id} = ${collectionNode.extends ? `extendCollection(${id in modifiedSymbols ? modifiedSymbols[id] : id}, ${makeJSCollectionSchema(ast, collectionNode, id)})` : `defineCollection(${makeJSCollectionSchema(ast, collectionNode, id)})`}`;
24
24
  const collectionDeclaration = `export const ${extendCollectionName} = (collection) => extendCollection(${id}, collection)`;
25
25
  collectionCodes[collectionNode.name] = [
26
26
  "//" + collectionNode.name,
@@ -30,7 +30,7 @@ const makeJSCollections = (ast, modifiedSymbols) => {
30
30
  }
31
31
  return Object.values(collectionCodes).join("\n\n");
32
32
  };
33
- const makeJSCollectionSchema = (collectionNode, collectionId) => {
33
+ const makeJSCollectionSchema = (ast, collectionNode, collectionId) => {
34
34
  const collectionSchema = {
35
35
  item: {},
36
36
  description: {
@@ -1,2 +1,2 @@
1
1
  import type * as AST from '../ast.js';
2
- export declare const generateTSCollections: (ast: AST.CollectionNode[]) => string;
2
+ export declare const generateTSCollections: (ast: AST.ProgramNode) => string;
@@ -11,16 +11,15 @@ const initialImportedTypes = [
11
11
  const generateTSCollections = (ast) => {
12
12
  let code = '';
13
13
  code += `import type { ${initialImportedTypes.join(', ')} } from '${utils_js_1.PACKAGE_NAME}'\n`; //Used types
14
- const importsResult = (0, utils_js_1.makeASTImports)(ast);
14
+ const importsResult = (0, utils_js_1.makeASTImports)(ast.collections);
15
15
  code += importsResult.code.join('\n') + '\n\n';
16
16
  code += makeTSCollections(ast, importsResult.modifiedSymbols) + '\n';
17
17
  return code;
18
18
  };
19
19
  exports.generateTSCollections = generateTSCollections;
20
- /** Creates the code exporting the collection type, declaration, schema and extend for each collection and returns them in a string */
21
20
  const makeTSCollections = (ast, modifiedSymbols) => {
22
21
  const collectionCodes = {};
23
- for (const collectionNode of ast) {
22
+ for (const collectionNode of ast.collections) {
24
23
  const id = (0, utils_js_1.getCollectionId)(collectionNode.name); // CollectionName -> collectionName
25
24
  const schemaName = (0, utils_js_1.resizeFirstChar)(collectionNode.name, true); // collectionName -> CollectionName
26
25
  const typeName = id + 'Collection'; // Pet -> petCollection
@@ -107,7 +106,6 @@ const makeTSCollectionSchema = (collectionNode, collectionId) => {
107
106
  }
108
107
  return (0, utils_js_1.stringify)(collectionSchema);
109
108
  };
110
- /** Turns each function to 'typeof functioName' if it's from aeria or not */
111
109
  const makeTSFunctions = (functions) => {
112
110
  return Object.keys(functions).reduce((acc, key) => {
113
111
  acc[key] = {
@@ -10,14 +10,14 @@ export const generateTSCollections = (ast) => {
10
10
  let code = "";
11
11
  code += `import type { ${initialImportedTypes.join(", ")} } from '${PACKAGE_NAME}'
12
12
  `;
13
- const importsResult = makeASTImports(ast);
13
+ const importsResult = makeASTImports(ast.collections);
14
14
  code += importsResult.code.join("\n") + "\n\n";
15
15
  code += makeTSCollections(ast, importsResult.modifiedSymbols) + "\n";
16
16
  return code;
17
17
  };
18
18
  const makeTSCollections = (ast, modifiedSymbols) => {
19
19
  const collectionCodes = {};
20
- for (const collectionNode of ast) {
20
+ for (const collectionNode of ast.collections) {
21
21
  const id = getCollectionId(collectionNode.name);
22
22
  const schemaName = resizeFirstChar(collectionNode.name, true);
23
23
  const typeName = id + "Collection";
@@ -3,13 +3,14 @@ import type { Property } from '@aeriajs/types';
3
3
  export declare const PACKAGE_NAME = "aeria";
4
4
  export declare const MIDDLEWARES_RUNTIME_PATH = "../../../dist/middlewares/index.js";
5
5
  export declare const DEFAULT_FUNCTIONS: string[];
6
+ export declare const UnquotedSymbol: unique symbol;
6
7
  export declare const ArraySymbol: unique symbol;
8
+ export type StringifyProperty = unknown | {
9
+ [UnquotedSymbol]: string;
10
+ };
7
11
  export declare const getExposedFunctions: (astFunctions: NonNullable<AST.CollectionNode["functions"]>) => {
8
12
  [k: string]: import("@aeriajs/types").AccessCondition;
9
13
  };
10
- /**
11
- * Obs: It will save and return any modified symbols to avoid name duplication later
12
- */
13
14
  export declare const makeASTImports: (ast: AST.Node[], initialImports?: Record<string, Set<string>>, options?: {
14
15
  includeRuntimeOnlyImports: boolean;
15
16
  }) => {
@@ -20,16 +21,8 @@ export declare const unwrapNode: <TNode extends {
20
21
  kind: string;
21
22
  }>(node: TNode) => Omit<TNode, "kind" | symbol>;
22
23
  export declare const unwrapPropertyNode: ({ property, nestedProperties, nestedAdditionalProperties }: Pick<AST.PropertyNode, "property" | "nestedProperties" | "nestedAdditionalProperties">) => Property;
23
- /** Transforms the AST properties to the format of aeria schema properties */
24
24
  export declare const recursivelyUnwrapPropertyNodes: <TProperties extends Record<string, AST.PropertyNode | AST.PropertyNode[]>, TReturnType = TProperties[keyof TProperties] extends Array<unknown> ? Record<string, Property[]> : Record<string, Property>>(properties: TProperties) => TReturnType;
25
- export declare const UnquotedSymbol: unique symbol;
26
- /** Serves to know if the value must be unquoted on strinfigy function */
27
- export type StringifyProperty = unknown | {
28
- [UnquotedSymbol]: string;
29
- };
30
- /** Assure if specific fields needs to be between quotes or not */
31
25
  export declare const stringify: (value: StringifyProperty, parents?: (symbol | string)[]) => string;
32
- /** Used to make the id and the schema name of the collection */
33
26
  export declare const resizeFirstChar: (text: string, capitalize: boolean) => string;
34
27
  export declare const getCollectionId: (name: string) => string;
35
28
  export declare const getExtendName: (name: string) => string;
@@ -1,6 +1,6 @@
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.MIDDLEWARES_RUNTIME_PATH = exports.PACKAGE_NAME = void 0;
3
+ exports.getExtendName = exports.getCollectionId = exports.resizeFirstChar = exports.stringify = exports.recursivelyUnwrapPropertyNodes = exports.unwrapPropertyNode = exports.unwrapNode = exports.makeASTImports = exports.getExposedFunctions = exports.ArraySymbol = exports.UnquotedSymbol = exports.DEFAULT_FUNCTIONS = exports.MIDDLEWARES_RUNTIME_PATH = exports.PACKAGE_NAME = void 0;
4
4
  exports.PACKAGE_NAME = 'aeria';
5
5
  exports.MIDDLEWARES_RUNTIME_PATH = '../../../dist/middlewares/index.js';
6
6
  exports.DEFAULT_FUNCTIONS = [
@@ -14,6 +14,7 @@ exports.DEFAULT_FUNCTIONS = [
14
14
  'unpaginatedGetAll',
15
15
  'upload',
16
16
  ];
17
+ exports.UnquotedSymbol = Symbol('unquoted');
17
18
  exports.ArraySymbol = Symbol('array');
18
19
  const getExposedFunctions = (astFunctions) => {
19
20
  return Object.fromEntries(Object.entries(astFunctions).map(([key, value]) => [
@@ -22,9 +23,6 @@ const getExposedFunctions = (astFunctions) => {
22
23
  ]));
23
24
  };
24
25
  exports.getExposedFunctions = getExposedFunctions;
25
- /**
26
- * Obs: It will save and return any modified symbols to avoid name duplication later
27
- */
28
26
  const makeASTImports = (ast, initialImports, options = {
29
27
  includeRuntimeOnlyImports: false,
30
28
  }) => {
@@ -121,7 +119,6 @@ const unwrapPropertyNode = ({ property, nestedProperties, nestedAdditionalProper
121
119
  return unwrappedProperty;
122
120
  };
123
121
  exports.unwrapPropertyNode = unwrapPropertyNode;
124
- /** Transforms the AST properties to the format of aeria schema properties */
125
122
  const recursivelyUnwrapPropertyNodes = (properties) => {
126
123
  return Object.entries(properties).reduce((acc, [key, value]) => {
127
124
  if (Array.isArray(value)) {
@@ -134,9 +131,7 @@ const recursivelyUnwrapPropertyNodes = (properties) => {
134
131
  }, {});
135
132
  };
136
133
  exports.recursivelyUnwrapPropertyNodes = recursivelyUnwrapPropertyNodes;
137
- exports.UnquotedSymbol = Symbol('unquoted');
138
134
  const isRecord = (value) => typeof value === 'object';
139
- /** Assure if specific fields needs to be between quotes or not */
140
135
  const stringify = (value, parents = []) => {
141
136
  if (Array.isArray(value)) {
142
137
  let arrayString = '[\n';
@@ -172,7 +167,6 @@ const checkQuotes = (parents, value) => {
172
167
  }
173
168
  return (0, exports.stringify)(value, parents);
174
169
  };
175
- /** Used to make the id and the schema name of the collection */
176
170
  const resizeFirstChar = (text, capitalize) => {
177
171
  if (capitalize === true) {
178
172
  return text.charAt(0).toUpperCase() + text.slice(1);
@@ -12,6 +12,7 @@ export const DEFAULT_FUNCTIONS = [
12
12
  "unpaginatedGetAll",
13
13
  "upload"
14
14
  ];
15
+ export const UnquotedSymbol = Symbol("unquoted");
15
16
  export const ArraySymbol = Symbol("array");
16
17
  export const getExposedFunctions = (astFunctions) => {
17
18
  return Object.fromEntries(Object.entries(astFunctions).map(([key, value]) => [
@@ -115,7 +116,6 @@ export const recursivelyUnwrapPropertyNodes = (properties) => {
115
116
  return acc;
116
117
  }, {});
117
118
  };
118
- export const UnquotedSymbol = Symbol("unquoted");
119
119
  const isRecord = (value) => typeof value === "object";
120
120
  export const stringify = (value, parents = []) => {
121
121
  if (Array.isArray(value)) {
package/dist/codegen.js CHANGED
@@ -37,20 +37,6 @@ exports.generateCode = void 0;
37
37
  const index_js_1 = require("./codegen/index.js");
38
38
  const fsPromises = __importStar(require("node:fs/promises"));
39
39
  const path = __importStar(require("node:path"));
40
- /**
41
- * Maps the path tree into a object with the full paths
42
- * {
43
- * folderX: {
44
- * folderY: {
45
- * file: ...
46
- * }
47
- * }
48
- * }
49
- * turns into
50
- * {
51
- * ['outDir/folderX/folderY/file']: ...
52
- * }
53
- */
54
40
  const generateFileMap = async (fileTree, outDir = '.') => {
55
41
  const mappedPaths = {};
56
42
  const mapPathTree = async (tree, previousPath) => {
@@ -71,14 +57,14 @@ const generateFileMap = async (fileTree, outDir = '.') => {
71
57
  return mappedPaths;
72
58
  };
73
59
  const generateCode = async (ast, options) => {
74
- const contracts = (0, index_js_1.generateContracts)(ast.contracts);
60
+ const contracts = (0, index_js_1.generateContracts)(ast);
75
61
  const exports = (0, index_js_1.generateExports)(ast, {
76
62
  hasContracts: !!contracts,
77
63
  });
78
64
  const fileTree = {
79
65
  ['collections']: {
80
- ['collections.d.ts']: (0, index_js_1.generateTSCollections)(ast.collections),
81
- ['collections.js']: (0, index_js_1.generateJSCollections)(ast.collections),
66
+ ['collections.d.ts']: (0, index_js_1.generateTSCollections)(ast),
67
+ ['collections.js']: (0, index_js_1.generateJSCollections)(ast),
82
68
  ['index.d.ts']: exports.collections.dts,
83
69
  ['index.js']: exports.collections.js,
84
70
  },
package/dist/codegen.mjs CHANGED
@@ -22,14 +22,14 @@ const generateFileMap = async (fileTree, outDir = ".") => {
22
22
  return mappedPaths;
23
23
  };
24
24
  export const generateCode = async (ast, options) => {
25
- const contracts = generateContracts(ast.contracts);
25
+ const contracts = generateContracts(ast);
26
26
  const exports = generateExports(ast, {
27
27
  hasContracts: !!contracts
28
28
  });
29
29
  const fileTree = {
30
30
  ["collections"]: {
31
- ["collections.d.ts"]: generateTSCollections(ast.collections),
32
- ["collections.mjs"]: generateJSCollections(ast.collections),
31
+ ["collections.d.ts"]: generateTSCollections(ast),
32
+ ["collections.mjs"]: generateJSCollections(ast),
33
33
  ["index.d.ts"]: exports.collections.dts,
34
34
  ["index.mjs"]: exports.collections.js
35
35
  },
package/dist/compile.d.ts CHANGED
@@ -1,11 +1,15 @@
1
+ import type * as AST from './ast.js';
1
2
  import type { CompilationOptions, CompilationResult } from './types.js';
2
3
  import { Diagnostic } from './diagnostic.js';
3
4
  export declare const GLOB_PATTERN = "**/*.aeria";
5
+ export declare const postflight: (ast: AST.ProgramNode) => {
6
+ errors: Diagnostic[];
7
+ };
4
8
  export declare const parseAndCheck: (sources: Record<string, string>, options?: Pick<CompilationOptions, "languageServer">) => Promise<CompilationResult>;
5
9
  export declare const compileFromFiles: (options: CompilationOptions) => Promise<CompilationResult | {
6
10
  emittedFiles: Record<string, string>;
7
11
  success: boolean;
8
- ast?: import("./ast.js").ProgramNode;
12
+ ast?: AST.ProgramNode;
9
13
  errors: Diagnostic[];
10
14
  errorCount: number;
11
15
  }>;
package/dist/compile.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.compileFromFiles = exports.parseAndCheck = exports.GLOB_PATTERN = void 0;
36
+ exports.compileFromFiles = exports.parseAndCheck = exports.postflight = exports.GLOB_PATTERN = void 0;
37
37
  const diagnostic_js_1 = require("./diagnostic.js");
38
38
  const lexer_js_1 = require("./lexer.js");
39
39
  const parser_js_1 = require("./parser.js");
@@ -41,12 +41,31 @@ const semantic_js_1 = require("./semantic.js");
41
41
  const codegen_js_1 = require("./codegen.js");
42
42
  const fs = __importStar(require("node:fs"));
43
43
  exports.GLOB_PATTERN = '**/*.aeria';
44
+ const postflight = (ast) => {
45
+ const errors = [];
46
+ for (const node of ast.collections) {
47
+ if (node.functionSets?.length) {
48
+ for (const [functionSetName, locationSymbol] of node.functionSets) {
49
+ const functionSet = ast.functionsets.find(({ name }) => name === functionSetName);
50
+ if (!functionSet) {
51
+ const location = parser_js_1.locationMap.get(locationSymbol);
52
+ errors.push(new diagnostic_js_1.Diagnostic(`invalid function set "${functionSetName}"`, location));
53
+ continue;
54
+ }
55
+ Object.assign(node.functions, functionSet.functions);
56
+ }
57
+ }
58
+ }
59
+ return {
60
+ errors,
61
+ };
62
+ };
63
+ exports.postflight = postflight;
44
64
  const parseAndCheck = async (sources, options = {}) => {
45
65
  const errors = [];
46
66
  const allTokens = [];
47
67
  for (const fileName in sources) {
48
- diagnostic_js_1.Diagnostic.currentFile = fileName;
49
- const { errors: lexerErrors, tokens } = (0, lexer_js_1.tokenize)(sources[fileName]);
68
+ const { errors: lexerErrors, tokens } = (0, lexer_js_1.tokenize)(sources[fileName], fileName);
50
69
  if (lexerErrors.length > 0) {
51
70
  errors.push(...lexerErrors);
52
71
  }
@@ -54,7 +73,8 @@ const parseAndCheck = async (sources, options = {}) => {
54
73
  }
55
74
  const { errors: parserErrors, ast } = (0, parser_js_1.parse)(allTokens);
56
75
  const { errors: semanticErrors } = await (0, semantic_js_1.analyze)(ast, options);
57
- errors.push(...parserErrors.concat(semanticErrors));
76
+ const { errors: postflightErrors } = (0, exports.postflight)(ast);
77
+ errors.push(...parserErrors.concat(semanticErrors, postflightErrors));
58
78
  return {
59
79
  success: errors.length === 0,
60
80
  errors,
package/dist/compile.mjs CHANGED
@@ -1,17 +1,35 @@
1
1
  "use strict";
2
2
  import { Diagnostic } from "./diagnostic.mjs";
3
3
  import { tokenize } from "./lexer.mjs";
4
- import { parse } from "./parser.mjs";
4
+ import { parse, locationMap } from "./parser.mjs";
5
5
  import { analyze } from "./semantic.mjs";
6
6
  import { generateCode } from "./codegen.mjs";
7
7
  import * as fs from "node:fs";
8
8
  export const GLOB_PATTERN = "**/*.aeria";
9
+ export const postflight = (ast) => {
10
+ const errors = [];
11
+ for (const node of ast.collections) {
12
+ if (node.functionSets?.length) {
13
+ for (const [functionSetName, locationSymbol] of node.functionSets) {
14
+ const functionSet = ast.functionsets.find(({ name }) => name === functionSetName);
15
+ if (!functionSet) {
16
+ const location = locationMap.get(locationSymbol);
17
+ errors.push(new Diagnostic(`invalid function set "${functionSetName}"`, location));
18
+ continue;
19
+ }
20
+ Object.assign(node.functions, functionSet.functions);
21
+ }
22
+ }
23
+ }
24
+ return {
25
+ errors
26
+ };
27
+ };
9
28
  export const parseAndCheck = async (sources, options = {}) => {
10
29
  const errors = [];
11
30
  const allTokens = [];
12
31
  for (const fileName in sources) {
13
- Diagnostic.currentFile = fileName;
14
- const { errors: lexerErrors, tokens } = tokenize(sources[fileName]);
32
+ const { errors: lexerErrors, tokens } = tokenize(sources[fileName], fileName);
15
33
  if (lexerErrors.length > 0) {
16
34
  errors.push(...lexerErrors);
17
35
  }
@@ -19,7 +37,8 @@ export const parseAndCheck = async (sources, options = {}) => {
19
37
  }
20
38
  const { errors: parserErrors, ast } = parse(allTokens);
21
39
  const { errors: semanticErrors } = await analyze(ast, options);
22
- errors.push(...parserErrors.concat(semanticErrors));
40
+ const { errors: postflightErrors } = postflight(ast);
41
+ errors.push(...parserErrors.concat(semanticErrors, postflightErrors));
23
42
  return {
24
43
  success: errors.length === 0,
25
44
  errors,
@@ -2,7 +2,5 @@ import type { Location } from './token.js';
2
2
  export declare class Diagnostic extends Error {
3
3
  message: string;
4
4
  location: Location;
5
- fileLocation: string | undefined;
6
- static currentFile: string | undefined;
7
- constructor(message: string, location?: Location, fileLocation?: string | undefined);
5
+ constructor(message: string, location?: Location);
8
6
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Diagnostic = void 0;
4
4
  const emptyLocation = {
5
+ file: '',
5
6
  index: 0,
6
7
  line: 0,
7
8
  start: 0,
@@ -10,13 +11,10 @@ const emptyLocation = {
10
11
  class Diagnostic extends Error {
11
12
  message;
12
13
  location;
13
- fileLocation;
14
- static currentFile;
15
- constructor(message, location = emptyLocation, fileLocation = Diagnostic.currentFile) {
14
+ constructor(message, location = emptyLocation) {
16
15
  super();
17
16
  this.message = message;
18
17
  this.location = location;
19
- this.fileLocation = fileLocation;
20
18
  if (process.env.NODE_ENV === 'debug') {
21
19
  console.error(message, location);
22
20
  }
@@ -1,19 +1,18 @@
1
1
  "use strict";
2
2
  const emptyLocation = {
3
+ file: "",
3
4
  index: 0,
4
5
  line: 0,
5
6
  start: 0,
6
7
  end: 0
7
8
  };
8
9
  export class Diagnostic extends Error {
9
- constructor(message, location = emptyLocation, fileLocation = Diagnostic.currentFile) {
10
+ constructor(message, location = emptyLocation) {
10
11
  super();
11
12
  this.message = message;
12
13
  this.location = location;
13
- this.fileLocation = fileLocation;
14
14
  if (false) {
15
15
  console.error(message, location);
16
16
  }
17
17
  }
18
- static currentFile;
19
18
  }
package/dist/lexer.d.ts CHANGED
@@ -13,7 +13,7 @@ export type Keyword = typeof COLLECTION_KEYWORDS[number] | typeof COLLECTION_ACT
13
13
  export declare const KEYWORDS: Keyword[];
14
14
  export declare const FINAL_OPERATORS: readonly ["==", "in", ">=", "<=", ">", "<", "!"];
15
15
  export declare const LOGICAL_OPERATORS: readonly ["&&", "||"];
16
- export declare const tokenize: (rawInput: string) => {
16
+ export declare const tokenize: (rawInput: string, fileLocation: string) => {
17
17
  tokens: Token[];
18
18
  errors: Diagnostic[];
19
19
  };
package/dist/lexer.js CHANGED
@@ -212,7 +212,7 @@ const TOKENS = [
212
212
  valueExtractor: (value) => value.slice(1),
213
213
  },
214
214
  ];
215
- const tokenize = function (rawInput) {
215
+ const tokenize = function (rawInput, fileLocation) {
216
216
  const input = rawInput.replace(/\r\n/g, '\n');
217
217
  let index = 0, line = 1, start = 0, end = 0;
218
218
  const tokens = [];
@@ -254,6 +254,7 @@ const tokenize = function (rawInput) {
254
254
  if (value) {
255
255
  let tokenValue;
256
256
  const location = {
257
+ file: fileLocation,
257
258
  index: index += value.length,
258
259
  line,
259
260
  end: end += value.length,
@@ -354,6 +355,7 @@ const tokenize = function (rawInput) {
354
355
  if (!hasMatch) {
355
356
  index += input.slice(index).search(/[ \t\n\{\}\(\)\[\]]/);
356
357
  errors.push(new diagnostic_js_1.Diagnostic('unexpected token', {
358
+ file: fileLocation,
357
359
  index,
358
360
  line,
359
361
  start,
package/dist/lexer.mjs CHANGED
@@ -220,7 +220,7 @@ const TOKENS = [
220
220
  valueExtractor: (value) => value.slice(1)
221
221
  }
222
222
  ];
223
- export const tokenize = function(rawInput) {
223
+ export const tokenize = function(rawInput, fileLocation) {
224
224
  const input = rawInput.replace(/\r\n/g, "\n");
225
225
  let index = 0, line = 1, start = 0, end = 0;
226
226
  const tokens = [];
@@ -260,6 +260,7 @@ export const tokenize = function(rawInput) {
260
260
  if (value) {
261
261
  let tokenValue;
262
262
  const location = {
263
+ file: fileLocation,
263
264
  index: index += value.length,
264
265
  line,
265
266
  end: end += value.length,
@@ -357,6 +358,7 @@ export const tokenize = function(rawInput) {
357
358
  if (!hasMatch) {
358
359
  index += input.slice(index).search(/[ \t\n\{\}\(\)\[\]]/);
359
360
  errors.push(new Diagnostic("unexpected token", {
361
+ file: fileLocation,
360
362
  index,
361
363
  line,
362
364
  start,
package/dist/parser.js CHANGED
@@ -667,7 +667,7 @@ const parse = (tokens) => {
667
667
  return checkForValidRoles(value, symbols);
668
668
  }
669
669
  };
670
- const parseCollection = (ast) => {
670
+ const parseCollection = () => {
671
671
  consume(token_js_1.TokenType.Keyword, 'collection');
672
672
  const { value: name } = consume(token_js_1.TokenType.Identifier);
673
673
  const node = {
@@ -719,7 +719,9 @@ const parse = (tokens) => {
719
719
  break;
720
720
  }
721
721
  case 'functions': {
722
- node[keyword] = parseFunctionsBlock(ast);
722
+ const { functions, functionSets } = parseFunctionsBlock();
723
+ node.functions = functions;
724
+ node.functionSets = functionSets;
723
725
  break;
724
726
  }
725
727
  case 'individualActions':
@@ -824,9 +826,10 @@ const parse = (tokens) => {
824
826
  consume(token_js_1.TokenType.RightBracket);
825
827
  return node;
826
828
  };
827
- const parseFunctionsBlock = (ast) => {
829
+ const parseFunctionsBlock = () => {
828
830
  consume(token_js_1.TokenType.LeftBracket);
829
831
  const functions = {};
832
+ const functionSets = [];
830
833
  while (!match(token_js_1.TokenType.RightBracket)) {
831
834
  try {
832
835
  if (match(token_js_1.TokenType.MacroName)) {
@@ -834,11 +837,12 @@ const parse = (tokens) => {
834
837
  switch (macroName) {
835
838
  case 'include': {
836
839
  const { value: functionSetName, location } = consume(token_js_1.TokenType.Identifier);
837
- const functionset = ast.functionsets.find((node) => node.name === functionSetName);
838
- if (!functionset) {
839
- throw new diagnostic_js_1.Diagnostic(`functionset "${functionSetName}" not found`, location);
840
- }
841
- Object.assign(functions, functionset.functions);
840
+ const functionSetSymbol = Symbol();
841
+ exports.locationMap.set(functionSetSymbol, location);
842
+ functionSets.push([
843
+ functionSetName,
844
+ functionSetSymbol,
845
+ ]);
842
846
  consume(token_js_1.TokenType.RightParens);
843
847
  break;
844
848
  }
@@ -880,15 +884,20 @@ const parse = (tokens) => {
880
884
  }
881
885
  }
882
886
  consume(token_js_1.TokenType.RightBracket);
883
- return functions;
887
+ return {
888
+ functions,
889
+ functionSets,
890
+ };
884
891
  };
885
- const parseFunctionSet = (ast) => {
892
+ const parseFunctionSet = () => {
886
893
  consume(token_js_1.TokenType.Keyword, 'functionset');
887
894
  const { value: name } = consume(token_js_1.TokenType.Identifier);
895
+ const { functions, functionSets } = parseFunctionsBlock();
888
896
  const node = {
889
897
  kind: 'functionset',
890
898
  name,
891
- functions: parseFunctionsBlock(ast),
899
+ functions,
900
+ functionSets,
892
901
  };
893
902
  return node;
894
903
  };
@@ -1227,6 +1236,12 @@ const parse = (tokens) => {
1227
1236
  if (match(token_js_1.TokenType.LeftParens)) {
1228
1237
  term2 = parseCondition(symbols);
1229
1238
  }
1239
+ else if (match(token_js_1.TokenType.LeftSquareBracket)) {
1240
+ term2 = parseArray([
1241
+ token_js_1.TokenType.QuotedString,
1242
+ token_js_1.TokenType.Number,
1243
+ ]).value;
1244
+ }
1230
1245
  else {
1231
1246
  term2 = current().value;
1232
1247
  advance();
@@ -1266,7 +1281,7 @@ const parse = (tokens) => {
1266
1281
  try {
1267
1282
  switch (declType) {
1268
1283
  case 'collection': {
1269
- const collection = parseCollection(ast);
1284
+ const collection = parseCollection();
1270
1285
  if (collection.name === 'User') {
1271
1286
  const { properties } = collection;
1272
1287
  if ('roles' in properties && 'items' in properties.roles.property && 'enum' in properties.roles.property.items) {
@@ -1281,7 +1296,7 @@ const parse = (tokens) => {
1281
1296
  break;
1282
1297
  }
1283
1298
  case 'functionset': {
1284
- ast.functionsets.push(parseFunctionSet(ast));
1299
+ ast.functionsets.push(parseFunctionSet());
1285
1300
  break;
1286
1301
  }
1287
1302
  default:
package/dist/parser.mjs CHANGED
@@ -614,7 +614,7 @@ export const parse = (tokens) => {
614
614
  return checkForValidRoles(value, symbols);
615
615
  }
616
616
  };
617
- const parseCollection = (ast2) => {
617
+ const parseCollection = () => {
618
618
  consume(TokenType.Keyword, "collection");
619
619
  const { value: name } = consume(TokenType.Identifier);
620
620
  const node = {
@@ -665,7 +665,9 @@ export const parse = (tokens) => {
665
665
  break;
666
666
  }
667
667
  case "functions": {
668
- node[keyword] = parseFunctionsBlock(ast2);
668
+ const { functions, functionSets } = parseFunctionsBlock();
669
+ node.functions = functions;
670
+ node.functionSets = functionSets;
669
671
  break;
670
672
  }
671
673
  case "individualActions":
@@ -769,9 +771,10 @@ export const parse = (tokens) => {
769
771
  consume(TokenType.RightBracket);
770
772
  return node;
771
773
  };
772
- const parseFunctionsBlock = (ast2) => {
774
+ const parseFunctionsBlock = () => {
773
775
  consume(TokenType.LeftBracket);
774
776
  const functions = {};
777
+ const functionSets = [];
775
778
  while (!match(TokenType.RightBracket)) {
776
779
  try {
777
780
  if (match(TokenType.MacroName)) {
@@ -779,11 +782,12 @@ export const parse = (tokens) => {
779
782
  switch (macroName) {
780
783
  case "include": {
781
784
  const { value: functionSetName, location } = consume(TokenType.Identifier);
782
- const functionset = ast2.functionsets.find((node) => node.name === functionSetName);
783
- if (!functionset) {
784
- throw new Diagnostic(`functionset "${functionSetName}" not found`, location);
785
- }
786
- Object.assign(functions, functionset.functions);
785
+ const functionSetSymbol = Symbol();
786
+ locationMap.set(functionSetSymbol, location);
787
+ functionSets.push([
788
+ functionSetName,
789
+ functionSetSymbol
790
+ ]);
787
791
  consume(TokenType.RightParens);
788
792
  break;
789
793
  }
@@ -823,15 +827,20 @@ export const parse = (tokens) => {
823
827
  }
824
828
  }
825
829
  consume(TokenType.RightBracket);
826
- return functions;
830
+ return {
831
+ functions,
832
+ functionSets
833
+ };
827
834
  };
828
- const parseFunctionSet = (ast2) => {
835
+ const parseFunctionSet = () => {
829
836
  consume(TokenType.Keyword, "functionset");
830
837
  const { value: name } = consume(TokenType.Identifier);
838
+ const { functions, functionSets } = parseFunctionsBlock();
831
839
  const node = {
832
840
  kind: "functionset",
833
841
  name,
834
- functions: parseFunctionsBlock(ast2)
842
+ functions,
843
+ functionSets
835
844
  };
836
845
  return node;
837
846
  };
@@ -1165,6 +1174,11 @@ export const parse = (tokens) => {
1165
1174
  let term2;
1166
1175
  if (match(TokenType.LeftParens)) {
1167
1176
  term2 = parseCondition(symbols);
1177
+ } else if (match(TokenType.LeftSquareBracket)) {
1178
+ term2 = parseArray([
1179
+ TokenType.QuotedString,
1180
+ TokenType.Number
1181
+ ]).value;
1168
1182
  } else {
1169
1183
  term2 = current().value;
1170
1184
  advance();
@@ -1204,7 +1218,7 @@ export const parse = (tokens) => {
1204
1218
  try {
1205
1219
  switch (declType) {
1206
1220
  case "collection": {
1207
- const collection = parseCollection(ast);
1221
+ const collection = parseCollection();
1208
1222
  if (collection.name === "User") {
1209
1223
  const { properties } = collection;
1210
1224
  if ("roles" in properties && "items" in properties.roles.property && "enum" in properties.roles.property.items) {
@@ -1219,7 +1233,7 @@ export const parse = (tokens) => {
1219
1233
  break;
1220
1234
  }
1221
1235
  case "functionset": {
1222
- ast.functionsets.push(parseFunctionSet(ast));
1236
+ ast.functionsets.push(parseFunctionSet());
1223
1237
  break;
1224
1238
  }
1225
1239
  default:
package/dist/token.d.ts CHANGED
@@ -29,6 +29,7 @@ export type TypeMap = {
29
29
  [TokenType.Range]: readonly [number, number];
30
30
  };
31
31
  export type Location = {
32
+ file: string;
32
33
  index: number;
33
34
  line: number;
34
35
  start: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeriajs/compiler",
3
- "version": "0.0.40",
3
+ "version": "0.0.42",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",