Skip to content

Commit

Permalink
fix env composer and strings replacer
Browse files Browse the repository at this point in the history
  • Loading branch information
blefnk committed Jan 19, 2025
1 parent 545147e commit 865088c
Show file tree
Hide file tree
Showing 37 changed files with 1,219 additions and 653 deletions.
2 changes: 1 addition & 1 deletion .reliverse
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"projectName": "@reliverse/cli",
"projectAuthor": "blefnk",
"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.",
"projectVersion": "1.4.28",
"projectVersion": "1.4.29",
"projectLicense": "MIT",
"projectRepository": "https://github.com/reliverse/cli",
"projectState": "creating",
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Reliverse CLI

**📚 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)
**✨ NPM**: [npmjs.com/@reliverse/cli](https://npmjs.com/@reliverse/cli)
**💙 Discord**: [discord.gg/Pb8uKbwpsJ](https://discord.gg/Pb8uKbwpsJ)
**⭐ GitHub**: [github.com/reliverse/cli](https://github.com/reliverse/cli)
**📚 Docs**: [docs.reliverse.org](https://docs.reliverse.org/cli)

@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.

Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion jsr.jsonc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reliverse/cli",
"version": "1.4.29",
"version": "1.4.30",
"author": "blefnk",
"license": "MIT",
"exports": "./dist-jsr/main.ts",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reliverse/cli",
"version": "1.4.29",
"version": "1.4.30",
"author": "reliverse",
"type": "module",
"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.",
Expand Down Expand Up @@ -81,6 +81,7 @@
"detect-package-manager": "^3.0.2",
"dotenv": "^16.4.7",
"drizzle-orm": "^0.38.3",
"escape-string-regexp": "^5.0.0",
"execa": "^9.5.2",
"fs-extra": "^11.2.0",
"geist": "^1.3.1",
Expand Down
9 changes: 9 additions & 0 deletions src/app/app-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@ export type AppParams = {
export type ParamsOmitPN = Omit<AppParams, "projectName">;
export type ParamsOmitSkipPN = Omit<AppParams, "skipPrompts" | "projectName">;
export type ParamsOmitReli = Omit<AppParams, "reli">;

/**
* Minimal object describing essential project info after initialization
*/
export type ProjectConfigReturn = {
cliUsername: string;
projectName: string;
primaryDomain: string;
};
3 changes: 2 additions & 1 deletion src/app/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import path from "pathe";
import pc from "picocolors";
import { fileURLToPath } from "url";

export const cliVersion = "1.4.29";
export const cliVersion = "1.4.30";
export const cliName = "@reliverse/cli";
export const cliDomain = "https://docs.reliverse.org";

export const useLocalhost = false;
export const isVerboseEnabled = false;
Expand Down
65 changes: 4 additions & 61 deletions src/app/menu/create-project/cp-impl.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
confirmPrompt,
selectPrompt,
spinnerTaskPrompt,
multiselectPrompt,
nextStepsPrompt,
inputPrompt,
Expand All @@ -14,17 +13,16 @@ import open from "open";
import os from "os";
import path from "pathe";

import type { ProjectConfigReturn } from "~/app/app-types.js";
import type { Behavior, DeploymentService } from "~/types.js";
import type { TemplateOption } from "~/utils/projectTemplate.js";
import type { ReliverseConfig } from "~/utils/schemaConfig.js";
import type { ReliverseMemory } from "~/utils/schemaMemory.js";

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

/**
* Minimal object describing essential project info after initialization
*/
export type ProjectConfig = {
cliUsername: string;
projectName: string;
primaryDomain: string;
};

/**
* Ensures a unique project name by prompting for a new one if the target directory exists.
*/
Expand Down Expand Up @@ -102,7 +91,7 @@ export async function initializeProjectConfig(
skipPrompts: boolean,
isDev: boolean,
cwd: string,
): Promise<ProjectConfig> {
): Promise<ProjectConfigReturn> {
// 1. Determine user (author)
const cliUsername =
skipPrompts &&
Expand Down Expand Up @@ -141,52 +130,6 @@ export async function initializeProjectConfig(
return { cliUsername, projectName, primaryDomain };
}

/**
* Replaces placeholders in the downloaded template with user-specified values.
*/
export async function replaceTemplateStrings(
projectPath: string,
webProjectTemplate: TemplateOption,
config: ProjectConfig,
) {
await spinnerTaskPrompt({
spinnerSolution: "ora",
initialMessage: "Editing texts in the initialized files...",
successMessage: "✅ Finished editing texts in the initialized files.",
errorMessage: "❌ Failed to edit some texts...",
async action(updateMessage: (msg: string) => void) {
const { author, projectName: oldProjectName } =
extractRepoInfo(webProjectTemplate);
updateMessage("Some magic is happening... Please wait...");

// Potential replacements
const replacements: Record<string, string> = {
[`${oldProjectName}.com`]: config.primaryDomain,
[author]: config.cliUsername,
[oldProjectName]: config.projectName,
["relivator.com"]: config.primaryDomain,
};

// Filter out empty or identical
const validReplacements = Object.fromEntries(
Object.entries(replacements).filter(
([key, value]) => key && value && key !== value,
),
);

try {
await replaceStringsInFiles(projectPath, validReplacements);
} catch (error) {
relinka(
"error",
"Failed to replace strings in files:",
error instanceof Error ? error.message : String(error),
);
}
},
});
}

/**
* Sets up i18n if needed and not already present.
* Uses config.i18nBehavior to determine automatic behavior.
Expand Down Expand Up @@ -402,7 +345,7 @@ export async function showSuccessAndNextSteps(

relinka(
"info",
`🎉 '${webProjectTemplate}' was installed at ${effectiveProjectPath}.`,
`🎉 Template '${webProjectTemplate}' was installed at ${effectiveProjectPath}.`,
);

const vscodeInstalled = isVSCodeInstalled();
Expand Down Expand Up @@ -515,7 +458,7 @@ export async function handleNextAction(
relinka(
"info",
vscodeInstalled
? "Opening project in VSCode-based IDE..."
? "Opening bootstrapped project in VSCode-based IDE..."
: "Trying to open project in default IDE...",
);
try {
Expand Down
2 changes: 1 addition & 1 deletion src/app/menu/create-project/cp-mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import {
getTemplateInfo,
type Template,
} from "~/utils/projectTemplate.js";
import { replaceTemplateStrings } from "~/utils/replacements/reps-mod.js";

import {
initializeProjectConfig,
setupI18nSupport,
replaceTemplateStrings,
handleDeployment,
handleDependencies,
showSuccessAndNextSteps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { getRepoUrl } from "~/app/constants.js";
import metadata from "~/app/menu/create-project/cp-modules/cli-main-modules/handlers/metadata.js";
import { productCategories } from "~/app/menu/create-project/cp-modules/cli-main-modules/handlers/products.js";

// TODO: deprecate this file

export function slugify(str: string) {
return str
.toLowerCase()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ export async function handleOpenProjectMenu(
"",
memory,
shouldMaskSecretInput,
"update",
);

if (deployService !== "none") {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,23 @@ async function generateVSCodeSettings(
const existingSettings = destr(content);

if (existingSettings && typeof existingSettings === "object") {
const existingCodeActions =
// @ts-expect-error TODO: fix ts
existingSettings["editor.codeActionsOnSave"] ?? {};
const defaultCodeActions: VSCodeSettings["editor.codeActionsOnSave"] = {
"quickfix.biome": "explicit",
"source.addMissingImports": "never",
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never",
"source.removeUnused": "never",
};
const existingCodeActions = {
...defaultCodeActions,
...((existingSettings as Record<string, unknown>)[
"editor.codeActionsOnSave"
] as typeof defaultCodeActions),
};
settings = {
...defaultSettings,
...existingSettings,
"editor.codeActionsOnSave": {
...existingCodeActions,
"quickfix.biome": "explicit",
"source.addMissingImports": "never",
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never",
"source.removeUnused": "never",
},
"editor.codeActionsOnSave": existingCodeActions,
};
}
} catch (error) {
Expand All @@ -110,8 +113,8 @@ async function generateVSCodeSettings(
relinka(
"success-verbose",
overwrite
? "Generated new .vscode/settings.json"
: "Updated .vscode/settings.json with required settings",
? "Generated brand new VSCode settings.json file"
: "Updated VSCode settings.json with required settings",
);
}

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

// Write with proper formatting and comments
Expand All @@ -186,15 +189,32 @@ export async function generateConfigFiles(
encoding: "utf-8",
});
relinka("success-verbose", "Generated .reliverse config");
return true;
},
"biome.json": async () => {
const result = await generateBiomeConfig(projectPath, overwrite);
return result;
},
"settings.json": async () => {
const result = await generateVSCodeSettings(projectPath, overwrite);
return result;
},
"biome.json": () => generateBiomeConfig(projectPath, overwrite),
"settings.json": () => generateVSCodeSettings(projectPath, overwrite),
};

const generatedFiles: string[] = [];
await Promise.all(
Object.entries(configGenerators)
.filter(([filename]) => shouldGenerateFile(filename))
.map(([_, generator]) => generator()),
.map(async ([filename, generator]) => {
const wasGenerated = await generator();
if (wasGenerated) {
generatedFiles.push(filename);
}
}),
);

updateMessage(
`✅ Configuration files generated successfully: ${generatedFiles.join(", ")}`,
);
} catch (error) {
relinka(
Expand Down
Loading

0 comments on commit 865088c

Please sign in to comment.