create-rsc-kit 0.7.0 → 0.7.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/dist/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  // several things in it that are invisible when wrong: NODE_ENV on the build,
6
6
  // @source for Tailwind, the ambient declaration for the generated engine
7
7
  // bundle. Each of those fails by producing a page that looks nearly right.
8
- import { existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs';
8
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
9
9
  import { dirname, join, resolve } from 'node:path';
10
10
  import { fileURLToPath } from 'node:url';
11
11
  import { spawnSync } from 'node:child_process';
@@ -16,6 +16,27 @@ import * as t from './templates.js';
16
16
  // Same treatment as a refusal from write(): a bad flag is a decision this tool
17
17
  // made, and it happens before the try/catch below because the flags are what
18
18
  // everything else is built from.
19
+ /**
20
+ * This package's own version, printed so a stale one is visible.
21
+ *
22
+ * `bun create rsc-kit` is `bunx create-rsc-kit`, and bunx caches its
23
+ * resolution of `latest` under that key — so a machine that ran it once keeps
24
+ * scaffolding from whatever it downloaded then, however many releases ago.
25
+ * There is nothing this package can do about that, but there is something it
26
+ * can do about the symptom, which was a prompt offering hosts that had been
27
+ * removed two releases earlier and no way to tell why.
28
+ *
29
+ * Read rather than baked in: the version is only written at publish time.
30
+ */
31
+ function selfVersion() {
32
+ try {
33
+ const path = join(dirname(fileURLToPath(import.meta.url)), '../package.json');
34
+ return `v${JSON.parse(readFileSync(path, 'utf-8')).version}`;
35
+ }
36
+ catch {
37
+ return '';
38
+ }
39
+ }
19
40
  const flags = (() => {
20
41
  try {
21
42
  return parseArgs(argv.slice(2));
@@ -32,6 +53,8 @@ if (flags.help) {
32
53
  const unattended = flags.yes === true || flags.host !== undefined;
33
54
  // Resolved once: it walks up from this file looking for the sibling package.
34
55
  const core = flags.core ?? defaultCore(dirname(fileURLToPath(import.meta.url)));
56
+ // Started before the first question and never awaited here — see notifyIfStale.
57
+ const staleCheck = checkForNewer();
35
58
  const options = await collect();
36
59
  try {
37
60
  write(options);
@@ -58,6 +81,7 @@ if (options.install) {
58
81
  }
59
82
  }
60
83
  report(options);
84
+ await notifyIfStale();
61
85
  // ── ─────────────────────────────────────────────────────────────────────────
62
86
  /** Declared, not assigned: collect() runs at module top level, above this. */
63
87
  function basename(path) {
@@ -88,7 +112,7 @@ async function collect() {
88
112
  HELP);
89
113
  exit(1);
90
114
  }
91
- stdout.write(`\n${bold('Create an RSC app')}\n\n`);
115
+ stdout.write(`\n${bold('Create an RSC app')} ${dim(selfVersion())}\n\n`);
92
116
  const p = new Prompter();
93
117
  try {
94
118
  const dir = flags.dir ?? (await p.text('Directory', 'my-app'));
@@ -187,6 +211,61 @@ function report(o) {
187
211
  stdout.write(` ${cyan(step)}\n`);
188
212
  stdout.write(`\n${dim('Pages live in src/app. Where it deploys is the Nitro preset in vite.config.ts.')}\n\n`);
189
213
  }
214
+ /**
215
+ * Ask the registry what `latest` is, so a stale copy can say so.
216
+ *
217
+ * Printing the version alone does not help: nobody knows 0.5.0 is two behind
218
+ * unless something tells them.
219
+ *
220
+ * `bun create rsc-kit` is `bunx create-rsc-kit`, and bunx reuses what it
221
+ * downloaded the first time — a machine that ran this once keeps scaffolding
222
+ * from that copy however many releases later. Writing the tag out is what
223
+ * makes it revalidate. Measured against a 0.6.0 planted in the cache:
224
+ *
225
+ * bun create rsc-kit stale
226
+ * bunx create-rsc-kit stale
227
+ * bun create rsc-kit@latest fresh
228
+ * bunx create-rsc-kit@latest fresh
229
+ * npx create-rsc-kit@latest fresh
230
+ *
231
+ * So the escape is one word, and this is what tells someone to use it — the
232
+ * form without it is the one every set of install instructions writes.
233
+ *
234
+ * create-next-app does this with the `update-check` package. Not here: this
235
+ * package is installed by bunx before it can ask anything, so a dependency is
236
+ * latency every user waits through — the same reason the prompts are written
237
+ * against readline. It is one request.
238
+ *
239
+ * Started before the first prompt and read after the last, so it costs nothing
240
+ * — a person answering questions is slower than a registry. Failure is
241
+ * silence: offline, behind a proxy, or a registry that is down are all just no
242
+ * notice rather than a scaffolder that will not run.
243
+ */
244
+ function checkForNewer() {
245
+ // Unknown is not stale. selfVersion() answers '' when it cannot read the
246
+ // manifest, and comparing against that would report every run as behind.
247
+ const mine = selfVersion().slice(1);
248
+ if (!mine)
249
+ return Promise.resolve(null);
250
+ return (async () => {
251
+ const response = await fetch('https://registry.npmjs.org/create-rsc-kit/latest', {
252
+ signal: AbortSignal.timeout(3000),
253
+ headers: { accept: 'application/json' },
254
+ });
255
+ if (!response.ok)
256
+ return null;
257
+ const latest = (await response.json()).version;
258
+ return latest && latest !== mine ? latest : null;
259
+ })().catch(() => null);
260
+ }
261
+ async function notifyIfStale() {
262
+ const latest = await staleCheck;
263
+ if (!latest)
264
+ return;
265
+ stdout.write(`${dim('A newer create-rsc-kit is out:')} ${bold(`v${latest}`)}${dim(`, and this is ${selfVersion()}.`)}\n` +
266
+ `${dim('bunx reuses the copy it downloaded first. Name the tag and it fetches:')}\n\n` +
267
+ ` ${cyan('bun create rsc-kit@latest')}\n\n`);
268
+ }
190
269
  /** A path the user can paste, when it is under where they are. */
191
270
  function relativeish(dir) {
192
271
  const cwd = process.cwd();
package/dist/options.d.ts CHANGED
@@ -93,4 +93,4 @@ export declare function assertUsableName(name: string): void;
93
93
  * generator nobody can run without reading it first.
94
94
  */
95
95
  export declare function assertInsideCwd(dir: string, cwd: string): void;
96
- export declare const HELP = "\n create-rsc-kit \u2014 scaffold an RSC app\n\n Usage\n create-rsc-kit <dir> [options]\n bun create rsc-kit <dir> [options] (once published)\n\n Options\n --host=bun|node|worker where it runs \u2014 picks the Nitro preset\n --compiler=none|oxc|babel React Compiler (prompt offers oxc; babel by flag)\n --tailwind / --no-tailwind include Tailwind\n --lint / --no-lint include oxlint\n --source-dir <dir> where app/ lives (default: src)\n --init add to the project here, rather than scaffold\n --core=<spec> engine dependency, e.g. file:../rsc-kit/packages/core\n --no-install skip installing dependencies\n --no-git skip git init\n -y, --yes accept every default, ask nothing\n -h, --help this\n";
96
+ export declare const HELP = "\n create-rsc-kit \u2014 scaffold an RSC app\n\n Usage\n create-rsc-kit <dir> [options]\n bun create rsc-kit@latest <dir> [options]\n\n Options\n --host=bun|node|worker where it runs \u2014 picks the Nitro preset\n --compiler=none|oxc|babel React Compiler (prompt offers oxc; babel by flag)\n --tailwind / --no-tailwind include Tailwind\n --lint / --no-lint include oxlint\n --source-dir <dir> where app/ lives (default: src)\n --init add to the project here, rather than scaffold\n --core=<spec> engine dependency, e.g. file:../rsc-kit/packages/core\n --no-install skip installing dependencies\n --no-git skip git init\n -y, --yes accept every default, ask nothing\n -h, --help this\n";
package/dist/options.js CHANGED
@@ -176,7 +176,7 @@ export const HELP = `
176
176
 
177
177
  Usage
178
178
  create-rsc-kit <dir> [options]
179
- bun create rsc-kit <dir> [options] (once published)
179
+ bun create rsc-kit@latest <dir> [options]
180
180
 
181
181
  Options
182
182
  --host=bun|node|worker where it runs — picks the Nitro preset
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-rsc-kit",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "type": "module",
5
5
  "description": "Scaffold an RSC app on Bun, Hono, Elysia or Node.",
6
6
  "bin": {