@aeriajs/compiler 0.0.4 → 0.0.7
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 +79 -0
- package/dist/ast.js +23 -0
- package/dist/ast.mjs +21 -0
- package/dist/codegen/generateContracts.d.ts +5 -0
- package/dist/codegen/generateContracts.js +84 -0
- package/dist/codegen/generateContracts.mjs +77 -0
- package/dist/codegen/generateExports.d.ts +15 -0
- package/dist/codegen/generateExports.js +41 -0
- package/dist/codegen/generateExports.mjs +32 -0
- package/dist/codegen/generateJSCollections.d.ts +2 -0
- package/dist/codegen/generateJSCollections.js +91 -0
- package/dist/codegen/generateJSCollections.mjs +82 -0
- package/dist/codegen/generateTSCollections.d.ts +2 -0
- package/dist/codegen/generateTSCollections.js +107 -0
- package/dist/codegen/generateTSCollections.mjs +99 -0
- package/dist/codegen/index.d.ts +4 -0
- package/dist/codegen/index.js +20 -0
- package/dist/codegen/index.mjs +5 -0
- package/dist/codegen/utils.d.ts +29 -0
- package/dist/codegen/utils.js +143 -0
- package/dist/codegen/utils.mjs +122 -0
- package/dist/codegen.d.ts +3 -0
- package/dist/codegen.js +102 -0
- package/dist/codegen.mjs +52 -0
- package/dist/compile.d.ts +21 -0
- package/dist/compile.js +96 -0
- package/dist/compile.mjs +57 -0
- package/dist/diagnostic.d.ts +8 -0
- package/dist/diagnostic.js +22 -0
- package/dist/diagnostic.mjs +16 -0
- package/dist/guards.d.ts +3 -0
- package/dist/guards.js +45 -0
- package/dist/guards.mjs +8 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +23 -0
- package/dist/index.mjs +8 -0
- package/dist/lexer.d.ts +14 -0
- package/dist/lexer.js +272 -0
- package/dist/lexer.mjs +270 -0
- package/dist/parser.d.ts +8 -0
- package/dist/parser.js +907 -0
- package/dist/parser.mjs +851 -0
- package/dist/semantic.d.ts +5 -0
- package/dist/semantic.js +149 -0
- package/dist/semantic.mjs +111 -0
- package/dist/token.d.ts +38 -0
- package/dist/token.js +24 -0
- package/dist/token.mjs +22 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +2 -0
- package/dist/utils.mjs +1 -0
- package/package.json +2 -3
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { getProperties, stringify, makeASTImports, resizeFirstChar, getCollectionId, UnquotedSymbol, getExposedFunctions, PACKAGE_NAME, DEFAULT_FUNCTIONS } from "./utils.mjs";
|
|
3
|
+
const initialImportedTypes = [
|
|
4
|
+
"Collection",
|
|
5
|
+
"SchemaWithId",
|
|
6
|
+
"ExtendCollection",
|
|
7
|
+
"Context"
|
|
8
|
+
];
|
|
9
|
+
export const generateTSCollections = (ast) => {
|
|
10
|
+
let code = "";
|
|
11
|
+
code += `import type { ${initialImportedTypes.join(", ")} } from '${PACKAGE_NAME}'
|
|
12
|
+
`;
|
|
13
|
+
const importsResult = makeASTImports(ast);
|
|
14
|
+
code += importsResult.code + "\n\n";
|
|
15
|
+
code += makeTSCollections(ast, importsResult.modifiedSymbols) + "\n";
|
|
16
|
+
return code;
|
|
17
|
+
};
|
|
18
|
+
const makeTSCollections = (ast, modifiedSymbols) => {
|
|
19
|
+
const collectionCodes = {};
|
|
20
|
+
for (const collectionNode of ast) {
|
|
21
|
+
const id = getCollectionId(collectionNode.name);
|
|
22
|
+
const schemaName = resizeFirstChar(collectionNode.name, true);
|
|
23
|
+
const typeName = id + "Collection";
|
|
24
|
+
const collectionType = `export declare type ${typeName} = ${id in modifiedSymbols ? `ExtendCollection<typeof ${modifiedSymbols[id]}, ${makeTSCollectionSchema(collectionNode, id)}>` : makeTSCollectionSchema(collectionNode, id)}`;
|
|
25
|
+
const collectionDeclaration = `export declare const ${id}: ${typeName} & { item: SchemaWithId<${typeName}["description"]> }`;
|
|
26
|
+
const collectionSchema = `export declare type ${schemaName} = SchemaWithId<typeof ${id}.description>`;
|
|
27
|
+
const collectionExtend = `export declare const extend${schemaName}Collection: <
|
|
28
|
+
const TCollection extends {
|
|
29
|
+
[P in Exclude<keyof Collection, "functions">]?: Partial<Collection[P]>
|
|
30
|
+
} & {
|
|
31
|
+
functions?: {
|
|
32
|
+
[F: string]: (payload: any, context: Context<typeof ${id}["description"]>) => unknown
|
|
33
|
+
}
|
|
34
|
+
}>(collection: TCollection) => ExtendCollection<typeof ${id}, TCollection>`;
|
|
35
|
+
collectionCodes[collectionNode.name] = [
|
|
36
|
+
"//" + collectionNode.name,
|
|
37
|
+
collectionType,
|
|
38
|
+
collectionDeclaration,
|
|
39
|
+
collectionSchema,
|
|
40
|
+
collectionExtend
|
|
41
|
+
].join("\n");
|
|
42
|
+
}
|
|
43
|
+
return Object.values(collectionCodes).join("\n\n");
|
|
44
|
+
};
|
|
45
|
+
const makeTSCollectionSchema = (collectionNode, collectionId) => {
|
|
46
|
+
const collectionSchema = {
|
|
47
|
+
description: {
|
|
48
|
+
$id: collectionId
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
for (const key of Object.keys(collectionNode)) {
|
|
52
|
+
if (collectionNode[key] === void 0) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
switch (key) {
|
|
56
|
+
case "properties":
|
|
57
|
+
collectionSchema.description.properties = getProperties(collectionNode[key]);
|
|
58
|
+
break;
|
|
59
|
+
case "owned":
|
|
60
|
+
collectionSchema.description.owned = collectionNode[key];
|
|
61
|
+
break;
|
|
62
|
+
case "functions":
|
|
63
|
+
collectionSchema.functions = makeTSFunctions(collectionNode[key]);
|
|
64
|
+
collectionSchema.exposedFunctions = getExposedFunctions(collectionNode[key]);
|
|
65
|
+
break;
|
|
66
|
+
case "table":
|
|
67
|
+
case "filters":
|
|
68
|
+
case "indexes":
|
|
69
|
+
case "form":
|
|
70
|
+
collectionSchema.description[key] = collectionNode[key];
|
|
71
|
+
break;
|
|
72
|
+
case "actions":
|
|
73
|
+
case "individualActions":
|
|
74
|
+
collectionSchema.description[key] = collectionNode[key];
|
|
75
|
+
break;
|
|
76
|
+
case "icon":
|
|
77
|
+
collectionSchema.description[key] = collectionNode[key];
|
|
78
|
+
break;
|
|
79
|
+
case "presets":
|
|
80
|
+
collectionSchema.description[key] = collectionNode[key];
|
|
81
|
+
break;
|
|
82
|
+
case "search":
|
|
83
|
+
collectionSchema.description[key] = collectionNode[key];
|
|
84
|
+
break;
|
|
85
|
+
case "required":
|
|
86
|
+
collectionSchema.description[key] = collectionNode[key];
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return stringify(collectionSchema);
|
|
91
|
+
};
|
|
92
|
+
const makeTSFunctions = (functions) => {
|
|
93
|
+
return Object.keys(functions).reduce((acc, key) => {
|
|
94
|
+
acc[key] = {
|
|
95
|
+
[UnquotedSymbol]: DEFAULT_FUNCTIONS.includes(key) ? `typeof ${key}` : "() => never"
|
|
96
|
+
};
|
|
97
|
+
return acc;
|
|
98
|
+
}, {});
|
|
99
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./generateJSCollections.js"), exports);
|
|
18
|
+
__exportStar(require("./generateTSCollections.js"), exports);
|
|
19
|
+
__exportStar(require("./generateExports.js"), exports);
|
|
20
|
+
__exportStar(require("./generateContracts.js"), exports);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type * as AST from '../ast.js';
|
|
2
|
+
import type { Property } from '@aeriajs/types';
|
|
3
|
+
export declare const PACKAGE_NAME = "aeria";
|
|
4
|
+
export declare const DEFAULT_FUNCTIONS: string[];
|
|
5
|
+
export declare const ArraySymbol: unique symbol;
|
|
6
|
+
export declare const getExposedFunctions: (astFunctions: NonNullable<AST.CollectionNode["functions"]>) => {
|
|
7
|
+
[k: string]: import("@aeriajs/types").AccessCondition;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Obs: It will save and return any modified symbols to avoid name duplication later
|
|
11
|
+
*/
|
|
12
|
+
export declare const makeASTImports: (ast: AST.Node[], initialImports?: Record<string, Set<string>>) => {
|
|
13
|
+
code: string[];
|
|
14
|
+
modifiedSymbols: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
export declare const propertyToSchema: (propertyNode: AST.PropertyNode) => Property;
|
|
17
|
+
/** Transforms the AST properties to the format of aeria schema properties */
|
|
18
|
+
export declare const getProperties: <TProperties extends Record<string, AST.PropertyNode | AST.PropertyNode[]>, TReturnType = TProperties[keyof TProperties] extends unknown[] ? Record<string, Property[]> : Record<string, Property>>(properties: TProperties) => TReturnType;
|
|
19
|
+
export declare const UnquotedSymbol: unique symbol;
|
|
20
|
+
/** Serves to know if the value must be unquoted on strinfigy function */
|
|
21
|
+
export type StringifyProperty = unknown | {
|
|
22
|
+
[UnquotedSymbol]: string;
|
|
23
|
+
};
|
|
24
|
+
/** Assure if specific fields needs to be between quotes or not */
|
|
25
|
+
export declare const stringify: (value: StringifyProperty, parents?: (symbol | string)[]) => string;
|
|
26
|
+
/** Used to make the id and the schema name of the collection */
|
|
27
|
+
export declare const resizeFirstChar: (text: string, capitalize: boolean) => string;
|
|
28
|
+
export declare const getCollectionId: (name: string) => string;
|
|
29
|
+
export declare const getExtendName: (name: string) => string;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getExtendName = exports.getCollectionId = exports.resizeFirstChar = exports.stringify = exports.UnquotedSymbol = exports.getProperties = exports.propertyToSchema = exports.makeASTImports = exports.getExposedFunctions = exports.ArraySymbol = exports.DEFAULT_FUNCTIONS = exports.PACKAGE_NAME = void 0;
|
|
4
|
+
exports.PACKAGE_NAME = 'aeria';
|
|
5
|
+
exports.DEFAULT_FUNCTIONS = [
|
|
6
|
+
'count',
|
|
7
|
+
'get',
|
|
8
|
+
'getAll',
|
|
9
|
+
'insert',
|
|
10
|
+
'upload',
|
|
11
|
+
'remove',
|
|
12
|
+
'removeAll',
|
|
13
|
+
'removeFile',
|
|
14
|
+
];
|
|
15
|
+
exports.ArraySymbol = Symbol('array');
|
|
16
|
+
const getExposedFunctions = (astFunctions) => {
|
|
17
|
+
return Object.fromEntries(Object.entries(astFunctions)
|
|
18
|
+
.map(([key, value]) => [
|
|
19
|
+
key,
|
|
20
|
+
value.accessCondition,
|
|
21
|
+
]));
|
|
22
|
+
};
|
|
23
|
+
exports.getExposedFunctions = getExposedFunctions;
|
|
24
|
+
/**
|
|
25
|
+
* Obs: It will save and return any modified symbols to avoid name duplication later
|
|
26
|
+
*/
|
|
27
|
+
const makeASTImports = (ast, initialImports) => {
|
|
28
|
+
const modifiedSymbols = {};
|
|
29
|
+
const toImport = ast.reduce((imports, node) => {
|
|
30
|
+
if (node.kind === 'collection') {
|
|
31
|
+
if (node.extends?.packageName) {
|
|
32
|
+
if (!(node.extends.packageName in imports)) {
|
|
33
|
+
imports[node.extends.packageName] = new Set();
|
|
34
|
+
}
|
|
35
|
+
const modifiedSymbol = `original${(0, exports.resizeFirstChar)(node.extends.symbolName, true)}`;
|
|
36
|
+
modifiedSymbols[node.extends.symbolName] = modifiedSymbol;
|
|
37
|
+
imports[node.extends.packageName].add(`${node.extends.symbolName} as ${modifiedSymbol}`);
|
|
38
|
+
}
|
|
39
|
+
if (node.functions) {
|
|
40
|
+
const functionsToImport = Object.keys(node.functions).filter((key) => exports.DEFAULT_FUNCTIONS.includes(key));
|
|
41
|
+
if (functionsToImport.length > 0) {
|
|
42
|
+
if (!(exports.PACKAGE_NAME in imports)) {
|
|
43
|
+
imports[exports.PACKAGE_NAME] = new Set();
|
|
44
|
+
}
|
|
45
|
+
for (const key of functionsToImport) {
|
|
46
|
+
imports[exports.PACKAGE_NAME].add(key);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return imports;
|
|
52
|
+
}, initialImports ?? {});
|
|
53
|
+
return {
|
|
54
|
+
code: Object.keys(toImport).map((key) => `import { ${Array.from(toImport[key]).join(', ')} } from '${key}'`),
|
|
55
|
+
modifiedSymbols,
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
exports.makeASTImports = makeASTImports;
|
|
59
|
+
const propertyToSchema = (propertyNode) => {
|
|
60
|
+
const propertySchema = propertyNode.property;
|
|
61
|
+
if ('$ref' in propertySchema) {
|
|
62
|
+
propertySchema.$ref = (0, exports.getCollectionId)(propertySchema.$ref);
|
|
63
|
+
}
|
|
64
|
+
else if ('items' in propertySchema && '$ref' in propertySchema.items) {
|
|
65
|
+
propertySchema.items.$ref = (0, exports.getCollectionId)(propertySchema.items.$ref);
|
|
66
|
+
}
|
|
67
|
+
if (propertyNode.nestedProperties && 'type' in propertySchema) {
|
|
68
|
+
if (propertySchema.type === 'object' && 'properties' in propertySchema) {
|
|
69
|
+
propertySchema.properties = (0, exports.getProperties)(propertyNode.nestedProperties);
|
|
70
|
+
}
|
|
71
|
+
else if (propertySchema.type === 'array') {
|
|
72
|
+
propertySchema.items = {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: (0, exports.getProperties)(propertyNode.nestedProperties),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return propertySchema;
|
|
79
|
+
};
|
|
80
|
+
exports.propertyToSchema = propertyToSchema;
|
|
81
|
+
/** Transforms the AST properties to the format of aeria schema properties */
|
|
82
|
+
const getProperties = (properties) => {
|
|
83
|
+
return Object.entries(properties).reduce((acc, [key, value]) => {
|
|
84
|
+
if (Array.isArray(value)) {
|
|
85
|
+
acc[key] = value.map((propertyNode) => (0, exports.propertyToSchema)(propertyNode));
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
acc[key] = (0, exports.propertyToSchema)(value);
|
|
89
|
+
}
|
|
90
|
+
return acc;
|
|
91
|
+
}, {});
|
|
92
|
+
};
|
|
93
|
+
exports.getProperties = getProperties;
|
|
94
|
+
exports.UnquotedSymbol = Symbol('unquoted');
|
|
95
|
+
const isRecord = (value) => typeof value === 'object';
|
|
96
|
+
/** Assure if specific fields needs to be between quotes or not */
|
|
97
|
+
const stringify = (value, parents = []) => {
|
|
98
|
+
if (Array.isArray(value)) {
|
|
99
|
+
let arrayString = '[\n';
|
|
100
|
+
value.map((element) => {
|
|
101
|
+
const currentParents = [
|
|
102
|
+
...parents,
|
|
103
|
+
exports.ArraySymbol,
|
|
104
|
+
];
|
|
105
|
+
arrayString += '\t'.repeat(currentParents.length) +
|
|
106
|
+
checkQuotes(currentParents, element) + ',\n';
|
|
107
|
+
});
|
|
108
|
+
return arrayString + `${'\t'.repeat(parents.length)}]`;
|
|
109
|
+
}
|
|
110
|
+
if (!isRecord(value)) {
|
|
111
|
+
return typeof value === 'number' || typeof value === 'boolean' || !value
|
|
112
|
+
? String(value)
|
|
113
|
+
: `"${String(value)}"`;
|
|
114
|
+
}
|
|
115
|
+
const objectString = Object.keys(value).map((key) => {
|
|
116
|
+
const currentParents = [
|
|
117
|
+
...parents,
|
|
118
|
+
key,
|
|
119
|
+
];
|
|
120
|
+
const prefix = '\t'.repeat(currentParents.length);
|
|
121
|
+
return `${prefix}${key}: ${checkQuotes(currentParents, value[key])}`;
|
|
122
|
+
}).join(',\n');
|
|
123
|
+
return `{\n${objectString}\n${'\t'.repeat(parents.length)}}`;
|
|
124
|
+
};
|
|
125
|
+
exports.stringify = stringify;
|
|
126
|
+
const checkQuotes = (parents, value) => {
|
|
127
|
+
if (value && typeof value === 'object' && exports.UnquotedSymbol in value) {
|
|
128
|
+
return value[exports.UnquotedSymbol];
|
|
129
|
+
}
|
|
130
|
+
return (0, exports.stringify)(value, parents);
|
|
131
|
+
};
|
|
132
|
+
/** Used to make the id and the schema name of the collection */
|
|
133
|
+
const resizeFirstChar = (text, capitalize) => {
|
|
134
|
+
if (capitalize === true) {
|
|
135
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
136
|
+
}
|
|
137
|
+
return text.charAt(0).toLowerCase() + text.slice(1);
|
|
138
|
+
};
|
|
139
|
+
exports.resizeFirstChar = resizeFirstChar;
|
|
140
|
+
const getCollectionId = (name) => (0, exports.resizeFirstChar)(name, false);
|
|
141
|
+
exports.getCollectionId = getCollectionId;
|
|
142
|
+
const getExtendName = (name) => `extend${(0, exports.resizeFirstChar)(name, true)}Collection`;
|
|
143
|
+
exports.getExtendName = getExtendName;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
export const PACKAGE_NAME = "aeria";
|
|
3
|
+
export const DEFAULT_FUNCTIONS = [
|
|
4
|
+
"count",
|
|
5
|
+
"get",
|
|
6
|
+
"getAll",
|
|
7
|
+
"insert",
|
|
8
|
+
"upload",
|
|
9
|
+
"remove",
|
|
10
|
+
"removeAll",
|
|
11
|
+
"removeFile"
|
|
12
|
+
];
|
|
13
|
+
export const ArraySymbol = Symbol("array");
|
|
14
|
+
export const getExposedFunctions = (astFunctions) => {
|
|
15
|
+
return Object.fromEntries(Object.entries(astFunctions).map(([key, value]) => [
|
|
16
|
+
key,
|
|
17
|
+
value.accessCondition
|
|
18
|
+
]));
|
|
19
|
+
};
|
|
20
|
+
export const makeASTImports = (ast, initialImports) => {
|
|
21
|
+
const modifiedSymbols = {};
|
|
22
|
+
const toImport = ast.reduce((imports, node) => {
|
|
23
|
+
if (node.kind === "collection") {
|
|
24
|
+
if (node.extends?.packageName) {
|
|
25
|
+
if (!(node.extends.packageName in imports)) {
|
|
26
|
+
imports[node.extends.packageName] = /* @__PURE__ */ new Set();
|
|
27
|
+
}
|
|
28
|
+
const modifiedSymbol = `original${resizeFirstChar(node.extends.symbolName, true)}`;
|
|
29
|
+
modifiedSymbols[node.extends.symbolName] = modifiedSymbol;
|
|
30
|
+
imports[node.extends.packageName].add(`${node.extends.symbolName} as ${modifiedSymbol}`);
|
|
31
|
+
}
|
|
32
|
+
if (node.functions) {
|
|
33
|
+
const functionsToImport = Object.keys(node.functions).filter((key) => DEFAULT_FUNCTIONS.includes(key));
|
|
34
|
+
if (functionsToImport.length > 0) {
|
|
35
|
+
if (!(PACKAGE_NAME in imports)) {
|
|
36
|
+
imports[PACKAGE_NAME] = /* @__PURE__ */ new Set();
|
|
37
|
+
}
|
|
38
|
+
for (const key of functionsToImport) {
|
|
39
|
+
imports[PACKAGE_NAME].add(key);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return imports;
|
|
45
|
+
}, initialImports ?? {});
|
|
46
|
+
return {
|
|
47
|
+
code: Object.keys(toImport).map((key) => `import { ${Array.from(toImport[key]).join(", ")} } from '${key}'`),
|
|
48
|
+
modifiedSymbols
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export const propertyToSchema = (propertyNode) => {
|
|
52
|
+
const propertySchema = propertyNode.property;
|
|
53
|
+
if ("$ref" in propertySchema) {
|
|
54
|
+
propertySchema.$ref = getCollectionId(propertySchema.$ref);
|
|
55
|
+
} else if ("items" in propertySchema && "$ref" in propertySchema.items) {
|
|
56
|
+
propertySchema.items.$ref = getCollectionId(propertySchema.items.$ref);
|
|
57
|
+
}
|
|
58
|
+
if (propertyNode.nestedProperties && "type" in propertySchema) {
|
|
59
|
+
if (propertySchema.type === "object" && "properties" in propertySchema) {
|
|
60
|
+
propertySchema.properties = getProperties(propertyNode.nestedProperties);
|
|
61
|
+
} else if (propertySchema.type === "array") {
|
|
62
|
+
propertySchema.items = {
|
|
63
|
+
type: "object",
|
|
64
|
+
properties: getProperties(propertyNode.nestedProperties)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return propertySchema;
|
|
69
|
+
};
|
|
70
|
+
export const getProperties = (properties) => {
|
|
71
|
+
return Object.entries(properties).reduce((acc, [key, value]) => {
|
|
72
|
+
if (Array.isArray(value)) {
|
|
73
|
+
acc[key] = value.map((propertyNode) => propertyToSchema(propertyNode));
|
|
74
|
+
} else {
|
|
75
|
+
acc[key] = propertyToSchema(value);
|
|
76
|
+
}
|
|
77
|
+
return acc;
|
|
78
|
+
}, {});
|
|
79
|
+
};
|
|
80
|
+
export const UnquotedSymbol = Symbol("unquoted");
|
|
81
|
+
const isRecord = (value) => typeof value === "object";
|
|
82
|
+
export const stringify = (value, parents = []) => {
|
|
83
|
+
if (Array.isArray(value)) {
|
|
84
|
+
let arrayString = "[\n";
|
|
85
|
+
value.map((element) => {
|
|
86
|
+
const currentParents = [
|
|
87
|
+
...parents,
|
|
88
|
+
ArraySymbol
|
|
89
|
+
];
|
|
90
|
+
arrayString += " ".repeat(currentParents.length) + checkQuotes(currentParents, element) + ",\n";
|
|
91
|
+
});
|
|
92
|
+
return arrayString + `${" ".repeat(parents.length)}]`;
|
|
93
|
+
}
|
|
94
|
+
if (!isRecord(value)) {
|
|
95
|
+
return typeof value === "number" || typeof value === "boolean" || !value ? String(value) : `"${String(value)}"`;
|
|
96
|
+
}
|
|
97
|
+
const objectString = Object.keys(value).map((key) => {
|
|
98
|
+
const currentParents = [
|
|
99
|
+
...parents,
|
|
100
|
+
key
|
|
101
|
+
];
|
|
102
|
+
const prefix = " ".repeat(currentParents.length);
|
|
103
|
+
return `${prefix}${key}: ${checkQuotes(currentParents, value[key])}`;
|
|
104
|
+
}).join(",\n");
|
|
105
|
+
return `{
|
|
106
|
+
${objectString}
|
|
107
|
+
${" ".repeat(parents.length)}}`;
|
|
108
|
+
};
|
|
109
|
+
const checkQuotes = (parents, value) => {
|
|
110
|
+
if (value && typeof value === "object" && UnquotedSymbol in value) {
|
|
111
|
+
return value[UnquotedSymbol];
|
|
112
|
+
}
|
|
113
|
+
return stringify(value, parents);
|
|
114
|
+
};
|
|
115
|
+
export const resizeFirstChar = (text, capitalize) => {
|
|
116
|
+
if (capitalize === true) {
|
|
117
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
118
|
+
}
|
|
119
|
+
return text.charAt(0).toLowerCase() + text.slice(1);
|
|
120
|
+
};
|
|
121
|
+
export const getCollectionId = (name) => resizeFirstChar(name, false);
|
|
122
|
+
export const getExtendName = (name) => `extend${resizeFirstChar(name, true)}Collection`;
|
package/dist/codegen.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateCode = void 0;
|
|
37
|
+
const index_js_1 = require("./codegen/index.js");
|
|
38
|
+
const fsPromises = __importStar(require("node:fs/promises"));
|
|
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
|
+
const generateFileMap = async (fileTree, outDir) => {
|
|
55
|
+
const mappedPaths = {};
|
|
56
|
+
const mapPathTree = async (tree, previousPath) => {
|
|
57
|
+
for (const treePath in tree) {
|
|
58
|
+
const currentPath = path.join(previousPath, treePath);
|
|
59
|
+
if (typeof tree[treePath] === 'object') {
|
|
60
|
+
await mapPathTree(tree[treePath], currentPath);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
await fsPromises.mkdir(previousPath, {
|
|
64
|
+
recursive: true,
|
|
65
|
+
});
|
|
66
|
+
mappedPaths[currentPath] = tree[treePath];
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
};
|
|
70
|
+
await mapPathTree(fileTree, outDir);
|
|
71
|
+
return mappedPaths;
|
|
72
|
+
};
|
|
73
|
+
const generateCode = async (ast, options) => {
|
|
74
|
+
const contracts = (0, index_js_1.generateContracts)(ast.contracts);
|
|
75
|
+
const exports = (0, index_js_1.generateExports)(ast, Boolean(contracts));
|
|
76
|
+
const fileTree = {
|
|
77
|
+
['collections']: {
|
|
78
|
+
['collections.d.ts']: (0, index_js_1.generateTSCollections)(ast.collections),
|
|
79
|
+
['collections.js']: (0, index_js_1.generateJSCollections)(ast.collections),
|
|
80
|
+
['index.d.ts']: exports.collections.dTs,
|
|
81
|
+
['index.js']: exports.collections.js,
|
|
82
|
+
},
|
|
83
|
+
['index.d.ts']: exports.main.dTs,
|
|
84
|
+
['index.js']: exports.main.js,
|
|
85
|
+
};
|
|
86
|
+
if (contracts) {
|
|
87
|
+
fileTree.contracts = {
|
|
88
|
+
['contracts.js']: contracts.js,
|
|
89
|
+
['contracts.d.ts']: contracts.dTs,
|
|
90
|
+
['index.d.ts']: exports.contracts.dTs,
|
|
91
|
+
['index.js']: exports.contracts.js,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const fileStructure = await generateFileMap(fileTree, options.outDir);
|
|
95
|
+
if (!options.dryRun) {
|
|
96
|
+
for (const path in fileStructure) {
|
|
97
|
+
await fsPromises.writeFile(path, fileStructure[path]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return fileStructure;
|
|
101
|
+
};
|
|
102
|
+
exports.generateCode = generateCode;
|
package/dist/codegen.mjs
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { generateContracts, generateExports, generateJSCollections, generateTSCollections } from "./codegen/index.mjs";
|
|
3
|
+
import * as fsPromises from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
const generateFileMap = async (fileTree, outDir) => {
|
|
6
|
+
const mappedPaths = {};
|
|
7
|
+
const mapPathTree = async (tree, previousPath) => {
|
|
8
|
+
for (const treePath in tree) {
|
|
9
|
+
const currentPath = path.join(previousPath, treePath);
|
|
10
|
+
if (typeof tree[treePath] === "object") {
|
|
11
|
+
await mapPathTree(tree[treePath], currentPath);
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
await fsPromises.mkdir(previousPath, {
|
|
15
|
+
recursive: true
|
|
16
|
+
});
|
|
17
|
+
mappedPaths[currentPath] = tree[treePath];
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
};
|
|
21
|
+
await mapPathTree(fileTree, outDir);
|
|
22
|
+
return mappedPaths;
|
|
23
|
+
};
|
|
24
|
+
export const generateCode = async (ast, options) => {
|
|
25
|
+
const contracts = generateContracts(ast.contracts);
|
|
26
|
+
const exports = generateExports(ast, Boolean(contracts));
|
|
27
|
+
const fileTree = {
|
|
28
|
+
["collections"]: {
|
|
29
|
+
["collections.d.ts"]: generateTSCollections(ast.collections),
|
|
30
|
+
["collections.mjs"]: generateJSCollections(ast.collections),
|
|
31
|
+
["index.d.ts"]: exports.collections.dTs,
|
|
32
|
+
["index.mjs"]: exports.collections.js
|
|
33
|
+
},
|
|
34
|
+
["index.d.ts"]: exports.main.dTs,
|
|
35
|
+
["index.mjs"]: exports.main.js
|
|
36
|
+
};
|
|
37
|
+
if (contracts) {
|
|
38
|
+
fileTree.contracts = {
|
|
39
|
+
["contracts.mjs"]: contracts.js,
|
|
40
|
+
["contracts.d.ts"]: contracts.dTs,
|
|
41
|
+
["index.d.ts"]: exports.contracts.dTs,
|
|
42
|
+
["index.mjs"]: exports.contracts.js
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const fileStructure = await generateFileMap(fileTree, options.outDir);
|
|
46
|
+
if (!options.dryRun) {
|
|
47
|
+
for (const path2 in fileStructure) {
|
|
48
|
+
await fsPromises.writeFile(path2, fileStructure[path2]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return fileStructure;
|
|
52
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type * as AST from './ast.js';
|
|
2
|
+
import { Diagnostic } from './diagnostic.js';
|
|
3
|
+
export type CompilationResult = {
|
|
4
|
+
success: boolean;
|
|
5
|
+
ast: AST.ProgramNode;
|
|
6
|
+
errors: Diagnostic[];
|
|
7
|
+
errorCount: number;
|
|
8
|
+
};
|
|
9
|
+
export type CompilationOptions = {
|
|
10
|
+
outDir: string;
|
|
11
|
+
dryRun?: true;
|
|
12
|
+
};
|
|
13
|
+
export declare const parseAndCheck: (sources: Record<string, string>) => Promise<CompilationResult>;
|
|
14
|
+
export declare const generateScaffolding: (options: CompilationOptions) => Promise<string[]>;
|
|
15
|
+
export declare const compileFromFiles: (schemaDir: string, options: CompilationOptions) => Promise<{
|
|
16
|
+
emittedFiles: Record<string, string>;
|
|
17
|
+
success: boolean;
|
|
18
|
+
ast: AST.ProgramNode;
|
|
19
|
+
errors: Diagnostic[];
|
|
20
|
+
errorCount: number;
|
|
21
|
+
}>;
|