@mxpicture/gcp-functions-generator 0.2.0

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.
Files changed (51) hide show
  1. package/dist/4testing/index.d.ts +1 -0
  2. package/dist/4testing/index.js +2 -0
  3. package/dist/4testing/templates/index.d.ts +2 -0
  4. package/dist/4testing/templates/index.js +3 -0
  5. package/dist/4testing/templates/template.medication.d.ts +35 -0
  6. package/dist/4testing/templates/template.medication.js +134 -0
  7. package/dist/4testing/templates/template.settings.d.ts +23 -0
  8. package/dist/4testing/templates/template.settings.js +73 -0
  9. package/dist/4testing/utils.d.ts +5 -0
  10. package/dist/4testing/utils.js +14 -0
  11. package/dist/common/Barrel.d.ts +24 -0
  12. package/dist/common/Barrel.js +80 -0
  13. package/dist/common/Collector.d.ts +22 -0
  14. package/dist/common/Collector.js +37 -0
  15. package/dist/common/Directories.d.ts +36 -0
  16. package/dist/common/Directories.js +69 -0
  17. package/dist/common/Evaluate.d.ts +12 -0
  18. package/dist/common/Evaluate.js +120 -0
  19. package/dist/common/Extractor.d.ts +33 -0
  20. package/dist/common/Extractor.js +201 -0
  21. package/dist/common/GenChangeDetector.d.ts +19 -0
  22. package/dist/common/GenChangeDetector.js +33 -0
  23. package/dist/common/generator.common.d.ts +21 -0
  24. package/dist/common/generator.common.js +86 -0
  25. package/dist/common/index.d.ts +7 -0
  26. package/dist/common/index.js +8 -0
  27. package/dist/generator/Generator.d.ts +41 -0
  28. package/dist/generator/Generator.js +132 -0
  29. package/dist/generator/GeneratorAnnotations.d.ts +9 -0
  30. package/dist/generator/GeneratorAnnotations.js +65 -0
  31. package/dist/generator/GeneratorBackend.d.ts +13 -0
  32. package/dist/generator/GeneratorBackend.js +134 -0
  33. package/dist/generator/GeneratorDoc.d.ts +9 -0
  34. package/dist/generator/GeneratorDoc.js +22 -0
  35. package/dist/generator/GeneratorFrontend.d.ts +12 -0
  36. package/dist/generator/GeneratorFrontend.js +94 -0
  37. package/dist/generator/GeneratorRoutes.d.ts +11 -0
  38. package/dist/generator/GeneratorRoutes.js +52 -0
  39. package/dist/generator/GeneratorZod.d.ts +25 -0
  40. package/dist/generator/GeneratorZod.js +149 -0
  41. package/dist/generator/index.d.ts +7 -0
  42. package/dist/generator/index.js +8 -0
  43. package/dist/meta/index.d.ts +3 -0
  44. package/dist/meta/index.js +4 -0
  45. package/dist/meta/meta.decorators.d.ts +26 -0
  46. package/dist/meta/meta.decorators.js +17 -0
  47. package/dist/meta/meta.imports.d.ts +11 -0
  48. package/dist/meta/meta.imports.js +54 -0
  49. package/dist/meta/meta.names.d.ts +13 -0
  50. package/dist/meta/meta.names.js +93 -0
  51. package/package.json +48 -0
@@ -0,0 +1,120 @@
1
+ import ts from "typescript";
2
+ export class Evaluate {
3
+ checker;
4
+ seen;
5
+ constructor(checker, seen = new Set()) {
6
+ this.checker = checker;
7
+ this.seen = seen;
8
+ }
9
+ array(expr) {
10
+ return ts.isArrayLiteralExpression(expr)
11
+ ? expr.elements.map((e) => new Evaluate(this.checker).run(e))
12
+ : undefined;
13
+ }
14
+ prop(expr) {
15
+ if (!ts.isPropertyAccessExpression(expr))
16
+ return;
17
+ const sym = this.checker.getSymbolAtLocation(expr);
18
+ if (!sym)
19
+ return expr.getText();
20
+ const decl = sym.valueDeclaration ?? sym.declarations?.[0];
21
+ if (!decl)
22
+ return expr.getText();
23
+ if (decl && ts.isEnumMember(decl)) {
24
+ try {
25
+ const val = this.checker.getConstantValue(decl);
26
+ if (val !== undefined)
27
+ return val;
28
+ }
29
+ catch { }
30
+ }
31
+ if (decl && ts.isVariableDeclaration(decl) && decl.initializer)
32
+ return new Evaluate(this.checker).run(decl.initializer);
33
+ return expr.getText();
34
+ }
35
+ identifier(expr) {
36
+ if (!ts.isIdentifier(expr))
37
+ return;
38
+ const sym = this.checker.getSymbolAtLocation(expr);
39
+ if (!sym)
40
+ return expr.text;
41
+ const decl = sym.valueDeclaration ?? sym.declarations?.[0];
42
+ if (!decl)
43
+ return expr.text;
44
+ // enum member or const variable with initializer
45
+ if (ts.isEnumMember(decl)) {
46
+ try {
47
+ const val = this.checker.getConstantValue(decl);
48
+ if (val !== undefined)
49
+ return val;
50
+ }
51
+ catch {
52
+ // fallthrough
53
+ }
54
+ }
55
+ if ((ts.isVariableDeclaration(decl) && decl.initializer) ||
56
+ (ts.isPropertyAssignment(decl) && decl.initializer))
57
+ return new Evaluate(this.checker).run(decl.initializer);
58
+ return expr.text;
59
+ }
60
+ object(expr) {
61
+ if (!ts.isObjectLiteralExpression(expr))
62
+ return undefined;
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ const out = {};
65
+ for (const prop of expr.properties) {
66
+ if (ts.isPropertyAssignment(prop)) {
67
+ const name = this.getNameText(prop.name);
68
+ if (name)
69
+ out[name] = new Evaluate(this.checker).run(prop.initializer);
70
+ continue;
71
+ }
72
+ if (ts.isShorthandPropertyAssignment(prop)) {
73
+ // shorthand -> same identifier; try to resolve initializer
74
+ out[prop.name.text] = new Evaluate(this.checker, this.seen).run(prop.name);
75
+ continue;
76
+ }
77
+ if (ts.isSpreadAssignment(prop)) {
78
+ const spread = new Evaluate(this.checker).run(prop.expression);
79
+ if (typeof spread === "object")
80
+ Object.assign(out, spread);
81
+ continue;
82
+ }
83
+ }
84
+ return out;
85
+ }
86
+ getNameText(name) {
87
+ if (ts.isIdentifier(name) ||
88
+ ts.isStringLiteral(name) ||
89
+ ts.isNumericLiteral(name))
90
+ return name.getText().replace(/^["']|["']$/g, "");
91
+ if (!ts.isComputedPropertyName(name))
92
+ return undefined;
93
+ const expr = name.expression;
94
+ if (ts.isStringLiteral(expr) || ts.isNumericLiteral(expr))
95
+ return expr.text;
96
+ return expr.getText();
97
+ }
98
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
+ run(expr) {
100
+ if (this.seen.has(expr))
101
+ return undefined;
102
+ this.seen.add(expr);
103
+ // Literals
104
+ if (ts.isStringLiteral(expr) || ts.isNoSubstitutionTemplateLiteral(expr))
105
+ return expr.text;
106
+ if (ts.isNumericLiteral(expr))
107
+ return Number(expr.text);
108
+ if (expr.kind === ts.SyntaxKind.TrueKeyword)
109
+ return true;
110
+ if (expr.kind === ts.SyntaxKind.FalseKeyword)
111
+ return false;
112
+ if (expr.kind === ts.SyntaxKind.NullKeyword)
113
+ return null;
114
+ return (this.array(expr) ??
115
+ this.prop(expr) ??
116
+ this.identifier(expr) ??
117
+ this.object(expr) ??
118
+ expr.getText());
119
+ }
120
+ }
@@ -0,0 +1,33 @@
1
+ import ts from "typescript";
2
+ import { DocumentData } from "@mxpicture/gcp-functions-common/types";
3
+ import { CrudRouteName, MetaHeadData, MetaHeadDecorator, MetaHeadOptionsBase, MetaPropertyData, MetaPropertyDecorator, MetaPropertyOptionsBase } from "@mxpicture/gcp-functions-common/meta";
4
+ import type { MetaRouteParams, MetaHeadInterfaceOptions, MetaFile } from "@mxpicture/gcp-functions-common/types";
5
+ export type MetaHeadExtract = {
6
+ [K in keyof MetaHeadOptionsBase]: (property: ts.ClassDeclaration) => MetaHeadData | undefined;
7
+ };
8
+ export type MetaPropertyExtract = {
9
+ [K in keyof MetaPropertyOptionsBase]: (property: ts.PropertyDeclaration) => MetaPropertyData | undefined;
10
+ };
11
+ export declare const createExtractors: (filePaths: string[]) => Promise<Extractor[]>;
12
+ export declare const extractFiles: (extractors: Extractor[]) => MetaFile[];
13
+ export declare const crudRoutes: (docName: string) => Record<CrudRouteName, MetaRouteParams>;
14
+ export declare class Extractor {
15
+ readonly filePath: string;
16
+ readonly checker: ts.TypeChecker;
17
+ readonly sourceFile: ts.SourceFile;
18
+ readonly rootDir: string;
19
+ protected propertyExtr: MetaPropertyExtract;
20
+ protected mainExtr: MetaHeadExtract;
21
+ constructor(filePath: string, checker: ts.TypeChecker, sourceFile: ts.SourceFile, rootDir: string);
22
+ run(): MetaFile;
23
+ header(main: ts.ClassDeclaration): MetaHeadData | undefined;
24
+ property(property: ts.PropertyDeclaration): MetaPropertyData | undefined;
25
+ protected buildPropertyExtr(): MetaPropertyExtract;
26
+ protected buildMainExtr(): MetaHeadExtract;
27
+ protected buildMainExtrRoutes(templateName: string, o: MetaHeadInterfaceOptions): Record<string, MetaRouteParams>;
28
+ protected findDecorator(modifiers: ts.NodeArray<ts.ModifierLike> | undefined, name: string): ts.Decorator | undefined;
29
+ protected extractType(property: ts.PropertyDeclaration): string;
30
+ protected extractProperty<K extends MetaPropertyDecorator, T extends MetaPropertyOptionsBase[K] = MetaPropertyOptionsBase[K]>(type: K, modifiers: ts.NodeArray<ts.ModifierLike> | undefined): T | undefined;
31
+ protected extractMain<K extends MetaHeadDecorator, T extends MetaHeadOptionsBase[K] = MetaHeadOptionsBase[K]>(type: K, modifiers: ts.NodeArray<ts.ModifierLike> | undefined): T | undefined;
32
+ protected extractAny<T extends DocumentData>(name: string, modifiers: ts.NodeArray<ts.ModifierLike> | undefined): T | undefined;
33
+ }
@@ -0,0 +1,201 @@
1
+ import ts from "typescript";
2
+ import { Evaluate } from "./Evaluate.js";
3
+ import { metaRename } from "../meta/meta.names.js";
4
+ import { relative } from "node:path";
5
+ import { VSCodeWorkspace } from "@mxpicture/gcp-functions-code/vscode";
6
+ import { createSourceFiles } from "@mxpicture/gcp-functions-code/common";
7
+ import { MetaFileType, MetaHeadType, metaMainOptionsMap, metaPropertyOptionsMap, } from "@mxpicture/gcp-functions-common/meta";
8
+ export const createExtractors = async (filePaths) => {
9
+ const rootDir = (await VSCodeWorkspace.loadAsync()).root;
10
+ return createSourceFiles(filePaths).map((f) => new Extractor(f.filePath, f.checker, f.sourceFile, rootDir));
11
+ };
12
+ export const extractFiles = (extractors) => extractors.map((extractor) => extractor.run());
13
+ export const crudRoutes = (docName) => ({
14
+ create: {
15
+ requestType: `WithoutKey<${docName}>`,
16
+ responseType: `WithKey<${docName}>`,
17
+ },
18
+ update: {
19
+ requestType: `WithKey<Partial<${docName}>>`,
20
+ responseType: `WithKey<${docName}>`,
21
+ },
22
+ delete: { requestType: "DocumentKey", responseType: "{ deleted: true }" },
23
+ get: { requestType: "DocumentKey", responseType: `WithKey<${docName}>` },
24
+ query: {
25
+ requestType: "ApiFilter | undefined | null | never",
26
+ responseType: `WithKey<${docName}>[]`,
27
+ },
28
+ count: {
29
+ requestType: "ApiFilter | undefined | null | never",
30
+ responseType: "{ count: number }",
31
+ },
32
+ exists: { requestType: "DocumentKey", responseType: "{ exists: boolean }" },
33
+ });
34
+ export class Extractor {
35
+ filePath;
36
+ checker;
37
+ sourceFile;
38
+ rootDir;
39
+ propertyExtr;
40
+ mainExtr;
41
+ constructor(filePath, checker, sourceFile, rootDir) {
42
+ this.filePath = filePath;
43
+ this.checker = checker;
44
+ this.sourceFile = sourceFile;
45
+ this.rootDir = rootDir;
46
+ this.propertyExtr = this.buildPropertyExtr();
47
+ this.mainExtr = this.buildMainExtr();
48
+ }
49
+ run() {
50
+ const result = {
51
+ templateFilePath: this.filePath,
52
+ templateRepoFilePath: relative(this.rootDir, this.filePath),
53
+ headers: [],
54
+ };
55
+ ts.forEachChild(this.sourceFile, (node) => {
56
+ if (!ts.isClassDeclaration(node))
57
+ return;
58
+ const header = this.header(node);
59
+ if (!header)
60
+ return;
61
+ for (const member of node.members) {
62
+ if (!ts.isPropertyDeclaration(member) || !member.type)
63
+ continue;
64
+ const prop = this.property(member);
65
+ if (!prop)
66
+ continue;
67
+ header.properties.push(prop);
68
+ }
69
+ result.headers.push(header);
70
+ });
71
+ return result;
72
+ }
73
+ header(main) {
74
+ for (const opt of Object.values(this.mainExtr)) {
75
+ const res = opt(main);
76
+ if (res)
77
+ return res;
78
+ }
79
+ return;
80
+ }
81
+ property(property) {
82
+ for (const opt of Object.values(this.propertyExtr)) {
83
+ const res = opt(property);
84
+ if (res)
85
+ return res;
86
+ }
87
+ return;
88
+ }
89
+ buildPropertyExtr() {
90
+ const opts = {};
91
+ for (const _key of Object.keys(metaPropertyOptionsMap)) {
92
+ const decoratorType = _key;
93
+ opts[decoratorType] = (property) => {
94
+ const o = this.extractProperty(decoratorType, property.modifiers);
95
+ if (!o)
96
+ return;
97
+ const res = {
98
+ ...o,
99
+ [decoratorType]: o,
100
+ propertyKey: property.name.getText(this.sourceFile),
101
+ propertyType: this.extractType(property),
102
+ type: metaPropertyOptionsMap[decoratorType],
103
+ };
104
+ return res;
105
+ };
106
+ }
107
+ return opts;
108
+ }
109
+ buildMainExtr() {
110
+ const opts = {};
111
+ for (const _key of Object.keys(metaMainOptionsMap)) {
112
+ const decoratorType = _key;
113
+ opts[decoratorType] = (cls) => {
114
+ const o = this.extractMain(decoratorType, cls.modifiers);
115
+ if (!o)
116
+ return;
117
+ const templateName = cls.name?.text ?? "<anonymous>";
118
+ o.type = metaMainOptionsMap[decoratorType];
119
+ let routes = {};
120
+ let additionalImports = undefined;
121
+ let prefix = undefined;
122
+ if (o.type === MetaHeadType.mainInterface) {
123
+ routes = this.buildMainExtrRoutes(templateName, o);
124
+ additionalImports = o.additionalImports;
125
+ prefix = o.prefix;
126
+ }
127
+ return {
128
+ ...o,
129
+ templateName,
130
+ inputFilePath: this.filePath,
131
+ repoInputFilePath: relative(this.rootDir, this.filePath),
132
+ properties: [],
133
+ routes,
134
+ additionalImports,
135
+ prefix,
136
+ };
137
+ };
138
+ }
139
+ return opts;
140
+ }
141
+ buildMainExtrRoutes(templateName, o) {
142
+ const routes = {};
143
+ for (const [routeName, _params] of Object.entries(o.routes)) {
144
+ if (typeof _params === "object") {
145
+ const params = _params;
146
+ routes[routeName] = { ...params };
147
+ continue;
148
+ }
149
+ // crud
150
+ if (typeof _params === "boolean" && _params) {
151
+ for (const [routeName, params] of Object.entries(crudRoutes(metaRename(templateName, MetaFileType.doc))))
152
+ routes[routeName] = { ...params };
153
+ continue;
154
+ }
155
+ }
156
+ return routes;
157
+ }
158
+ findDecorator(modifiers, name) {
159
+ return modifiers?.find((m) => {
160
+ if (!ts.isDecorator(m))
161
+ return false;
162
+ const expr = m.expression;
163
+ // bare identifier: @Track
164
+ if (ts.isIdentifier(expr) && expr.text === name)
165
+ return true;
166
+ // call expression: @Tracked("...")
167
+ if (ts.isCallExpression(expr) &&
168
+ ts.isIdentifier(expr.expression) &&
169
+ expr.expression.text === name)
170
+ return true;
171
+ return false;
172
+ });
173
+ }
174
+ extractType(property) {
175
+ return property.type
176
+ ? this.checker.typeToString(this.checker.getTypeFromTypeNode(property.type))
177
+ : "unknown";
178
+ }
179
+ extractProperty(type, modifiers) {
180
+ return this.extractAny(type, modifiers);
181
+ }
182
+ extractMain(type, modifiers) {
183
+ return this.extractAny(type, modifiers);
184
+ }
185
+ extractAny(name, modifiers) {
186
+ const decorator = this.findDecorator(modifiers, name);
187
+ if (!decorator)
188
+ return;
189
+ const expr = decorator.expression;
190
+ if (!ts.isCallExpression(expr) || expr.arguments.length === 0)
191
+ return;
192
+ const first = expr.arguments[0];
193
+ const e = new Evaluate(this.checker);
194
+ // If it's already an object literal, evaluate to a plain object
195
+ if (ts.isObjectLiteralExpression(first))
196
+ return e.run(first);
197
+ // If it's an identifier / enum / referenced const, try to resolve it to a value
198
+ const resolved = e.run(first);
199
+ return typeof resolved === "object" ? resolved : undefined;
200
+ }
201
+ }
@@ -0,0 +1,19 @@
1
+ import { MetaFileType } from "@mxpicture/gcp-functions-common/meta";
2
+ import { ChangeDetector, ChangeEventHandler, Changelog, PackageVersion } from "@mxpicture/gcp-functions-code/changelog";
3
+ import { GitChangesCommit } from "@mxpicture/gcp-functions-code/git";
4
+ export interface GenChangeParams {
5
+ gitSinceCommit: {
6
+ rootDir: string;
7
+ sinceCommit: string;
8
+ } | GitChangesCommit;
9
+ log?: Changelog;
10
+ sinceVersion?: PackageVersion;
11
+ }
12
+ export interface GenChangeResult {
13
+ fileTypes: MetaFileType[];
14
+ templateNames: string[];
15
+ }
16
+ export declare class GenChangeDetector<T extends GenChangeResult = GenChangeResult> extends ChangeDetector<T> {
17
+ }
18
+ export declare const genChangeEventHandler: ChangeEventHandler<GenChangeResult>;
19
+ export declare const createGenChangeDetector: (p: GenChangeParams) => GenChangeDetector;
@@ -0,0 +1,33 @@
1
+ import { ChangeDetector, ChangeWatchType, Changelog, } from "@mxpicture/gcp-functions-code/changelog";
2
+ import { GitChangesCommit } from "@mxpicture/gcp-functions-code/git";
3
+ import { createGenerators, } from "@mxpicture/gcp-functions-generator/common";
4
+ export class GenChangeDetector extends ChangeDetector {
5
+ }
6
+ const endsWithName = (path, filenameWoExt) => path.endsWith(`/${filenameWoExt}.ts`) ||
7
+ path.endsWith(`/${filenameWoExt}.js`);
8
+ const findEndsWithName = (paths, gen) => !!paths.find((path) => endsWithName(path, gen.filenameWoExt));
9
+ export const genChangeEventHandler = async (paths,
10
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
11
+ watch) => {
12
+ const gens = await createGenerators();
13
+ if (gens.length === 0)
14
+ return null;
15
+ const result = { fileTypes: [], templateNames: [] };
16
+ for (const gen of gens)
17
+ if (findEndsWithName(paths, gen))
18
+ result.fileTypes.push(gen.gen.type);
19
+ return result;
20
+ };
21
+ export const createGenChangeDetector = (p) => {
22
+ const git = p.gitSinceCommit instanceof GitChangesCommit
23
+ ? p.gitSinceCommit
24
+ : new GitChangesCommit(p.gitSinceCommit.rootDir, p.gitSinceCommit.sinceCommit);
25
+ const log = p.log ?? new Changelog(git);
26
+ const det = new GenChangeDetector(log, git, p.sinceVersion);
27
+ det.addWatch({
28
+ handler: genChangeEventHandler,
29
+ pattern: "packages/generator/src/generator/Generator*",
30
+ type: ChangeWatchType.changelog,
31
+ });
32
+ return det;
33
+ };
@@ -0,0 +1,21 @@
1
+ import { Generator, GeneratorResultFile } from "../generator/Generator.js";
2
+ import { DirectoriesParams } from "./Directories.js";
3
+ import { MetaFile } from "@mxpicture/gcp-functions-common/types";
4
+ export declare const generatorDirPath: string;
5
+ export declare const toolsDirPath: string;
6
+ export interface GeneratorFile {
7
+ filename: string;
8
+ filePath: string;
9
+ filenameWoExt: string;
10
+ fileExt: string;
11
+ }
12
+ export interface GeneratorEntry extends GeneratorFile {
13
+ gen: Generator;
14
+ }
15
+ export declare const readGeneratorFiles: () => Promise<GeneratorFile[]>;
16
+ export declare const readGeneratorFile: (filename: string) => Promise<GeneratorFile | null>;
17
+ export declare const createGenerator: (file: GeneratorFile) => Promise<GeneratorEntry | null>;
18
+ export declare const createGenerators: () => Promise<GeneratorEntry[]>;
19
+ export declare const runGeneration: (params: DirectoriesParams) => Promise<void>;
20
+ export declare const runFile: (file: MetaFile, gen: Generator) => Promise<GeneratorResultFile>;
21
+ export declare const runFiles: (files: MetaFile[], gen: Generator) => Promise<GeneratorResultFile[]>;
@@ -0,0 +1,86 @@
1
+ import { dirname, join, parse, resolve } from "node:path";
2
+ import { Generator } from "../generator/Generator.js";
3
+ import { fileURLToPath } from "node:url";
4
+ import { readdir } from "node:fs/promises";
5
+ import { directories } from "./Directories.js";
6
+ import { createExtractors, extractFiles } from "./Extractor.js";
7
+ import { Barrel } from "./Barrel.js";
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ export const generatorDirPath = resolve(__dirname, "../generator");
10
+ export const toolsDirPath = resolve(__dirname, "../..");
11
+ const generators = [];
12
+ let generatorFiles = null;
13
+ export const readGeneratorFiles = async () => {
14
+ if (!generatorFiles) {
15
+ const filenames = (await readdir(generatorDirPath)).filter((filename) => filename !== "Generator.ts" &&
16
+ filename !== "Generator.js" &&
17
+ !filename.endsWith(".d.ts") &&
18
+ (filename.endsWith(".ts") || filename.endsWith(".js")));
19
+ generatorFiles = await Promise.all(filenames.map(async (filename) => {
20
+ const filePath = join(generatorDirPath, filename);
21
+ const parsed = parse(filename);
22
+ return {
23
+ filename,
24
+ filePath,
25
+ filenameWoExt: parsed.name,
26
+ fileExt: parsed.ext,
27
+ };
28
+ }));
29
+ }
30
+ return generatorFiles;
31
+ };
32
+ export const readGeneratorFile = async (filename) => (await readGeneratorFiles()).find((file) => file.filename === filename) ??
33
+ null;
34
+ export const createGenerator = async (file) => {
35
+ let found = generators.find((generator) => generator.filePath === file.filePath);
36
+ if (found)
37
+ return found;
38
+ const gen = (await import(file.filePath)).default;
39
+ if (!(gen instanceof Generator))
40
+ return null;
41
+ found = { ...file, gen };
42
+ generators.push(found);
43
+ return found;
44
+ };
45
+ export const createGenerators = async () => {
46
+ const files = await readGeneratorFiles();
47
+ const promises = files.map(createGenerator);
48
+ const entries = await Promise.all(promises);
49
+ return entries.filter((entry) => !!entry);
50
+ };
51
+ export const runGeneration = async (params) => {
52
+ const { files, entries } = await prepareRunGeneration(params);
53
+ console.log("using:");
54
+ const targetFilesFiles = await Promise.all(entries.map(async (entry) => {
55
+ const resultFiles = await runFiles(files, entry.gen);
56
+ await Generator.write(...resultFiles);
57
+ return resultFiles;
58
+ }));
59
+ const targetFiles = [];
60
+ for (const tarFiles of targetFilesFiles) {
61
+ targetFiles.push(...tarFiles);
62
+ for (const tarFile of tarFiles)
63
+ Barrel.instance(tarFile.targetType).add(tarFile.targetFilePath);
64
+ }
65
+ const promises = [];
66
+ for (const barrel of Barrel.instances) {
67
+ const barrelFiles = barrel.create();
68
+ promises.push(barrel.write(barrelFiles));
69
+ promises.push(barrel.ensurePackageBarrels(barrelFiles));
70
+ }
71
+ await Promise.all(promises);
72
+ };
73
+ const prepareRunGeneration = async (params) => {
74
+ directories.setup(params);
75
+ const templateFilePaths = await directories.templatesPathRead();
76
+ const files = extractFiles(await createExtractors(templateFilePaths));
77
+ const entries = await createGenerators();
78
+ return { files, entries };
79
+ };
80
+ export const runFile = async (file, gen) => {
81
+ console.log(` - ${gen.type} (${gen.ext})`);
82
+ const resultFile = await gen.run(file);
83
+ await Generator.write(resultFile);
84
+ return resultFile;
85
+ };
86
+ export const runFiles = async (files, gen) => Promise.all(files.map(async (file) => gen.run(file)));
@@ -0,0 +1,7 @@
1
+ export * from "./Barrel.js";
2
+ export * from "./Collector.js";
3
+ export * from "./Directories.js";
4
+ export * from "./Evaluate.js";
5
+ export * from "./Extractor.js";
6
+ export * from "./GenChangeDetector.js";
7
+ export * from "./generator.common.js";
@@ -0,0 +1,8 @@
1
+ // This file is auto-generated. Do not edit manually.
2
+ export * from "./Barrel.js";
3
+ export * from "./Collector.js";
4
+ export * from "./Directories.js";
5
+ export * from "./Evaluate.js";
6
+ export * from "./Extractor.js";
7
+ export * from "./GenChangeDetector.js";
8
+ export * from "./generator.common.js";
@@ -0,0 +1,41 @@
1
+ import { MetaFile, MetaImport, MetaNames } from "@mxpicture/gcp-functions-common/types";
2
+ import { MetaFileType, MetaFileExtension, MetaTargetType, MetaHeadData } from "@mxpicture/gcp-functions-common/meta";
3
+ import { Collector } from "../common/Collector.js";
4
+ export interface GeneratorBase {
5
+ imports: MetaImport[];
6
+ code: string[];
7
+ }
8
+ export interface GeneratorCode extends GeneratorBase {
9
+ name: string;
10
+ }
11
+ export interface GeneratorResultFile extends GeneratorBase {
12
+ type: MetaFileType;
13
+ ext: MetaFileExtension;
14
+ inputFilePath: string;
15
+ targetFilePath: string;
16
+ targetType: MetaTargetType;
17
+ importsCode: string[];
18
+ }
19
+ export declare const importsToCode: (imports: MetaImport[]) => string[];
20
+ export declare const importsToCodeAsync: (imports: MetaImport[]) => Promise<string[]>;
21
+ export declare abstract class Generator {
22
+ readonly type: MetaFileType;
23
+ readonly ext: MetaFileExtension;
24
+ readonly targetType: MetaTargetType;
25
+ readonly collector: Collector;
26
+ readonly useAdditionalImports: boolean;
27
+ constructor(type: MetaFileType, ext: MetaFileExtension, targetType: MetaTargetType, collector: Collector, useAdditionalImports?: boolean);
28
+ run(file: MetaFile): Promise<GeneratorResultFile>;
29
+ static write(...files: GeneratorResultFile[]): Promise<void>;
30
+ resolveImport(targetType: MetaTargetType, fileType: MetaFileType): string;
31
+ importCommon(fileType: MetaFileType): string;
32
+ importFrontend(fileType: MetaFileType): string;
33
+ importBackend(fileType: MetaFileType): string;
34
+ protected addCode(res: GeneratorResultFile, code: string[]): void;
35
+ protected addImport(res: GeneratorResultFile, imp: MetaImport): void;
36
+ protected addImports(res: GeneratorResultFile, imports: MetaImport[]): void;
37
+ protected processHeader(header: MetaHeadData): Promise<(GeneratorCode & {
38
+ inputFilePath: string;
39
+ }) | null>;
40
+ protected abstract runHeader(interfaceData: MetaHeadData, names: MetaNames): Promise<GeneratorCode | null>;
41
+ }