@stdout-design/cli 0.2.3 → 0.2.5
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.
- package/dist/index.mjs +165 -3
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -4,10 +4,11 @@ import { Command } from "commander";
|
|
|
4
4
|
import { AppError, ErrorCode, importTemplateForBatch, loadConfig, openCache, runBatch, zodToJsonSchemaShape } from "@stdout-design/core";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { execSync, spawnSync } from "node:child_process";
|
|
7
|
-
import { existsSync } from "node:fs";
|
|
7
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
8
8
|
import { resolveCommand } from "package-manager-detector/commands";
|
|
9
9
|
import { detect } from "package-manager-detector/detect";
|
|
10
10
|
import { cp, mkdir, writeFile } from "node:fs/promises";
|
|
11
|
+
import { pathToFileURL } from "node:url";
|
|
11
12
|
//#region src/lib/display.ts
|
|
12
13
|
const formatBytes = (bytes) => {
|
|
13
14
|
if (bytes < 1024) return `${bytes} B`;
|
|
@@ -3221,6 +3222,24 @@ const getScaffoldVersion = () => {
|
|
|
3221
3222
|
};
|
|
3222
3223
|
//#endregion
|
|
3223
3224
|
//#region src/commands/init/scaffold.ts
|
|
3225
|
+
const getDefaults = () => ({
|
|
3226
|
+
defaultPreset: "instagram-square",
|
|
3227
|
+
presets: [{
|
|
3228
|
+
height: 1080,
|
|
3229
|
+
id: "instagram-square",
|
|
3230
|
+
platform: "instagram",
|
|
3231
|
+
width: 1080
|
|
3232
|
+
}, {
|
|
3233
|
+
height: 1200,
|
|
3234
|
+
id: "x-card",
|
|
3235
|
+
platform: "x",
|
|
3236
|
+
width: 1200
|
|
3237
|
+
}],
|
|
3238
|
+
templates: { "bento-feature": {
|
|
3239
|
+
componentPath: "./templates/bento-feature",
|
|
3240
|
+
description: "Apple-style bento feature card."
|
|
3241
|
+
} }
|
|
3242
|
+
});
|
|
3224
3243
|
const getConfigTemplate = (version) => `import type { StudioConfig } from "@stdout-design/cli";
|
|
3225
3244
|
|
|
3226
3245
|
const config: StudioConfig = {
|
|
@@ -3505,6 +3524,146 @@ const render = async (templateId, propArgs, options) => {
|
|
|
3505
3524
|
if (manifest.failed.length > 0) process.exit(1);
|
|
3506
3525
|
};
|
|
3507
3526
|
//#endregion
|
|
3527
|
+
//#region src/commands/init/deps.ts
|
|
3528
|
+
const updatePackageJsonDeps = (contents, currentVersion) => {
|
|
3529
|
+
const pkg = JSON.parse(contents);
|
|
3530
|
+
const deps = pkg.dependencies ??= {};
|
|
3531
|
+
const currentRange = `^${currentVersion}`;
|
|
3532
|
+
if (deps["@stdout-design/cli"] === currentRange) return {
|
|
3533
|
+
changed: false,
|
|
3534
|
+
updated: contents
|
|
3535
|
+
};
|
|
3536
|
+
deps["@stdout-design/cli"] = currentRange;
|
|
3537
|
+
return {
|
|
3538
|
+
changed: true,
|
|
3539
|
+
updated: JSON.stringify(pkg, null, 2)
|
|
3540
|
+
};
|
|
3541
|
+
};
|
|
3542
|
+
//#endregion
|
|
3543
|
+
//#region src/commands/init/merge-config.ts
|
|
3544
|
+
const mergePresets = (existing, defaults, deprecatedPresetIds) => {
|
|
3545
|
+
const existingIds = new Set(existing.presets.map((p) => p.id));
|
|
3546
|
+
const addedPresets = [];
|
|
3547
|
+
const presets = [...existing.presets];
|
|
3548
|
+
for (const defaultPreset of defaults.presets) if (!existingIds.has(defaultPreset.id)) {
|
|
3549
|
+
const marked = deprecatedPresetIds.has(defaultPreset.id) ? {
|
|
3550
|
+
...defaultPreset,
|
|
3551
|
+
deprecated: true
|
|
3552
|
+
} : { ...defaultPreset };
|
|
3553
|
+
presets.push(marked);
|
|
3554
|
+
addedPresets.push(defaultPreset.id);
|
|
3555
|
+
}
|
|
3556
|
+
const presetsWithDeprecation = presets.map((p) => deprecatedPresetIds.has(p.id) && !p.deprecated ? {
|
|
3557
|
+
...p,
|
|
3558
|
+
deprecated: true
|
|
3559
|
+
} : p);
|
|
3560
|
+
return {
|
|
3561
|
+
addedPresets,
|
|
3562
|
+
deprecatedPresets: [...new Set(presetsWithDeprecation.filter((p) => p.deprecated).map((p) => p.id))],
|
|
3563
|
+
presets: presetsWithDeprecation
|
|
3564
|
+
};
|
|
3565
|
+
};
|
|
3566
|
+
const mergeTemplates = (existing, defaults) => {
|
|
3567
|
+
const addedTemplates = [];
|
|
3568
|
+
const templates = { ...existing.templates };
|
|
3569
|
+
for (const [key, template] of Object.entries(defaults.templates)) if (!(key in templates)) {
|
|
3570
|
+
templates[key] = { ...template };
|
|
3571
|
+
addedTemplates.push(key);
|
|
3572
|
+
}
|
|
3573
|
+
return {
|
|
3574
|
+
addedTemplates,
|
|
3575
|
+
templates
|
|
3576
|
+
};
|
|
3577
|
+
};
|
|
3578
|
+
const resolveDefaultPreset = (presets, existing, defaults) => {
|
|
3579
|
+
const mergedIds = new Set(presets.map((p) => p.id));
|
|
3580
|
+
const current = existing.defaultPreset;
|
|
3581
|
+
if (current && mergedIds.has(current)) return current;
|
|
3582
|
+
return defaults.defaultPreset ?? defaults.presets[0]?.id;
|
|
3583
|
+
};
|
|
3584
|
+
const mergeConfig = (existing, defaults, currentVersion, deprecatedPresetIds) => {
|
|
3585
|
+
const oldVersion = existing.scaffoldVersion ?? null;
|
|
3586
|
+
const { presets, addedPresets, deprecatedPresets } = mergePresets(existing, defaults, deprecatedPresetIds);
|
|
3587
|
+
const { templates, addedTemplates } = mergeTemplates(existing, defaults);
|
|
3588
|
+
return {
|
|
3589
|
+
config: {
|
|
3590
|
+
...existing,
|
|
3591
|
+
defaultPreset: resolveDefaultPreset(presets, existing, defaults),
|
|
3592
|
+
presets,
|
|
3593
|
+
scaffoldVersion: currentVersion,
|
|
3594
|
+
templates
|
|
3595
|
+
},
|
|
3596
|
+
summary: {
|
|
3597
|
+
addedPresets,
|
|
3598
|
+
addedTemplates,
|
|
3599
|
+
deprecatedPresets,
|
|
3600
|
+
newVersion: currentVersion,
|
|
3601
|
+
oldVersion
|
|
3602
|
+
}
|
|
3603
|
+
};
|
|
3604
|
+
};
|
|
3605
|
+
//#endregion
|
|
3606
|
+
//#region src/commands/update.ts
|
|
3607
|
+
const DEPRECATED_PRESET_IDS = /* @__PURE__ */ new Set();
|
|
3608
|
+
const serializeConfig = (config) => `import type { StudioConfig } from "@stdout-design/cli";
|
|
3609
|
+
|
|
3610
|
+
const config: StudioConfig = ${JSON.stringify(config, null, 2)};
|
|
3611
|
+
|
|
3612
|
+
export default config;
|
|
3613
|
+
`;
|
|
3614
|
+
const update = async (projectDir, options) => {
|
|
3615
|
+
const cwd = process.cwd();
|
|
3616
|
+
const dir = path.resolve(cwd, projectDir ?? ".");
|
|
3617
|
+
const configPath = path.resolve(dir, "studio.config.ts");
|
|
3618
|
+
if (!existsSync(configPath)) throw new Error("No studio project found. Run `studio init` first.");
|
|
3619
|
+
const existingModule = await import(pathToFileURL(configPath).href);
|
|
3620
|
+
const existing = existingModule.default ?? existingModule;
|
|
3621
|
+
const existingConfig = {
|
|
3622
|
+
defaultPreset: existing.defaultPreset,
|
|
3623
|
+
outDir: existing.outDir,
|
|
3624
|
+
presets: existing.presets ?? [],
|
|
3625
|
+
scaffoldVersion: existing.scaffoldVersion,
|
|
3626
|
+
templates: existing.templates ?? {}
|
|
3627
|
+
};
|
|
3628
|
+
const defaults = getDefaults();
|
|
3629
|
+
const currentVersion = getScaffoldVersion();
|
|
3630
|
+
const { config: merged, summary } = mergeConfig(existingConfig, defaults, currentVersion, DEPRECATED_PRESET_IDS);
|
|
3631
|
+
const { intro, outro, confirm } = await import("@clack/prompts");
|
|
3632
|
+
intro("studio update");
|
|
3633
|
+
if (!(summary.addedPresets.length > 0 || summary.deprecatedPresets.length > 0 || summary.addedTemplates.length > 0 || summary.oldVersion !== summary.newVersion)) {
|
|
3634
|
+
console.log("Project is already up to date.");
|
|
3635
|
+
outro("Done");
|
|
3636
|
+
return;
|
|
3637
|
+
}
|
|
3638
|
+
console.log("");
|
|
3639
|
+
if (summary.oldVersion !== summary.newVersion) console.log(` scaffoldVersion ${summary.oldVersion ?? "(none)"} -> ${summary.newVersion}`);
|
|
3640
|
+
for (const id of summary.addedPresets) console.log(` presets +${id}`);
|
|
3641
|
+
for (const id of summary.deprecatedPresets) console.log(` presets ! ${id} (deprecated)`);
|
|
3642
|
+
for (const id of summary.addedTemplates) console.log(` templates +${id}`);
|
|
3643
|
+
console.log(" assets tsconfig.json, .gitignore, types.d.ts (overwrite)");
|
|
3644
|
+
console.log(` deps @stdout-design/cli ^x -> ^${currentVersion}`);
|
|
3645
|
+
console.log("");
|
|
3646
|
+
if (!options?.yes) {
|
|
3647
|
+
if (!await confirm({
|
|
3648
|
+
initialValue: true,
|
|
3649
|
+
message: "Apply these changes?"
|
|
3650
|
+
})) {
|
|
3651
|
+
console.log("Cancelled.");
|
|
3652
|
+
outro("Done");
|
|
3653
|
+
return;
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
await writeFile(configPath, serializeConfig(merged));
|
|
3657
|
+
await copyStaticAssets(dir);
|
|
3658
|
+
const pkgPath = path.resolve(dir, "package.json");
|
|
3659
|
+
if (existsSync(pkgPath)) {
|
|
3660
|
+
const { updated, changed } = updatePackageJsonDeps(readFileSync(pkgPath, "utf-8"), currentVersion);
|
|
3661
|
+
if (changed) await writeFile(pkgPath, updated);
|
|
3662
|
+
}
|
|
3663
|
+
console.log("");
|
|
3664
|
+
outro("Done");
|
|
3665
|
+
};
|
|
3666
|
+
//#endregion
|
|
3508
3667
|
//#region src/lib/runner.ts
|
|
3509
3668
|
const handlers = {
|
|
3510
3669
|
cache: cacheStats,
|
|
@@ -3513,7 +3672,8 @@ const handlers = {
|
|
|
3513
3672
|
dev,
|
|
3514
3673
|
init,
|
|
3515
3674
|
lint,
|
|
3516
|
-
render
|
|
3675
|
+
render,
|
|
3676
|
+
update
|
|
3517
3677
|
};
|
|
3518
3678
|
const run = (moduleName, handlerName) => async (...args) => {
|
|
3519
3679
|
try {
|
|
@@ -3527,8 +3687,9 @@ const run = (moduleName, handlerName) => async (...args) => {
|
|
|
3527
3687
|
};
|
|
3528
3688
|
//#endregion
|
|
3529
3689
|
//#region src/index.ts
|
|
3690
|
+
const pkg = createRequire(import.meta.url)("../package.json");
|
|
3530
3691
|
const program = new Command().allowExcessArguments(true);
|
|
3531
|
-
program.name("studio").description("Social media design tool — render, preview, batch").version(
|
|
3692
|
+
program.name("studio").description("Social media design tool — render, preview, batch").version(pkg.version, "-v, -V, --version");
|
|
3532
3693
|
program.command("dev").description("Start the studio dev server with live preview").argument("[rootDir]", "Project root directory (default: cwd)").option("-p, --port <number>", "Port to run on", "3000").option("--open", "Open browser on start").action(run("dev"));
|
|
3533
3694
|
program.command("render").description("Render a template — single or batch with --data").argument("<template>", "Template ID from studio.config.ts").argument("[props...]", "Props as key=value pairs (e.g. title=\"Hello\")").option("--data <path>", "CSV or JSON data file for batch rendering").option("--preset <ids>", "Comma-separated preset IDs").option("--locale <locales>", "Comma-separated locale codes").option("--out-dir <path>", "Output directory").option("--concurrency <n>", "Max concurrent renders in batch mode", "4").option("--fail-fast", "Stop batch on first error").option("--json", "Output results as JSON").action(run("render"));
|
|
3534
3695
|
const cacheCmd = program.command("cache").description("Manage the render cache");
|
|
@@ -3536,6 +3697,7 @@ cacheCmd.command("stats").description("Show cache statistics").option("--json",
|
|
|
3536
3697
|
cacheCmd.command("clean").description("Clear the render cache").option("--json", "Output as JSON").argument("[rootDir]", "Project root directory (default: cwd)").action(run("cache", "cacheClean"));
|
|
3537
3698
|
program.command("lint").description("Check templates for compatibility (coming soon)").argument("[rootDir]", "Project root directory (default: cwd)").action(run("lint"));
|
|
3538
3699
|
program.command("init").description("Scaffold a new studio project").argument("[projectDir]", "Project directory (default: cwd)").option("-y, --yes", "Skip prompts, use defaults").action(run("init"));
|
|
3700
|
+
program.command("update").description("Update an existing studio project to the latest CLI version").argument("[projectDir]", "Project directory (default: cwd)").option("-y, --yes", "Skip confirmation prompts").action(run("update"));
|
|
3539
3701
|
program.parse();
|
|
3540
3702
|
//#endregion
|
|
3541
3703
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stdout-design/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "stdout-design CLI — shallow front door to @stdout-design/core and @stdout-design/dev-server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"package-manager-detector": "^1.8.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@stdout-design/config": "
|
|
65
|
+
"@stdout-design/config": "workspace:*",
|
|
66
66
|
"tsdown": "^0.22.5",
|
|
67
67
|
"typescript": "^7.0.2"
|
|
68
68
|
},
|