@snowtop/ent 0.1.0-alpha16 → 0.1.0-alpha24
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/core/ent.d.ts +4 -4
- package/core/ent.js +4 -0
- package/package.json +1 -1
- package/schema/schema.js +1 -0
- package/scripts/{move_generated.d.ts → migrate_v0.1.d.ts} +0 -0
- package/scripts/migrate_v0.1.js +36 -0
- package/tsc/ast.d.ts +13 -2
- package/tsc/ast.js +100 -23
- package/tsc/move_generated.d.ts +1 -0
- package/tsc/move_generated.js +160 -0
- package/tsc/transform.d.ts +21 -0
- package/tsc/transform.js +168 -0
- package/tsc/transform_action.d.ts +20 -0
- package/tsc/transform_action.js +169 -0
- package/tsc/transform_ent.d.ts +17 -0
- package/tsc/transform_ent.js +59 -0
- package/tsc/transform_schema.d.ts +27 -0
- package/{scripts → tsc}/transform_schema.js +106 -107
- package/scripts/move_generated.js +0 -141
- package/scripts/transform_actions.d.ts +0 -1
- package/scripts/transform_actions.js +0 -266
- package/scripts/transform_code.d.ts +0 -1
- package/scripts/transform_code.js +0 -111
- package/scripts/transform_schema.d.ts +0 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { customInfo } from "../tsc/ast";
|
|
3
|
+
import { TransformFile } from "./transform";
|
|
4
|
+
export declare class TransformAction implements TransformFile {
|
|
5
|
+
private customInfo;
|
|
6
|
+
glob: string;
|
|
7
|
+
prettierGlob: string;
|
|
8
|
+
constructor(customInfo: customInfo);
|
|
9
|
+
traverseChild(sourceFile: ts.SourceFile, contents: string, file: string, node: ts.Node): {
|
|
10
|
+
node: ts.Node;
|
|
11
|
+
rawString?: undefined;
|
|
12
|
+
traversed?: undefined;
|
|
13
|
+
imports?: undefined;
|
|
14
|
+
} | {
|
|
15
|
+
rawString: string;
|
|
16
|
+
traversed: boolean;
|
|
17
|
+
imports: Map<string, string[]>;
|
|
18
|
+
node?: undefined;
|
|
19
|
+
} | undefined;
|
|
20
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.TransformAction = void 0;
|
|
26
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
27
|
+
const ast_1 = require("../tsc/ast");
|
|
28
|
+
const action_1 = require("../action");
|
|
29
|
+
const viewer_1 = require("../core/viewer");
|
|
30
|
+
const path = __importStar(require("path"));
|
|
31
|
+
const snake_case_1 = require("snake-case");
|
|
32
|
+
function findInput(file, classInfo, sourceFile) {
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
const importStatements = sourceFile.statements.filter((stmt) => typescript_1.default.isImportDeclaration(stmt));
|
|
35
|
+
for (const imp of importStatements) {
|
|
36
|
+
const text = imp.moduleSpecifier.getText(sourceFile).slice(1, -1);
|
|
37
|
+
if ((0, ast_1.isSrcGeneratedImport)(imp, sourceFile) ||
|
|
38
|
+
(0, ast_1.isRelativeGeneratedImport)(imp, sourceFile)) {
|
|
39
|
+
// base file and we're importing from it
|
|
40
|
+
// e.g. in create_user_action, we're importing from create_user_action_base
|
|
41
|
+
if (path.basename(file).slice(0, -3) + "_base" !== path.basename(text)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const impInfo = (0, ast_1.getImportInfo)(imp, sourceFile);
|
|
45
|
+
if (!impInfo) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
let inputs = impInfo.imports
|
|
49
|
+
.filter((imp) => imp.trim() && imp.endsWith("Input"))
|
|
50
|
+
.map((v) => v.trim());
|
|
51
|
+
if (inputs.length === 1) {
|
|
52
|
+
return inputs[0];
|
|
53
|
+
}
|
|
54
|
+
if (inputs.length && classInfo.name.endsWith("Action")) {
|
|
55
|
+
const prefix = classInfo.name.slice(0, classInfo.name.length - 6);
|
|
56
|
+
inputs = inputs.filter((imp) => imp.slice(0, imp.length - 5) === prefix);
|
|
57
|
+
if (inputs.length === 1) {
|
|
58
|
+
return inputs[0];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
let m = {
|
|
66
|
+
triggers: {
|
|
67
|
+
m: "getTriggers",
|
|
68
|
+
i: "Trigger",
|
|
69
|
+
},
|
|
70
|
+
observers: {
|
|
71
|
+
m: "getObservers",
|
|
72
|
+
i: "Observer",
|
|
73
|
+
},
|
|
74
|
+
validators: {
|
|
75
|
+
m: "getValidators",
|
|
76
|
+
i: "Validator",
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
function getConversionInfo(mm) {
|
|
80
|
+
if (mm.kind !== typescript_1.default.SyntaxKind.PropertyDeclaration) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const text = mm.name.escapedText;
|
|
84
|
+
const v = m[text];
|
|
85
|
+
if (v === undefined) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
text,
|
|
90
|
+
method: v.m,
|
|
91
|
+
interface: v.i,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
class TransformAction {
|
|
95
|
+
constructor(customInfo) {
|
|
96
|
+
this.customInfo = customInfo;
|
|
97
|
+
this.glob = "src/ent/**/actions/**/*_action.ts";
|
|
98
|
+
this.prettierGlob = "src/ent/**/actions/**.ts";
|
|
99
|
+
}
|
|
100
|
+
traverseChild(sourceFile, contents, file, node) {
|
|
101
|
+
if (!typescript_1.default.isClassDeclaration(node) || !node.heritageClauses) {
|
|
102
|
+
return { node };
|
|
103
|
+
}
|
|
104
|
+
let classInfo = (0, ast_1.getClassInfo)(contents, sourceFile, node);
|
|
105
|
+
// only do classes
|
|
106
|
+
if (!classInfo || !classInfo.default) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// require action
|
|
110
|
+
const p = require(path.join(process.cwd(), "./" + file.slice(0, -3)));
|
|
111
|
+
const action = new p.default(new viewer_1.LoggedOutViewer(), {});
|
|
112
|
+
const builder = action.builder.constructor.name;
|
|
113
|
+
const nodeName = action.builder.ent.name;
|
|
114
|
+
const existingEnt = action.builder.operation === action_1.WriteOperation.Insert
|
|
115
|
+
? `${nodeName} | null`
|
|
116
|
+
: nodeName;
|
|
117
|
+
const viewer = this.customInfo.viewerInfo.name;
|
|
118
|
+
const input = findInput(file, classInfo, sourceFile);
|
|
119
|
+
if (!input) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
let klassContents = "";
|
|
123
|
+
let traversed = false;
|
|
124
|
+
let newImports = [];
|
|
125
|
+
for (const mm of node.members) {
|
|
126
|
+
const conv = getConversionInfo(mm);
|
|
127
|
+
if (conv !== null) {
|
|
128
|
+
const property = mm;
|
|
129
|
+
// if invalid, bounce
|
|
130
|
+
if (!property.initializer) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
traversed = true;
|
|
134
|
+
const pp = property.initializer.getFullText(sourceFile).trim();
|
|
135
|
+
const code = `${conv.method}(): ${conv.interface}<${nodeName}, ${builder}<${input}, ${existingEnt}>, ${viewer}, ${input}, ${existingEnt}>[] {
|
|
136
|
+
return ${pp}
|
|
137
|
+
}`;
|
|
138
|
+
newImports.push(conv.interface);
|
|
139
|
+
klassContents += (0, ast_1.getPreText)(contents, mm, sourceFile) + code;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
klassContents += mm.getFullText(sourceFile);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const builderPath = `src/ent/generated/${(0, snake_case_1.snakeCase)(nodeName)}/actions/${(0, snake_case_1.snakeCase)(builder)}.ts`;
|
|
146
|
+
let imports = new Map([
|
|
147
|
+
[
|
|
148
|
+
(0, ast_1.transformRelative)(file, this.customInfo.viewerInfo.path, this.customInfo.relativeImports),
|
|
149
|
+
[viewer],
|
|
150
|
+
],
|
|
151
|
+
[
|
|
152
|
+
(0, ast_1.transformRelative)(file, "src/ent", this.customInfo.relativeImports),
|
|
153
|
+
[nodeName],
|
|
154
|
+
],
|
|
155
|
+
["@snowtop/ent/action", newImports],
|
|
156
|
+
[
|
|
157
|
+
(0, ast_1.transformRelative)(file, builderPath, this.customInfo.relativeImports),
|
|
158
|
+
[builder],
|
|
159
|
+
],
|
|
160
|
+
]);
|
|
161
|
+
// wrap comments and transform to export class Foo extends Bar { ${inner} }
|
|
162
|
+
return {
|
|
163
|
+
rawString: classInfo.wrapClassContents(klassContents),
|
|
164
|
+
traversed,
|
|
165
|
+
imports,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.TransformAction = TransformAction;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { TransformFile } from "./transform";
|
|
3
|
+
export declare class TransformEnt implements TransformFile {
|
|
4
|
+
glob: string;
|
|
5
|
+
traverseChild(sourceFile: ts.SourceFile, contents: string, file: string, node: ts.Node): {
|
|
6
|
+
node: ts.Node;
|
|
7
|
+
rawString?: undefined;
|
|
8
|
+
traversed?: undefined;
|
|
9
|
+
imports?: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
rawString: string;
|
|
12
|
+
traversed: boolean;
|
|
13
|
+
imports: Map<string, string[]>;
|
|
14
|
+
node?: undefined;
|
|
15
|
+
} | undefined;
|
|
16
|
+
prettierGlob: string;
|
|
17
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TransformEnt = void 0;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
const ast_1 = require("./ast");
|
|
9
|
+
function isPrivacyPolicy(mm) {
|
|
10
|
+
return (mm.kind === typescript_1.default.SyntaxKind.PropertyDeclaration &&
|
|
11
|
+
mm.name.escapedText === "privacyPolicy");
|
|
12
|
+
}
|
|
13
|
+
class TransformEnt {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.glob = "src/ent/*.ts";
|
|
16
|
+
this.prettierGlob = "src/ent/*.ts";
|
|
17
|
+
}
|
|
18
|
+
traverseChild(sourceFile, contents, file, node) {
|
|
19
|
+
if (!typescript_1.default.isClassDeclaration(node) || !node.heritageClauses) {
|
|
20
|
+
return { node };
|
|
21
|
+
}
|
|
22
|
+
let classInfo = (0, ast_1.getClassInfo)(contents, sourceFile, node);
|
|
23
|
+
if (!classInfo) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// different class. ignore
|
|
27
|
+
// only do classes which extend a base class e.g. User extends UserBase
|
|
28
|
+
// if different class (e.g. privacy rule), just return it
|
|
29
|
+
if (classInfo.extends !== classInfo.name + "Base") {
|
|
30
|
+
return { node };
|
|
31
|
+
}
|
|
32
|
+
let klassContents = "";
|
|
33
|
+
let traversed = false;
|
|
34
|
+
for (const mm of node.members) {
|
|
35
|
+
if (isPrivacyPolicy(mm)) {
|
|
36
|
+
const property = mm;
|
|
37
|
+
// if invalid privacy policy, bounce
|
|
38
|
+
if (!property.initializer) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const pp = property.initializer.getFullText(sourceFile);
|
|
42
|
+
const code = `getPrivacyPolicy(): PrivacyPolicy<this> {
|
|
43
|
+
return ${pp}
|
|
44
|
+
}`;
|
|
45
|
+
klassContents += (0, ast_1.getPreText)(contents, mm, sourceFile) + code;
|
|
46
|
+
traversed = true;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
klassContents += mm.getFullText(sourceFile);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
rawString: classInfo.wrapClassContents(klassContents),
|
|
54
|
+
traversed,
|
|
55
|
+
imports: new Map([["@snowtop/ent", ["PrivacyPolicy"]]]),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.TransformEnt = TransformEnt;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { TransformFile } from "./transform";
|
|
3
|
+
export declare class TransformSchema implements TransformFile {
|
|
4
|
+
private relativeImports;
|
|
5
|
+
private oldBaseClass?;
|
|
6
|
+
private newSchemaClass?;
|
|
7
|
+
private transformPath?;
|
|
8
|
+
constructor(relativeImports: boolean, oldBaseClass?: string | undefined, newSchemaClass?: string | undefined, transformPath?: string | undefined);
|
|
9
|
+
glob: string;
|
|
10
|
+
private transformSchema;
|
|
11
|
+
traverseChild(sourceFile: ts.SourceFile, contents: string, file: string, node: ts.Node): {
|
|
12
|
+
node: ts.Node;
|
|
13
|
+
traversed?: undefined;
|
|
14
|
+
rawString?: undefined;
|
|
15
|
+
removeImports?: undefined;
|
|
16
|
+
imports?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
traversed: boolean;
|
|
19
|
+
rawString: string;
|
|
20
|
+
removeImports: string[];
|
|
21
|
+
imports: Map<string, string[]>;
|
|
22
|
+
node?: undefined;
|
|
23
|
+
} | undefined;
|
|
24
|
+
fileToWrite(file: string): string;
|
|
25
|
+
postProcess(file: string): void;
|
|
26
|
+
prettierGlob: string;
|
|
27
|
+
}
|
|
@@ -22,109 +22,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
|
|
25
|
+
exports.TransformSchema = void 0;
|
|
26
26
|
const typescript_1 = __importDefault(require("typescript"));
|
|
27
27
|
const fs = __importStar(require("fs"));
|
|
28
|
-
const compilerOptions_1 = require("../tsc/compilerOptions");
|
|
29
|
-
const child_process_1 = require("child_process");
|
|
30
28
|
const path_1 = __importDefault(require("path"));
|
|
31
29
|
const ast_1 = require("../tsc/ast");
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const target = (0, compilerOptions_1.getTargetFromCurrentDir)();
|
|
35
|
-
// filter to only event.ts e.g. for comments and whitespace...
|
|
36
|
-
// files = files.filter((f) => f.endsWith("event.ts"));
|
|
37
|
-
files.forEach((file) => {
|
|
38
|
-
// assume valid file since we do glob above
|
|
39
|
-
// const idx = file.lastIndexOf(".ts");
|
|
40
|
-
// const writeFile = file.substring(0, idx) + "2" + ".ts";
|
|
41
|
-
// console.debug(file);
|
|
42
|
-
const writeFile = "src/schema/" + path_1.default.basename(file).slice(0, -3) + "_schema.ts";
|
|
43
|
-
// const writeFile = file;
|
|
44
|
-
// console.debug(file, writeFile);
|
|
45
|
-
// go through the file and print everything back if not starting immediately after other position
|
|
46
|
-
let { contents, sourceFile } = (0, compilerOptions_1.createSourceFile)(target, file);
|
|
47
|
-
const nodes = [];
|
|
48
|
-
let updateImport = false;
|
|
49
|
-
let removeImports = [];
|
|
50
|
-
const f = {
|
|
51
|
-
trackNode: function (tni) {
|
|
52
|
-
nodes.push({
|
|
53
|
-
node: tni.node,
|
|
54
|
-
importNode: tni.node && typescript_1.default.isImportDeclaration(tni.node),
|
|
55
|
-
rawString: tni.rawString,
|
|
56
|
-
});
|
|
57
|
-
if (tni.removeImports) {
|
|
58
|
-
removeImports.push(...tni.removeImports);
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
flagUpdateImport() {
|
|
62
|
-
updateImport = true;
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
if (!traverse(contents, sourceFile, f)) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
let newContents = "";
|
|
69
|
-
for (const node of nodes) {
|
|
70
|
-
if (updateImport && node.importNode) {
|
|
71
|
-
const importNode = node.node;
|
|
72
|
-
const transformedImport = (0, ast_1.transformImport)(contents, importNode, sourceFile, {
|
|
73
|
-
removeImports,
|
|
74
|
-
transform: transformSchema,
|
|
75
|
-
});
|
|
76
|
-
if (transformedImport) {
|
|
77
|
-
newContents += transformedImport;
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (node.node) {
|
|
82
|
-
newContents += node.node.getFullText(sourceFile);
|
|
83
|
-
}
|
|
84
|
-
else if (node.rawString) {
|
|
85
|
-
newContents += node.rawString;
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
console.error("invalid node");
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// console.debug(newContents);
|
|
92
|
-
// ideally there's a flag that indicates if we write
|
|
93
|
-
fs.writeFileSync(writeFile, newContents);
|
|
94
|
-
fs.rmSync(file);
|
|
95
|
-
});
|
|
96
|
-
(0, child_process_1.execSync)("prettier src/schema/*.ts --write");
|
|
97
|
-
}
|
|
98
|
-
function traverse(fileContents, sourceFile, f) {
|
|
99
|
-
let traversed = false;
|
|
100
|
-
typescript_1.default.forEachChild(sourceFile, function (node) {
|
|
101
|
-
if (typescript_1.default.isClassDeclaration(node)) {
|
|
102
|
-
traversed = true;
|
|
103
|
-
// TODO address implicit schema doesn't work here...
|
|
104
|
-
// console.debug(sourceFile.fileName, node.kind);
|
|
105
|
-
if (traverseClass(fileContents, sourceFile, node, f)) {
|
|
106
|
-
f.flagUpdateImport();
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
f.trackNode({ node });
|
|
111
|
-
});
|
|
112
|
-
return traversed;
|
|
113
|
-
}
|
|
114
|
-
function traverseClass(fileContents, sourceFile, node, f) {
|
|
115
|
-
const ci = getTransformClassInfo(fileContents, sourceFile, node);
|
|
30
|
+
function traverseClass(fileContents, sourceFile, node, transformSchema) {
|
|
31
|
+
const ci = getTransformClassInfo(fileContents, sourceFile, node, transformSchema);
|
|
116
32
|
if (!ci) {
|
|
117
|
-
return
|
|
33
|
+
return;
|
|
118
34
|
}
|
|
119
|
-
let klassContents = `${ci.comment}const ${ci.name} = new ${ci.class}({\n`;
|
|
35
|
+
let klassContents = `${ci.comment}const ${ci.name} = new ${transformSchema(ci.class)}({\n`;
|
|
120
36
|
let removeImports = [];
|
|
121
37
|
if (ci.implementsSchema) {
|
|
122
38
|
removeImports.push("Schema");
|
|
123
39
|
}
|
|
40
|
+
removeImports.push(ci.class);
|
|
41
|
+
let newImports = [transformSchema(ci.class)];
|
|
124
42
|
for (let member of node.members) {
|
|
125
43
|
const fInfo = getClassElementInfo(fileContents, member, sourceFile);
|
|
126
44
|
if (!fInfo) {
|
|
127
|
-
return
|
|
45
|
+
return;
|
|
128
46
|
}
|
|
129
47
|
klassContents += `${fInfo.comment}${fInfo.key}:${fInfo.value},\n`;
|
|
130
48
|
if (fInfo.type) {
|
|
@@ -139,20 +57,13 @@ function traverseClass(fileContents, sourceFile, node, f) {
|
|
|
139
57
|
klassContents = "export " + klassContents;
|
|
140
58
|
}
|
|
141
59
|
// console.debug(klassContents);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (str === "BaseEntSchema" || str === "BaseEntSchemaWithTZ") {
|
|
148
|
-
return str.substring(4);
|
|
149
|
-
}
|
|
150
|
-
return str;
|
|
60
|
+
return {
|
|
61
|
+
rawString: klassContents,
|
|
62
|
+
removeImports: removeImports,
|
|
63
|
+
newImports,
|
|
64
|
+
};
|
|
151
65
|
}
|
|
152
|
-
|
|
153
|
-
// and then have a schema specific version
|
|
154
|
-
// may make sense to just duplicate this logic...
|
|
155
|
-
function getTransformClassInfo(fileContents, sourceFile, node) {
|
|
66
|
+
function getTransformClassInfo(fileContents, sourceFile, node, transformSchema) {
|
|
156
67
|
const generic = (0, ast_1.getClassInfo)(fileContents, sourceFile, node);
|
|
157
68
|
if (!generic) {
|
|
158
69
|
return;
|
|
@@ -163,6 +74,7 @@ function getTransformClassInfo(fileContents, sourceFile, node) {
|
|
|
163
74
|
}
|
|
164
75
|
let implementsSchema = generic.implements?.some((v) => v == "Schema");
|
|
165
76
|
let classExtends = generic.extends;
|
|
77
|
+
// nothing transformed here, so nothing to do here
|
|
166
78
|
if (classExtends && classExtends === transformSchema(classExtends)) {
|
|
167
79
|
return undefined;
|
|
168
80
|
}
|
|
@@ -222,7 +134,7 @@ function getFieldElementInfo(fileContents, member, sourceFile) {
|
|
|
222
134
|
if (parsed === null) {
|
|
223
135
|
return;
|
|
224
136
|
}
|
|
225
|
-
const { callEx, name, nameComment, properties } = parsed;
|
|
137
|
+
const { callEx, name, nameComment, properties, suffix } = parsed;
|
|
226
138
|
let property = "";
|
|
227
139
|
const fieldComment = (0, ast_1.getPreText)(fileContents, element, sourceFile).trim();
|
|
228
140
|
if (fieldComment) {
|
|
@@ -237,7 +149,7 @@ function getFieldElementInfo(fileContents, member, sourceFile) {
|
|
|
237
149
|
if (properties.length) {
|
|
238
150
|
fnCall = `{${properties.join(",")}}`;
|
|
239
151
|
}
|
|
240
|
-
property += `${name}:${call}(${fnCall}),`;
|
|
152
|
+
property += `${name}:${call}(${fnCall})${suffix || ""},`;
|
|
241
153
|
fieldMap += property;
|
|
242
154
|
}
|
|
243
155
|
fieldMap += "}";
|
|
@@ -308,13 +220,24 @@ function isFieldElement(member, sourceFile) {
|
|
|
308
220
|
}
|
|
309
221
|
return true;
|
|
310
222
|
}
|
|
311
|
-
function parseFieldElement(element, sourceFile, fileContents) {
|
|
223
|
+
function parseFieldElement(element, sourceFile, fileContents, nested) {
|
|
312
224
|
if (element.kind !== typescript_1.default.SyntaxKind.CallExpression) {
|
|
313
225
|
console.error("skipped non-call expression");
|
|
314
226
|
return null;
|
|
315
227
|
}
|
|
316
228
|
let callEx = element;
|
|
317
229
|
if (callEx.arguments.length !== 1) {
|
|
230
|
+
// have a situation like: StringType({ name: "canonicalName" }).trim().toLowerCase(),
|
|
231
|
+
// need to keep calling this until we find what we want and then get the suffix we should just add to the end of the transformed code
|
|
232
|
+
if (callEx.expression.kind === typescript_1.default.SyntaxKind.PropertyAccessExpression) {
|
|
233
|
+
const ret = parseFieldElement(callEx.expression.expression, sourceFile, fileContents, true);
|
|
234
|
+
if (ret !== null) {
|
|
235
|
+
if (!nested) {
|
|
236
|
+
ret.suffix = fileContents.substring(ret.callEx.getEnd(), callEx.getEnd());
|
|
237
|
+
}
|
|
238
|
+
return ret;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
318
241
|
console.error("callExpression with arguments not of length 1");
|
|
319
242
|
return null;
|
|
320
243
|
}
|
|
@@ -352,4 +275,80 @@ function parseFieldElement(element, sourceFile, fileContents) {
|
|
|
352
275
|
nameComment: propertyComment,
|
|
353
276
|
};
|
|
354
277
|
}
|
|
355
|
-
|
|
278
|
+
// find which of these importPaths is being used and use that to replace
|
|
279
|
+
function findSchemaImportPath(sourceFile) {
|
|
280
|
+
const paths = {
|
|
281
|
+
"@snowtop/ent": true,
|
|
282
|
+
"@snowtop/ent/schema": true,
|
|
283
|
+
"@snowtop/ent/schema/": true,
|
|
284
|
+
};
|
|
285
|
+
// @ts-ignore
|
|
286
|
+
const importStatements = sourceFile.statements.filter((stmt) => typescript_1.default.isImportDeclaration(stmt));
|
|
287
|
+
for (const imp of importStatements) {
|
|
288
|
+
const impInfo = (0, ast_1.getImportInfo)(imp, sourceFile);
|
|
289
|
+
if (!impInfo) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (paths[impInfo.importPath] !== undefined) {
|
|
293
|
+
return impInfo.importPath;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
class TransformSchema {
|
|
298
|
+
// we only end up doing this once because we change the schema representation
|
|
299
|
+
// so safe to run this multiple times
|
|
300
|
+
constructor(relativeImports, oldBaseClass, newSchemaClass, transformPath) {
|
|
301
|
+
this.relativeImports = relativeImports;
|
|
302
|
+
this.oldBaseClass = oldBaseClass;
|
|
303
|
+
this.newSchemaClass = newSchemaClass;
|
|
304
|
+
this.transformPath = transformPath;
|
|
305
|
+
this.glob = "src/schema/*.ts";
|
|
306
|
+
this.prettierGlob = "src/schema/*.ts";
|
|
307
|
+
}
|
|
308
|
+
transformSchema(className) {
|
|
309
|
+
if (className === "BaseEntSchema" || className === "BaseEntSchemaWithTZ") {
|
|
310
|
+
return className.substring(4);
|
|
311
|
+
}
|
|
312
|
+
if (className === this.oldBaseClass && this.newSchemaClass) {
|
|
313
|
+
return this.newSchemaClass;
|
|
314
|
+
}
|
|
315
|
+
return className;
|
|
316
|
+
}
|
|
317
|
+
traverseChild(sourceFile, contents, file, node) {
|
|
318
|
+
if (!typescript_1.default.isClassDeclaration(node)) {
|
|
319
|
+
return { node };
|
|
320
|
+
}
|
|
321
|
+
// TODO address implicit schema doesn't work here...
|
|
322
|
+
const ret = traverseClass(contents, sourceFile, node, this.transformSchema.bind(this));
|
|
323
|
+
if (ret === undefined) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
let imports = new Map();
|
|
327
|
+
const imp = findSchemaImportPath(sourceFile);
|
|
328
|
+
if (imp) {
|
|
329
|
+
if (this.transformPath) {
|
|
330
|
+
imports.set(imp, []);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
imports.set(imp, ret.newImports);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (this.transformPath) {
|
|
337
|
+
// add new imports to this path
|
|
338
|
+
imports.set((0, ast_1.transformRelative)(file, this.transformPath, this.relativeImports), ret.newImports);
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
traversed: true,
|
|
342
|
+
rawString: ret.rawString,
|
|
343
|
+
removeImports: ret.removeImports,
|
|
344
|
+
imports: imports,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
fileToWrite(file) {
|
|
348
|
+
return "src/schema/" + path_1.default.basename(file).slice(0, -3) + "_schema.ts";
|
|
349
|
+
}
|
|
350
|
+
postProcess(file) {
|
|
351
|
+
fs.rmSync(file);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
exports.TransformSchema = TransformSchema;
|