feat: add command (#337)

This commit is contained in:
Aman Varshney
2025-06-22 03:20:05 +05:30
committed by GitHub
parent 198d0e7434
commit 9c7a0f0110
29 changed files with 1015 additions and 255 deletions

View 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;
});
}

View 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) {}
}