@reliverse/dler 1.7.22 → 1.7.23
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/bin/app/cmds.d.ts +1 -1
- package/bin/app/cmds.js +1 -1
- package/bin/app/inject/cmd.d.ts +0 -24
- package/bin/app/inject/cmd.js +0 -47
- package/bin/app/{spell → magic}/cmd.d.ts +2 -0
- package/bin/app/magic/cmd.js +101 -0
- package/bin/app/pub/impl.js +4 -2
- package/bin/libs/cfg/cfg-mod.d.ts +1 -1
- package/bin/libs/cfg/cfg-mod.js +1 -1
- package/bin/libs/cfg/rse/rse-impl/rse-create.js +1 -1
- package/bin/libs/cfg/rse/rse-impl/rse-define.d.ts +10 -10
- package/bin/libs/cfg/rse/rse-mod.d.ts +1 -1
- package/bin/libs/cfg/rse/rse-mod.js +1 -1
- package/bin/libs/sdk/sdk-impl/cmds/inject/inject-impl-mod.d.ts +63 -0
- package/bin/libs/sdk/sdk-impl/cmds/inject/inject-impl-mod.js +237 -0
- package/bin/libs/sdk/sdk-impl/config/info.js +1 -1
- package/bin/libs/sdk/sdk-impl/magic/apply.d.ts +63 -0
- package/bin/libs/sdk/sdk-impl/{spell/applyMagicSpells.js → magic/apply.js} +223 -70
- package/bin/libs/sdk/sdk-impl/{spell → magic}/spells.d.ts +16 -1
- package/bin/libs/sdk/sdk-impl/{spell → magic}/spells.js +41 -1
- package/bin/libs/sdk/sdk-mod.d.ts +4 -4
- package/bin/libs/sdk/sdk-mod.js +2 -2
- package/package.json +2 -2
- package/bin/app/inject/impl.d.ts +0 -5
- package/bin/app/inject/impl.js +0 -159
- package/bin/app/spell/cmd.js +0 -47
- package/bin/libs/sdk/sdk-impl/spell/applyMagicSpells.d.ts +0 -38
- /package/bin/app/{spell → magic}/old.d.ts +0 -0
- /package/bin/app/{spell → magic}/old.js +0 -0
- /package/bin/libs/cfg/rse/rse-impl/{rse-inject.d.ts → rse-comments.d.ts} +0 -0
- /package/bin/libs/cfg/rse/rse-impl/{rse-inject.js → rse-comments.js} +0 -0
package/bin/app/cmds.d.ts
CHANGED
|
@@ -12,5 +12,5 @@ export declare const getMigrateCmd: () => Promise<Command>;
|
|
|
12
12
|
export declare const getPubCmd: () => Promise<Command>;
|
|
13
13
|
export declare const getRemptsCmd: () => Promise<Command>;
|
|
14
14
|
export declare const getRenameCmd: () => Promise<Command>;
|
|
15
|
-
export declare const
|
|
15
|
+
export declare const getMagicCmd: () => Promise<Command>;
|
|
16
16
|
export declare const getSplitCmd: () => Promise<Command>;
|
package/bin/app/cmds.js
CHANGED
|
@@ -12,5 +12,5 @@ export const getMigrateCmd = async () => loadCommand("migrate");
|
|
|
12
12
|
export const getPubCmd = async () => loadCommand("pub");
|
|
13
13
|
export const getRemptsCmd = async () => loadCommand("rempts");
|
|
14
14
|
export const getRenameCmd = async () => loadCommand("rename");
|
|
15
|
-
export const
|
|
15
|
+
export const getMagicCmd = async () => loadCommand("magic");
|
|
16
16
|
export const getSplitCmd = async () => loadCommand("split");
|
package/bin/app/inject/cmd.d.ts
CHANGED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
declare const _default: import("@reliverse/rempts").Command<{
|
|
2
|
-
dev: {
|
|
3
|
-
type: "boolean";
|
|
4
|
-
description: string;
|
|
5
|
-
};
|
|
6
|
-
cwd: {
|
|
7
|
-
type: "string";
|
|
8
|
-
description: string;
|
|
9
|
-
};
|
|
10
|
-
files: {
|
|
11
|
-
type: "positional";
|
|
12
|
-
description: string;
|
|
13
|
-
default: string;
|
|
14
|
-
};
|
|
15
|
-
comment: {
|
|
16
|
-
type: "string";
|
|
17
|
-
description: string;
|
|
18
|
-
};
|
|
19
|
-
tscPaths: {
|
|
20
|
-
type: "string";
|
|
21
|
-
description: string;
|
|
22
|
-
};
|
|
23
|
-
}>;
|
|
24
|
-
export default _default;
|
package/bin/app/inject/cmd.js
CHANGED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { relinka } from "@reliverse/relinka";
|
|
2
|
-
import { defineArgs, defineCommand } from "@reliverse/rempts";
|
|
3
|
-
import { useTsExpectError } from "./impl.js";
|
|
4
|
-
export default defineCommand({
|
|
5
|
-
meta: {
|
|
6
|
-
name: "expect",
|
|
7
|
-
version: "1.0.0",
|
|
8
|
-
description: "Inject `@ts-expect-error` above lines where TS errors occur"
|
|
9
|
-
},
|
|
10
|
-
args: defineArgs({
|
|
11
|
-
dev: {
|
|
12
|
-
type: "boolean",
|
|
13
|
-
description: "Run the CLI in dev mode"
|
|
14
|
-
},
|
|
15
|
-
cwd: {
|
|
16
|
-
type: "string",
|
|
17
|
-
description: "The working directory to run the CLI in"
|
|
18
|
-
},
|
|
19
|
-
files: {
|
|
20
|
-
type: "positional",
|
|
21
|
-
description: `'auto' or path(s) to line references file(s)`,
|
|
22
|
-
default: "auto"
|
|
23
|
-
},
|
|
24
|
-
comment: {
|
|
25
|
-
type: "string",
|
|
26
|
-
description: "Override the comment line to insert. Default is `// @ts-expect-error TODO: fix ts`"
|
|
27
|
-
},
|
|
28
|
-
tscPaths: {
|
|
29
|
-
type: "string",
|
|
30
|
-
description: "Optional: specify path(s) to restrict TSC processing (only effective when using 'auto')"
|
|
31
|
-
}
|
|
32
|
-
}),
|
|
33
|
-
async run({ args }) {
|
|
34
|
-
if (args.dev) {
|
|
35
|
-
relinka("verbose", "Using dev mode");
|
|
36
|
-
}
|
|
37
|
-
let pathsTsc = args.tscPaths;
|
|
38
|
-
if (pathsTsc === void 0 && args.files === "auto") {
|
|
39
|
-
pathsTsc = "./tsconfig.json";
|
|
40
|
-
}
|
|
41
|
-
await useTsExpectError({
|
|
42
|
-
files: [args.files],
|
|
43
|
-
comment: args.comment,
|
|
44
|
-
tscPaths: [pathsTsc]
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
});
|
|
@@ -11,10 +11,12 @@ declare const _default: import("@reliverse/rempts").Command<{
|
|
|
11
11
|
concurrency: {
|
|
12
12
|
type: "number";
|
|
13
13
|
description: string;
|
|
14
|
+
default: number;
|
|
14
15
|
};
|
|
15
16
|
batchSize: {
|
|
16
17
|
type: "number";
|
|
17
18
|
description: string;
|
|
19
|
+
default: number;
|
|
18
20
|
};
|
|
19
21
|
stopOnError: {
|
|
20
22
|
type: "boolean";
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { defineArgs, defineCommand } from "@reliverse/rempts";
|
|
2
|
+
import { applyMagicSpells } from "../../libs/sdk/sdk-impl/magic/apply.js";
|
|
3
|
+
import { formatError } from "../../libs/sdk/sdk-impl/utils/utils-error-cwd.js";
|
|
4
|
+
export default defineCommand({
|
|
5
|
+
meta: {
|
|
6
|
+
name: "magic",
|
|
7
|
+
version: "1.0.0",
|
|
8
|
+
description: `Apply magic directives to files.
|
|
9
|
+
Target Types:
|
|
10
|
+
1. Distribution Targets (dist-*):
|
|
11
|
+
- dist-npm: Process files in dist-npm/bin
|
|
12
|
+
- dist-jsr: Process files in dist-jsr/bin
|
|
13
|
+
- dist-libs: Process all libraries in dist-libs
|
|
14
|
+
- dist-libs/<lib>: Process specific library (e.g., dist-libs/sdk)
|
|
15
|
+
For dist-* targets, magic directives are first searched in src/ directory,
|
|
16
|
+
then applied to corresponding files in the distribution directories.
|
|
17
|
+
2. Custom Targets:
|
|
18
|
+
- Any directory name that is not dist-* (e.g., "my-output", "custom-build")
|
|
19
|
+
For custom targets, magic directives are processed directly in the target files.
|
|
20
|
+
No source directory scanning is performed.
|
|
21
|
+
Examples:
|
|
22
|
+
# Process all distribution targets
|
|
23
|
+
dler magic dist-npm dist-jsr dist-libs
|
|
24
|
+
# Process specific library
|
|
25
|
+
dler magic dist-libs/sdk
|
|
26
|
+
# Process custom target
|
|
27
|
+
dler magic my-custom-output
|
|
28
|
+
# Mix distribution and custom targets
|
|
29
|
+
dler magic dist-npm my-custom-output`
|
|
30
|
+
},
|
|
31
|
+
args: defineArgs({
|
|
32
|
+
targets: {
|
|
33
|
+
type: "array",
|
|
34
|
+
description: `Targets to process. Can be:
|
|
35
|
+
- Distribution targets: dist-npm, dist-jsr, dist-libs, dist-libs/<lib>
|
|
36
|
+
- Custom targets: any directory name that is not dist-*`,
|
|
37
|
+
required: true
|
|
38
|
+
},
|
|
39
|
+
lib: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "Library name to process (e.g., sdk, cfg). Only valid with dist-libs target."
|
|
42
|
+
},
|
|
43
|
+
concurrency: {
|
|
44
|
+
type: "number",
|
|
45
|
+
description: "Number of files to process in parallel (default: 4)",
|
|
46
|
+
default: 4
|
|
47
|
+
},
|
|
48
|
+
batchSize: {
|
|
49
|
+
type: "number",
|
|
50
|
+
description: "Number of files to process in each batch (default: 100)",
|
|
51
|
+
default: 100
|
|
52
|
+
},
|
|
53
|
+
stopOnError: {
|
|
54
|
+
type: "boolean",
|
|
55
|
+
description: "Stop processing on first error (default: true)",
|
|
56
|
+
default: true
|
|
57
|
+
}
|
|
58
|
+
}),
|
|
59
|
+
async run({ args }) {
|
|
60
|
+
const { targets, lib, concurrency, batchSize, stopOnError } = args;
|
|
61
|
+
if (lib) {
|
|
62
|
+
if (!targets?.includes("dist-libs")) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
"The 'lib' parameter can only be used with 'dist-libs' target. Example: dler magic dist-libs/sdk"
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (targets.some((t) => t.startsWith("dist-libs/") && t !== `dist-libs/${lib}`)) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
"Cannot specify both 'lib' parameter and dist-libs/<lib> in targets. Use one or the other."
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const finalTargets = targets?.map(
|
|
75
|
+
(target) => target === "dist-libs" && lib ? `${target}/${lib}` : target
|
|
76
|
+
) ?? [];
|
|
77
|
+
const distTargets = finalTargets.filter((t) => t.startsWith("dist-"));
|
|
78
|
+
const customTargets = finalTargets.filter((t) => !t.startsWith("dist-"));
|
|
79
|
+
if (distTargets.length > 0) {
|
|
80
|
+
console.log("\nProcessing distribution targets:");
|
|
81
|
+
for (const target of distTargets) {
|
|
82
|
+
console.log(` - ${target} (will scan src/ for magic directives)`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (customTargets.length > 0) {
|
|
86
|
+
console.log("\nProcessing custom targets:");
|
|
87
|
+
for (const target of customTargets) {
|
|
88
|
+
console.log(` - ${target} (will process magic directives directly in target files)`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
await applyMagicSpells(finalTargets, {
|
|
92
|
+
concurrency,
|
|
93
|
+
batchSize,
|
|
94
|
+
stopOnError
|
|
95
|
+
});
|
|
96
|
+
console.log("\n\u2728 Magic spells applied successfully!");
|
|
97
|
+
} catch (error) {
|
|
98
|
+
throw new Error(`\u274C Processing failed: ${formatError(error)}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
package/bin/app/pub/impl.js
CHANGED
|
@@ -4,8 +4,8 @@ import fs from "@reliverse/relifso";
|
|
|
4
4
|
import { relinka } from "@reliverse/relinka";
|
|
5
5
|
import { getConfigDler } from "../../libs/sdk/sdk-impl/config/load.js";
|
|
6
6
|
import { processLibraryFlow } from "../../libs/sdk/sdk-impl/library-flow.js";
|
|
7
|
+
import { applyMagicSpells } from "../../libs/sdk/sdk-impl/magic/apply.js";
|
|
7
8
|
import { processRegularFlow } from "../../libs/sdk/sdk-impl/regular-flow.js";
|
|
8
|
-
import { applyMagicSpells } from "../../libs/sdk/sdk-impl/spell/applyMagicSpells.js";
|
|
9
9
|
import { finalizeBuildPub } from "../../libs/sdk/sdk-impl/utils/finalize.js";
|
|
10
10
|
import { resolveAllCrossLibs } from "../../libs/sdk/sdk-impl/utils/resolve-cross-libs.js";
|
|
11
11
|
import { removeDistFolders } from "../../libs/sdk/sdk-impl/utils/utils-clean.js";
|
|
@@ -45,7 +45,9 @@ export async function dlerPub(isDev, config) {
|
|
|
45
45
|
await processRegularFlow(timer, isDev, effectiveConfig);
|
|
46
46
|
await processLibraryFlow(timer, isDev, effectiveConfig);
|
|
47
47
|
await resolveAllCrossLibs();
|
|
48
|
-
|
|
48
|
+
if (isDev) {
|
|
49
|
+
await applyMagicSpells(["dist-jsr", "dist-npm", "dist-libs"]);
|
|
50
|
+
}
|
|
49
51
|
relinka("log", "[processDistDirectory] dist-npm");
|
|
50
52
|
await processDistDirectory("dist-npm", "~");
|
|
51
53
|
relinka("log", "[processDistDirectory] dist-jsr");
|
|
@@ -10,7 +10,7 @@ export { DEFAULT_CONFIG_RSE, PROJECT_FRAMEWORK_FILES } from "./rse/rse-impl/rse-
|
|
|
10
10
|
export { defineConfigRse } from "./rse/rse-impl/rse-define.js";
|
|
11
11
|
export { detectProjectFramework, getPackageJson, getPackageJsonSafe, detectProject, detectProjectsWithRseConfig, detectFeatures, } from "./rse/rse-impl/rse-detect.js";
|
|
12
12
|
export { generateConfigFiles, generateProjectConfigs } from "./rse/rse-impl/rse-gen-cfg.js";
|
|
13
|
-
export { injectSectionComments } from "./rse/rse-impl/rse-
|
|
13
|
+
export { injectSectionComments } from "./rse/rse-impl/rse-comments.js";
|
|
14
14
|
export { migrateRseConfig } from "./rse/rse-impl/rse-migrate.js";
|
|
15
15
|
export { getRseConfigPath } from "./rse/rse-impl/rse-path.js";
|
|
16
16
|
export { askRseConfigType } from "./rse/rse-impl/rse-prompts.js";
|
package/bin/libs/cfg/cfg-mod.js
CHANGED
|
@@ -49,7 +49,7 @@ export {
|
|
|
49
49
|
detectFeatures
|
|
50
50
|
} from "./rse/rse-impl/rse-detect.js";
|
|
51
51
|
export { generateConfigFiles, generateProjectConfigs } from "./rse/rse-impl/rse-gen-cfg.js";
|
|
52
|
-
export { injectSectionComments } from "./rse/rse-impl/rse-
|
|
52
|
+
export { injectSectionComments } from "./rse/rse-impl/rse-comments.js";
|
|
53
53
|
export { migrateRseConfig } from "./rse/rse-impl/rse-migrate.js";
|
|
54
54
|
export { getRseConfigPath } from "./rse/rse-impl/rse-path.js";
|
|
55
55
|
export { askRseConfigType } from "./rse/rse-impl/rse-prompts.js";
|
|
@@ -5,12 +5,12 @@ import { confirmPrompt } from "@reliverse/rempts";
|
|
|
5
5
|
import { Value } from "@sinclair/typebox/value";
|
|
6
6
|
import { execaCommand } from "execa";
|
|
7
7
|
import { addDevDependency } from "nypm";
|
|
8
|
+
import { injectSectionComments } from "./rse-comments.js";
|
|
8
9
|
import { cliDomainDocs } from "./rse-consts.js";
|
|
9
10
|
import { UNKNOWN_VALUE, rseName, DEFAULT_DOMAIN, RSE_SCHEMA_DEV } from "./rse-consts.js";
|
|
10
11
|
import { generateDefaultRulesForProject, getDefaultRseConfig } from "./rse-def-utils.js";
|
|
11
12
|
import { DEFAULT_CONFIG_RSE } from "./rse-default.js";
|
|
12
13
|
import { getPackageJson, detectFeatures } from "./rse-detect.js";
|
|
13
|
-
import { injectSectionComments } from "./rse-inject.js";
|
|
14
14
|
import { getRseConfigPath } from "./rse-path.js";
|
|
15
15
|
import { readRseConfig } from "./rse-read.js";
|
|
16
16
|
import { rseSchema } from "./rse-schema.js";
|
|
@@ -10,11 +10,11 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
10
10
|
projectDomain?: string | undefined;
|
|
11
11
|
projectGitService?: "none" | "github" | "gitlab" | "bitbucket" | undefined;
|
|
12
12
|
projectDeployService?: "none" | "vercel" | "netlify" | "railway" | "deno" | undefined;
|
|
13
|
-
projectPackageManager?: "
|
|
13
|
+
projectPackageManager?: "npm" | "bun" | "pnpm" | "yarn" | undefined;
|
|
14
14
|
projectState?: "creating" | "created" | undefined;
|
|
15
|
-
projectCategory?: "
|
|
15
|
+
projectCategory?: "browser" | "cli" | "unknown" | "website" | "vscode" | "library" | "mobile" | undefined;
|
|
16
16
|
projectSubcategory?: "unknown" | "e-commerce" | "tool" | undefined;
|
|
17
|
-
projectFramework?: "unknown" | "vscode" | "nextjs" | "vite" | "svelte" | "remix" | "astro" | "nuxt" | "solid" | "qwik" | "vue" | "wxt" | "lynx" | "react-native" | "expo" | "capacitor" | "ionic" | "electron" | "tauri" | "neutralino" | "rempts" | "citty" | "commander" | "cac" | "meow" | "yargs" | "webextension" | "browser-extension" |
|
|
17
|
+
projectFramework?: "npm-jsr" | "unknown" | "vscode" | "nextjs" | "vite" | "svelte" | "remix" | "astro" | "nuxt" | "solid" | "qwik" | "vue" | "wxt" | "lynx" | "react-native" | "expo" | "capacitor" | "ionic" | "electron" | "tauri" | "neutralino" | "rempts" | "citty" | "commander" | "cac" | "meow" | "yargs" | "webextension" | "browser-extension" | undefined;
|
|
18
18
|
projectTemplate?: "unknown" | "blefnk/relivator-nextjs-template" | "blefnk/relivator-docker-template" | "blefnk/next-react-ts-src-minimal" | "blefnk/all-in-one-nextjs-template" | "blefnk/create-t3-app" | "blefnk/create-next-app" | "blefnk/astro-starlight-template" | "blefnk/versator-nextjs-template" | "blefnk/relivator-lynxjs-template" | "blefnk/relivator-react-native-template" | "reliverse/template-browser-extension" | "microsoft/vscode-extension-samples" | "microsoft/vscode-extension-template" | "rsetarter-template" | "blefnk/deno-cli-tutorial" | undefined;
|
|
19
19
|
projectTemplateDate?: string | undefined;
|
|
20
20
|
features?: {
|
|
@@ -38,15 +38,15 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
38
38
|
analytics?: "unknown" | "vercel" | undefined;
|
|
39
39
|
authentication?: "unknown" | "better-auth" | "clerk" | "next-auth" | "supabase-auth" | "auth0" | undefined;
|
|
40
40
|
api?: "unknown" | "hono" | "trpc" | "graphql" | "rest" | undefined;
|
|
41
|
-
testing?: "
|
|
41
|
+
testing?: "bun" | "unknown" | "vitest" | "jest" | "playwright" | "cypress" | undefined;
|
|
42
42
|
stateManagement?: "unknown" | "zustand" | "jotai" | "redux-toolkit" | undefined;
|
|
43
43
|
formManagement?: "unknown" | "react-hook-form" | "formik" | undefined;
|
|
44
44
|
styling?: "unknown" | "tailwind" | "styled-components" | "css-modules" | "sass" | undefined;
|
|
45
45
|
uiComponents?: "unknown" | "shadcn-ui" | "chakra-ui" | "material-ui" | undefined;
|
|
46
46
|
databaseLibrary?: "unknown" | "drizzle" | "prisma" | "supabase" | undefined;
|
|
47
47
|
databaseProvider?: "unknown" | "pg" | "mysql" | "sqlite" | "mongodb" | undefined;
|
|
48
|
-
linting?: "
|
|
49
|
-
formatting?: "
|
|
48
|
+
linting?: "eslint" | "unknown" | undefined;
|
|
49
|
+
formatting?: "biome" | "unknown" | undefined;
|
|
50
50
|
payment?: "unknown" | "stripe" | undefined;
|
|
51
51
|
monitoring?: "unknown" | "sentry" | undefined;
|
|
52
52
|
logging?: "unknown" | "axiom" | undefined;
|
|
@@ -75,7 +75,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
75
75
|
indentStyle?: "space" | "tab" | undefined;
|
|
76
76
|
quoteMark?: "single" | "double" | undefined;
|
|
77
77
|
semicolons?: boolean | undefined;
|
|
78
|
-
trailingComma?: "
|
|
78
|
+
trailingComma?: "none" | "es5" | "all" | undefined;
|
|
79
79
|
bracketSpacing?: boolean | undefined;
|
|
80
80
|
arrowParens?: "always" | "avoid" | undefined;
|
|
81
81
|
tabWidth?: number | undefined;
|
|
@@ -83,7 +83,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
83
83
|
dontRemoveComments?: boolean | undefined;
|
|
84
84
|
shouldAddComments?: boolean | undefined;
|
|
85
85
|
typeOrInterface?: "type" | "interface" | "mixed" | undefined;
|
|
86
|
-
importOrRequire?: "
|
|
86
|
+
importOrRequire?: "mixed" | "import" | "require" | undefined;
|
|
87
87
|
cjsToEsm?: boolean | undefined;
|
|
88
88
|
modernize?: {
|
|
89
89
|
replaceFs?: boolean | undefined;
|
|
@@ -96,7 +96,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
96
96
|
importSymbol?: string | undefined;
|
|
97
97
|
} | undefined;
|
|
98
98
|
monorepo?: {
|
|
99
|
-
type?: "none" | "
|
|
99
|
+
type?: "none" | "bun" | "turborepo" | "nx" | "pnpm" | undefined;
|
|
100
100
|
packages?: string[] | undefined;
|
|
101
101
|
sharedPackages?: string[] | undefined;
|
|
102
102
|
} | undefined;
|
|
@@ -113,7 +113,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
113
113
|
repoBranch?: string | undefined;
|
|
114
114
|
repoPrivacy?: "unknown" | "public" | "private" | undefined;
|
|
115
115
|
projectArchitecture?: "unknown" | "fullstack" | "separated" | undefined;
|
|
116
|
-
projectRuntime?: "
|
|
116
|
+
projectRuntime?: "node" | "bun" | "deno" | undefined;
|
|
117
117
|
skipPromptsUseAutoBehavior?: boolean | undefined;
|
|
118
118
|
deployBehavior?: "prompt" | "autoYes" | "autoNo" | undefined;
|
|
119
119
|
depsBehavior?: "prompt" | "autoYes" | "autoNo" | undefined;
|
|
@@ -8,7 +8,7 @@ export * from "./rse-impl/rse-default";
|
|
|
8
8
|
export * from "./rse-impl/rse-define";
|
|
9
9
|
export * from "./rse-impl/rse-detect";
|
|
10
10
|
export * from "./rse-impl/rse-gen-cfg";
|
|
11
|
-
export * from "./rse-impl/rse-
|
|
11
|
+
export * from "./rse-impl/rse-comments";
|
|
12
12
|
export * from "./rse-impl/rse-migrate";
|
|
13
13
|
export * from "./rse-impl/rse-path";
|
|
14
14
|
export * from "./rse-impl/rse-prompts";
|
|
@@ -8,7 +8,7 @@ export * from "./rse-impl/rse-default.js";
|
|
|
8
8
|
export * from "./rse-impl/rse-define.js";
|
|
9
9
|
export * from "./rse-impl/rse-detect.js";
|
|
10
10
|
export * from "./rse-impl/rse-gen-cfg.js";
|
|
11
|
-
export * from "./rse-impl/rse-
|
|
11
|
+
export * from "./rse-impl/rse-comments.js";
|
|
12
12
|
export * from "./rse-impl/rse-migrate.js";
|
|
13
13
|
export * from "./rse-impl/rse-path.js";
|
|
14
14
|
export * from "./rse-impl/rse-prompts.js";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inject-impl-mod.ts
|
|
3
|
+
* -----------
|
|
4
|
+
* Utility for injecting content into files at specific line/column positions.
|
|
5
|
+
*
|
|
6
|
+
* Fully async -– works with Node, Bun, and other
|
|
7
|
+
* runtimes that support the `fs/promises` API.
|
|
8
|
+
*
|
|
9
|
+
* @author blefnk
|
|
10
|
+
*/
|
|
11
|
+
export interface InjectionConfig {
|
|
12
|
+
/** Absolute or relative path to target file. */
|
|
13
|
+
filePath: string;
|
|
14
|
+
/** 1-based line number (1 == first visible line in editors) */
|
|
15
|
+
line: number;
|
|
16
|
+
/** 1-based column number (1 == first visible column in editors) */
|
|
17
|
+
column?: number;
|
|
18
|
+
/** String or array of strings to inject. */
|
|
19
|
+
content: string | string[];
|
|
20
|
+
/** If `true`, inserts string (or first element of array) content on a new line AFTER the target line. */
|
|
21
|
+
createNewLine?: boolean;
|
|
22
|
+
/** Configuration for comment wrapping. */
|
|
23
|
+
commentsMode?: {
|
|
24
|
+
/** Whether to wrap content in comments. */
|
|
25
|
+
activate: boolean;
|
|
26
|
+
/** Whether to use JSDoc style for multiline comments. */
|
|
27
|
+
useJsdocForMultiline?: boolean;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface InjectionResult {
|
|
31
|
+
/** Absolute or relative path to target file. */
|
|
32
|
+
filePath: string;
|
|
33
|
+
/** Whether the injection was successful. */
|
|
34
|
+
success: boolean;
|
|
35
|
+
/** Error message if injection failed. */
|
|
36
|
+
error?: string;
|
|
37
|
+
/** Generated source map if available. */
|
|
38
|
+
sourcemap?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Injects content into the given file at the requested location.
|
|
42
|
+
*
|
|
43
|
+
* @param filePath Absolute or relative path to target file.
|
|
44
|
+
* @param line 1-based line number (1 == first visible line in editors, internally == 0).
|
|
45
|
+
* @param column 1-based column number (optional, 1 == first visible column in editors, internally == 0).
|
|
46
|
+
* @param content String or array of strings to inject.
|
|
47
|
+
* @param createNewLine If `true`, inserts string (or first element of array) content on a new line AFTER the target line.
|
|
48
|
+
* @param commentsMode If `true`, wraps injected content in file-type comments.
|
|
49
|
+
* @param generateSourceMap If `true`, generates a source map for the transformation.
|
|
50
|
+
*
|
|
51
|
+
* @returns `true` on success, `false` on failure (errors are logged).
|
|
52
|
+
*/
|
|
53
|
+
export declare function injectAtLocation(filePath: string, line: number, column: number | undefined, content: string | string[], createNewLine?: boolean, commentsMode?: {
|
|
54
|
+
activate: boolean;
|
|
55
|
+
}, generateSourceMap?: boolean): Promise<boolean>;
|
|
56
|
+
/**
|
|
57
|
+
* Processes multiple injections efficiently by grouping by file and applying in reverse order.
|
|
58
|
+
*
|
|
59
|
+
* @param configs Array of {@link InjectionConfig}.
|
|
60
|
+
* @param generateSourceMaps If `true`, generates source maps for transformations.
|
|
61
|
+
* @returns Array of {@link InjectionResult} in the same order as `configs`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function injectMultiple(configs: InjectionConfig[], generateSourceMaps?: boolean): Promise<InjectionResult[]>;
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import MagicString from "magic-string";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { isBinaryExt } from "../../utils/binary.js";
|
|
5
|
+
export async function injectAtLocation(filePath, line, column, content, createNewLine = false, commentsMode = { activate: false }, generateSourceMap = false) {
|
|
6
|
+
try {
|
|
7
|
+
await validateInput(filePath, line, column);
|
|
8
|
+
const originalContent = await fs.readFile(filePath, "utf8");
|
|
9
|
+
const magicString = new MagicString(originalContent, {
|
|
10
|
+
filename: path.basename(filePath)
|
|
11
|
+
});
|
|
12
|
+
const pieces = Array.isArray(content) ? content : [content];
|
|
13
|
+
const preparedContent = prepareContentForInjection(
|
|
14
|
+
pieces,
|
|
15
|
+
commentsMode,
|
|
16
|
+
path.extname(filePath),
|
|
17
|
+
createNewLine
|
|
18
|
+
);
|
|
19
|
+
const success = injectWithMagicString(
|
|
20
|
+
magicString,
|
|
21
|
+
originalContent,
|
|
22
|
+
line,
|
|
23
|
+
column,
|
|
24
|
+
preparedContent,
|
|
25
|
+
createNewLine
|
|
26
|
+
);
|
|
27
|
+
if (!success) return false;
|
|
28
|
+
const result = magicString.toString();
|
|
29
|
+
await fs.writeFile(filePath, result, "utf8");
|
|
30
|
+
if (generateSourceMap) {
|
|
31
|
+
const map = magicString.generateMap({
|
|
32
|
+
source: filePath,
|
|
33
|
+
file: `${filePath}.map`,
|
|
34
|
+
includeContent: true,
|
|
35
|
+
hires: true
|
|
36
|
+
});
|
|
37
|
+
await fs.writeFile(`${filePath}.map`, map.toString(), "utf8");
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.error(`[injector] ${filePath}: ${err.message}`);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function injectMultiple(configs, generateSourceMaps = false) {
|
|
46
|
+
const configsByFile = /* @__PURE__ */ new Map();
|
|
47
|
+
configs.forEach((config, index) => {
|
|
48
|
+
if (!configsByFile.has(config.filePath)) {
|
|
49
|
+
configsByFile.set(config.filePath, []);
|
|
50
|
+
}
|
|
51
|
+
configsByFile.get(config.filePath)?.push({ config, originalIndex: index });
|
|
52
|
+
});
|
|
53
|
+
const results = new Array(configs.length);
|
|
54
|
+
for (const [filePath, fileConfigs] of configsByFile) {
|
|
55
|
+
try {
|
|
56
|
+
const firstConfig = fileConfigs[0]?.config;
|
|
57
|
+
if (!firstConfig) {
|
|
58
|
+
throw new Error(`No valid configs found for file: ${filePath}`);
|
|
59
|
+
}
|
|
60
|
+
await validateInput(firstConfig.filePath, firstConfig.line, firstConfig.column);
|
|
61
|
+
const originalContent = await fs.readFile(filePath, "utf8");
|
|
62
|
+
const magicString = new MagicString(originalContent, {
|
|
63
|
+
filename: path.basename(filePath)
|
|
64
|
+
});
|
|
65
|
+
const sortedConfigs = [...fileConfigs].sort((a, b) => {
|
|
66
|
+
const aLine = a.config.line;
|
|
67
|
+
const bLine = b.config.line;
|
|
68
|
+
if (aLine !== bLine) return bLine - aLine;
|
|
69
|
+
const aCol = a.config.column ?? Number.MAX_SAFE_INTEGER;
|
|
70
|
+
const bCol = b.config.column ?? Number.MAX_SAFE_INTEGER;
|
|
71
|
+
return bCol - aCol;
|
|
72
|
+
});
|
|
73
|
+
let allSuccessful = true;
|
|
74
|
+
for (const { config, originalIndex } of sortedConfigs) {
|
|
75
|
+
const { line, column, content, createNewLine, commentsMode } = config;
|
|
76
|
+
const pieces = Array.isArray(content) ? content : [content];
|
|
77
|
+
const preparedContent = prepareContentForInjection(
|
|
78
|
+
pieces,
|
|
79
|
+
commentsMode,
|
|
80
|
+
path.extname(filePath),
|
|
81
|
+
createNewLine ?? false
|
|
82
|
+
);
|
|
83
|
+
const success = injectWithMagicString(
|
|
84
|
+
magicString,
|
|
85
|
+
originalContent,
|
|
86
|
+
line,
|
|
87
|
+
column,
|
|
88
|
+
preparedContent,
|
|
89
|
+
createNewLine ?? false
|
|
90
|
+
);
|
|
91
|
+
results[originalIndex] = success ? { filePath, success } : {
|
|
92
|
+
filePath,
|
|
93
|
+
success: false,
|
|
94
|
+
error: `Injection failed for ${filePath} at line ${line}`
|
|
95
|
+
};
|
|
96
|
+
if (!success) {
|
|
97
|
+
allSuccessful = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (allSuccessful) {
|
|
101
|
+
const result = magicString.toString();
|
|
102
|
+
await fs.writeFile(filePath, result, "utf8");
|
|
103
|
+
if (generateSourceMaps) {
|
|
104
|
+
const map = magicString.generateMap({
|
|
105
|
+
source: filePath,
|
|
106
|
+
file: `${filePath}.map`,
|
|
107
|
+
includeContent: true,
|
|
108
|
+
hires: true
|
|
109
|
+
});
|
|
110
|
+
await fs.writeFile(`${filePath}.map`, map.toString(), "utf8");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch (err) {
|
|
114
|
+
for (const { originalIndex } of fileConfigs) {
|
|
115
|
+
results[originalIndex] = {
|
|
116
|
+
filePath,
|
|
117
|
+
success: false,
|
|
118
|
+
error: `File processing failed: ${err.message}`
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return results;
|
|
124
|
+
}
|
|
125
|
+
async function validateInput(filePath, line, column) {
|
|
126
|
+
await fs.access(filePath).catch(() => {
|
|
127
|
+
throw new Error("File does not exist.");
|
|
128
|
+
});
|
|
129
|
+
if (await isBinaryExt(filePath)) {
|
|
130
|
+
throw new Error("Cannot inject into binary files.");
|
|
131
|
+
}
|
|
132
|
+
if (!Number.isInteger(line) || line < 1)
|
|
133
|
+
throw new Error("`line` must be a positive 1-based integer.");
|
|
134
|
+
if (column !== void 0 && (!Number.isInteger(column) || column < 1))
|
|
135
|
+
throw new Error("`column` must be a positive 1-based integer when provided.");
|
|
136
|
+
}
|
|
137
|
+
function getCharacterIndex(content, line1Based, column1Based) {
|
|
138
|
+
const lines = content.split(/\r?\n/);
|
|
139
|
+
const eolLength = content.includes("\r\n") ? 2 : 1;
|
|
140
|
+
while (lines.length < line1Based) {
|
|
141
|
+
lines.push("");
|
|
142
|
+
}
|
|
143
|
+
let index = 0;
|
|
144
|
+
for (let i = 0; i < line1Based - 1; i++) {
|
|
145
|
+
index += lines[i]?.length ?? 0;
|
|
146
|
+
if (i < lines.length - 1) index += eolLength;
|
|
147
|
+
}
|
|
148
|
+
const targetLine = lines[line1Based - 1] || "";
|
|
149
|
+
const lineStart = index;
|
|
150
|
+
const lineEnd = lineStart + targetLine.length;
|
|
151
|
+
if (column1Based !== void 0) {
|
|
152
|
+
const colIndex = Math.min(column1Based - 1, targetLine.length);
|
|
153
|
+
index += colIndex;
|
|
154
|
+
} else {
|
|
155
|
+
index = lineEnd;
|
|
156
|
+
}
|
|
157
|
+
return { index, lineEnd, lineStart };
|
|
158
|
+
}
|
|
159
|
+
function prepareContentForInjection(pieces, commentsMode, ext, createNewLine) {
|
|
160
|
+
let preparedPieces = pieces.slice();
|
|
161
|
+
if (commentsMode?.activate) {
|
|
162
|
+
preparedPieces = applyCommentWrapping(preparedPieces, commentsMode, ext);
|
|
163
|
+
}
|
|
164
|
+
let result = preparedPieces.join("\n");
|
|
165
|
+
if (createNewLine && result) {
|
|
166
|
+
result = "\n" + result;
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
function applyCommentWrapping(pieces, commentsMode, ext) {
|
|
171
|
+
const { lineComment, blockStart, blockEnd } = getCommentSymbols(ext);
|
|
172
|
+
if (pieces.length === 1) {
|
|
173
|
+
return pieces.map((p) => ` ${lineComment} ${p}`);
|
|
174
|
+
}
|
|
175
|
+
const isJsdoc = commentsMode.useJsdocForMultiline;
|
|
176
|
+
const processedPieces = pieces.map((p) => p === "" ? " " : p);
|
|
177
|
+
return [
|
|
178
|
+
` ${blockStart}${isJsdoc ? "*" : ""} ${processedPieces[0]}`,
|
|
179
|
+
...processedPieces.slice(1, -1).map((p) => ` ${isJsdoc ? "*" : ""} ${p}`),
|
|
180
|
+
` ${isJsdoc ? "*" : ""} ${processedPieces[processedPieces.length - 1]} ${blockEnd}`
|
|
181
|
+
];
|
|
182
|
+
}
|
|
183
|
+
function injectWithMagicString(magicString, originalContent, line1Based, column1Based, preparedContent, createNewLine) {
|
|
184
|
+
try {
|
|
185
|
+
const { index, lineEnd, lineStart } = getCharacterIndex(
|
|
186
|
+
originalContent,
|
|
187
|
+
line1Based,
|
|
188
|
+
column1Based
|
|
189
|
+
);
|
|
190
|
+
const currentLength = originalContent.length;
|
|
191
|
+
if (index > currentLength) {
|
|
192
|
+
const linesNeeded = Math.ceil((index - currentLength) / 50);
|
|
193
|
+
const extension = "\n".repeat(linesNeeded);
|
|
194
|
+
magicString.append(extension);
|
|
195
|
+
}
|
|
196
|
+
if (createNewLine) {
|
|
197
|
+
if (column1Based !== void 0) {
|
|
198
|
+
const currentLineContent = originalContent.split(/\r?\n/)[line1Based - 1] || "";
|
|
199
|
+
const beforeColumn = currentLineContent.slice(0, column1Based - 1);
|
|
200
|
+
const afterColumn = currentLineContent.slice(column1Based - 1);
|
|
201
|
+
const replacement = beforeColumn + "\n" + preparedContent + (afterColumn ? "\n" + afterColumn : "");
|
|
202
|
+
magicString.overwrite(lineStart, lineEnd, replacement);
|
|
203
|
+
} else {
|
|
204
|
+
magicString.appendRight(lineEnd, preparedContent);
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
magicString.appendRight(index, preparedContent);
|
|
208
|
+
}
|
|
209
|
+
return true;
|
|
210
|
+
} catch (err) {
|
|
211
|
+
console.error(`[injector] MagicString injection failed: ${err.message}`);
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function getCommentSymbols(ext) {
|
|
216
|
+
const map = {
|
|
217
|
+
".js": { line: "//", blockStart: "/*", blockEnd: "*/" },
|
|
218
|
+
".ts": { line: "//", blockStart: "/*", blockEnd: "*/" },
|
|
219
|
+
".jsx": { line: "//", blockStart: "/*", blockEnd: "*/" },
|
|
220
|
+
".tsx": { line: "//", blockStart: "/*", blockEnd: "*/" },
|
|
221
|
+
".css": { line: "//", blockStart: "/*", blockEnd: "*/" },
|
|
222
|
+
".scss": { line: "//", blockStart: "/*", blockEnd: "*/" },
|
|
223
|
+
".html": { line: "//", blockStart: "<!--", blockEnd: "-->" },
|
|
224
|
+
".py": { line: "#", blockStart: '"""', blockEnd: '"""' },
|
|
225
|
+
".sh": { line: "#", blockStart: ": <<'BLOCK'", blockEnd: "BLOCK" },
|
|
226
|
+
".yaml": { line: "#", blockStart: "# ---", blockEnd: "# ---" },
|
|
227
|
+
".yml": { line: "#", blockStart: "# ---", blockEnd: "# ---" },
|
|
228
|
+
".json": { line: "//", blockStart: "/*", blockEnd: "*/" },
|
|
229
|
+
".jsonc": { line: "//", blockStart: "/*", blockEnd: "*/" }
|
|
230
|
+
};
|
|
231
|
+
const symbols = map[ext.toLowerCase()] ?? { line: "//", blockStart: "/*", blockEnd: "*/" };
|
|
232
|
+
return {
|
|
233
|
+
lineComment: symbols.line ?? "//",
|
|
234
|
+
blockStart: symbols.blockStart,
|
|
235
|
+
blockEnd: symbols.blockEnd
|
|
236
|
+
};
|
|
237
|
+
}
|