@reliverse/dler 1.2.2 → 1.2.4
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 +126 -69
- package/bin/app/build/cmd.js +17 -0
- package/bin/app/cmds.js +6 -0
- package/bin/{cli/args → app}/inject/README.md +20 -20
- package/bin/{cli/args/inject/inject-mod.js → app/inject/cmd.js} +7 -3
- package/bin/app/inject/expect/cmd.js +43 -0
- package/bin/app/inject/expect/impl.js +162 -0
- package/bin/app/libs/cmd.js +0 -0
- package/bin/app/mono/cmd.js +0 -0
- package/bin/app/pub/cmd.js +17 -0
- package/bin/app/relifso/cmd.js +36 -0
- package/bin/{cli/args/init/init-mod.txt → app/relifso/init/cmd.js} +93 -121
- package/bin/app/relifso/init/impl/mod.js +248 -0
- package/bin/app/relifso/init/impl/types.js +0 -0
- package/bin/app/relinka/cmd.js +0 -0
- package/bin/{cli/args/init/cmd/index.js → app/rempts/init/cmd/cmd.js} +3 -2
- package/bin/app/rempts/init/cmds/cmd.js +80 -0
- package/bin/app/spell/cmd.js +0 -0
- package/bin/app/split/cmd.js +0 -0
- package/bin/{cli/args/tools/index.js → app/tools/cmd.js} +1 -1
- package/bin/cli.js +101 -1
- package/bin/init.js +22 -2
- package/bin/libs/cfg/cfg-default.js +4 -1
- package/bin/libs/sdk/sdk-impl/build/build-library.js +57 -25
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/mkdist.js +3 -1
- package/bin/mod.js +7 -39
- package/package.json +6 -7
- package/bin/cli/args/deps/deps-mod.js +0 -48
- package/bin/cli/args/init/libs/reinit/reinit-mod.js +0 -5
- package/bin/cli/args/init/libs/reinit/reint-impl/reinit-mod.txt +0 -395
- package/bin/cli/args/init/types.js +0 -1
- package/bin/cli/args/inject/arg-ts-expect-error.txt +0 -49
- package/bin/cli/args/inject/inject-mod.txt +0 -28
- package/bin/cli/args/inject/reinject.config.js +0 -4
- package/bin/cli/args/inject/ts-expect-error.txt +0 -277
- package/bin/cli/args/spell/spell-mod.js +0 -44
- package/bin/cli/args/split/split-mod.js +0 -26
- /package/bin/{cli/args/agg/agg-mod.js → app/agg/cmd.js} +0 -0
- /package/bin/{cli/args/conv/conv-mod.js → app/auth/cmd.js} +0 -0
- /package/bin/{cli/args → app}/conv/README.md +0 -0
- /package/bin/{cli/args/deps/types.js → app/conv/cmd.js} +0 -0
- /package/bin/{cli/args/init/libs/reinit/reint-impl/types.js → app/deps/cmd.js} +0 -0
- /package/bin/{cli/args/deps → app/deps/impl}/analyzer.js +0 -0
- /package/bin/{cli/args/deps → app/deps/impl}/filesystem.js +0 -0
- /package/bin/{cli/args/deps → app/deps/impl}/formatter.js +0 -0
- /package/bin/{cli/args/deps → app/deps/impl}/parser.js +0 -0
- /package/bin/{cli/args/mono/mono-mod.js → app/deps/impl/types.js} +0 -0
- /package/bin/{cli/args/merger → app/merge}/README.md +0 -0
- /package/bin/{cli/args/merger/merger-mod.txt → app/merge/cmd.txt} +0 -0
- /package/bin/{cli/args/init/libs/reinit/reint-impl → app/relifso/init/impl}/const.js +0 -0
- /package/bin/{cli/args/init/libs/reinit/reint-impl → app/relifso/init/impl}/templates/t-gitignore.js +0 -0
- /package/bin/{cli/args/init/libs/reinit/reint-impl → app/relifso/init/impl}/templates/t-license.js +0 -0
- /package/bin/{cli/args/init/libs/reinit/reint-impl → app/relifso/init/impl}/templates/t-readme.js +0 -0
- /package/bin/{cli/args/init/libs/reinit/reint-impl → app/relifso/init/impl}/utils.js +0 -0
- /package/bin/{cli/args/init → app/rempts}/README.md +0 -0
- /package/bin/{cli/args → app}/split/README.md +0 -0
- /package/bin/{cli/args/split/split-impl.js → app/split/impl.js} +0 -0
- /package/bin/{cli/args/tools/tools-impl.js → app/tools/impl.js} +0 -0
- /package/bin/{tools.txt → app/tools/tools.txt} +0 -0
|
@@ -1,121 +1,93 @@
|
|
|
1
|
-
import { relinka } from "@reliverse/relinka";
|
|
2
|
-
import {
|
|
3
|
-
defineCommand,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
type: "
|
|
27
|
-
description: "
|
|
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
|
-
concurrency
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
} else {
|
|
95
|
-
// Single file approach
|
|
96
|
-
let finalFileType = effectiveFileType;
|
|
97
|
-
if (!finalFileType) {
|
|
98
|
-
// If user didn't specify, prompt for a single file type
|
|
99
|
-
const possibleTypes = FILE_TYPES.map((ft) => ft.type);
|
|
100
|
-
const picked = await selectPrompt({
|
|
101
|
-
title: "Pick a file type to initialize",
|
|
102
|
-
options: possibleTypes.map((pt) => ({ label: pt, value: pt })),
|
|
103
|
-
});
|
|
104
|
-
finalFileType = picked;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const result = await initFile({
|
|
108
|
-
fileType: finalFileType,
|
|
109
|
-
destDir,
|
|
110
|
-
});
|
|
111
|
-
relinka("verbose", `Single file result: ${JSON.stringify(result)}`);
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
await runMain(main).catch((error: unknown) => {
|
|
117
|
-
errorHandler(
|
|
118
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
119
|
-
"An unhandled error occurred, please report it at https://github.com/reliverse/reinit",
|
|
120
|
-
);
|
|
121
|
-
});
|
|
1
|
+
import { relinka } from "@reliverse/relinka";
|
|
2
|
+
import {
|
|
3
|
+
defineCommand,
|
|
4
|
+
multiselectPrompt,
|
|
5
|
+
selectPrompt
|
|
6
|
+
} from "@reliverse/rempts";
|
|
7
|
+
import { FILE_TYPES } from "./impl/const.js";
|
|
8
|
+
import { initFile, initFiles } from "./impl/mod.js";
|
|
9
|
+
export default defineCommand({
|
|
10
|
+
meta: {
|
|
11
|
+
name: "relifso",
|
|
12
|
+
version: "1.0.0",
|
|
13
|
+
description: "relifso helper utils"
|
|
14
|
+
},
|
|
15
|
+
args: {
|
|
16
|
+
dev: {
|
|
17
|
+
type: "boolean",
|
|
18
|
+
description: "Runs the CLI in dev mode"
|
|
19
|
+
},
|
|
20
|
+
fileType: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "File type to initialize (e.g. 'md:README')",
|
|
23
|
+
required: false
|
|
24
|
+
},
|
|
25
|
+
destDir: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Destination directory",
|
|
28
|
+
default: ".",
|
|
29
|
+
required: false
|
|
30
|
+
},
|
|
31
|
+
multiple: {
|
|
32
|
+
type: "boolean",
|
|
33
|
+
description: "Whether to select multiple file types from the library",
|
|
34
|
+
required: false,
|
|
35
|
+
default: false
|
|
36
|
+
},
|
|
37
|
+
parallel: {
|
|
38
|
+
type: "boolean",
|
|
39
|
+
description: "Run tasks in parallel",
|
|
40
|
+
required: false,
|
|
41
|
+
default: false
|
|
42
|
+
},
|
|
43
|
+
concurrency: {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "Concurrency limit if parallel is true",
|
|
46
|
+
required: false,
|
|
47
|
+
default: "4"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
async run({ args }) {
|
|
51
|
+
const { fileType, destDir, multiple, parallel, concurrency } = args;
|
|
52
|
+
const concurrencyNum = Number(concurrency);
|
|
53
|
+
if (fileType && !FILE_TYPES.find((ft) => ft.type === fileType)) {
|
|
54
|
+
throw new Error(`Invalid file type: ${fileType}`);
|
|
55
|
+
}
|
|
56
|
+
const effectiveFileType = fileType;
|
|
57
|
+
if (multiple) {
|
|
58
|
+
const possibleTypes = FILE_TYPES.map((ft) => ft.type);
|
|
59
|
+
const chosen = await multiselectPrompt({
|
|
60
|
+
title: "Select file types to initialize",
|
|
61
|
+
options: possibleTypes.map((pt) => ({ label: pt, value: pt }))
|
|
62
|
+
});
|
|
63
|
+
if (chosen.length === 0) {
|
|
64
|
+
relinka("log", "No file types selected. Exiting...");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const requests = chosen.map((ct) => ({
|
|
68
|
+
fileType: ct,
|
|
69
|
+
destDir
|
|
70
|
+
}));
|
|
71
|
+
const results = await initFiles(requests, {
|
|
72
|
+
parallel,
|
|
73
|
+
concurrency: concurrencyNum
|
|
74
|
+
});
|
|
75
|
+
relinka("verbose", `Multiple files result: ${JSON.stringify(results)}`);
|
|
76
|
+
} else {
|
|
77
|
+
let finalFileType = effectiveFileType;
|
|
78
|
+
if (!finalFileType) {
|
|
79
|
+
const possibleTypes = FILE_TYPES.map((ft) => ft.type);
|
|
80
|
+
const picked = await selectPrompt({
|
|
81
|
+
title: "Pick a file type to initialize",
|
|
82
|
+
options: possibleTypes.map((pt) => ({ label: pt, value: pt }))
|
|
83
|
+
});
|
|
84
|
+
finalFileType = picked;
|
|
85
|
+
}
|
|
86
|
+
const result = await initFile({
|
|
87
|
+
fileType: finalFileType,
|
|
88
|
+
destDir
|
|
89
|
+
});
|
|
90
|
+
relinka("verbose", `Single file result: ${JSON.stringify(result)}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { relinka } from "@reliverse/relinka";
|
|
2
|
+
import { selectPrompt } from "@reliverse/rempts";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import pMap from "p-map";
|
|
5
|
+
import path from "pathe";
|
|
6
|
+
import { FILE_TYPES } from "./const.js";
|
|
7
|
+
import { gitignoreTemplate } from "./templates/t-gitignore.js";
|
|
8
|
+
import { licenseTemplate } from "./templates/t-license.js";
|
|
9
|
+
import { readmeTemplate } from "./templates/t-readme.js";
|
|
10
|
+
import { escapeMarkdownCodeBlocks } from "./utils.js";
|
|
11
|
+
const DEFAULT_CONFIG = {
|
|
12
|
+
defaultInitBehaviour: "create",
|
|
13
|
+
defaultDestFileExistsBehaviour: "prompt",
|
|
14
|
+
parallelByDefault: false,
|
|
15
|
+
parallelConcurrency: 4
|
|
16
|
+
};
|
|
17
|
+
const fileExistsCache = /* @__PURE__ */ new Map();
|
|
18
|
+
export async function createFileFromScratch(destPath, fileType, contentCreateMode) {
|
|
19
|
+
try {
|
|
20
|
+
await fs.ensureDir(path.dirname(destPath));
|
|
21
|
+
let content = "";
|
|
22
|
+
switch (fileType) {
|
|
23
|
+
case "md:LICENSE":
|
|
24
|
+
content = licenseTemplate;
|
|
25
|
+
break;
|
|
26
|
+
case "md:README":
|
|
27
|
+
content = escapeMarkdownCodeBlocks(readmeTemplate);
|
|
28
|
+
break;
|
|
29
|
+
case "git:gitignore":
|
|
30
|
+
content = gitignoreTemplate;
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
content = `// Auto-generated file for type: ${fileType}`;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
if (contentCreateMode) {
|
|
37
|
+
content = contentCreateMode;
|
|
38
|
+
relinka("verbose", `Using custom content for file ${destPath}`);
|
|
39
|
+
}
|
|
40
|
+
await fs.outputFile(destPath, content, { encoding: "utf-8" });
|
|
41
|
+
} catch (error) {
|
|
42
|
+
relinka("error", `Failed to create file ${destPath}: ${error}`);
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function initFile(req, userCfg) {
|
|
47
|
+
const config = { ...DEFAULT_CONFIG, ...userCfg };
|
|
48
|
+
const initBehaviour = req.initBehaviour ?? config.defaultInitBehaviour;
|
|
49
|
+
const existsBehaviour = req.destFileExistsBehaviour ?? config.defaultDestFileExistsBehaviour;
|
|
50
|
+
config.onFileStart?.(req);
|
|
51
|
+
let result;
|
|
52
|
+
try {
|
|
53
|
+
result = await doInitFile(
|
|
54
|
+
req,
|
|
55
|
+
initBehaviour,
|
|
56
|
+
existsBehaviour
|
|
57
|
+
);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
result = {
|
|
60
|
+
requested: req,
|
|
61
|
+
status: "error",
|
|
62
|
+
error: err instanceof Error ? err.message : String(err)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
config.onFileComplete?.(result);
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
export async function initFiles(items, options, userCfg) {
|
|
69
|
+
const config = { ...DEFAULT_CONFIG, ...userCfg };
|
|
70
|
+
const parallel = options?.parallel ?? config.parallelByDefault;
|
|
71
|
+
const concurrency = options?.concurrency ?? config.parallelConcurrency;
|
|
72
|
+
if (parallel) {
|
|
73
|
+
return pMap(items, (item) => initFile(item, config), { concurrency });
|
|
74
|
+
}
|
|
75
|
+
return Promise.all(items.map((item) => initFile(item, config)));
|
|
76
|
+
}
|
|
77
|
+
async function checkFileExists(filePath) {
|
|
78
|
+
const cached = fileExistsCache.get(filePath);
|
|
79
|
+
if (cached !== void 0) {
|
|
80
|
+
return cached;
|
|
81
|
+
}
|
|
82
|
+
const exists = await fs.pathExists(filePath);
|
|
83
|
+
fileExistsCache.set(filePath, exists);
|
|
84
|
+
return exists;
|
|
85
|
+
}
|
|
86
|
+
async function doInitFile(req, initBehaviour, destFileExistsBehaviour) {
|
|
87
|
+
const { fileType, destDir, options } = req;
|
|
88
|
+
const { destFileName } = options ?? {};
|
|
89
|
+
const knownType = FILE_TYPES.find(
|
|
90
|
+
(f) => f.type.toLowerCase() === fileType.toLowerCase()
|
|
91
|
+
);
|
|
92
|
+
if (!knownType) {
|
|
93
|
+
throw new Error(`Unknown file type: ${fileType}`);
|
|
94
|
+
}
|
|
95
|
+
const variations = knownType.variations;
|
|
96
|
+
const chosenVariation = variations.length === 1 ? variations[0] : await selectPrompt({
|
|
97
|
+
title: `Select variation for ${fileType}`,
|
|
98
|
+
options: variations.map((v) => ({ label: v, value: v }))
|
|
99
|
+
});
|
|
100
|
+
const finalName = destFileName ?? chosenVariation;
|
|
101
|
+
const absoluteDestDir = path.resolve(process.cwd(), destDir || "");
|
|
102
|
+
const resolvedDestPath = path.join(absoluteDestDir, finalName);
|
|
103
|
+
relinka(
|
|
104
|
+
"verbose",
|
|
105
|
+
`Preparing to init file:
|
|
106
|
+
- File Type: ${fileType}
|
|
107
|
+
- Variation: ${chosenVariation}
|
|
108
|
+
- Destination Dir: ${absoluteDestDir}
|
|
109
|
+
- Final Path: ${resolvedDestPath}
|
|
110
|
+
`
|
|
111
|
+
);
|
|
112
|
+
const alreadyExists = await checkFileExists(resolvedDestPath);
|
|
113
|
+
if (alreadyExists) {
|
|
114
|
+
const maybeNewDest = await handleExistingFile(
|
|
115
|
+
resolvedDestPath,
|
|
116
|
+
destFileExistsBehaviour
|
|
117
|
+
);
|
|
118
|
+
if (!maybeNewDest) {
|
|
119
|
+
return { requested: req, status: "skipped" };
|
|
120
|
+
}
|
|
121
|
+
if (maybeNewDest !== resolvedDestPath) {
|
|
122
|
+
relinka("log", `Using new path: ${maybeNewDest}`);
|
|
123
|
+
return finalizeInit(req, initBehaviour, chosenVariation, maybeNewDest);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return finalizeInit(req, initBehaviour, chosenVariation, resolvedDestPath);
|
|
127
|
+
}
|
|
128
|
+
async function finalizeInit(req, initBehaviour, chosenVariation, resolvedDestPath) {
|
|
129
|
+
try {
|
|
130
|
+
switch (initBehaviour) {
|
|
131
|
+
case "copy":
|
|
132
|
+
return await runCopy(req, chosenVariation, resolvedDestPath);
|
|
133
|
+
case "create":
|
|
134
|
+
return await runCreate(req, resolvedDestPath);
|
|
135
|
+
default:
|
|
136
|
+
try {
|
|
137
|
+
return await runCopy(req, chosenVariation, resolvedDestPath);
|
|
138
|
+
} catch {
|
|
139
|
+
relinka(
|
|
140
|
+
"warn",
|
|
141
|
+
`Copy failed for ${chosenVariation}, falling back to create...`
|
|
142
|
+
);
|
|
143
|
+
return await runCreate(req, resolvedDestPath);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch (err) {
|
|
147
|
+
return {
|
|
148
|
+
requested: req,
|
|
149
|
+
status: "error",
|
|
150
|
+
error: err instanceof Error ? err.message : String(err)
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function runCopy(req, chosenVariation, resolvedDestPath) {
|
|
155
|
+
const { srcCopyMode, fallbackSource } = req.options ?? {};
|
|
156
|
+
const resolvedSrcDir = path.resolve(process.cwd(), srcCopyMode || "");
|
|
157
|
+
try {
|
|
158
|
+
const srcPath = path.join(resolvedSrcDir, chosenVariation);
|
|
159
|
+
if (await checkFileExists(srcPath)) {
|
|
160
|
+
await fs.copy(srcPath, resolvedDestPath);
|
|
161
|
+
return {
|
|
162
|
+
requested: req,
|
|
163
|
+
finalPath: resolvedDestPath,
|
|
164
|
+
status: "copied"
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (fallbackSource) {
|
|
168
|
+
const fallbackPath = path.join(
|
|
169
|
+
path.resolve(process.cwd(), fallbackSource),
|
|
170
|
+
chosenVariation
|
|
171
|
+
);
|
|
172
|
+
if (await checkFileExists(fallbackPath)) {
|
|
173
|
+
await fs.copy(fallbackPath, resolvedDestPath);
|
|
174
|
+
return {
|
|
175
|
+
requested: req,
|
|
176
|
+
finalPath: resolvedDestPath,
|
|
177
|
+
status: "copied"
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
throw new Error(`Source file not found: ${chosenVariation}`);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
`Copy failed: ${error instanceof Error ? error.message : String(error)}`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function runCreate(req, resolvedDestPath) {
|
|
189
|
+
try {
|
|
190
|
+
const { contentCreateMode } = req.options ?? {};
|
|
191
|
+
await createFileFromScratch(
|
|
192
|
+
resolvedDestPath,
|
|
193
|
+
req.fileType,
|
|
194
|
+
contentCreateMode
|
|
195
|
+
);
|
|
196
|
+
return {
|
|
197
|
+
requested: req,
|
|
198
|
+
finalPath: resolvedDestPath,
|
|
199
|
+
status: "created"
|
|
200
|
+
};
|
|
201
|
+
} catch (error) {
|
|
202
|
+
throw new Error(
|
|
203
|
+
`Create failed: ${error instanceof Error ? error.message : String(error)}`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async function handleExistingFile(destPath, behaviour) {
|
|
208
|
+
switch (behaviour) {
|
|
209
|
+
case "rewrite":
|
|
210
|
+
return destPath;
|
|
211
|
+
case "skip":
|
|
212
|
+
return null;
|
|
213
|
+
case "attach-index":
|
|
214
|
+
return attachIndex(destPath);
|
|
215
|
+
case "prompt": {
|
|
216
|
+
const action = await selectPrompt({
|
|
217
|
+
title: `File ${destPath} already exists`,
|
|
218
|
+
options: [
|
|
219
|
+
{ label: "Skip", value: "skip" },
|
|
220
|
+
{ label: "Rewrite", value: "rewrite" },
|
|
221
|
+
{ label: "Attach Index", value: "attach-index" }
|
|
222
|
+
]
|
|
223
|
+
});
|
|
224
|
+
switch (action) {
|
|
225
|
+
case "skip":
|
|
226
|
+
return null;
|
|
227
|
+
case "rewrite":
|
|
228
|
+
return destPath;
|
|
229
|
+
case "attach-index":
|
|
230
|
+
return attachIndex(destPath);
|
|
231
|
+
default:
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
async function attachIndex(originalPath) {
|
|
238
|
+
const dir = path.dirname(originalPath);
|
|
239
|
+
const ext = path.extname(originalPath);
|
|
240
|
+
const base = path.basename(originalPath, ext);
|
|
241
|
+
let index = 1;
|
|
242
|
+
let newPath;
|
|
243
|
+
do {
|
|
244
|
+
newPath = path.join(dir, `${base}-${index}${ext}`);
|
|
245
|
+
index++;
|
|
246
|
+
} while (await checkFileExists(newPath));
|
|
247
|
+
return newPath;
|
|
248
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -12,7 +12,8 @@ export default defineCommand({
|
|
|
12
12
|
cmd: {
|
|
13
13
|
type: "array",
|
|
14
14
|
required: true,
|
|
15
|
-
description: "Names of commands to initialize"
|
|
15
|
+
description: "Names of commands to initialize",
|
|
16
|
+
options: ["cmd1", "cmd2", "cmd3"]
|
|
16
17
|
},
|
|
17
18
|
force: {
|
|
18
19
|
type: "boolean",
|
|
@@ -21,7 +22,7 @@ export default defineCommand({
|
|
|
21
22
|
}
|
|
22
23
|
},
|
|
23
24
|
async run({ args }) {
|
|
24
|
-
const root = path.resolve("src/
|
|
25
|
+
const root = path.resolve("src/app");
|
|
25
26
|
for (const cmdName of args.cmd) {
|
|
26
27
|
const dirPath = path.join(root, cmdName);
|
|
27
28
|
const filePath = path.join(dirPath, "index.ts");
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { relinka } from "@reliverse/relinka";
|
|
2
|
+
import { defineCommand } from "@reliverse/rempts";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import path from "pathe";
|
|
5
|
+
export default defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "cmds",
|
|
8
|
+
version: "1.0.0",
|
|
9
|
+
description: "Generate command exports file for cmd.ts files."
|
|
10
|
+
},
|
|
11
|
+
args: {
|
|
12
|
+
outFile: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Output file path (relative to workspace root)",
|
|
15
|
+
default: "src/app/cmds.ts"
|
|
16
|
+
},
|
|
17
|
+
cmdDirs: {
|
|
18
|
+
type: "array",
|
|
19
|
+
description: "Command directories to scan (relative to src/app)",
|
|
20
|
+
default: [],
|
|
21
|
+
options: ["relifso", "inject", "rempts"]
|
|
22
|
+
},
|
|
23
|
+
force: {
|
|
24
|
+
type: "boolean",
|
|
25
|
+
default: false,
|
|
26
|
+
description: "Overwrite existing file"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
async run({ args }) {
|
|
30
|
+
const root = path.resolve("src/app");
|
|
31
|
+
const outPath = path.resolve(args.outFile ?? "src/app/cmds.ts");
|
|
32
|
+
if (await fs.pathExists(outPath) && !args.force) {
|
|
33
|
+
relinka(
|
|
34
|
+
"warn",
|
|
35
|
+
`\u274C File "${outPath}" already exists. Use --force to overwrite.`
|
|
36
|
+
);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const cmdDirs = (args.cmdDirs ?? []).length > 0 ? args.cmdDirs ?? [] : await findCommandDirs(root);
|
|
40
|
+
if (cmdDirs.length === 0) {
|
|
41
|
+
relinka("warn", "No command directories found with cmd.ts files.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const exports = generateExports(cmdDirs);
|
|
45
|
+
await fs.ensureDir(path.dirname(outPath));
|
|
46
|
+
await fs.writeFile(outPath, exports, "utf-8");
|
|
47
|
+
relinka("success", `\u2705 Generated command exports at: ${outPath}`);
|
|
48
|
+
relinka("log", `Found ${cmdDirs.length} command(s): ${cmdDirs.join(", ")}`);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
async function findCommandDirs(root) {
|
|
52
|
+
const cmdDirs = [];
|
|
53
|
+
async function scan(dir) {
|
|
54
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
55
|
+
for (const entry of entries) {
|
|
56
|
+
const fullPath = path.join(dir, entry.name);
|
|
57
|
+
if (entry.isDirectory()) {
|
|
58
|
+
if (await fs.pathExists(path.join(fullPath, "cmd.ts"))) {
|
|
59
|
+
const relPath = path.relative(root, fullPath);
|
|
60
|
+
cmdDirs.push(relPath);
|
|
61
|
+
} else {
|
|
62
|
+
await scan(fullPath);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await scan(root);
|
|
68
|
+
return cmdDirs;
|
|
69
|
+
}
|
|
70
|
+
function generateExports(cmdDirs) {
|
|
71
|
+
const imports = cmdDirs.map((dir) => {
|
|
72
|
+
const funcName = `getCmd${dir.split(/[/\\]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")}`;
|
|
73
|
+
return `export async function ${funcName}() {
|
|
74
|
+
return (await import("./${dir}/cmd.js")).default;
|
|
75
|
+
}`;
|
|
76
|
+
});
|
|
77
|
+
return `// Generated command exports - DO NOT EDIT
|
|
78
|
+
${imports.join("\n\n")}
|
|
79
|
+
`;
|
|
80
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { relinka } from "@reliverse/relinka";
|
|
2
2
|
import { defineCommand } from "@reliverse/rempts";
|
|
3
3
|
import path from "pathe";
|
|
4
|
-
import { printUsage, useAggregator } from "./
|
|
4
|
+
import { printUsage, useAggregator } from "./impl.js";
|
|
5
5
|
const TOOLS = ["agg"];
|
|
6
6
|
export default defineCommand({
|
|
7
7
|
meta: {
|