@stdout-design/cli 0.2.2 → 0.2.4

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.
Files changed (2) hide show
  1. package/dist/index.mjs +170 -7
  2. 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 = {
@@ -3242,18 +3261,20 @@ const config: StudioConfig = {
3242
3261
  export default config;
3243
3262
  `;
3244
3263
  const getPkgJson = (name, version) => ({
3245
- dependencies: {
3246
- "@stdout-design/cli": `^${version}`,
3247
- "@types/react": "^19.2.17"
3248
- },
3249
3264
  name,
3250
3265
  private: true,
3266
+ type: "module",
3251
3267
  scripts: {
3252
3268
  build: "studio build",
3253
3269
  dev: "studio dev",
3254
3270
  export: "studio export"
3255
3271
  },
3256
- type: "module"
3272
+ dependencies: {
3273
+ "@stdout-design/cli": `^${version}`,
3274
+ "@stdout-design/dev-server": "^0.2.0",
3275
+ "@stdout-design/web-ui": "^0.2.0",
3276
+ "@types/react": "^19.2.17"
3277
+ }
3257
3278
  });
3258
3279
  const resolveTemplateDir = () => {
3259
3280
  const fromDist = path.resolve(import.meta.dirname, "../template");
@@ -3503,6 +3524,146 @@ const render = async (templateId, propArgs, options) => {
3503
3524
  if (manifest.failed.length > 0) process.exit(1);
3504
3525
  };
3505
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
3506
3667
  //#region src/lib/runner.ts
3507
3668
  const handlers = {
3508
3669
  cache: cacheStats,
@@ -3511,7 +3672,8 @@ const handlers = {
3511
3672
  dev,
3512
3673
  init,
3513
3674
  lint,
3514
- render
3675
+ render,
3676
+ update
3515
3677
  };
3516
3678
  const run = (moduleName, handlerName) => async (...args) => {
3517
3679
  try {
@@ -3534,6 +3696,7 @@ cacheCmd.command("stats").description("Show cache statistics").option("--json",
3534
3696
  cacheCmd.command("clean").description("Clear the render cache").option("--json", "Output as JSON").argument("[rootDir]", "Project root directory (default: cwd)").action(run("cache", "cacheClean"));
3535
3697
  program.command("lint").description("Check templates for compatibility (coming soon)").argument("[rootDir]", "Project root directory (default: cwd)").action(run("lint"));
3536
3698
  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"));
3699
+ 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"));
3537
3700
  program.parse();
3538
3701
  //#endregion
3539
3702
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stdout-design/cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
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": "0.0.0",
65
+ "@stdout-design/config": "workspace:*",
66
66
  "tsdown": "^0.22.5",
67
67
  "typescript": "^7.0.2"
68
68
  },