create-shibumi 0.2.0 → 0.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-shibumi",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Scaffold a Shibumi Stack project: Bun, Hono, Zod, Drizzle, SQLite, Alpine",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,5 +18,5 @@
18
18
  "version": "1.0.1"
19
19
  }
20
20
  ],
21
- "sha256": "0b62997fb6c813bc77f6e84030158a060454bfd4926d43d8c926e74969f7777c"
21
+ "sha256": "10386d9e6db61626780e85ef6bcc423e88402606b8ce9baa2c222e61cd32f134"
22
22
  }
@@ -506,21 +506,22 @@ interface CliIo {
506
506
  out: (line: string) => void;
507
507
  err: (line: string) => void;
508
508
  confirm: (message: string) => Promise<boolean>;
509
+ // Optional branded emitters; interactive runs wire these to clack so the
510
+ // installer looks like create and ship. Plain io (tests, pipes) omits them.
511
+ title?: (line: string) => void;
512
+ success?: (line: string) => void;
509
513
  }
510
514
 
511
515
  function previewAdd(ext: ExtensionBundle, plan: AddPlan, io: CliIo): void {
512
- io.out(`shibumi add ${ext.name}: ${ext.description}`);
513
- io.out("");
514
- io.out("New files:");
515
- for (const file of plan.files) {
516
- io.out(` ${file.to}${plan.conflicts.includes(file.to) ? " (exists: conflict)" : ""}`);
517
- }
518
- io.out(` ${join("agents", `${ext.name}.md`)}`);
516
+ (io.title ?? io.out)(`shibumi add ${ext.name}: ${ext.description}`);
517
+ if (!io.title) io.out("");
518
+ io.out([
519
+ "New files:",
520
+ ...plan.files.map((file) => ` ${file.to}${plan.conflicts.includes(file.to) ? " (exists: conflict)" : ""}`),
521
+ ` ${join("agents", `${ext.name}.md`)}`,
522
+ ].join("\n"));
519
523
  if (plan.edits.length > 0) {
520
- io.out("Edits:");
521
- for (const edit of plan.edits) {
522
- io.out(` ${edit.file}: ${edit.kind} at "${edit.find.trim().slice(0, 60)}"`);
523
- }
524
+ io.out(["Edits:", ...plan.edits.map((edit) => ` ${edit.file}: ${edit.kind} at "${edit.find.trim().slice(0, 60)}"`)].join("\n"));
524
525
  }
525
526
  if (plan.migrationName) io.out(`Migration:\n ${join(MIGRATIONS_DIR, plan.migrationName)}`);
526
527
  const deps = Object.entries(plan.deps);
@@ -529,12 +530,12 @@ function previewAdd(ext: ExtensionBundle, plan: AddPlan, io: CliIo): void {
529
530
  }
530
531
  if (plan.env.length > 0) io.out(`Environment variables (values stay out of code):\n ${plan.env.join(", ")}`);
531
532
  io.out(`agents.md:\n + section for ${ext.name} (guide at agents/${ext.name}.md)`);
532
- io.out("");
533
+ if (!io.title) io.out("");
533
534
  }
534
535
 
535
536
  function previewRemove(ext: ExtensionBundle, plan: RemovePlan, io: CliIo): void {
536
- io.out(`shibumi remove ${ext.name}`);
537
- io.out("");
537
+ (io.title ?? io.out)(`shibumi remove ${ext.name}`);
538
+ if (!io.title) io.out("");
538
539
  if (plan.deletions.length > 0) io.out(`Delete:\n${plan.deletions.map((file) => ` ${file}`).join("\n")}`);
539
540
  if (plan.modified.length > 0) {
540
541
  io.out(`Modified since install (kept without --force):\n${plan.modified.map((file) => ` ${file}`).join("\n")}`);
@@ -553,7 +554,7 @@ function previewRemove(ext: ExtensionBundle, plan: RemovePlan, io: CliIo): void
553
554
  }
554
555
  io.out("Tables are never dropped by tooling.");
555
556
  if (ext.removeNote) io.out(ext.removeNote);
556
- io.out("");
557
+ if (!io.title) io.out("");
557
558
  }
558
559
 
559
560
  async function defaultConfirm(message: string): Promise<boolean> {
@@ -750,7 +751,7 @@ export async function runCli(
750
751
  );
751
752
  return 1;
752
753
  }
753
- io.out(`${ext.title} installed. Run: bun test && bun run check`);
754
+ (io.success ?? io.out)(`${ext.title} installed. Run: bun test && bun run check`);
754
755
  if (Object.keys(fresh.plan.deps).length > 0) io.out("Dependencies were added; run: bun install");
755
756
  return 0;
756
757
  }
@@ -800,10 +801,31 @@ export async function runCli(
800
801
  );
801
802
  return 1;
802
803
  }
803
- io.out(`${ext.title} removed. Tables (if any) were kept; see the note above.`);
804
+ (io.success ?? io.out)(`${ext.title} removed. Tables (if any) were kept; see the note above.`);
804
805
  return 0;
805
806
  }
806
807
 
807
808
  if (import.meta.main) {
808
- process.exit(await runCli(process.argv.slice(2), process.cwd()));
809
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
810
+ const color = interactive && !("NO_COLOR" in process.env) && process.env.TERM !== "dumb";
811
+ if (!color) {
812
+ process.exit(await runCli(process.argv.slice(2), process.cwd()));
813
+ }
814
+ // Branded frame, matching create and ship.
815
+ const { intro, outro, log, confirm, isCancel } = await import("@clack/prompts");
816
+ const accent = (value: string) => `\x1b[38;5;208m${value}\x1b[0m`;
817
+ intro("渋み shibumi");
818
+ const io: CliIo = {
819
+ out: (line) => log.message(line),
820
+ err: (line) => log.error(line),
821
+ confirm: async (message) => {
822
+ const answer = await confirm({ message });
823
+ return !isCancel(answer) && answer === true;
824
+ },
825
+ title: (line) => log.step(line),
826
+ success: (line) => log.success(line),
827
+ };
828
+ const code = await runCli(process.argv.slice(2), process.cwd(), io, true);
829
+ outro(code === 0 ? `Docs: ${accent("https://shibumistack.dev/extensions")}` : "Stopped; see the messages above.");
830
+ process.exit(code);
809
831
  }