@adonisjs/assembler 8.0.0-next.3 → 8.0.0-next.30
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/README.md +87 -59
- package/build/codemod_exception-vyN1VXuX.js +137 -0
- package/build/helpers-DDurYRsZ.js +72 -0
- package/build/index.d.ts +4 -0
- package/build/index.js +925 -1319
- package/build/main-BeV45LeF.js +246 -0
- package/build/main-CknPN3rJ.js +188 -0
- package/build/src/bundler.d.ts +44 -3
- package/build/src/code_scanners/routes_scanner/main.d.ts +63 -11
- package/build/src/code_scanners/routes_scanner/main.js +4 -0
- package/build/src/code_scanners/routes_scanner/validator_extractor.d.ts +12 -4
- package/build/src/code_transformer/main.d.ts +53 -43
- package/build/src/code_transformer/main.js +354 -599
- package/build/src/code_transformer/rc_file_transformer.d.ts +83 -5
- package/build/src/debug.d.ts +13 -1
- package/build/src/dev_server.d.ts +92 -17
- package/build/src/exceptions/codemod_exception.d.ts +178 -0
- package/build/src/file_buffer.d.ts +87 -0
- package/build/src/file_system.d.ts +46 -8
- package/build/src/helpers.d.ts +79 -4
- package/build/src/helpers.js +2 -0
- package/build/src/index_generator/main.d.ts +68 -0
- package/build/src/index_generator/main.js +3 -0
- package/build/src/index_generator/source.d.ts +60 -0
- package/build/src/paths_resolver.d.ts +29 -3
- package/build/src/shortcuts_manager.d.ts +42 -4
- package/build/src/test_runner.d.ts +57 -12
- package/build/src/types/code_scanners.d.ts +160 -30
- package/build/src/types/code_transformer.d.ts +69 -19
- package/build/src/types/common.d.ts +233 -55
- package/build/src/types/hooks.d.ts +238 -22
- package/build/src/types/main.d.ts +15 -1
- package/build/src/types/main.js +1 -0
- package/build/src/utils.d.ts +96 -15
- package/build/src/virtual_file_system.d.ts +112 -0
- package/build/virtual_file_system-bGeoWsK-.js +285 -0
- package/package.json +46 -36
- package/build/chunk-RR4HCA4M.js +0 -7
- package/build/src/ast_file_system.d.ts +0 -17
|
@@ -1,612 +1,367 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from "
|
|
1
|
+
import { t as CodemodException } from "../../codemod_exception-vyN1VXuX.js";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { detectPackageManager, installPackage } from "@antfu/install-pkg";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { Node, Project, QuoteKind, SyntaxKind } from "ts-morph";
|
|
6
|
+
const ALLOWED_ENVIRONMENTS = [
|
|
7
|
+
"web",
|
|
8
|
+
"console",
|
|
9
|
+
"test",
|
|
10
|
+
"repl"
|
|
11
|
+
];
|
|
12
|
+
var RcFileTransformer = class {
|
|
13
|
+
#cwd;
|
|
14
|
+
#project;
|
|
15
|
+
#editorSettings = {
|
|
16
|
+
indentSize: 2,
|
|
17
|
+
convertTabsToSpaces: true,
|
|
18
|
+
trimTrailingWhitespace: true,
|
|
19
|
+
ensureNewLineAtEndOfFile: true,
|
|
20
|
+
indentStyle: 2,
|
|
21
|
+
semicolons: "remove"
|
|
22
|
+
};
|
|
23
|
+
constructor(cwd, project) {
|
|
24
|
+
this.#cwd = cwd;
|
|
25
|
+
this.#project = project;
|
|
26
|
+
}
|
|
27
|
+
#getRcFileOrThrow() {
|
|
28
|
+
const filePath = "adonisrc.ts";
|
|
29
|
+
const rcFileUrl = fileURLToPath(new URL(`./${filePath}`, this.#cwd));
|
|
30
|
+
const file = this.#project.getSourceFile(rcFileUrl);
|
|
31
|
+
if (!file) throw CodemodException.missingRcFile(filePath, `import { defineConfig } from '@adonisjs/core/app'
|
|
4
32
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
QuoteKind,
|
|
18
|
-
SyntaxKind as SyntaxKind2
|
|
19
|
-
} from "ts-morph";
|
|
33
|
+
export default defineConfig({
|
|
34
|
+
// Add your configuration here
|
|
35
|
+
})`);
|
|
36
|
+
return file;
|
|
37
|
+
}
|
|
38
|
+
#isInSpecificEnvironment(environments) {
|
|
39
|
+
if (!environments) return false;
|
|
40
|
+
return !!ALLOWED_ENVIRONMENTS.find((env) => !environments.includes(env));
|
|
41
|
+
}
|
|
42
|
+
#locateDefineConfigCallOrThrow(file) {
|
|
43
|
+
const call = file.getDescendantsOfKind(SyntaxKind.CallExpression).find((statement) => statement.getExpression().getText() === "defineConfig");
|
|
44
|
+
if (!call) throw CodemodException.invalidRcFile("adonisrc.ts", `import { defineConfig } from '@adonisjs/core/app'
|
|
20
45
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
return !!ALLOWED_ENVIRONMENTS.find((env) => !environments.includes(env));
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Locate the `defineConfig` call inside the `adonisrc.ts` file
|
|
65
|
-
*/
|
|
66
|
-
#locateDefineConfigCallOrThrow(file) {
|
|
67
|
-
const call = file.getDescendantsOfKind(SyntaxKind.CallExpression).find((statement) => statement.getExpression().getText() === "defineConfig");
|
|
68
|
-
if (!call) {
|
|
69
|
-
throw new Error("Could not locate the defineConfig call.");
|
|
70
|
-
}
|
|
71
|
-
return call;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Return the ObjectLiteralExpression of the defineConfig call
|
|
75
|
-
*/
|
|
76
|
-
#getDefineConfigObjectOrThrow(defineConfigCall) {
|
|
77
|
-
const configObject = defineConfigCall.getArguments()[0].asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
78
|
-
return configObject;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Check if the defineConfig() call has the property assignment
|
|
82
|
-
* inside it or not. If not, it will create one and return it.
|
|
83
|
-
*/
|
|
84
|
-
#getPropertyAssignmentInDefineConfigCall(propertyName, initializer) {
|
|
85
|
-
const file = this.#getRcFileOrThrow();
|
|
86
|
-
const defineConfigCall = this.#locateDefineConfigCallOrThrow(file);
|
|
87
|
-
const configObject = this.#getDefineConfigObjectOrThrow(defineConfigCall);
|
|
88
|
-
let property = configObject.getProperty(propertyName);
|
|
89
|
-
if (!property) {
|
|
90
|
-
configObject.addPropertyAssignment({ name: propertyName, initializer });
|
|
91
|
-
property = configObject.getProperty(propertyName);
|
|
92
|
-
}
|
|
93
|
-
return property;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Extract list of imported modules from an ArrayLiteralExpression
|
|
97
|
-
*
|
|
98
|
-
* It assumes that the array can have two types of elements:
|
|
99
|
-
*
|
|
100
|
-
* - Simple lazy imported modules: [() => import('path/to/file')]
|
|
101
|
-
* - Or an object entry: [{ file: () => import('path/to/file'), environment: ['web', 'console'] }]
|
|
102
|
-
* where the `file` property is a lazy imported module.
|
|
103
|
-
*/
|
|
104
|
-
#extractModulesFromArray(array) {
|
|
105
|
-
const modules = array.getElements().map((element) => {
|
|
106
|
-
if (Node.isArrowFunction(element)) {
|
|
107
|
-
const importExp = element.getFirstDescendantByKindOrThrow(SyntaxKind.CallExpression);
|
|
108
|
-
const literal = importExp.getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral);
|
|
109
|
-
return literal.getLiteralValue();
|
|
110
|
-
}
|
|
111
|
-
if (Node.isObjectLiteralExpression(element)) {
|
|
112
|
-
const fileProp = element.getPropertyOrThrow("file");
|
|
113
|
-
const arrowFn = fileProp.getFirstDescendantByKindOrThrow(SyntaxKind.ArrowFunction);
|
|
114
|
-
const importExp = arrowFn.getFirstDescendantByKindOrThrow(SyntaxKind.CallExpression);
|
|
115
|
-
const literal = importExp.getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral);
|
|
116
|
-
return literal.getLiteralValue();
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
return modules.filter(Boolean);
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Extract a specific property from an ArrayLiteralExpression
|
|
123
|
-
* that contains object entries.
|
|
124
|
-
*
|
|
125
|
-
* This function is mainly used for extractring the `pattern` property
|
|
126
|
-
* when adding a new meta files entry, or the `name` property when
|
|
127
|
-
* adding a new test suite.
|
|
128
|
-
*/
|
|
129
|
-
#extractPropertyFromArray(array, propertyName) {
|
|
130
|
-
const property = array.getElements().map((el) => {
|
|
131
|
-
if (!Node.isObjectLiteralExpression(el)) return;
|
|
132
|
-
const nameProp = el.getPropertyOrThrow(propertyName);
|
|
133
|
-
if (!Node.isPropertyAssignment(nameProp)) return;
|
|
134
|
-
const name = nameProp.getInitializerIfKindOrThrow(SyntaxKind.StringLiteral);
|
|
135
|
-
return name.getLiteralValue();
|
|
136
|
-
});
|
|
137
|
-
return property.filter(Boolean);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Build a new module entry for the preloads and providers array
|
|
141
|
-
* based upon the environments specified
|
|
142
|
-
*/
|
|
143
|
-
#buildNewModuleEntry(modulePath, environments) {
|
|
144
|
-
if (!this.#isInSpecificEnvironment(environments)) {
|
|
145
|
-
return `() => import('${modulePath}')`;
|
|
146
|
-
}
|
|
147
|
-
return `{
|
|
46
|
+
export default defineConfig({
|
|
47
|
+
// Add your configuration here
|
|
48
|
+
})`, "Could not locate the defineConfig call.");
|
|
49
|
+
return call;
|
|
50
|
+
}
|
|
51
|
+
#getDefineConfigObjectOrThrow(defineConfigCall) {
|
|
52
|
+
return defineConfigCall.getArguments()[0].asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
53
|
+
}
|
|
54
|
+
#getPropertyAssignmentInDefineConfigCall(propertyName, initializer) {
|
|
55
|
+
const file = this.#getRcFileOrThrow();
|
|
56
|
+
const defineConfigCall = this.#locateDefineConfigCallOrThrow(file);
|
|
57
|
+
const configObject = this.#getDefineConfigObjectOrThrow(defineConfigCall);
|
|
58
|
+
let property = configObject.getProperty(propertyName);
|
|
59
|
+
if (!property) {
|
|
60
|
+
configObject.addPropertyAssignment({
|
|
61
|
+
name: propertyName,
|
|
62
|
+
initializer
|
|
63
|
+
});
|
|
64
|
+
property = configObject.getProperty(propertyName);
|
|
65
|
+
}
|
|
66
|
+
return property;
|
|
67
|
+
}
|
|
68
|
+
#extractModulesFromArray(array) {
|
|
69
|
+
return array.getElements().map((element) => {
|
|
70
|
+
if (Node.isArrowFunction(element)) return element.getFirstDescendantByKindOrThrow(SyntaxKind.CallExpression).getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
|
|
71
|
+
if (Node.isObjectLiteralExpression(element)) return element.getPropertyOrThrow("file").getFirstDescendantByKindOrThrow(SyntaxKind.ArrowFunction).getFirstDescendantByKindOrThrow(SyntaxKind.CallExpression).getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
|
|
72
|
+
}).filter(Boolean);
|
|
73
|
+
}
|
|
74
|
+
#extractPropertyFromArray(array, propertyName) {
|
|
75
|
+
return array.getElements().map((el) => {
|
|
76
|
+
if (!Node.isObjectLiteralExpression(el)) return;
|
|
77
|
+
const nameProp = el.getPropertyOrThrow(propertyName);
|
|
78
|
+
if (!Node.isPropertyAssignment(nameProp)) return;
|
|
79
|
+
return nameProp.getInitializerIfKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
|
|
80
|
+
}).filter(Boolean);
|
|
81
|
+
}
|
|
82
|
+
#buildNewModuleEntry(modulePath, environments) {
|
|
83
|
+
if (!this.#isInSpecificEnvironment(environments)) return `() => import('${modulePath}')`;
|
|
84
|
+
return `{
|
|
148
85
|
file: () => import('${modulePath}'),
|
|
149
86
|
environment: [${environments?.map((env) => `'${env}'`).join(", ")}],
|
|
150
87
|
}`;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const existingPreloadedFiles = this.#extractModulesFromArray(preloadsArray);
|
|
176
|
-
const isDuplicate = existingPreloadedFiles.includes(modulePath);
|
|
177
|
-
if (isDuplicate) {
|
|
178
|
-
return this;
|
|
179
|
-
}
|
|
180
|
-
preloadsArray.addElement(this.#buildNewModuleEntry(modulePath, environments));
|
|
181
|
-
return this;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Add a new provider to the rcFile
|
|
185
|
-
*/
|
|
186
|
-
addProvider(providerPath, environments) {
|
|
187
|
-
const property = this.#getPropertyAssignmentInDefineConfigCall("providers", "[]");
|
|
188
|
-
const providersArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
189
|
-
const existingProviderPaths = this.#extractModulesFromArray(providersArray);
|
|
190
|
-
const isDuplicate = existingProviderPaths.includes(providerPath);
|
|
191
|
-
if (isDuplicate) {
|
|
192
|
-
return this;
|
|
193
|
-
}
|
|
194
|
-
providersArray.addElement(this.#buildNewModuleEntry(providerPath, environments));
|
|
195
|
-
return this;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Add a new meta file to the rcFile
|
|
199
|
-
*/
|
|
200
|
-
addMetaFile(globPattern, reloadServer = false) {
|
|
201
|
-
const property = this.#getPropertyAssignmentInDefineConfigCall("metaFiles", "[]");
|
|
202
|
-
const metaFilesArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
203
|
-
const alreadyDefinedPatterns = this.#extractPropertyFromArray(metaFilesArray, "pattern");
|
|
204
|
-
if (alreadyDefinedPatterns.includes(globPattern)) {
|
|
205
|
-
return this;
|
|
206
|
-
}
|
|
207
|
-
metaFilesArray.addElement(
|
|
208
|
-
`{
|
|
88
|
+
}
|
|
89
|
+
addCommand(commandPath) {
|
|
90
|
+
const commandsArray = this.#getPropertyAssignmentInDefineConfigCall("commands", "[]").getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
91
|
+
const commandString = `() => import('${commandPath}')`;
|
|
92
|
+
if (commandsArray.getElements().some((el) => el.getText() === commandString)) return this;
|
|
93
|
+
commandsArray.addElement(commandString);
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
addPreloadFile(modulePath, environments) {
|
|
97
|
+
const preloadsArray = this.#getPropertyAssignmentInDefineConfigCall("preloads", "[]").getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
98
|
+
if (this.#extractModulesFromArray(preloadsArray).includes(modulePath)) return this;
|
|
99
|
+
preloadsArray.addElement(this.#buildNewModuleEntry(modulePath, environments));
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
addProvider(providerPath, environments) {
|
|
103
|
+
const providersArray = this.#getPropertyAssignmentInDefineConfigCall("providers", "[]").getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
104
|
+
if (this.#extractModulesFromArray(providersArray).includes(providerPath)) return this;
|
|
105
|
+
providersArray.addElement(this.#buildNewModuleEntry(providerPath, environments));
|
|
106
|
+
return this;
|
|
107
|
+
}
|
|
108
|
+
addMetaFile(globPattern, reloadServer = false) {
|
|
109
|
+
const metaFilesArray = this.#getPropertyAssignmentInDefineConfigCall("metaFiles", "[]").getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
110
|
+
if (this.#extractPropertyFromArray(metaFilesArray, "pattern").includes(globPattern)) return this;
|
|
111
|
+
metaFilesArray.addElement(`{
|
|
209
112
|
pattern: '${globPattern}',
|
|
210
113
|
reloadServer: ${reloadServer},
|
|
211
|
-
}`
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Add a new test suite to the rcFile
|
|
235
|
-
*/
|
|
236
|
-
addSuite(suiteName, files, timeout) {
|
|
237
|
-
const testProperty = this.#getPropertyAssignmentInDefineConfigCall(
|
|
238
|
-
"tests",
|
|
239
|
-
`{ suites: [], forceExit: true, timeout: 2000 }`
|
|
240
|
-
);
|
|
241
|
-
const property = testProperty.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression).getPropertyOrThrow("suites");
|
|
242
|
-
const suitesArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
243
|
-
const existingSuitesNames = this.#extractPropertyFromArray(suitesArray, "name");
|
|
244
|
-
if (existingSuitesNames.includes(suiteName)) {
|
|
245
|
-
return this;
|
|
246
|
-
}
|
|
247
|
-
const filesArray = Array.isArray(files) ? files : [files];
|
|
248
|
-
suitesArray.addElement(
|
|
249
|
-
`{
|
|
114
|
+
}`);
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
setDirectory(key, value) {
|
|
118
|
+
this.#getPropertyAssignmentInDefineConfigCall("directories", "{}").getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression).addPropertyAssignment({
|
|
119
|
+
name: key,
|
|
120
|
+
initializer: `'${value}'`
|
|
121
|
+
});
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
setCommandAlias(alias, command) {
|
|
125
|
+
this.#getPropertyAssignmentInDefineConfigCall("commandsAliases", "{}").getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression).addPropertyAssignment({
|
|
126
|
+
name: alias,
|
|
127
|
+
initializer: `'${command}'`
|
|
128
|
+
});
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
addSuite(suiteName, files, timeout) {
|
|
132
|
+
const suitesArray = this.#getPropertyAssignmentInDefineConfigCall("tests", `{ suites: [], forceExit: true, timeout: 2000 }`).getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression).getPropertyOrThrow("suites").getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
133
|
+
if (this.#extractPropertyFromArray(suitesArray, "name").includes(suiteName)) return this;
|
|
134
|
+
const filesArray = Array.isArray(files) ? files : [files];
|
|
135
|
+
suitesArray.addElement(`{
|
|
250
136
|
name: '${suiteName}',
|
|
251
137
|
files: [${filesArray.map((file) => `'${file}'`).join(", ")}],
|
|
252
138
|
timeout: ${timeout ?? 2e3},
|
|
253
|
-
}`
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
139
|
+
}`);
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
addAssemblerHook(type, value, raw = false) {
|
|
143
|
+
const hooks = this.#getPropertyAssignmentInDefineConfigCall("hooks", "{}").getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
144
|
+
let hookArray = hooks.getProperty(type);
|
|
145
|
+
if (!hookArray) {
|
|
146
|
+
hooks.addPropertyAssignment({
|
|
147
|
+
name: type,
|
|
148
|
+
initializer: "[]"
|
|
149
|
+
});
|
|
150
|
+
hookArray = hooks.getProperty(type);
|
|
151
|
+
}
|
|
152
|
+
const hooksArray = hookArray.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
153
|
+
if (raw) hooksArray.addElement(value);
|
|
154
|
+
else {
|
|
155
|
+
if (this.#extractModulesFromArray(hooksArray).includes(value)) return this;
|
|
156
|
+
hooksArray.addElement(`() => import('${value}')`);
|
|
157
|
+
}
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
addNamedImport(specifier, names) {
|
|
161
|
+
this.#getRcFileOrThrow().addImportDeclaration({
|
|
162
|
+
moduleSpecifier: specifier,
|
|
163
|
+
namedImports: names
|
|
164
|
+
});
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
addDefaultImport(specifier, name) {
|
|
168
|
+
this.#getRcFileOrThrow().addImportDeclaration({
|
|
169
|
+
moduleSpecifier: specifier,
|
|
170
|
+
defaultImport: name
|
|
171
|
+
});
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
getDirectory(key, defaultValue) {
|
|
175
|
+
try {
|
|
176
|
+
const file = this.#getRcFileOrThrow();
|
|
177
|
+
const defineConfigCall = this.#locateDefineConfigCallOrThrow(file);
|
|
178
|
+
const directoriesProperty = this.#getDefineConfigObjectOrThrow(defineConfigCall).getProperty("directories");
|
|
179
|
+
if (!directoriesProperty || !Node.isPropertyAssignment(directoriesProperty)) return defaultValue;
|
|
180
|
+
const directoriesObject = directoriesProperty.getInitializer();
|
|
181
|
+
if (!directoriesObject || !Node.isObjectLiteralExpression(directoriesObject)) return defaultValue;
|
|
182
|
+
const property = directoriesObject.getProperty(key);
|
|
183
|
+
if (!property || !Node.isPropertyAssignment(property)) return defaultValue;
|
|
184
|
+
const initializer = property.getInitializer();
|
|
185
|
+
if (!initializer || !Node.isStringLiteral(initializer)) return defaultValue;
|
|
186
|
+
return initializer.getLiteralValue();
|
|
187
|
+
} catch {
|
|
188
|
+
return defaultValue;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
save() {
|
|
192
|
+
const file = this.#getRcFileOrThrow();
|
|
193
|
+
file.formatText(this.#editorSettings);
|
|
194
|
+
return file.save();
|
|
195
|
+
}
|
|
284
196
|
};
|
|
285
|
-
|
|
286
|
-
// src/code_transformer/main.ts
|
|
287
197
|
var CodeTransformer = class {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
* your `start/kernel.ts` file.
|
|
457
|
-
*/
|
|
458
|
-
async addMiddlewareToStack(stack, middleware) {
|
|
459
|
-
const kernelUrl = join(this.#cwdPath, "./start/kernel.ts");
|
|
460
|
-
const file = this.project.getSourceFileOrThrow(kernelUrl);
|
|
461
|
-
for (const middlewareEntry of middleware) {
|
|
462
|
-
if (stack === "named") {
|
|
463
|
-
this.#addToNamedMiddleware(file, middlewareEntry);
|
|
464
|
-
} else {
|
|
465
|
-
this.#addToMiddlewareArray(file, `${stack}.use`, middlewareEntry);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
file.formatText(this.#editorSettings);
|
|
469
|
-
await file.save();
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* Update the `adonisrc.ts` file
|
|
473
|
-
*/
|
|
474
|
-
async updateRcFile(callback) {
|
|
475
|
-
const rcFileTransformer = new RcFileTransformer(this.#cwd, this.project);
|
|
476
|
-
callback(rcFileTransformer);
|
|
477
|
-
await rcFileTransformer.save();
|
|
478
|
-
}
|
|
479
|
-
/**
|
|
480
|
-
* Add a new Japa plugin in the `tests/bootstrap.ts` file
|
|
481
|
-
*/
|
|
482
|
-
async addJapaPlugin(pluginCall, importDeclarations) {
|
|
483
|
-
const testBootstrapUrl = join(this.#cwdPath, "./tests/bootstrap.ts");
|
|
484
|
-
const file = this.project.getSourceFileOrThrow(testBootstrapUrl);
|
|
485
|
-
this.#addImportDeclarations(file, importDeclarations);
|
|
486
|
-
const pluginsArray = file.getVariableDeclaration("plugins")?.getInitializerIfKind(SyntaxKind2.ArrayLiteralExpression);
|
|
487
|
-
if (pluginsArray) {
|
|
488
|
-
if (!pluginsArray.getElements().find((element) => element.getText() === pluginCall)) {
|
|
489
|
-
pluginsArray.addElement(pluginCall);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
file.formatText(this.#editorSettings);
|
|
493
|
-
await file.save();
|
|
494
|
-
}
|
|
495
|
-
/**
|
|
496
|
-
* Add a new Vite plugin
|
|
497
|
-
*/
|
|
498
|
-
async addVitePlugin(pluginCall, importDeclarations) {
|
|
499
|
-
const viteConfigTsUrl = join(this.#cwdPath, "./vite.config.ts");
|
|
500
|
-
const file = this.project.getSourceFile(viteConfigTsUrl);
|
|
501
|
-
if (!file) {
|
|
502
|
-
throw new Error(
|
|
503
|
-
"Cannot find vite.config.ts file. Make sure to rename vite.config.js to vite.config.ts"
|
|
504
|
-
);
|
|
505
|
-
}
|
|
506
|
-
this.#addImportDeclarations(file, importDeclarations);
|
|
507
|
-
const defaultExport = file.getDefaultExportSymbol();
|
|
508
|
-
if (!defaultExport) {
|
|
509
|
-
throw new Error("Cannot find the default export in vite.config.ts");
|
|
510
|
-
}
|
|
511
|
-
const declaration = defaultExport.getDeclarations()[0];
|
|
512
|
-
const options = declaration.getChildrenOfKind(SyntaxKind2.ObjectLiteralExpression)[0] || declaration.getChildrenOfKind(SyntaxKind2.CallExpression)[0].getArguments()[0];
|
|
513
|
-
const pluginsArray = options.getPropertyOrThrow("plugins").getFirstChildByKindOrThrow(SyntaxKind2.ArrayLiteralExpression);
|
|
514
|
-
if (!pluginsArray.getElements().find((element) => element.getText() === pluginCall)) {
|
|
515
|
-
pluginsArray.addElement(pluginCall);
|
|
516
|
-
}
|
|
517
|
-
file.formatText(this.#editorSettings);
|
|
518
|
-
await file.save();
|
|
519
|
-
}
|
|
520
|
-
/**
|
|
521
|
-
* Adds a policy to the list of `policies` object configured
|
|
522
|
-
* inside the `app/policies/main.ts` file.
|
|
523
|
-
*/
|
|
524
|
-
async addPolicies(policies) {
|
|
525
|
-
const kernelUrl = join(this.#cwdPath, "./app/policies/main.ts");
|
|
526
|
-
const file = this.project.getSourceFileOrThrow(kernelUrl);
|
|
527
|
-
for (const policy of policies) {
|
|
528
|
-
this.#addToPoliciesList(file, policy);
|
|
529
|
-
}
|
|
530
|
-
file.formatText(this.#editorSettings);
|
|
531
|
-
await file.save();
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Creates an index file that exports an object in which the key is the PascalCase
|
|
535
|
-
* name of the entity and the value is a dynamic import.
|
|
536
|
-
*
|
|
537
|
-
* For example, in case of controllers, the index file will be the list of controller
|
|
538
|
-
* names pointing a dynamically imported controller file.
|
|
539
|
-
*
|
|
540
|
-
* ```ts
|
|
541
|
-
* export const controllers = {
|
|
542
|
-
* LoginController: () => import('#controllers/login_controller'),
|
|
543
|
-
* LogoutController: () => import('#controllers/logout_controller'),
|
|
544
|
-
* }
|
|
545
|
-
* ```
|
|
546
|
-
*
|
|
547
|
-
* @param source
|
|
548
|
-
* @param outputPath
|
|
549
|
-
* @param importAlias
|
|
550
|
-
*/
|
|
551
|
-
async makeEntityIndex(input, output) {
|
|
552
|
-
const inputs = Array.isArray(input) ? input : [input];
|
|
553
|
-
const outputPath = join(this.#cwdPath, output.destination);
|
|
554
|
-
const outputDir = dirname(outputPath);
|
|
555
|
-
const exportName = output.exportName ?? new StringBuilder(basename(output.destination)).removeExtension().camelCase();
|
|
556
|
-
debug_default(
|
|
557
|
-
'creating index for "%s" at destination "%s" using sources %O',
|
|
558
|
-
exportName,
|
|
559
|
-
outputPath,
|
|
560
|
-
inputs
|
|
561
|
-
);
|
|
562
|
-
const entries = await Promise.all(
|
|
563
|
-
inputs.map(async ({ source, importAlias, allowedExtensions }) => {
|
|
564
|
-
const sourcePath = join(this.#cwdPath, source);
|
|
565
|
-
const filesList = await fsReadAll(sourcePath, {
|
|
566
|
-
filter: (filePath) => {
|
|
567
|
-
if (allowedExtensions) {
|
|
568
|
-
const ext = extname(filePath);
|
|
569
|
-
return allowedExtensions.includes(ext);
|
|
570
|
-
}
|
|
571
|
-
return isScriptFile(filePath);
|
|
572
|
-
},
|
|
573
|
-
pathType: "absolute"
|
|
574
|
-
});
|
|
575
|
-
const knownBaseNames = /* @__PURE__ */ new Set();
|
|
576
|
-
return filesList.map((filePath) => {
|
|
577
|
-
let baseName = basename(filePath);
|
|
578
|
-
if (output.computeBaseName) {
|
|
579
|
-
baseName = output.computeBaseName?.(filePath, sourcePath);
|
|
580
|
-
} else {
|
|
581
|
-
if (knownBaseNames.has(baseName)) {
|
|
582
|
-
baseName = string.toUnixSlash(relative(sourcePath, filePath));
|
|
583
|
-
}
|
|
584
|
-
knownBaseNames.add(baseName);
|
|
585
|
-
}
|
|
586
|
-
const name = new StringBuilder(baseName).removeExtension().removeSuffix(output.removeNameSuffix ?? "").pascalCase().toString();
|
|
587
|
-
const baseImportPath = importAlias ? string.toUnixSlash(relative(sourcePath, filePath)) : string.toUnixSlash(relative(outputDir, filePath));
|
|
588
|
-
const importPath = importAlias ? `${importAlias}/${new StringBuilder(baseImportPath).removeExtension().toString()}` : baseImportPath;
|
|
589
|
-
return {
|
|
590
|
-
name,
|
|
591
|
-
importPath
|
|
592
|
-
};
|
|
593
|
-
});
|
|
594
|
-
})
|
|
595
|
-
);
|
|
596
|
-
const computeOutput = output.computeOutput ?? ((list) => {
|
|
597
|
-
return list.reduce(
|
|
598
|
-
(result, entry) => {
|
|
599
|
-
debug_default('adding "%O" to the index', entry);
|
|
600
|
-
result.push(` ${entry.name}: () => import('${entry.importPath}'),`);
|
|
601
|
-
return result;
|
|
602
|
-
},
|
|
603
|
-
[`export const ${exportName} = {`]
|
|
604
|
-
).concat("}").join("\n");
|
|
605
|
-
});
|
|
606
|
-
await mkdir(outputDir, { recursive: true });
|
|
607
|
-
await writeFile(outputPath, computeOutput(entries.flat(2)));
|
|
608
|
-
}
|
|
609
|
-
};
|
|
610
|
-
export {
|
|
611
|
-
CodeTransformer
|
|
198
|
+
installPackage = installPackage;
|
|
199
|
+
detectPackageManager = detectPackageManager;
|
|
200
|
+
#cwd;
|
|
201
|
+
#cwdPath;
|
|
202
|
+
project;
|
|
203
|
+
#editorSettings = {
|
|
204
|
+
indentSize: 2,
|
|
205
|
+
convertTabsToSpaces: true,
|
|
206
|
+
trimTrailingWhitespace: true,
|
|
207
|
+
ensureNewLineAtEndOfFile: true,
|
|
208
|
+
indentStyle: 2,
|
|
209
|
+
semicolons: "remove"
|
|
210
|
+
};
|
|
211
|
+
constructor(cwd) {
|
|
212
|
+
this.#cwd = cwd;
|
|
213
|
+
this.#cwdPath = fileURLToPath(this.#cwd);
|
|
214
|
+
this.project = new Project({
|
|
215
|
+
tsConfigFilePath: join(fileURLToPath(this.#cwd), "tsconfig.json"),
|
|
216
|
+
manipulationSettings: { quoteKind: QuoteKind.Single }
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
getDirectories() {
|
|
220
|
+
const rcFileTransformer = new RcFileTransformer(this.#cwd, this.project);
|
|
221
|
+
return {
|
|
222
|
+
start: rcFileTransformer.getDirectory("start", "start"),
|
|
223
|
+
tests: rcFileTransformer.getDirectory("tests", "tests"),
|
|
224
|
+
policies: rcFileTransformer.getDirectory("policies", "app/policies")
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
#addToMiddlewareArray(file, target, middlewareEntry) {
|
|
228
|
+
const callExpressions = file.getDescendantsOfKind(SyntaxKind.CallExpression).filter((statement) => statement.getExpression().getText() === target);
|
|
229
|
+
if (!callExpressions.length) throw new Error(`Cannot find ${target} statement in the file.`);
|
|
230
|
+
const arrayLiteralExpression = callExpressions[0].getArguments()[0];
|
|
231
|
+
if (!arrayLiteralExpression || !Node.isArrayLiteralExpression(arrayLiteralExpression)) throw new Error(`Cannot find middleware array in ${target} statement.`);
|
|
232
|
+
const middleware = `() => import('${middlewareEntry.path}')`;
|
|
233
|
+
if (arrayLiteralExpression.getElements().findIndex((element) => element.getText() === middleware) === -1) if (middlewareEntry.position === "before") arrayLiteralExpression.insertElement(0, middleware);
|
|
234
|
+
else arrayLiteralExpression.addElement(middleware);
|
|
235
|
+
}
|
|
236
|
+
#addToNamedMiddleware(file, middlewareEntry) {
|
|
237
|
+
if (!middlewareEntry.name) throw new Error("Named middleware requires a name.");
|
|
238
|
+
const callArguments = file.getVariableDeclarationOrThrow("middleware").getInitializerIfKindOrThrow(SyntaxKind.CallExpression).getArguments();
|
|
239
|
+
if (callArguments.length === 0) throw new Error("Named middleware call has no arguments.");
|
|
240
|
+
const namedMiddlewareObject = callArguments[0];
|
|
241
|
+
if (!Node.isObjectLiteralExpression(namedMiddlewareObject)) throw new Error("The argument of the named middleware call is not an object literal.");
|
|
242
|
+
if (!namedMiddlewareObject.getProperty(middlewareEntry.name)) {
|
|
243
|
+
const middleware = `${middlewareEntry.name}: () => import('${middlewareEntry.path}')`;
|
|
244
|
+
namedMiddlewareObject.insertProperty(0, middleware);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
#addToPoliciesList(file, policyEntry) {
|
|
248
|
+
const policiesObject = file.getVariableDeclarationOrThrow("policies").getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
249
|
+
if (!policiesObject.getProperty(policyEntry.name)) {
|
|
250
|
+
const policy = `${policyEntry.name}: () => import('${policyEntry.path}')`;
|
|
251
|
+
policiesObject.insertProperty(0, policy);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
#addImportDeclarations(file, importDeclarations) {
|
|
255
|
+
const existingImports = file.getImportDeclarations();
|
|
256
|
+
importDeclarations.forEach((importDeclaration) => {
|
|
257
|
+
const existingImport = existingImports.find((mod) => mod.getModuleSpecifierValue() === importDeclaration.module);
|
|
258
|
+
if (existingImport && importDeclaration.isNamed) {
|
|
259
|
+
if (!existingImport.getNamedImports().find((namedImport) => namedImport.getName() === importDeclaration.identifier)) existingImport.addNamedImport(importDeclaration.identifier);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (existingImport) return;
|
|
263
|
+
file.addImportDeclaration({
|
|
264
|
+
...importDeclaration.isNamed ? { namedImports: [importDeclaration.identifier] } : { defaultImport: importDeclaration.identifier },
|
|
265
|
+
moduleSpecifier: importDeclaration.module
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
#addLeadingComment(writer, comment) {
|
|
270
|
+
if (!comment) return writer.blankLine();
|
|
271
|
+
return writer.blankLine().writeLine("/*").writeLine(`|----------------------------------------------------------`).writeLine(`| ${comment}`).writeLine(`|----------------------------------------------------------`).writeLine(`*/`);
|
|
272
|
+
}
|
|
273
|
+
async defineEnvValidations(definition) {
|
|
274
|
+
const filePath = `${this.getDirectories().start}/env.ts`;
|
|
275
|
+
const envUrl = join(this.#cwdPath, `./${filePath}`);
|
|
276
|
+
const file = this.project.getSourceFile(envUrl);
|
|
277
|
+
if (!file) throw CodemodException.missingEnvFile(filePath, definition);
|
|
278
|
+
const callExpressions = file.getDescendantsOfKind(SyntaxKind.CallExpression).filter((statement) => statement.getExpression().getText() === "Env.create");
|
|
279
|
+
if (!callExpressions.length) throw CodemodException.missingEnvCreate(filePath, definition);
|
|
280
|
+
const objectLiteralExpression = callExpressions[0].getArguments()[1];
|
|
281
|
+
if (!Node.isObjectLiteralExpression(objectLiteralExpression)) throw CodemodException.invalidEnvCreate(filePath, definition);
|
|
282
|
+
let shouldAddComment = true;
|
|
283
|
+
for (const [variable, validation] of Object.entries(definition.variables)) {
|
|
284
|
+
const existingProperty = objectLiteralExpression.getProperty(variable);
|
|
285
|
+
if (existingProperty) shouldAddComment = false;
|
|
286
|
+
if (!existingProperty) objectLiteralExpression.addPropertyAssignment({
|
|
287
|
+
name: variable,
|
|
288
|
+
initializer: validation,
|
|
289
|
+
leadingTrivia: (writer) => {
|
|
290
|
+
if (!shouldAddComment) return;
|
|
291
|
+
shouldAddComment = false;
|
|
292
|
+
return this.#addLeadingComment(writer, definition.leadingComment);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
file.formatText(this.#editorSettings);
|
|
297
|
+
await file.save();
|
|
298
|
+
}
|
|
299
|
+
async addMiddlewareToStack(stack, middleware) {
|
|
300
|
+
const filePath = `${this.getDirectories().start}/kernel.ts`;
|
|
301
|
+
const kernelUrl = join(this.#cwdPath, `./${filePath}`);
|
|
302
|
+
const file = this.project.getSourceFile(kernelUrl);
|
|
303
|
+
if (!file) throw CodemodException.missingKernelFile(filePath, stack, middleware);
|
|
304
|
+
try {
|
|
305
|
+
for (const middlewareEntry of middleware) if (stack === "named") this.#addToNamedMiddleware(file, middlewareEntry);
|
|
306
|
+
else this.#addToMiddlewareArray(file, `${stack}.use`, middlewareEntry);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
if (error instanceof Error) throw CodemodException.invalidMiddlewareStack(filePath, stack, middleware, error.message);
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
311
|
+
file.formatText(this.#editorSettings);
|
|
312
|
+
await file.save();
|
|
313
|
+
}
|
|
314
|
+
async updateRcFile(callback) {
|
|
315
|
+
const rcFileTransformer = new RcFileTransformer(this.#cwd, this.project);
|
|
316
|
+
callback(rcFileTransformer);
|
|
317
|
+
await rcFileTransformer.save();
|
|
318
|
+
}
|
|
319
|
+
async addJapaPlugin(pluginCall, importDeclarations) {
|
|
320
|
+
const filePath = `${this.getDirectories().tests}/bootstrap.ts`;
|
|
321
|
+
const testBootstrapUrl = join(this.#cwdPath, `./${filePath}`);
|
|
322
|
+
const file = this.project.getSourceFile(testBootstrapUrl);
|
|
323
|
+
if (!file) throw CodemodException.missingJapaBootstrap(filePath, pluginCall, importDeclarations);
|
|
324
|
+
this.#addImportDeclarations(file, importDeclarations);
|
|
325
|
+
const pluginsArray = file.getVariableDeclaration("plugins")?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression);
|
|
326
|
+
if (pluginsArray) {
|
|
327
|
+
if (!pluginsArray.getElements().find((element) => element.getText() === pluginCall)) pluginsArray.addElement(pluginCall);
|
|
328
|
+
}
|
|
329
|
+
file.formatText(this.#editorSettings);
|
|
330
|
+
await file.save();
|
|
331
|
+
}
|
|
332
|
+
async addVitePlugin(pluginCall, importDeclarations) {
|
|
333
|
+
const filePath = "vite.config.ts";
|
|
334
|
+
const viteConfigTsUrl = join(this.#cwdPath, `./${filePath}`);
|
|
335
|
+
const file = this.project.getSourceFile(viteConfigTsUrl);
|
|
336
|
+
if (!file) throw CodemodException.missingViteConfig(filePath, pluginCall, importDeclarations);
|
|
337
|
+
try {
|
|
338
|
+
this.#addImportDeclarations(file, importDeclarations);
|
|
339
|
+
const defaultExport = file.getDefaultExportSymbol();
|
|
340
|
+
if (!defaultExport) throw new Error("Cannot find the default export in vite.config.ts");
|
|
341
|
+
const declaration = defaultExport.getDeclarations()[0];
|
|
342
|
+
const pluginsArray = (declaration.getChildrenOfKind(SyntaxKind.ObjectLiteralExpression)[0] || declaration.getChildrenOfKind(SyntaxKind.CallExpression)[0].getArguments()[0]).getPropertyOrThrow("plugins").getFirstChildByKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
|
343
|
+
if (!pluginsArray.getElements().find((element) => element.getText() === pluginCall)) pluginsArray.addElement(pluginCall);
|
|
344
|
+
} catch (error) {
|
|
345
|
+
if (error instanceof CodemodException) throw error;
|
|
346
|
+
if (error instanceof Error) throw CodemodException.invalidViteConfig(filePath, pluginCall, importDeclarations, error.message);
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
file.formatText(this.#editorSettings);
|
|
350
|
+
await file.save();
|
|
351
|
+
}
|
|
352
|
+
async addPolicies(policies) {
|
|
353
|
+
const filePath = `${this.getDirectories().policies}/main.ts`;
|
|
354
|
+
const policiesUrl = join(this.#cwdPath, `./${filePath}`);
|
|
355
|
+
const file = this.project.getSourceFile(policiesUrl);
|
|
356
|
+
if (!file) throw CodemodException.missingPoliciesFile(filePath, policies);
|
|
357
|
+
try {
|
|
358
|
+
for (const policy of policies) this.#addToPoliciesList(file, policy);
|
|
359
|
+
} catch (error) {
|
|
360
|
+
if (error instanceof Error) throw CodemodException.invalidPoliciesFile(filePath, policies, error.message);
|
|
361
|
+
throw error;
|
|
362
|
+
}
|
|
363
|
+
file.formatText(this.#editorSettings);
|
|
364
|
+
await file.save();
|
|
365
|
+
}
|
|
612
366
|
};
|
|
367
|
+
export { CodeTransformer };
|