mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
feat: add command (#337)
This commit is contained in:
42
apps/cli/src/utils/addon-compatibility.ts
Normal file
42
apps/cli/src/utils/addon-compatibility.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { ADDON_COMPATIBILITY } from "../constants";
|
||||
import type { Addons, Frontend } from "../types";
|
||||
|
||||
export function validateAddonCompatibility(
|
||||
addon: Addons,
|
||||
frontend: Frontend[],
|
||||
): { isCompatible: boolean; reason?: string } {
|
||||
const compatibleFrontends = ADDON_COMPATIBILITY[addon];
|
||||
|
||||
if (compatibleFrontends.length === 0) {
|
||||
return { isCompatible: true };
|
||||
}
|
||||
|
||||
const hasCompatibleFrontend = frontend.some((f) =>
|
||||
(compatibleFrontends as readonly string[]).includes(f),
|
||||
);
|
||||
|
||||
if (!hasCompatibleFrontend) {
|
||||
const frontendList = compatibleFrontends.join(", ");
|
||||
return {
|
||||
isCompatible: false,
|
||||
reason: `${addon} addon requires one of these frontends: ${frontendList}`,
|
||||
};
|
||||
}
|
||||
|
||||
return { isCompatible: true };
|
||||
}
|
||||
|
||||
export function getCompatibleAddons(
|
||||
allAddons: Addons[],
|
||||
frontend: Frontend[],
|
||||
existingAddons: Addons[] = [],
|
||||
): Addons[] {
|
||||
return allAddons.filter((addon) => {
|
||||
if (existingAddons.includes(addon)) return false;
|
||||
|
||||
if (addon === "none") return false;
|
||||
|
||||
const { isCompatible } = validateAddonCompatibility(addon, frontend);
|
||||
return isCompatible;
|
||||
});
|
||||
}
|
||||
120
apps/cli/src/utils/bts-config.ts
Normal file
120
apps/cli/src/utils/bts-config.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import path from "node:path";
|
||||
import fs from "fs-extra";
|
||||
import * as JSONC from "jsonc-parser";
|
||||
import type { BetterTStackConfig, ProjectConfig } from "../types";
|
||||
import { getLatestCLIVersion } from "./get-latest-cli-version";
|
||||
|
||||
const BTS_CONFIG_FILE = "bts.jsonc";
|
||||
|
||||
export async function writeBtsConfig(
|
||||
projectConfig: ProjectConfig,
|
||||
): Promise<void> {
|
||||
const btsConfig: BetterTStackConfig = {
|
||||
version: getLatestCLIVersion(),
|
||||
createdAt: new Date().toISOString(),
|
||||
database: projectConfig.database,
|
||||
orm: projectConfig.orm,
|
||||
backend: projectConfig.backend,
|
||||
runtime: projectConfig.runtime,
|
||||
frontend: projectConfig.frontend,
|
||||
addons: projectConfig.addons,
|
||||
examples: projectConfig.examples,
|
||||
auth: projectConfig.auth,
|
||||
packageManager: projectConfig.packageManager,
|
||||
dbSetup: projectConfig.dbSetup,
|
||||
api: projectConfig.api,
|
||||
};
|
||||
|
||||
const baseContent = {
|
||||
$schema: "https://better-t-stack.dev/schema.json",
|
||||
version: btsConfig.version,
|
||||
createdAt: btsConfig.createdAt,
|
||||
database: btsConfig.database,
|
||||
orm: btsConfig.orm,
|
||||
backend: btsConfig.backend,
|
||||
runtime: btsConfig.runtime,
|
||||
frontend: btsConfig.frontend,
|
||||
addons: btsConfig.addons,
|
||||
examples: btsConfig.examples,
|
||||
auth: btsConfig.auth,
|
||||
packageManager: btsConfig.packageManager,
|
||||
dbSetup: btsConfig.dbSetup,
|
||||
api: btsConfig.api,
|
||||
};
|
||||
|
||||
let configContent = JSON.stringify(baseContent);
|
||||
|
||||
const formatResult = JSONC.format(configContent, undefined, {
|
||||
tabSize: 2,
|
||||
insertSpaces: true,
|
||||
eol: "\n",
|
||||
});
|
||||
|
||||
configContent = JSONC.applyEdits(configContent, formatResult);
|
||||
|
||||
const finalContent = `// Better-T-Stack configuration file
|
||||
// safe to delete
|
||||
|
||||
${configContent}`;
|
||||
const configPath = path.join(projectConfig.projectDir, BTS_CONFIG_FILE);
|
||||
await fs.writeFile(configPath, finalContent, "utf-8");
|
||||
}
|
||||
|
||||
export async function readBtsConfig(
|
||||
projectDir: string,
|
||||
): Promise<BetterTStackConfig | null> {
|
||||
try {
|
||||
const configPath = path.join(projectDir, BTS_CONFIG_FILE);
|
||||
|
||||
if (!(await fs.pathExists(configPath))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const configContent = await fs.readFile(configPath, "utf-8");
|
||||
|
||||
const errors: JSONC.ParseError[] = [];
|
||||
const config = JSONC.parse(configContent, errors, {
|
||||
allowTrailingComma: true,
|
||||
disallowComments: false,
|
||||
}) as BetterTStackConfig;
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.warn("Warning: Found errors parsing bts.jsonc:", errors);
|
||||
return null;
|
||||
}
|
||||
|
||||
return config;
|
||||
} catch (_error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateBtsConfig(
|
||||
projectDir: string,
|
||||
updates: Partial<Pick<BetterTStackConfig, "addons">>,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const configPath = path.join(projectDir, BTS_CONFIG_FILE);
|
||||
|
||||
if (!(await fs.pathExists(configPath))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const configContent = await fs.readFile(configPath, "utf-8");
|
||||
|
||||
let modifiedContent = configContent;
|
||||
|
||||
for (const [key, value] of Object.entries(updates)) {
|
||||
const editResult = JSONC.modify(modifiedContent, [key], value, {
|
||||
formattingOptions: {
|
||||
tabSize: 2,
|
||||
insertSpaces: true,
|
||||
eol: "\n",
|
||||
},
|
||||
});
|
||||
modifiedContent = JSONC.applyEdits(modifiedContent, editResult);
|
||||
}
|
||||
|
||||
await fs.writeFile(configPath, modifiedContent, "utf-8");
|
||||
} catch (_error) {}
|
||||
}
|
||||
Reference in New Issue
Block a user