Skip to content

Commit 865088c

Browse files
committed
fix env composer and strings replacer
1 parent 545147e commit 865088c

37 files changed

+1219
-653
lines changed

.reliverse

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"projectName": "@reliverse/cli",
99
"projectAuthor": "blefnk",
1010
"projectDescription": "This superapp CLI tool can help you easily create new web projects, manage existing projects, and automatically make advanced codebase modifications, with more features coming soon.",
11-
"projectVersion": "1.4.28",
11+
"projectVersion": "1.4.29",
1212
"projectLicense": "MIT",
1313
"projectRepository": "https://github.com/reliverse/cli",
1414
"projectState": "creating",

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Reliverse CLI
22

3-
**📚 Docs**: [docs.reliverse.org](https://docs.reliverse.org/cli) | **💙 Discord**: [discord.gg/Pb8uKbwpsJ](https://discord.gg/Pb8uKbwpsJ) | [NPM](https://npmjs.com/@reliverse/cli) | [GitHub](https://github.com/reliverse/cli)
3+
**✨ NPM**: [npmjs.com/@reliverse/cli](https://npmjs.com/@reliverse/cli)
4+
**💙 Discord**: [discord.gg/Pb8uKbwpsJ](https://discord.gg/Pb8uKbwpsJ)
5+
**⭐ GitHub**: [github.com/reliverse/cli](https://github.com/reliverse/cli)
6+
**📚 Docs**: [docs.reliverse.org](https://docs.reliverse.org/cli)
47

58
@reliverse/cli is a powerful command-line interface tool that helps you effortlessly create new web projects, manage existing ones, and apply advanced, automated modifications to the codebase. Having Reliverse CLI is like having a superapp right in the terminal.
69

bun.lockb

32 Bytes
Binary file not shown.

jsr.jsonc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reliverse/cli",
3-
"version": "1.4.29",
3+
"version": "1.4.30",
44
"author": "blefnk",
55
"license": "MIT",
66
"exports": "./dist-jsr/main.ts",

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reliverse/cli",
3-
"version": "1.4.29",
3+
"version": "1.4.30",
44
"author": "reliverse",
55
"type": "module",
66
"description": "This superapp CLI tool can help you easily create new web projects, manage existing projects, and automatically make advanced codebase modifications, with more features coming soon.",
@@ -81,6 +81,7 @@
8181
"detect-package-manager": "^3.0.2",
8282
"dotenv": "^16.4.7",
8383
"drizzle-orm": "^0.38.3",
84+
"escape-string-regexp": "^5.0.0",
8485
"execa": "^9.5.2",
8586
"fs-extra": "^11.2.0",
8687
"geist": "^1.3.1",

src/app/app-types.ts

+9
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,12 @@ export type AppParams = {
1414
export type ParamsOmitPN = Omit<AppParams, "projectName">;
1515
export type ParamsOmitSkipPN = Omit<AppParams, "skipPrompts" | "projectName">;
1616
export type ParamsOmitReli = Omit<AppParams, "reli">;
17+
18+
/**
19+
* Minimal object describing essential project info after initialization
20+
*/
21+
export type ProjectConfigReturn = {
22+
cliUsername: string;
23+
projectName: string;
24+
primaryDomain: string;
25+
};

src/app/constants.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import path from "pathe";
22
import pc from "picocolors";
33
import { fileURLToPath } from "url";
44

5-
export const cliVersion = "1.4.29";
5+
export const cliVersion = "1.4.30";
66
export const cliName = "@reliverse/cli";
7+
export const cliDomain = "https://docs.reliverse.org";
78

89
export const useLocalhost = false;
910
export const isVerboseEnabled = false;

src/app/menu/create-project/cp-impl.ts

+4-61
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
confirmPrompt,
33
selectPrompt,
4-
spinnerTaskPrompt,
54
multiselectPrompt,
65
nextStepsPrompt,
76
inputPrompt,
@@ -14,17 +13,16 @@ import open from "open";
1413
import os from "os";
1514
import path from "pathe";
1615

16+
import type { ProjectConfigReturn } from "~/app/app-types.js";
1717
import type { Behavior, DeploymentService } from "~/types.js";
1818
import type { TemplateOption } from "~/utils/projectTemplate.js";
1919
import type { ReliverseConfig } from "~/utils/schemaConfig.js";
2020
import type { ReliverseMemory } from "~/utils/schemaMemory.js";
2121

2222
import { experimental, UNKNOWN_VALUE } from "~/app/constants.js";
2323
import { setupI18nFiles } from "~/app/menu/create-project/cp-modules/cli-main-modules/downloads/downloadI18nFiles.js";
24-
import { extractRepoInfo } from "~/app/menu/create-project/cp-modules/cli-main-modules/handlers/extractRepoInfo.js";
2524
import { isVSCodeInstalled } from "~/app/menu/create-project/cp-modules/cli-main-modules/handlers/isAppInstalled.js";
2625
import { promptPackageJsonScripts } from "~/app/menu/create-project/cp-modules/cli-main-modules/handlers/promptPackageJsonScripts.js";
27-
import { replaceStringsInFiles } from "~/app/menu/create-project/cp-modules/cli-main-modules/handlers/replaceStringsInFiles.js";
2826
import { askProjectName } from "~/app/menu/create-project/cp-modules/cli-main-modules/modules/askProjectName.js";
2927
import { askUserName } from "~/app/menu/create-project/cp-modules/cli-main-modules/modules/askUserName.js";
3028
import { promptGitDeploy } from "~/app/menu/create-project/cp-modules/git-deploy-prompts/gdp-mod.js";
@@ -41,15 +39,6 @@ export type PackageJson = {
4139
devDependencies?: Record<string, string>;
4240
};
4341

44-
/**
45-
* Minimal object describing essential project info after initialization
46-
*/
47-
export type ProjectConfig = {
48-
cliUsername: string;
49-
projectName: string;
50-
primaryDomain: string;
51-
};
52-
5342
/**
5443
* Ensures a unique project name by prompting for a new one if the target directory exists.
5544
*/
@@ -102,7 +91,7 @@ export async function initializeProjectConfig(
10291
skipPrompts: boolean,
10392
isDev: boolean,
10493
cwd: string,
105-
): Promise<ProjectConfig> {
94+
): Promise<ProjectConfigReturn> {
10695
// 1. Determine user (author)
10796
const cliUsername =
10897
skipPrompts &&
@@ -141,52 +130,6 @@ export async function initializeProjectConfig(
141130
return { cliUsername, projectName, primaryDomain };
142131
}
143132

144-
/**
145-
* Replaces placeholders in the downloaded template with user-specified values.
146-
*/
147-
export async function replaceTemplateStrings(
148-
projectPath: string,
149-
webProjectTemplate: TemplateOption,
150-
config: ProjectConfig,
151-
) {
152-
await spinnerTaskPrompt({
153-
spinnerSolution: "ora",
154-
initialMessage: "Editing texts in the initialized files...",
155-
successMessage: "✅ Finished editing texts in the initialized files.",
156-
errorMessage: "❌ Failed to edit some texts...",
157-
async action(updateMessage: (msg: string) => void) {
158-
const { author, projectName: oldProjectName } =
159-
extractRepoInfo(webProjectTemplate);
160-
updateMessage("Some magic is happening... Please wait...");
161-
162-
// Potential replacements
163-
const replacements: Record<string, string> = {
164-
[`${oldProjectName}.com`]: config.primaryDomain,
165-
[author]: config.cliUsername,
166-
[oldProjectName]: config.projectName,
167-
["relivator.com"]: config.primaryDomain,
168-
};
169-
170-
// Filter out empty or identical
171-
const validReplacements = Object.fromEntries(
172-
Object.entries(replacements).filter(
173-
([key, value]) => key && value && key !== value,
174-
),
175-
);
176-
177-
try {
178-
await replaceStringsInFiles(projectPath, validReplacements);
179-
} catch (error) {
180-
relinka(
181-
"error",
182-
"Failed to replace strings in files:",
183-
error instanceof Error ? error.message : String(error),
184-
);
185-
}
186-
},
187-
});
188-
}
189-
190133
/**
191134
* Sets up i18n if needed and not already present.
192135
* Uses config.i18nBehavior to determine automatic behavior.
@@ -402,7 +345,7 @@ export async function showSuccessAndNextSteps(
402345

403346
relinka(
404347
"info",
405-
`🎉 '${webProjectTemplate}' was installed at ${effectiveProjectPath}.`,
348+
`🎉 Template '${webProjectTemplate}' was installed at ${effectiveProjectPath}.`,
406349
);
407350

408351
const vscodeInstalled = isVSCodeInstalled();
@@ -515,7 +458,7 @@ export async function handleNextAction(
515458
relinka(
516459
"info",
517460
vscodeInstalled
518-
? "Opening project in VSCode-based IDE..."
461+
? "Opening bootstrapped project in VSCode-based IDE..."
519462
: "Trying to open project in default IDE...",
520463
);
521464
try {

src/app/menu/create-project/cp-mod.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import {
2020
getTemplateInfo,
2121
type Template,
2222
} from "~/utils/projectTemplate.js";
23+
import { replaceTemplateStrings } from "~/utils/replacements/reps-mod.js";
2324

2425
import {
2526
initializeProjectConfig,
2627
setupI18nSupport,
27-
replaceTemplateStrings,
2828
handleDeployment,
2929
handleDependencies,
3030
showSuccessAndNextSteps,

src/app/menu/create-project/cp-modules/cli-main-modules/configs/app.ts

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { getRepoUrl } from "~/app/constants.js";
44
import metadata from "~/app/menu/create-project/cp-modules/cli-main-modules/handlers/metadata.js";
55
import { productCategories } from "~/app/menu/create-project/cp-modules/cli-main-modules/handlers/products.js";
66

7+
// TODO: deprecate this file
8+
79
export function slugify(str: string) {
810
return str
911
.toLowerCase()

src/app/menu/create-project/cp-modules/cli-main-modules/detections/detectedProjectsMenu.ts

+1
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ export async function handleOpenProjectMenu(
359359
"",
360360
memory,
361361
shouldMaskSecretInput,
362+
"update",
362363
);
363364

364365
if (deployService !== "none") {

src/app/menu/create-project/cp-modules/cli-main-modules/handlers/extractRepoInfo.ts

-23
This file was deleted.

src/app/menu/create-project/cp-modules/cli-main-modules/handlers/generateProjectConfigs.ts

+38-18
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,23 @@ async function generateVSCodeSettings(
8181
const existingSettings = destr(content);
8282

8383
if (existingSettings && typeof existingSettings === "object") {
84-
const existingCodeActions =
85-
// @ts-expect-error TODO: fix ts
86-
existingSettings["editor.codeActionsOnSave"] ?? {};
84+
const defaultCodeActions: VSCodeSettings["editor.codeActionsOnSave"] = {
85+
"quickfix.biome": "explicit",
86+
"source.addMissingImports": "never",
87+
"source.fixAll.eslint": "explicit",
88+
"source.organizeImports": "never",
89+
"source.removeUnused": "never",
90+
};
91+
const existingCodeActions = {
92+
...defaultCodeActions,
93+
...((existingSettings as Record<string, unknown>)[
94+
"editor.codeActionsOnSave"
95+
] as typeof defaultCodeActions),
96+
};
8797
settings = {
8898
...defaultSettings,
8999
...existingSettings,
90-
"editor.codeActionsOnSave": {
91-
...existingCodeActions,
92-
"quickfix.biome": "explicit",
93-
"source.addMissingImports": "never",
94-
"source.fixAll.eslint": "explicit",
95-
"source.organizeImports": "never",
96-
"source.removeUnused": "never",
97-
},
100+
"editor.codeActionsOnSave": existingCodeActions,
98101
};
99102
}
100103
} catch (error) {
@@ -110,8 +113,8 @@ async function generateVSCodeSettings(
110113
relinka(
111114
"success-verbose",
112115
overwrite
113-
? "Generated new .vscode/settings.json"
114-
: "Updated .vscode/settings.json with required settings",
116+
? "Generated brand new VSCode settings.json file"
117+
: "Updated VSCode settings.json with required settings",
115118
);
116119
}
117120

@@ -134,7 +137,7 @@ export async function generateConfigFiles(
134137
: `Generating the following configuration files: ${filesToGenerate.join(", ")}...`,
135138
successMessage: "✅ Configuration files generated successfully!",
136139
errorMessage: "❌ Failed to generate configuration files",
137-
async action() {
140+
async action(updateMessage) {
138141
try {
139142
const shouldGenerateFile = (filename: string): boolean => {
140143
return (
@@ -176,7 +179,7 @@ export async function generateConfigFiles(
176179
const configPath = path.join(projectPath, ".reliverse");
177180
if (!overwrite && (await fs.pathExists(configPath))) {
178181
relinka("info", "Reliverse config already exists, skipping...");
179-
return;
182+
return false;
180183
}
181184

182185
// Write with proper formatting and comments
@@ -186,15 +189,32 @@ export async function generateConfigFiles(
186189
encoding: "utf-8",
187190
});
188191
relinka("success-verbose", "Generated .reliverse config");
192+
return true;
193+
},
194+
"biome.json": async () => {
195+
const result = await generateBiomeConfig(projectPath, overwrite);
196+
return result;
197+
},
198+
"settings.json": async () => {
199+
const result = await generateVSCodeSettings(projectPath, overwrite);
200+
return result;
189201
},
190-
"biome.json": () => generateBiomeConfig(projectPath, overwrite),
191-
"settings.json": () => generateVSCodeSettings(projectPath, overwrite),
192202
};
193203

204+
const generatedFiles: string[] = [];
194205
await Promise.all(
195206
Object.entries(configGenerators)
196207
.filter(([filename]) => shouldGenerateFile(filename))
197-
.map(([_, generator]) => generator()),
208+
.map(async ([filename, generator]) => {
209+
const wasGenerated = await generator();
210+
if (wasGenerated) {
211+
generatedFiles.push(filename);
212+
}
213+
}),
214+
);
215+
216+
updateMessage(
217+
`✅ Configuration files generated successfully: ${generatedFiles.join(", ")}`,
198218
);
199219
} catch (error) {
200220
relinka(

0 commit comments

Comments
 (0)