create-patties 0.0.8 → 0.0.9

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.
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env bun
2
+ export {};
3
+
2
4
  if (typeof Bun === "undefined") {
3
5
  console.error(
4
6
  "create-patties requires Bun. Install Bun first: https://bun.sh",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-patties",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "description": "Scaffolder for new Patties projects.",
6
6
  "bin": {
@@ -16,6 +16,11 @@
16
16
  "README.md",
17
17
  "CHANGELOG.md"
18
18
  ],
19
+ "scripts": {
20
+ "test": "bun test",
21
+ "typecheck": "tsc --noEmit",
22
+ "lint": "biome check ."
23
+ },
19
24
  "engines": {
20
25
  "bun": ">=1.0.0"
21
26
  }
package/src/index.ts CHANGED
@@ -12,6 +12,32 @@ import {
12
12
  } from "./prompts.ts";
13
13
  import { renderTemplatesInTree } from "./readme.ts";
14
14
 
15
+ // Step logger — visible progress so the user can see what scaffolding does.
16
+ // Honors NO_COLOR; degrades gracefully on non-TTY streams.
17
+ function colorOn(): boolean {
18
+ if (process.env.NO_COLOR) return false;
19
+ return Boolean((process.stdout as NodeJS.WriteStream).isTTY);
20
+ }
21
+ const COL = colorOn();
22
+ const c = {
23
+ dim: (s: string) => (COL ? `\x1b[2m${s}\x1b[0m` : s),
24
+ green: (s: string) => (COL ? `\x1b[32m${s}\x1b[0m` : s),
25
+ cyan: (s: string) => (COL ? `\x1b[36m${s}\x1b[0m` : s),
26
+ bold: (s: string) => (COL ? `\x1b[1m${s}\x1b[0m` : s),
27
+ };
28
+ function step(msg: string): void {
29
+ process.stdout.write(` ${c.green("✓")} ${msg}\n`);
30
+ }
31
+ function pending(msg: string): void {
32
+ process.stdout.write(` ${c.dim("…")} ${msg}\n`);
33
+ }
34
+ function header(msg: string): void {
35
+ process.stdout.write(`\n${c.bold(c.cyan("▲"))} ${msg}\n\n`);
36
+ }
37
+ function fmtMs(ms: number): string {
38
+ return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`;
39
+ }
40
+
15
41
  interface Args {
16
42
  name?: string;
17
43
  template: AgentTemplate;
@@ -86,22 +112,33 @@ export async function run(argv: string[]): Promise<number> {
86
112
 
87
113
  probeTools();
88
114
 
115
+ header(`create-patties — scaffolding ${c.bold(args.name)}`);
116
+
89
117
  await Bun.$`mkdir -p ${targetDir}`.quiet();
118
+ step(`created directory ${c.dim(targetDir)}`);
119
+
90
120
  await Bun.$`cp -R ${baseDir}/. ${targetDir}`.quiet();
121
+ step(`copied base template ${c.dim("(default)")}`);
91
122
 
92
123
  await renameTemplateFiles(targetDir);
93
124
  await writePackageJson(targetDir, args.name);
125
+ step(`wrote package.json ${c.dim(`(name: ${args.name})`)}`);
94
126
  await patchPattiesConfig(targetDir, args);
127
+ step(`patched patties.config.ts ${c.dim(`(target: ${args.target})`)}`);
95
128
 
96
129
  if (args.template !== "none") {
97
130
  const overlay = resolve(TEMPLATES_ROOT, `_${args.template}`);
98
131
  if (existsSync(overlay)) {
99
132
  await Bun.$`cp -R ${overlay}/. ${targetDir}`.quiet();
133
+ step(`applied agent overlay ${c.dim(`(${args.template})`)}`);
100
134
  }
101
135
  }
102
136
 
103
137
  if (args.scaffold === "blank") {
104
138
  await applyBlankScaffold(targetDir);
139
+ step("applied blank scaffold (no demo)");
140
+ } else {
141
+ step("included interactive todo demo");
105
142
  }
106
143
 
107
144
  await renderTemplatesInTree(targetDir, {
@@ -111,9 +148,22 @@ export async function run(argv: string[]): Promise<number> {
111
148
  deploy: args.deploy,
112
149
  scaffold: args.scaffold,
113
150
  });
151
+ step("rendered template variables (README, AGENTS.md, …)");
114
152
 
115
153
  if (args.install) {
116
- await Bun.$`bun install`.cwd(targetDir).quiet().nothrow();
154
+ pending("installing dependencies (bun install)…");
155
+ const t0 = performance.now();
156
+ const proc = await Bun.$`bun install`.cwd(targetDir).quiet().nothrow();
157
+ const dt = performance.now() - t0;
158
+ if (proc.exitCode === 0) {
159
+ step(`installed dependencies ${c.dim(`(${fmtMs(dt)})`)}`);
160
+ } else {
161
+ step(
162
+ `bun install exited with code ${proc.exitCode} — you may need to retry it manually`,
163
+ );
164
+ }
165
+ } else {
166
+ step(`skipped ${c.dim("`bun install`")} (--no-install)`);
117
167
  }
118
168
 
119
169
  let gitSkippedReason: string | undefined;
@@ -125,6 +175,7 @@ export async function run(argv: string[]): Promise<number> {
125
175
  .cwd(targetDir)
126
176
  .quiet()
127
177
  .nothrow();
178
+ step("initialized git and committed");
128
179
  } else {
129
180
  gitSkippedReason = "git-missing";
130
181
  }
@@ -1,5 +1,11 @@
1
+ import { Island } from "patties/render";
1
2
  import TodoApp from "../islands/TodoApp.tsx";
2
3
 
4
+ export const meta = {
5
+ title: "Welcome to Patties",
6
+ description: "A Bun-native full-stack meta-framework.",
7
+ };
8
+
3
9
  export default function Index(): JSX.Element {
4
10
  return (
5
11
  <main>
@@ -8,7 +14,9 @@ export default function Index(): JSX.Element {
8
14
  This page is server-rendered. The list below is a client island —{" "}
9
15
  <code>app/islands/TodoApp.tsx</code> — hydrated in the browser.
10
16
  </p>
11
- <TodoApp />
17
+ <Island name="TodoApp">
18
+ <TodoApp />
19
+ </Island>
12
20
  <hr />
13
21
  <p>
14
22
  <small>
@@ -1,4 +1,4 @@
1
- import type { DevServer } from "patties/dev";
1
+ import { type DevServer, setupDevClient } from "patties/dev";
2
2
  import { createRenderer } from "patties/render";
3
3
  import { createRouter } from "patties/router";
4
4
  import { startServer } from "patties/server";
@@ -11,7 +11,10 @@ interface StartOpts {
11
11
  }
12
12
 
13
13
  export default async function start(opts: StartOpts): Promise<void> {
14
- const renderer = createRenderer({ dev: true });
14
+ // Bundle islands and serve their chunks under `/_patties/client/*`.
15
+ // `manifest` tells the renderer which <script> to inject so islands hydrate.
16
+ const devClient = await setupDevClient({ appDir: opts.appDir });
17
+ const renderer = createRenderer({ manifest: devClient.manifest, dev: true });
15
18
  const router = await createRouter({ appDir: opts.appDir, renderer });
16
19
 
17
20
  startServer({
@@ -19,7 +22,7 @@ export default async function start(opts: StartOpts): Promise<void> {
19
22
  hostname: opts.host,
20
23
  dev: true,
21
24
  devServer: opts.devServer,
22
- routes: router.routes,
25
+ routes: { ...devClient.routes, ...router.routes },
23
26
  fallback: router.fallback,
24
27
  });
25
28
  }