@reliverse/dler 1.7.16 → 1.7.18

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.
Files changed (165) hide show
  1. package/README.md +134 -206
  2. package/bin/app/agg/run.js +2 -8
  3. package/bin/app/build/cmd.js +4 -4
  4. package/bin/app/build/impl.d.ts +2 -6
  5. package/bin/app/build/impl.js +2 -46
  6. package/bin/app/conv/cmd.d.ts +8 -33
  7. package/bin/app/conv/cmd.js +185 -163
  8. package/bin/app/copy/cmd.js +1 -1
  9. package/bin/app/init/init-impl.js +3 -3
  10. package/bin/app/init/init-types.d.ts +8 -8
  11. package/bin/app/merge/cmd.d.ts +10 -24
  12. package/bin/app/merge/cmd.js +47 -464
  13. package/bin/app/migrate/codemods/anything-bun.js +1 -1
  14. package/bin/app/migrate/codemods/fs-relifso.d.ts +2 -2
  15. package/bin/app/migrate/codemods/fs-relifso.js +1 -1
  16. package/bin/app/migrate/codemods/nodenext-bundler.d.ts +2 -2
  17. package/bin/app/migrate/codemods/nodenext-bundler.js +1 -1
  18. package/bin/app/migrate/codemods/path-pathkit.d.ts +2 -2
  19. package/bin/app/migrate/codemods/path-pathkit.js +1 -1
  20. package/bin/app/migrate/codemods/readdir-glob.d.ts +2 -2
  21. package/bin/app/migrate/codemods/readdir-glob.js +1 -1
  22. package/bin/app/mkdist/cmd.js +4 -2
  23. package/bin/app/pack/cmd.d.ts +44 -0
  24. package/bin/app/pack/cmd.js +313 -0
  25. package/bin/app/pub/cmd.js +4 -4
  26. package/bin/app/pub/impl.d.ts +7 -0
  27. package/bin/app/pub/impl.js +97 -0
  28. package/bin/app/rename/cmd.js +1 -1
  29. package/bin/app/spell/cmd.d.ts +14 -5
  30. package/bin/app/spell/cmd.js +33 -33
  31. package/bin/app/spell/old.js +0 -0
  32. package/bin/app/{mock → unpack}/cmd.d.ts +10 -14
  33. package/bin/app/unpack/cmd.js +200 -0
  34. package/bin/cli.js +2 -2
  35. package/bin/libs/cfg/cfg-mod.d.ts +69 -0
  36. package/bin/libs/cfg/cfg-mod.js +61 -0
  37. package/bin/libs/cfg/rse/rse-impl/rse-biome.d.ts +2 -0
  38. package/bin/libs/cfg/rse/rse-impl/rse-biome.js +34 -0
  39. package/bin/libs/cfg/rse/rse-impl/rse-consts.d.ts +35 -0
  40. package/bin/libs/cfg/rse/rse-impl/rse-consts.js +37 -0
  41. package/bin/libs/cfg/rse/rse-impl/rse-content.d.ts +14 -0
  42. package/bin/libs/cfg/rse/rse-impl/rse-content.js +15 -0
  43. package/bin/libs/cfg/rse/rse-impl/rse-core.d.ts +14 -0
  44. package/bin/libs/cfg/rse/rse-impl/rse-core.js +63 -0
  45. package/bin/libs/cfg/rse/rse-impl/rse-create.d.ts +36 -0
  46. package/bin/libs/cfg/rse/rse-impl/rse-create.js +254 -0
  47. package/bin/libs/cfg/rse/rse-impl/rse-def-utils.d.ts +6 -0
  48. package/bin/libs/cfg/rse/rse-impl/rse-def-utils.js +225 -0
  49. package/bin/libs/cfg/rse/rse-impl/rse-default.d.ts +3 -0
  50. package/bin/libs/cfg/rse/rse-impl/rse-default.js +155 -0
  51. package/bin/libs/cfg/rse/rse-impl/rse-define.d.ts +125 -0
  52. package/bin/libs/cfg/rse/rse-impl/rse-define.js +4 -0
  53. package/bin/libs/cfg/rse/rse-impl/rse-detect.d.ts +23 -0
  54. package/bin/libs/cfg/rse/rse-impl/rse-detect.js +347 -0
  55. package/bin/libs/cfg/rse/rse-impl/rse-gen-cfg.d.ts +3 -0
  56. package/bin/libs/cfg/rse/rse-impl/rse-gen-cfg.js +186 -0
  57. package/bin/libs/cfg/rse/rse-impl/rse-inject.d.ts +1 -0
  58. package/bin/libs/cfg/rse/rse-impl/rse-inject.js +57 -0
  59. package/bin/libs/cfg/rse/rse-impl/rse-migrate.d.ts +5 -0
  60. package/bin/libs/cfg/rse/rse-impl/rse-migrate.js +56 -0
  61. package/bin/libs/cfg/rse/rse-impl/rse-path.d.ts +11 -0
  62. package/bin/libs/cfg/rse/rse-impl/rse-path.js +33 -0
  63. package/bin/libs/cfg/rse/rse-impl/rse-prompts.d.ts +5 -0
  64. package/bin/libs/cfg/rse/rse-impl/rse-prompts.js +12 -0
  65. package/bin/libs/cfg/rse/rse-impl/rse-read.d.ts +11 -0
  66. package/bin/libs/cfg/rse/rse-impl/rse-read.js +84 -0
  67. package/bin/libs/cfg/rse/rse-impl/rse-repair.d.ts +16 -0
  68. package/bin/libs/cfg/rse/rse-impl/rse-repair.js +137 -0
  69. package/bin/libs/cfg/rse/rse-impl/rse-schema.d.ts +130 -0
  70. package/bin/libs/cfg/rse/rse-impl/rse-schema.js +444 -0
  71. package/bin/libs/cfg/rse/rse-impl/rse-types.d.ts +75 -0
  72. package/bin/libs/cfg/rse/rse-impl/rse-types.js +0 -0
  73. package/bin/libs/cfg/rse/rse-impl/rse-unstable.d.ts +11 -0
  74. package/bin/libs/cfg/rse/rse-impl/rse-unstable.js +41 -0
  75. package/bin/libs/cfg/rse/rse-impl/rse-update.d.ts +10 -0
  76. package/bin/libs/cfg/rse/rse-impl/rse-update.js +152 -0
  77. package/bin/libs/cfg/rse/rse-impl/rse-utils.d.ts +17 -0
  78. package/bin/libs/cfg/rse/rse-impl/rse-utils.js +86 -0
  79. package/bin/libs/cfg/rse/rse-mod.d.ts +20 -0
  80. package/bin/libs/cfg/rse/rse-mod.js +20 -0
  81. package/bin/libs/cfg/types.d.ts +533 -0
  82. package/bin/libs/cfg/types.js +0 -0
  83. package/bin/libs/sdk/sdk-impl/build/build-library.d.ts +5 -5
  84. package/bin/libs/sdk/sdk-impl/build/build-library.js +1 -174
  85. package/bin/libs/sdk/sdk-impl/build/build-regular.d.ts +2 -1
  86. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/build.js +287 -240
  87. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/loaders/vue.d.ts +4 -4
  88. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/make.d.ts +8 -5
  89. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/make.js +199 -119
  90. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/spinner.d.ts +99 -0
  91. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/spinner.js +206 -0
  92. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/mkdist-mod.js +92 -46
  93. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/plugins/raw.d.ts +2 -2
  94. package/bin/libs/sdk/sdk-impl/build/bundlers/unified/utils.d.ts +2 -2
  95. package/bin/libs/sdk/sdk-impl/config/default.d.ts +6 -0
  96. package/bin/libs/sdk/sdk-impl/{cfg → config}/default.js +8 -18
  97. package/bin/libs/sdk/sdk-impl/{cfg → config}/info.js +1 -1
  98. package/bin/libs/sdk/sdk-impl/{cfg → config}/init.js +53 -43
  99. package/bin/libs/sdk/sdk-impl/{cfg → config}/load.d.ts +2 -2
  100. package/bin/libs/sdk/sdk-impl/{cfg → config}/load.js +6 -6
  101. package/bin/libs/sdk/sdk-impl/config/types.d.ts +533 -0
  102. package/bin/libs/sdk/sdk-impl/config/types.js +0 -0
  103. package/bin/libs/sdk/sdk-impl/library-flow.d.ts +2 -1
  104. package/bin/libs/sdk/sdk-impl/regular-flow.d.ts +2 -1
  105. package/bin/libs/sdk/sdk-impl/rules/reliverse/dler-config-health/dler-config-health.js +2 -2
  106. package/bin/libs/sdk/sdk-impl/rules/reliverse/missing-deps/deps-types.d.ts +6 -6
  107. package/bin/libs/sdk/sdk-impl/rules/reliverse/missing-deps/filesystem.js +1 -1
  108. package/bin/libs/sdk/sdk-impl/rules/reliverse/no-index-files/no-index-files.js +1 -1
  109. package/bin/libs/sdk/sdk-impl/rules/reliverse/self-include/self-include.js +2 -2
  110. package/bin/libs/sdk/sdk-impl/spell/applyMagicSpells.d.ts +38 -0
  111. package/bin/libs/sdk/sdk-impl/spell/applyMagicSpells.js +474 -0
  112. package/bin/libs/sdk/sdk-impl/spell/spells.d.ts +31 -0
  113. package/bin/libs/sdk/sdk-impl/spell/spells.js +85 -0
  114. package/bin/libs/sdk/sdk-impl/utils/binary.js +1 -1
  115. package/bin/libs/sdk/sdk-impl/utils/comments.d.ts +6 -0
  116. package/bin/libs/sdk/sdk-impl/utils/comments.js +41 -0
  117. package/bin/libs/sdk/sdk-impl/utils/finalize.d.ts +2 -1
  118. package/bin/libs/sdk/sdk-impl/utils/finalize.js +1 -0
  119. package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-constants.d.ts +6 -0
  120. package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-constants.js +7 -0
  121. package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-file-utils.d.ts +5 -0
  122. package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-file-utils.js +40 -0
  123. package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-types.d.ts +24 -0
  124. package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-types.js +0 -0
  125. package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pub-json-utils.d.ts +17 -0
  126. package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pub-json-utils.js +46 -0
  127. package/bin/libs/sdk/sdk-impl/utils/replacements.d.ts +0 -0
  128. package/bin/libs/sdk/sdk-impl/utils/replacements.js +0 -0
  129. package/bin/libs/sdk/sdk-impl/utils/resolve-cross-libs.d.ts +3 -0
  130. package/bin/libs/sdk/sdk-impl/utils/resolve-cross-libs.js +194 -0
  131. package/bin/libs/sdk/sdk-impl/utils/utils-build.d.ts +1 -2
  132. package/bin/libs/sdk/sdk-impl/utils/utils-clean.d.ts +1 -1
  133. package/bin/libs/sdk/sdk-impl/utils/utils-deps.d.ts +1 -1
  134. package/bin/libs/sdk/sdk-impl/utils/utils-determine.d.ts +1 -1
  135. package/bin/libs/sdk/sdk-impl/utils/utils-error-cwd.d.ts +4 -0
  136. package/bin/libs/sdk/sdk-impl/utils/utils-error-cwd.js +1 -0
  137. package/bin/libs/sdk/sdk-impl/utils/utils-jsr-json.d.ts +1 -1
  138. package/bin/libs/sdk/sdk-impl/utils/utils-package-json-libraries.d.ts +1 -1
  139. package/bin/libs/sdk/sdk-impl/utils/utils-package-json-regular.d.ts +1 -1
  140. package/bin/libs/sdk/sdk-impl/utils/utils-security.d.ts +1 -3
  141. package/bin/libs/sdk/sdk-impl/utils/utils-security.js +11 -10
  142. package/bin/libs/sdk/sdk-mod.d.ts +1 -6
  143. package/bin/libs/sdk/sdk-mod.js +0 -31
  144. package/bin/libs/sdk/sdk-types.d.ts +39 -582
  145. package/bin/mod.d.ts +1 -1
  146. package/bin/mod.js +1 -1
  147. package/package.json +12 -4
  148. package/bin/app/mock/cmd.js +0 -284
  149. package/bin/app/mock/mock.d.ts +0 -11
  150. package/bin/app/mock/mock.js +0 -97
  151. package/bin/libs/sdk/sdk-impl/cfg/default.d.ts +0 -5
  152. package/bin/libs/sdk/sdk-impl/cfg/define.d.ts +0 -2
  153. package/bin/libs/sdk/sdk-impl/cfg/define.js +0 -4
  154. package/bin/libs/sdk/sdk-impl/spell/spell-executors.d.ts +0 -10
  155. package/bin/libs/sdk/sdk-impl/spell/spell-executors.js +0 -307
  156. package/bin/libs/sdk/sdk-impl/spell/spell-filesystem.d.ts +0 -7
  157. package/bin/libs/sdk/sdk-impl/spell/spell-filesystem.js +0 -74
  158. package/bin/libs/sdk/sdk-impl/spell/spell-mod.d.ts +0 -4
  159. package/bin/libs/sdk/sdk-impl/spell/spell-mod.js +0 -87
  160. package/bin/libs/sdk/sdk-impl/spell/spell-parser.d.ts +0 -4
  161. package/bin/libs/sdk/sdk-impl/spell/spell-parser.js +0 -58
  162. package/bin/libs/sdk/sdk-impl/spell/spell-types.d.ts +0 -60
  163. /package/bin/{libs/sdk/sdk-impl/spell/spell-types.js → app/spell/old.d.ts} +0 -0
  164. /package/bin/libs/sdk/sdk-impl/{cfg → config}/info.d.ts +0 -0
  165. /package/bin/libs/sdk/sdk-impl/{cfg → config}/init.d.ts +0 -0
@@ -0,0 +1,186 @@
1
+ import path from "@reliverse/pathkit";
2
+ import { ensuredir } from "@reliverse/relifso";
3
+ import fs from "@reliverse/relifso";
4
+ import { relinka } from "@reliverse/relinka";
5
+ import { destr } from "destr";
6
+ import { execaCommand } from "execa";
7
+ import { CONFIG_CATEGORIES, UNKNOWN_VALUE } from "./rse-consts.js";
8
+ import { generateRseConfig } from "./rse-create.js";
9
+ import { getRseConfigPath } from "./rse-path.js";
10
+ async function generateBiomeConfig(projectPath) {
11
+ const biomePath = path.join(projectPath, "biome.json");
12
+ const biomeExists = await fs.pathExists(biomePath);
13
+ if (!biomeExists) {
14
+ await execaCommand("bunx biome init", {
15
+ cwd: projectPath,
16
+ stdio: "inherit"
17
+ });
18
+ relinka("verbose", "Generated biome.json");
19
+ }
20
+ }
21
+ async function generateVSCodeSettings(projectPath, overwrite) {
22
+ const vscodePath = path.join(projectPath, ".vscode");
23
+ await ensuredir(vscodePath);
24
+ const settingsPath = path.join(vscodePath, "settings.json");
25
+ const defaultSettings = {
26
+ "editor.formatOnSave": true,
27
+ "editor.defaultFormatter": "biomejs.biome",
28
+ "editor.codeActionsOnSave": {
29
+ "quickfix.biome": "explicit",
30
+ "source.addMissingImports": "never",
31
+ "source.fixAll.eslint": "explicit",
32
+ "source.organizeImports": "never",
33
+ "source.removeUnused": "never"
34
+ },
35
+ "eslint.ignoreUntitled": true,
36
+ "eslint.rules.customizations": [
37
+ {
38
+ rule: "perfectionist/sort-imports",
39
+ severity: "off"
40
+ }
41
+ ],
42
+ "markdownlint.config": {
43
+ MD033: false
44
+ },
45
+ "typescript.enablePromptUseWorkspaceTsdk": true
46
+ };
47
+ let settings = { ...defaultSettings };
48
+ if (!overwrite && await fs.pathExists(settingsPath)) {
49
+ try {
50
+ const content = await fs.readFile(settingsPath, "utf-8");
51
+ const existingSettings = destr(content);
52
+ if (existingSettings && typeof existingSettings === "object") {
53
+ const defaultCodeActions = {
54
+ "quickfix.biome": "explicit",
55
+ "source.addMissingImports": "never",
56
+ "source.fixAll.eslint": "explicit",
57
+ "source.organizeImports": "never",
58
+ "source.removeUnused": "never"
59
+ };
60
+ const existingCodeActions = {
61
+ ...defaultCodeActions,
62
+ ...existingSettings["editor.codeActionsOnSave"]
63
+ };
64
+ settings = {
65
+ ...defaultSettings,
66
+ ...existingSettings,
67
+ "editor.codeActionsOnSave": existingCodeActions
68
+ };
69
+ }
70
+ } catch (error) {
71
+ relinka(
72
+ "verbose",
73
+ "Error reading existing settings.json, creating new one",
74
+ error instanceof Error ? error.message : String(error)
75
+ );
76
+ }
77
+ }
78
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
79
+ relinka(
80
+ "verbose",
81
+ overwrite ? "Generated brand new VSCode settings.json file" : "Updated VSCode settings.json with required settings"
82
+ );
83
+ }
84
+ export async function generateConfigFiles(projectPath, overwrite, projectName, deployService, primaryDomain, frontendUsername, enableI18n, isDev, filesToGenerate = []) {
85
+ try {
86
+ const shouldGenerateFile = (filename) => {
87
+ return filesToGenerate.length === 0 || filesToGenerate.includes(filename);
88
+ };
89
+ const cleanDomain = primaryDomain.replace(/^https?:\/\//, "").replace(/\/.*$/, "");
90
+ const finalFrontendUsername = isDev && frontendUsername === "blefnk" ? "reliverse" : frontendUsername;
91
+ const configInfo = await getRseConfigPath(projectPath, isDev, false);
92
+ const mainConfigFileName = path.basename(configInfo.configPath);
93
+ const configGenerators = {
94
+ [mainConfigFileName]: async () => {
95
+ await generateRseConfig({
96
+ projectName,
97
+ frontendUsername: !finalFrontendUsername || finalFrontendUsername.trim() === "" ? UNKNOWN_VALUE : finalFrontendUsername,
98
+ deployService,
99
+ primaryDomain: cleanDomain,
100
+ projectPath,
101
+ githubUsername: UNKNOWN_VALUE,
102
+ enableI18n,
103
+ overwrite,
104
+ isDev,
105
+ configInfo,
106
+ ...isDev && configInfo?.isTS ? {
107
+ customPathToTypes: "./src/libs/sdk/sdk-mod"
108
+ } : {},
109
+ overrides: {}
110
+ });
111
+ return true;
112
+ },
113
+ "biome.json": async () => {
114
+ await generateBiomeConfig(projectPath);
115
+ return true;
116
+ },
117
+ "settings.json": async () => {
118
+ await generateVSCodeSettings(projectPath, overwrite);
119
+ return true;
120
+ }
121
+ };
122
+ const generatedFiles = [];
123
+ await Promise.all(
124
+ Object.entries(configGenerators).filter(([filename]) => shouldGenerateFile(filename)).map(async ([filename, generator]) => {
125
+ const wasGenerated = await generator();
126
+ if (wasGenerated) {
127
+ generatedFiles.push(filename);
128
+ }
129
+ })
130
+ );
131
+ if (generatedFiles.length > 0) {
132
+ relinka("verbose", `Generated configuration files: ${generatedFiles.join(", ")}`);
133
+ }
134
+ } catch (error) {
135
+ relinka(
136
+ "error",
137
+ "Error generating config files:",
138
+ error instanceof Error ? error.message : String(error)
139
+ );
140
+ throw error;
141
+ }
142
+ }
143
+ export async function generateProjectConfigs(projectPath, projectName, frontendUsername, deployService, primaryDomain, enableI18n, isDev) {
144
+ try {
145
+ const existingFiles = [];
146
+ for (const category of Object.keys(CONFIG_CATEGORIES)) {
147
+ const files = CONFIG_CATEGORIES[category];
148
+ for (const file of files) {
149
+ const filePath = path.join(projectPath, file);
150
+ if (await fs.pathExists(filePath)) {
151
+ existingFiles.push(file);
152
+ }
153
+ }
154
+ }
155
+ if (existingFiles.length > 0) {
156
+ relinka("verbose", `Found ${existingFiles.length} existing configuration files`);
157
+ await generateConfigFiles(
158
+ projectPath,
159
+ false,
160
+ projectName,
161
+ deployService,
162
+ primaryDomain,
163
+ frontendUsername,
164
+ enableI18n,
165
+ isDev
166
+ );
167
+ } else {
168
+ await generateConfigFiles(
169
+ projectPath,
170
+ true,
171
+ projectName,
172
+ deployService,
173
+ primaryDomain,
174
+ frontendUsername,
175
+ enableI18n,
176
+ isDev
177
+ );
178
+ }
179
+ } catch (error) {
180
+ relinka(
181
+ "error",
182
+ `Failed to set up configuration files: ${error instanceof Error ? error.message : String(error)}`
183
+ );
184
+ throw error;
185
+ }
186
+ }
@@ -0,0 +1 @@
1
+ export declare function injectSectionComments(fileContent: string): string;
@@ -0,0 +1,57 @@
1
+ import MagicString from "magic-string";
2
+ import { cliDomainDocs } from "./rse-consts.js";
3
+ export function injectSectionComments(fileContent) {
4
+ const ms = new MagicString(fileContent);
5
+ const comment = (text) => text ? `// ${text}` : "";
6
+ const commentSections = {
7
+ $schema: [
8
+ comment(`RSE CONFIG (${cliDomainDocs})`),
9
+ comment("Restart the CLI to apply your config changes")
10
+ ],
11
+ projectName: [comment("General project information")],
12
+ skipPromptsUseAutoBehavior: [
13
+ comment("Enable auto-answering for prompts to skip manual confirmations."),
14
+ comment("Make sure you have unknown values configured above.")
15
+ ],
16
+ features: [comment("Project features")],
17
+ projectFramework: [comment("Primary tech stack/framework")],
18
+ codeStyle: [comment("Code style preferences")],
19
+ multipleRepoCloneMode: [comment("Settings for cloning an existing repo")],
20
+ envComposerOpenBrowser: [
21
+ comment("Set to false to disable opening the browser during env composing")
22
+ ],
23
+ ignoreDependencies: [comment("List dependencies to exclude from checks")],
24
+ customRules: [
25
+ comment("Provide custom rules for Reliverse AI"),
26
+ comment("You can use any json type here in {}")
27
+ ],
28
+ deployBehavior: [
29
+ comment("Prompt behavior for deployment"),
30
+ comment("Options: prompt | autoYes | autoNo")
31
+ ],
32
+ existingRepoBehavior: [
33
+ comment("Behavior for existing GitHub repos during project creation"),
34
+ comment("Options: prompt | autoYes | autoYesSkipCommit | autoNo")
35
+ ],
36
+ relinterConfirm: [
37
+ comment("Behavior for Reliverse AI chat and agent mode"),
38
+ comment("Options: promptOnce | promptEachFile | autoYes")
39
+ ]
40
+ };
41
+ for (const [section, lines] of Object.entries(commentSections)) {
42
+ if (!lines?.length) continue;
43
+ const combinedComments = lines.map((line, idx) => idx === 0 ? line : ` ${line}`).join("\n");
44
+ const regex = new RegExp(`(\\s+)(["']?)${section.replace("$", "\\$")}(\\2):`, "g");
45
+ let match = regex.exec(fileContent);
46
+ while (match !== null) {
47
+ const insertPos = match.index;
48
+ const insertion = `
49
+ ${combinedComments}`;
50
+ ms.prependLeft(insertPos, insertion);
51
+ match = regex.exec(fileContent);
52
+ }
53
+ }
54
+ let result = ms.toString();
55
+ result = result.replace(/\n{3,}/g, "\n\n").replace(/{\n\n/g, "{\n").replace(/\n\n}/g, "\n}");
56
+ return result.trim().concat("\n");
57
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Migrates an external rseg file into the current project config.
3
+ * Only migrates fields that exist in the current schema.
4
+ */
5
+ export declare function migrateRseConfig(externalrseth: string, projectPath: string, isDev: boolean): Promise<void>;
@@ -0,0 +1,56 @@
1
+ import fs from "@reliverse/relifso";
2
+ import { relinka } from "@reliverse/relinka";
3
+ import { parseJSONC } from "confbox";
4
+ import { updateRseConfig } from "./rse-update.js";
5
+ export async function migrateRseConfig(externalrseth, projectPath, isDev) {
6
+ try {
7
+ const content = await fs.readFile(externalrseth, "utf-8");
8
+ const parsed = parseJSONC(content);
9
+ if (!parsed || typeof parsed !== "object") {
10
+ throw new Error("Invalid JSONC format in external config file");
11
+ }
12
+ const tempConfig = parsed;
13
+ const migratedFields = [];
14
+ const validConfig = {};
15
+ const keysToMigrate = [
16
+ "projectDescription",
17
+ "version",
18
+ "projectLicense",
19
+ "projectRepository",
20
+ "projectCategory",
21
+ "projectSubcategory",
22
+ "projectFramework",
23
+ "projectTemplate",
24
+ "projectArchitecture",
25
+ "deployBehavior",
26
+ "depsBehavior",
27
+ "gitBehavior",
28
+ "i18nBehavior",
29
+ "scriptsBehavior",
30
+ "existingRepoBehavior",
31
+ "repoPrivacy",
32
+ "features",
33
+ "preferredLibraries",
34
+ "codeStyle",
35
+ "monorepo",
36
+ "ignoreDependencies",
37
+ "customRules",
38
+ "skipPromptsUseAutoBehavior",
39
+ "relinterConfirm"
40
+ ];
41
+ for (const key of keysToMigrate) {
42
+ if (tempConfig[key] !== void 0) {
43
+ validConfig[key] = tempConfig[key];
44
+ migratedFields.push(String(key));
45
+ }
46
+ }
47
+ const success = await updateRseConfig(projectPath, validConfig, isDev);
48
+ if (success) {
49
+ relinka("success", "Successfully migrated config");
50
+ relinka("verbose", "Migrated fields:", migratedFields.join(", "));
51
+ }
52
+ await fs.remove(externalrseth);
53
+ } catch (error) {
54
+ relinka("warn", "Failed to migrate external config:", String(error));
55
+ }
56
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Determines the rse config file path and whether it's TS or JSONC.
3
+ * Always looks in the .config directory first.
4
+ * - In dev mode, automatically selects the TS path.
5
+ * - Honors a custom tsconfig.json path if provided.
6
+ * - Caches results by projectPath.
7
+ */
8
+ export declare function getRseConfigPath(projectPath: string, isDev: boolean, skipPrompt: boolean, customTsconfigPath?: string): Promise<{
9
+ configPath: string;
10
+ isTS: boolean;
11
+ }>;
@@ -0,0 +1,33 @@
1
+ import path from "@reliverse/pathkit";
2
+ import fs from "@reliverse/relifso";
3
+ import { tsconfigJson } from "./rse-consts.js";
4
+ import { askRseConfigType } from "./rse-prompts.js";
5
+ const configPathCache = /* @__PURE__ */ new Map();
6
+ export async function getRseConfigPath(projectPath, isDev, skipPrompt, customTsconfigPath) {
7
+ const cached = configPathCache.get(projectPath);
8
+ if (cached) {
9
+ return cached;
10
+ }
11
+ const finalTsconfigPath = customTsconfigPath ? path.resolve(customTsconfigPath) : path.join(projectPath, tsconfigJson);
12
+ const configDir = path.join(projectPath, ".config");
13
+ const rseJsonc = path.join(configDir, "rse.jsonc");
14
+ const rseTs = path.join(configDir, "rse.ts");
15
+ const [tsconfigExists, jsoncExists, tsExists] = await Promise.all([
16
+ fs.pathExists(finalTsconfigPath),
17
+ fs.pathExists(rseJsonc),
18
+ fs.pathExists(rseTs)
19
+ ]);
20
+ let result;
21
+ if (isDev) {
22
+ result = { configPath: rseTs, isTS: true };
23
+ } else if (tsExists) {
24
+ result = { configPath: rseTs, isTS: true };
25
+ } else if (tsconfigExists && !jsoncExists && !skipPrompt) {
26
+ const choice = await askRseConfigType();
27
+ result = choice === "ts" ? { configPath: rseTs, isTS: true } : { configPath: rseJsonc, isTS: false };
28
+ } else {
29
+ result = { configPath: rseJsonc, isTS: false };
30
+ }
31
+ configPathCache.set(projectPath, result);
32
+ return result;
33
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Prompts the user to select a config file type (JSONC or TS)
3
+ * @returns The selected config type ('jsonc' or 'ts')
4
+ */
5
+ export declare function askRseConfigType(): Promise<"jsonc" | "ts">;
@@ -0,0 +1,12 @@
1
+ import { selectPrompt } from "@reliverse/rempts";
2
+ export async function askRseConfigType() {
3
+ return await selectPrompt({
4
+ title: "Please select a rseonfiguration file type. JSONC is recommended for most projects.",
5
+ content: "A tsconfig.json file was detected. You can use the TypeScript config type for this project; however, it requires @reliverse/rse to be installed (as a dev dependency); without it, the rse CLI may not run correctly when using the TS config type.",
6
+ options: [
7
+ { label: "TypeScript (rse) (recommended)", value: "ts" },
8
+ { label: "JSONC (rse)", value: "jsonc" }
9
+ ],
10
+ defaultValue: "jsonc"
11
+ });
12
+ }
@@ -0,0 +1,11 @@
1
+ import type { RseConfig } from "./rse-types";
2
+ /**
3
+ * Helper for TS config reading.
4
+ * Uses jiti for TypeScript module loading.
5
+ */
6
+ export declare function readRseTs(configPath: string): Promise<RseConfig | null>;
7
+ /**
8
+ * Reads and validates the config file.
9
+ * If errors are detected, it attempts to merge missing or invalid fields with defaults.
10
+ */
11
+ export declare function readRseConfig(configPath: string, isDev: boolean): Promise<RseConfig | null>;
@@ -0,0 +1,84 @@
1
+ import fs from "@reliverse/relifso";
2
+ import { relinka } from "@reliverse/relinka";
3
+ import { Value } from "@sinclair/typebox/value";
4
+ import { parseJSONC } from "confbox";
5
+ import { createJiti } from "jiti";
6
+ import { writeRseConfig } from "./rse-create.js";
7
+ import { repairAndParseJSON } from "./rse-repair.js";
8
+ import { rseSchema } from "./rse-schema.js";
9
+ import { mergeWithDefaults } from "./rse-update.js";
10
+ import { getBackupAndTempPaths } from "./rse-utils.js";
11
+ const jiti = createJiti(import.meta.url);
12
+ async function parseRseConfig(configPath) {
13
+ try {
14
+ const content = (await fs.readFile(configPath, "utf-8")).trim();
15
+ if (!content || content === "{}") return null;
16
+ let parsed = parseJSONC(content);
17
+ if (!parsed || typeof parsed !== "object") {
18
+ const repaired = repairAndParseJSON(content);
19
+ if (!repaired) return null;
20
+ parsed = repaired;
21
+ relinka("info", "Config JSON was repaired.");
22
+ relinka("verbose", "Used tool: jsonrepair.");
23
+ }
24
+ const schemaProperties = Object.keys(rseSchema.properties);
25
+ const filteredParsed = Object.fromEntries(
26
+ Object.entries(parsed).filter(
27
+ ([key]) => schemaProperties.includes(key)
28
+ )
29
+ );
30
+ const isValid = Value.Check(rseSchema, filteredParsed);
31
+ return isValid ? { parsed: filteredParsed, errors: null } : {
32
+ parsed: filteredParsed,
33
+ errors: Value.Errors(rseSchema, filteredParsed)
34
+ };
35
+ } catch {
36
+ return null;
37
+ }
38
+ }
39
+ export async function readRseTs(configPath) {
40
+ try {
41
+ const config = await jiti.import(configPath, { default: true });
42
+ if (Value.Check(rseSchema, config)) {
43
+ return config;
44
+ }
45
+ relinka("warn", "TS config does not match the schema.");
46
+ return null;
47
+ } catch (error) {
48
+ relinka(
49
+ "error",
50
+ "Failed to import TS config:",
51
+ error instanceof Error ? error.message : String(error)
52
+ );
53
+ return null;
54
+ }
55
+ }
56
+ export async function readRseConfig(configPath, isDev) {
57
+ if (configPath.endsWith(".ts")) {
58
+ return await readRseTs(configPath);
59
+ }
60
+ if (!await fs.pathExists(configPath)) return null;
61
+ const { backupPath } = getBackupAndTempPaths(configPath);
62
+ const parseResult = await parseRseConfig(configPath);
63
+ if (!parseResult) return null;
64
+ if (!parseResult.errors) return parseResult.parsed;
65
+ const errors = [...parseResult.errors].map((err) => `Path "${err.path}": ${err.message}`);
66
+ relinka("verbose", "Detected invalid fields in config:", errors.join("; "));
67
+ const merged = mergeWithDefaults(parseResult.parsed);
68
+ if (Value.Check(rseSchema, merged)) {
69
+ await writeRseConfig(configPath, merged, isDev);
70
+ relinka("info", "Merged missing or invalid fields into config");
71
+ return merged;
72
+ }
73
+ if (await fs.pathExists(backupPath)) {
74
+ const backupResult = await parseRseConfig(backupPath);
75
+ if (backupResult && !backupResult.errors) {
76
+ await fs.copy(backupPath, configPath);
77
+ relinka("info", "Restored config from backup");
78
+ return backupResult.parsed;
79
+ }
80
+ relinka("warn", "Backup also invalid. Returning null.");
81
+ return null;
82
+ }
83
+ return null;
84
+ }
@@ -0,0 +1,16 @@
1
+ import type { TSchema } from "@sinclair/typebox";
2
+ import type { RseConfig } from "./rse-types";
3
+ export declare function repairAndParseJSON(raw: string): any;
4
+ /**
5
+ * Recursively fixes each property in the object. Returns the fixed config and
6
+ * an array of property paths that were changed.
7
+ */
8
+ export declare function fixLineByLine(userConfig: unknown, defaultConfig: unknown, schema: TSchema): {
9
+ fixedConfig: unknown;
10
+ changedKeys: string[];
11
+ };
12
+ /**
13
+ * Reads the config file, fixes invalid lines based on the schema,
14
+ * writes back the fixed config, and returns the fixed config.
15
+ */
16
+ export declare function parseAndFixRseConfig(configPath: string, isDev: boolean): Promise<RseConfig | null>;
@@ -0,0 +1,137 @@
1
+ import fs from "@reliverse/relifso";
2
+ import { relinka } from "@reliverse/relinka";
3
+ import { Type } from "@sinclair/typebox";
4
+ import { Value } from "@sinclair/typebox/value";
5
+ import { parseJSONC } from "confbox";
6
+ import { jsonrepair } from "jsonrepair";
7
+ import { writeRseConfig } from "./rse-create.js";
8
+ import { DEFAULT_CONFIG_RSE } from "./rse-default.js";
9
+ import { rseSchema } from "./rse-schema.js";
10
+ import { cleanGitHubUrl } from "./rse-utils.js";
11
+ export function repairAndParseJSON(raw) {
12
+ try {
13
+ const repaired = jsonrepair(raw);
14
+ return JSON.parse(repaired);
15
+ } catch (error) {
16
+ return null;
17
+ }
18
+ }
19
+ function createSinglePropertySchema(key, subSchema) {
20
+ return Type.Object({ [key]: subSchema }, {
21
+ additionalProperties: false,
22
+ required: [key]
23
+ });
24
+ }
25
+ function fixSingleProperty(schema, propName, userValue, defaultValue) {
26
+ const singlePropertySchema = createSinglePropertySchema(propName, schema);
27
+ const testObject = { [propName]: userValue };
28
+ return Value.Check(singlePropertySchema, testObject) ? userValue : defaultValue;
29
+ }
30
+ export function fixLineByLine(userConfig, defaultConfig, schema) {
31
+ const isObjectSchema = schema.type === "object" && schema.properties;
32
+ if (!isObjectSchema || typeof userConfig !== "object" || userConfig === null) {
33
+ const isValid = Value.Check(schema, userConfig);
34
+ return {
35
+ fixedConfig: isValid ? userConfig : defaultConfig,
36
+ changedKeys: isValid ? [] : ["<entire_object>"]
37
+ };
38
+ }
39
+ const properties = schema.properties;
40
+ const result = { ...defaultConfig ?? {} };
41
+ const changedKeys = [];
42
+ const missingKeys = [];
43
+ for (const propName of Object.keys(properties)) {
44
+ const subSchema = properties[propName];
45
+ const userValue = userConfig[propName];
46
+ const defaultValue = defaultConfig[propName];
47
+ if (!subSchema) {
48
+ result[propName] = defaultValue;
49
+ changedKeys.push(propName);
50
+ continue;
51
+ }
52
+ if (userValue === void 0 && !(propName in userConfig)) {
53
+ missingKeys.push(propName);
54
+ result[propName] = defaultValue;
55
+ continue;
56
+ }
57
+ if (propName === "customUserFocusedRepos" || propName === "customDevsFocusedRepos") {
58
+ if (Array.isArray(userValue)) {
59
+ result[propName] = userValue.map((url) => cleanGitHubUrl(String(url)));
60
+ continue;
61
+ }
62
+ }
63
+ const isValidStructure = Value.Check(createSinglePropertySchema(propName, subSchema), {
64
+ [propName]: userValue
65
+ });
66
+ if (!isValidStructure) {
67
+ result[propName] = defaultValue;
68
+ changedKeys.push(propName);
69
+ } else if (subSchema && typeof subSchema === "object" && "type" in subSchema && subSchema.type === "object") {
70
+ const { fixedConfig, changedKeys: nestedChanges } = fixLineByLine(
71
+ userValue,
72
+ defaultValue,
73
+ subSchema
74
+ );
75
+ result[propName] = fixedConfig;
76
+ if (nestedChanges.length > 0) {
77
+ changedKeys.push(...nestedChanges.map((nc) => `${propName}.${nc}`));
78
+ }
79
+ } else {
80
+ const originalValue = userValue;
81
+ const validatedValue = fixSingleProperty(subSchema, propName, userValue, defaultValue);
82
+ result[propName] = validatedValue;
83
+ if (originalValue !== void 0 && validatedValue !== originalValue) {
84
+ changedKeys.push(propName);
85
+ }
86
+ }
87
+ }
88
+ if (missingKeys.length > 0) {
89
+ relinka("verbose", "Missing fields injected from default config:", missingKeys.join(", "));
90
+ }
91
+ return { fixedConfig: result, changedKeys };
92
+ }
93
+ export async function parseAndFixRseConfig(configPath, isDev) {
94
+ try {
95
+ const raw = await fs.readFile(configPath, "utf-8");
96
+ let parsed = parseJSONC(raw);
97
+ if (!parsed || typeof parsed !== "object") {
98
+ const repaired = repairAndParseJSON(raw);
99
+ if (repaired) {
100
+ relinka("info", "Config JSON was repaired.");
101
+ relinka("verbose", "Used tool: jsonrepair.");
102
+ }
103
+ parsed = repaired;
104
+ }
105
+ if (parsed && typeof parsed === "object") {
106
+ const originalErrors = [...Value.Errors(rseSchema, parsed)];
107
+ if (originalErrors.length === 0) return parsed;
108
+ const { fixedConfig, changedKeys } = fixLineByLine(parsed, DEFAULT_CONFIG_RSE, rseSchema);
109
+ if (Value.Check(rseSchema, fixedConfig)) {
110
+ await writeRseConfig(configPath, fixedConfig, isDev);
111
+ const originalInvalidPaths = originalErrors.map((err) => err.path);
112
+ relinka(
113
+ "info",
114
+ "Your config has been fixed. Please ensure it aligns with your project.",
115
+ `Changed keys: ${changedKeys.join(", ") || "(none)"}`
116
+ );
117
+ relinka(
118
+ "verbose",
119
+ `Originally invalid paths were: ${originalInvalidPaths.join(", ") || "(none)"}`
120
+ );
121
+ return fixedConfig;
122
+ }
123
+ const newErrs = [...Value.Errors(rseSchema, fixedConfig)].map(
124
+ (e) => `Path "${e.path}": ${e.message}`
125
+ );
126
+ relinka("warn", "Could not fix all invalid config lines:", newErrs.join("; "));
127
+ return null;
128
+ }
129
+ } catch (error) {
130
+ relinka(
131
+ "warn",
132
+ "Failed to parse/fix config line-by-line:",
133
+ error instanceof Error ? error.message : String(error)
134
+ );
135
+ }
136
+ return null;
137
+ }