@reliverse/dler 1.2.4 → 1.2.5
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 +14 -22
- package/bin/app/rempts/migrate/cmd.js +38 -0
- package/bin/app/rempts/migrate/impl/commander.js +265 -0
- package/package.json +3 -2
- package/bin/app/auth/cmd.js +0 -0
package/README.md
CHANGED
|
@@ -116,7 +116,7 @@ bun dev # bun src/mod.ts --dev
|
|
|
116
116
|
|
|
117
117
|
## 🔌 plugins
|
|
118
118
|
|
|
119
|
-
dler ships with a flexible plugin system and **
|
|
119
|
+
dler ships with a flexible plugin system and **14 built-in plugins** (from [@reliverse/addons](https://reliverse.org/addons)).
|
|
120
120
|
|
|
121
121
|
feel free to create your own plugins. plugins can be implemented as built-in directly in `src/app/plugin-name/impl/*` and then imported from `src/app/plugin-name/cmd.ts`; or implemented in your own library and then imported from `src/app/plugin-name/cmd.ts`.
|
|
122
122
|
|
|
@@ -128,15 +128,7 @@ generates aggregator file with content like `import { getsomething } from "./uti
|
|
|
128
128
|
dler agg ...
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
### 2. `
|
|
132
|
-
|
|
133
|
-
best friend of auth+db libs like [better-auth](https://better-auth.com) and [drizzle-orm](https://orm.drizzle.team).
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
dler auth better-auth generate
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### 3. `build`
|
|
131
|
+
### 2. `build`
|
|
140
132
|
|
|
141
133
|
since dler is fully modular, build command is separated for its own build-in plugin as well.
|
|
142
134
|
|
|
@@ -144,11 +136,11 @@ since dler is fully modular, build command is separated for its own build-in plu
|
|
|
144
136
|
dler build ...
|
|
145
137
|
```
|
|
146
138
|
|
|
147
|
-
###
|
|
139
|
+
### 3. `conv`
|
|
148
140
|
|
|
149
141
|
not yet documented.
|
|
150
142
|
|
|
151
|
-
###
|
|
143
|
+
### 4. `deps`
|
|
152
144
|
|
|
153
145
|
finds missing dependencies in your project by scanning your code for imports and comparing them to your `package.json`.
|
|
154
146
|
|
|
@@ -195,11 +187,11 @@ dler deps --all --directory ./src --include-builtins
|
|
|
195
187
|
missing dependencies are shown only once, even if used in multiple files.
|
|
196
188
|
deep imports like `dep/some/file` or `@org/dep/some/thing` are always resolved to their root package.
|
|
197
189
|
|
|
198
|
-
###
|
|
190
|
+
### 5. `inject`
|
|
199
191
|
|
|
200
192
|
not yet documented.
|
|
201
193
|
|
|
202
|
-
###
|
|
194
|
+
### 6. `libs`
|
|
203
195
|
|
|
204
196
|
builds and publishes specific subdirectories of your main project as standalone packages.
|
|
205
197
|
|
|
@@ -235,15 +227,15 @@ libslist: {
|
|
|
235
227
|
|
|
236
228
|
- more magic commands coming soon...
|
|
237
229
|
|
|
238
|
-
###
|
|
230
|
+
### 7. `merge`
|
|
239
231
|
|
|
240
232
|
not yet documented.
|
|
241
233
|
|
|
242
|
-
###
|
|
234
|
+
### 8. `mono`
|
|
243
235
|
|
|
244
236
|
not yet documented.
|
|
245
237
|
|
|
246
|
-
###
|
|
238
|
+
### 9. `pub`
|
|
247
239
|
|
|
248
240
|
pub command is separated for its own build-in plugin as well.
|
|
249
241
|
|
|
@@ -253,13 +245,13 @@ it already calls build command by itself, so you don't need to run `dler build`
|
|
|
253
245
|
dler pub ...
|
|
254
246
|
```
|
|
255
247
|
|
|
256
|
-
###
|
|
248
|
+
### 10. `relifso`
|
|
257
249
|
|
|
258
250
|
```bash
|
|
259
251
|
dler relifso init ...
|
|
260
252
|
```
|
|
261
253
|
|
|
262
|
-
###
|
|
254
|
+
### 11. `relinka`
|
|
263
255
|
|
|
264
256
|
@reliverse/relinka's best friend. learn more in its [docs](https://github.com/reliverse/relinka).
|
|
265
257
|
|
|
@@ -267,7 +259,7 @@ dler relifso init ...
|
|
|
267
259
|
dler relinka --console-to-relinka
|
|
268
260
|
```
|
|
269
261
|
|
|
270
|
-
###
|
|
262
|
+
### 12. `rempts`
|
|
271
263
|
|
|
272
264
|
@reliverse/rempts's best friend. learn more in its [docs](https://github.com/reliverse/rempts).
|
|
273
265
|
|
|
@@ -276,7 +268,7 @@ dler rempts init --cmd my-cmd-1
|
|
|
276
268
|
dler rempts init --cmds
|
|
277
269
|
```
|
|
278
270
|
|
|
279
|
-
###
|
|
271
|
+
### 13. `spell`
|
|
280
272
|
|
|
281
273
|
**available spell types:**
|
|
282
274
|
|
|
@@ -334,7 +326,7 @@ await dler.spell({ spells: ["rename-file"], files: [] });
|
|
|
334
326
|
|
|
335
327
|
p.s. [see how rse cli uses hooked=true](https://github.com/reliverse/rse/blob/main/src/postbuild.ts)
|
|
336
328
|
|
|
337
|
-
###
|
|
329
|
+
### 14. `tools`
|
|
338
330
|
|
|
339
331
|
lets you run standalone dler features directly from the cli:
|
|
340
332
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { defineCommand, defineArgs, confirmPrompt } from "@reliverse/rempts";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import { commanderToRempts } from "./impl/commander.js";
|
|
4
|
+
export default defineCommand({
|
|
5
|
+
args: defineArgs({
|
|
6
|
+
provider: {
|
|
7
|
+
type: "string",
|
|
8
|
+
description: "The provider to migrate from",
|
|
9
|
+
required: true,
|
|
10
|
+
allowed: ["commander"]
|
|
11
|
+
},
|
|
12
|
+
input: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Target directory path containing the files to migrate",
|
|
15
|
+
required: true
|
|
16
|
+
}
|
|
17
|
+
}),
|
|
18
|
+
async run({ args }) {
|
|
19
|
+
const { provider, input } = args;
|
|
20
|
+
const confidence = await confirmPrompt({
|
|
21
|
+
title: `This is an experimental feature and probably may broke some things.
|
|
22
|
+
It will be improved in the future.
|
|
23
|
+
Are you sure you want to migrate files in ${input}?`,
|
|
24
|
+
defaultValue: false
|
|
25
|
+
});
|
|
26
|
+
if (!confidence) {
|
|
27
|
+
throw new Error("Migration cancelled");
|
|
28
|
+
}
|
|
29
|
+
if (!await fs.pathExists(input)) {
|
|
30
|
+
throw new Error(`Input directory does not exist: ${input}`);
|
|
31
|
+
}
|
|
32
|
+
if (provider === "commander") {
|
|
33
|
+
await commanderToRempts(input);
|
|
34
|
+
} else {
|
|
35
|
+
throw new Error(`Unsupported provider: ${provider}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { glob } from "glob";
|
|
2
|
+
import {
|
|
3
|
+
Project,
|
|
4
|
+
Node,
|
|
5
|
+
ScriptTarget,
|
|
6
|
+
ModuleKind,
|
|
7
|
+
SyntaxKind
|
|
8
|
+
} from "ts-morph";
|
|
9
|
+
function parseCommanderFlags(flags) {
|
|
10
|
+
const parts = flags.split(/[\s,]+/).filter(Boolean);
|
|
11
|
+
let longName = "";
|
|
12
|
+
let shortName;
|
|
13
|
+
let takesValue = false;
|
|
14
|
+
for (const part of parts) {
|
|
15
|
+
if (part.startsWith("--")) {
|
|
16
|
+
longName = part.substring(2);
|
|
17
|
+
} else if (part.startsWith("-") && part.length === 2) {
|
|
18
|
+
shortName = part.substring(1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (flags.includes("<") || flags.includes("[")) {
|
|
22
|
+
takesValue = true;
|
|
23
|
+
longName = longName.replace(/[<[].*/, "").trim();
|
|
24
|
+
}
|
|
25
|
+
if (!longName && shortName) {
|
|
26
|
+
if (flags.includes(`<${shortName}>`)) takesValue = true;
|
|
27
|
+
longName = shortName;
|
|
28
|
+
}
|
|
29
|
+
if (!longName) {
|
|
30
|
+
throw new Error(`Could not parse flags: ${flags}`);
|
|
31
|
+
}
|
|
32
|
+
return { longName, shortName, takesValue };
|
|
33
|
+
}
|
|
34
|
+
function getDefaultValueText(node) {
|
|
35
|
+
if (!node) return void 0;
|
|
36
|
+
if (Node.isLiteralExpression(node)) {
|
|
37
|
+
return node.getText();
|
|
38
|
+
}
|
|
39
|
+
if (Node.isIdentifier(node) || Node.isPropertyAccessExpression(node)) {
|
|
40
|
+
return node.getText();
|
|
41
|
+
}
|
|
42
|
+
if (Node.isCallExpression(node)) {
|
|
43
|
+
return node.getText();
|
|
44
|
+
}
|
|
45
|
+
if (Node.isPrefixUnaryExpression(node)) {
|
|
46
|
+
return node.getText();
|
|
47
|
+
}
|
|
48
|
+
console.warn(
|
|
49
|
+
`Unhandled default value type: ${node.getKindName()}, text: ${node.getText()}`
|
|
50
|
+
);
|
|
51
|
+
return node.getText();
|
|
52
|
+
}
|
|
53
|
+
async function transformCommand(varDecl, info, sourceFile) {
|
|
54
|
+
const commandName = info.commandName;
|
|
55
|
+
if (!commandName) {
|
|
56
|
+
console.warn("No command name found");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let actionBodyText = "";
|
|
60
|
+
if (info.actionFunction) {
|
|
61
|
+
if (Node.isArrowFunction(info.actionFunction) || Node.isFunctionExpression(info.actionFunction) || Node.isFunctionDeclaration(info.actionFunction)) {
|
|
62
|
+
const body = info.actionFunction.getBody();
|
|
63
|
+
if (body) {
|
|
64
|
+
actionBodyText = body.getText();
|
|
65
|
+
if (Node.isBlock(body)) {
|
|
66
|
+
actionBodyText = actionBodyText.slice(1, -1).trim();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
console.warn(
|
|
71
|
+
`Unhandled action function type: ${info.actionFunction.getKindName()}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
info.options.reverse();
|
|
76
|
+
if (info.actionFunctionParam) {
|
|
77
|
+
const paramRegex = new RegExp(`\\b${info.actionFunctionParam}\\b`, "g");
|
|
78
|
+
actionBodyText = actionBodyText.replace(paramRegex, "args");
|
|
79
|
+
}
|
|
80
|
+
const argsProperties = info.options.map((opt) => {
|
|
81
|
+
const defaultValueStr = opt.defaultValue ? `,
|
|
82
|
+
default: ${String(opt.defaultValue)}` : "";
|
|
83
|
+
const requiredStr = opt.required ? ",\n required: true" : "";
|
|
84
|
+
return ` ${opt.name}: {
|
|
85
|
+
type: "${opt.type}",
|
|
86
|
+
description: "${opt.description}"${defaultValueStr}${requiredStr}
|
|
87
|
+
}`;
|
|
88
|
+
}).join(",\n");
|
|
89
|
+
const defineCommandText = `
|
|
90
|
+
export const ${varDecl.getName()} = defineCommand({
|
|
91
|
+
meta: {
|
|
92
|
+
name: "${commandName}",
|
|
93
|
+
version: "${info.version || "1.0.0"}",
|
|
94
|
+
description: "${info.description || "Migrated from Commander"}",
|
|
95
|
+
},
|
|
96
|
+
args: {
|
|
97
|
+
${argsProperties}
|
|
98
|
+
},
|
|
99
|
+
async run({ args }) {
|
|
100
|
+
${actionBodyText}
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Add runMain at the end of the file
|
|
105
|
+
await runMain(${varDecl.getName()});
|
|
106
|
+
`;
|
|
107
|
+
varDecl.replaceWithText(defineCommandText);
|
|
108
|
+
if (info.actionFunction && Node.isIdentifier(info.actionFunction)) {
|
|
109
|
+
const funcName = info.actionFunction.getText();
|
|
110
|
+
const funcDecl = sourceFile.getFunction(funcName);
|
|
111
|
+
if (funcDecl) {
|
|
112
|
+
funcDecl.remove();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
sourceFile.fixMissingImports();
|
|
116
|
+
await sourceFile.save();
|
|
117
|
+
console.log(`Transformed command in: ${sourceFile.getFilePath()}`);
|
|
118
|
+
}
|
|
119
|
+
function extractCommandInfo(node, sourceFile) {
|
|
120
|
+
const info = {
|
|
121
|
+
options: []
|
|
122
|
+
};
|
|
123
|
+
if (Node.isNewExpression(node)) {
|
|
124
|
+
const expr = node.getExpression();
|
|
125
|
+
if (expr && Node.isIdentifier(expr) && expr.getText() === "Command") {
|
|
126
|
+
const commandArg = node.getArguments()[0];
|
|
127
|
+
if (commandArg && Node.isStringLiteral(commandArg)) {
|
|
128
|
+
info.commandName = commandArg.getLiteralText();
|
|
129
|
+
}
|
|
130
|
+
return info;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (Node.isCallExpression(node)) {
|
|
134
|
+
let tempExpr = node;
|
|
135
|
+
while (tempExpr && Node.isCallExpression(tempExpr)) {
|
|
136
|
+
const expression = tempExpr.getExpression();
|
|
137
|
+
if (Node.isPropertyAccessExpression(expression)) {
|
|
138
|
+
const methodName = expression.getName();
|
|
139
|
+
switch (methodName) {
|
|
140
|
+
case "action":
|
|
141
|
+
handleActionMethod(tempExpr, info, sourceFile);
|
|
142
|
+
break;
|
|
143
|
+
case "option":
|
|
144
|
+
handleOptionMethod(tempExpr, info);
|
|
145
|
+
break;
|
|
146
|
+
case "description":
|
|
147
|
+
handleDescriptionMethod(tempExpr, info);
|
|
148
|
+
break;
|
|
149
|
+
case "version":
|
|
150
|
+
handleVersionMethod(tempExpr, info);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const parent = tempExpr.getParent();
|
|
155
|
+
tempExpr = Node.isCallExpression(parent) ? parent : void 0;
|
|
156
|
+
}
|
|
157
|
+
return info;
|
|
158
|
+
}
|
|
159
|
+
return void 0;
|
|
160
|
+
}
|
|
161
|
+
function handleActionMethod(node, info, sourceFile) {
|
|
162
|
+
const [actionArg] = node.getArguments();
|
|
163
|
+
if (actionArg && Node.isIdentifier(actionArg)) {
|
|
164
|
+
const funcDef = sourceFile.getFunction(actionArg.getText()) || sourceFile.getVariableDeclaration(actionArg.getText())?.getInitializer();
|
|
165
|
+
if (funcDef && (Node.isArrowFunction(funcDef) || Node.isFunctionDeclaration(funcDef) || Node.isFunctionExpression(funcDef))) {
|
|
166
|
+
info.actionFunction = funcDef;
|
|
167
|
+
const firstParam = funcDef.getParameters()[0];
|
|
168
|
+
if (firstParam) {
|
|
169
|
+
info.actionFunctionParam = firstParam.getName();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function handleOptionMethod(node, info) {
|
|
175
|
+
const [flagsArg, descArg, defaultValueArg] = node.getArguments();
|
|
176
|
+
if (flagsArg && Node.isStringLiteral(flagsArg)) {
|
|
177
|
+
const { longName, shortName, takesValue } = parseCommanderFlags(
|
|
178
|
+
flagsArg.getLiteralText()
|
|
179
|
+
);
|
|
180
|
+
info.options.push({
|
|
181
|
+
name: longName,
|
|
182
|
+
shortFlag: shortName,
|
|
183
|
+
type: takesValue ? "string" : "boolean",
|
|
184
|
+
description: Node.isStringLiteral(descArg) ? descArg.getLiteralText() : "TODO: Add description",
|
|
185
|
+
defaultValue: defaultValueArg ? getDefaultValueText(defaultValueArg) : void 0
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function handleDescriptionMethod(node, info) {
|
|
190
|
+
const [descArg] = node.getArguments();
|
|
191
|
+
if (descArg && Node.isStringLiteral(descArg)) {
|
|
192
|
+
info.description = descArg.getLiteralText();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function handleVersionMethod(node, info) {
|
|
196
|
+
const [versionArg] = node.getArguments();
|
|
197
|
+
if (versionArg && Node.isStringLiteral(versionArg)) {
|
|
198
|
+
info.version = versionArg.getLiteralText();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
export async function commanderToRempts(targetDirectory) {
|
|
202
|
+
if (!targetDirectory) {
|
|
203
|
+
throw new Error("Target directory is required");
|
|
204
|
+
}
|
|
205
|
+
const project = new Project({
|
|
206
|
+
compilerOptions: {
|
|
207
|
+
target: ScriptTarget.ESNext,
|
|
208
|
+
module: ModuleKind.ESNext,
|
|
209
|
+
esModuleInterop: true,
|
|
210
|
+
skipLibCheck: true
|
|
211
|
+
},
|
|
212
|
+
skipAddingFilesFromTsConfig: true
|
|
213
|
+
});
|
|
214
|
+
const filePaths = await glob(`${targetDirectory}/**/*.ts`, {
|
|
215
|
+
ignore: ["**/node_modules/**", "**/*.d.ts"],
|
|
216
|
+
absolute: true
|
|
217
|
+
});
|
|
218
|
+
for (const filePath of filePaths) {
|
|
219
|
+
console.log(`Processing: ${filePath}`);
|
|
220
|
+
project.addSourceFileAtPath(filePath);
|
|
221
|
+
try {
|
|
222
|
+
await transformFile(filePath, project);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.error(`Error transforming file ${filePath}:`, error);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
console.log("Migration completed successfully.");
|
|
228
|
+
}
|
|
229
|
+
async function transformFile(filePath, project) {
|
|
230
|
+
const sourceFile = project.getSourceFile(filePath);
|
|
231
|
+
if (!sourceFile) {
|
|
232
|
+
console.error(`Could not find source file: ${filePath}`);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const commanderImport = sourceFile.getImportDeclaration("commander");
|
|
236
|
+
if (commanderImport) {
|
|
237
|
+
commanderImport.remove();
|
|
238
|
+
}
|
|
239
|
+
const remptsImport = sourceFile.getImportDeclaration("@reliverse/rempts");
|
|
240
|
+
const neededRemptsImports = ["defineCommand", "runMain"];
|
|
241
|
+
if (remptsImport) {
|
|
242
|
+
const existingNamedImports = remptsImport.getNamedImports().map((ni) => ni.getName());
|
|
243
|
+
for (const neededImport of neededRemptsImports) {
|
|
244
|
+
if (!existingNamedImports.includes(neededImport)) {
|
|
245
|
+
remptsImport.addNamedImport(neededImport);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
sourceFile.addImportDeclaration({
|
|
250
|
+
moduleSpecifier: "@reliverse/rempts",
|
|
251
|
+
namedImports: neededRemptsImports
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
const variableDeclarations = sourceFile.getDescendantsOfKind(
|
|
255
|
+
SyntaxKind.VariableDeclaration
|
|
256
|
+
);
|
|
257
|
+
for (const varDecl of variableDeclarations) {
|
|
258
|
+
const initializer = varDecl.getInitializer();
|
|
259
|
+
if (!initializer) continue;
|
|
260
|
+
const commandInfo = extractCommandInfo(initializer, sourceFile);
|
|
261
|
+
if (commandInfo) {
|
|
262
|
+
await transformCommand(varDecl, commandInfo, sourceFile);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"@reliverse/relico": "^1.1.2",
|
|
4
4
|
"@reliverse/relinka": "^1.4.5",
|
|
5
|
-
"@reliverse/rempts": "^1.7.
|
|
5
|
+
"@reliverse/rempts": "^1.7.10",
|
|
6
6
|
"@rollup/plugin-alias": "^5.1.1",
|
|
7
7
|
"@rollup/plugin-commonjs": "^28.0.3",
|
|
8
8
|
"@rollup/plugin-json": "^6.1.0",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"scule": "^1.3.0",
|
|
34
34
|
"semver": "^7.7.2",
|
|
35
35
|
"tinyglobby": "^0.2.13",
|
|
36
|
+
"ts-morph": "^25.0.1",
|
|
36
37
|
"untyped": "^2.0.0"
|
|
37
38
|
},
|
|
38
39
|
"description": "dler (prev. relidler) is a flexible, unified, and fully automated bundler for TypeScript and JavaScript projects, as well as an NPM and JSR publishing tool.",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"license": "MIT",
|
|
41
42
|
"name": "@reliverse/dler",
|
|
42
43
|
"type": "module",
|
|
43
|
-
"version": "1.2.
|
|
44
|
+
"version": "1.2.5",
|
|
44
45
|
"keywords": [
|
|
45
46
|
"reliverse",
|
|
46
47
|
"cli",
|
package/bin/app/auth/cmd.js
DELETED
|
File without changes
|