@rshono/create 1.0.0-rc.0 → 1.0.0-rc.10

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/README.md CHANGED
@@ -1,65 +1,98 @@
1
- # @rshono/create
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/rshono/rshono/main/logo.svg" alt="" width="72" height="72" />
3
+ </p>
2
4
 
3
- Scaffolds a new [rshono](https://github.com/rshono/rshono) app — Hono + Rspack + React Server Components.
5
+ <h1 align="center">@rshono/create</h1>
6
+
7
+ <p align="center">
8
+ Scaffolds a new <a href="https://github.com/rshono/rshono">rshono</a> app — Hono + Rspack + React Server Components.
9
+ </p>
4
10
 
5
11
  ```bash
6
- npm create @rshono@latest my-app
7
- pnpm create @rshono my-app
12
+ npx @rshono/create@latest my-app
13
+ pnx @rshono/create my-app
14
+ bunx @rshono/create my-app
8
15
  yarn create @rshono my-app
9
- bun create @rshono my-app
10
16
  ```
11
17
 
12
- The package manager that ran it is the one the project gets: it is read from `npm_config_user_agent`, used
13
- for the install, written into `packageManager` for Corepack, and used in every command the closing summary
14
- prints. Nothing asks you which one you meant.
18
+ The package manager that ran it is the one the project gets: it is read from `npm_config_user_agent`, which
19
+ every one of these runners sets, and it is used for the install, written into `packageManager` for Corepack,
20
+ and used in every command the closing summary prints. Nothing asks you which one you meant.
21
+
22
+ Yarn is the odd row out because `yarn dlx` is Berry-only, while `yarn create` works in either — and `pnx`
23
+ arrived in pnpm 10.16, before which it is `pnpm dlx`.
15
24
 
16
25
  ## The questions
17
26
 
18
27
  Six, each with a default, and each answerable by a flag instead:
19
28
 
20
- | Question | Default | Flag |
21
- | --------------------- | ------------------ | ------------------------------------------------------------------- |
22
- | Where should it go? | `my-rshono-app` | first positional argument, or `.` |
23
- | Where is it deployed? | `node` | `--deploy node\|bun\|deno\|cloudflare\|vercel\|netlify\|aws-lambda` |
24
- | Styling | plain CSS | `--tailwind` / `--no-tailwind` |
25
- | Formatting & linting | Prettier + oxlint | `--quality prettier-oxlint\|biome\|oxc\|none` |
26
- | Install dependencies? | yes | `--no-install` |
27
- | Initialize git? | yes, unless nested | `--no-git` |
28
-
29
- Plus `--formatter` and `--linter` to set either half of the quality preset on its own, `--force` to
30
- scaffold into a directory that is not empty, `--dry-run` to see the file list and write nothing, and `-y`
31
- to take the defaults for everything not given. **A non-interactive terminal implies `-y`**, so this is one
32
- command in CI or from an agent:
29
+ | Question | Default | Flag |
30
+ | --------------------- | ------------------ | -------------------------------------------------------------- |
31
+ | Where should it go? | `my-rshono-app` | first positional argument, or `.` |
32
+ | Where is it deployed? | `node` | `-d, --deploy node\|cloudflare\|vercel\|aws-lambda` |
33
+ | Styling | plain CSS | `--tailwind` / `--no-tailwind` |
34
+ | Formatting & linting | Prettier + oxlint | `--quality prettier-oxlint\|prettier-eslint\|biome\|oxc\|none` |
35
+ | Install dependencies? | yes | `--no-install` |
36
+ | Initialize git? | yes, unless nested | `--no-git` |
37
+
38
+ Plus `--formatter prettier\|biome\|oxfmt\|none` and `--linter oxlint\|eslint\|biome\|none` to set either half
39
+ of the quality preset on its own, `--pm npm\|pnpm\|yarn\|bun` to override the package manager that was
40
+ detected, `--force` to scaffold into a directory that is not empty, `--dry-run` to see the file list and write
41
+ nothing, and `-y` to take the defaults for everything not given. **A non-interactive terminal implies `-y`**,
42
+ so this is one command in CI or from an agent:
33
43
 
34
44
  ```bash
35
- npm create @rshono@latest my-app -y --deploy cloudflare --tailwind --quality biome
45
+ npx @rshono/create@latest my-app -y --deploy cloudflare --tailwind --quality biome
36
46
  ```
37
47
 
38
- The deploy targets, and the deploy command each one prints, are generated from the framework's own
39
- presets — a target added to rshono appears here with no edit.
48
+ The deploy targets, and the deploy command each one prints, are generated from the framework's own presets —
49
+ a target added to rshono appears here with no edit.
40
50
 
41
51
  ## What you get
42
52
 
43
53
  ```
44
- rshono.config.ts the chosen deploy target; everything else commented with its default
54
+ package.json scripts, and the exact dependency versions rshono is tested against
55
+ rshono.config.ts the chosen deploy target; every other setting takes its default
45
56
  tsconfig.json strict, with @/* → ./src/*
46
57
  .env committed defaults; secrets go in .env.local
58
+ .gitignore plus whatever each chosen feature adds, under a heading naming it
59
+ README.md the app's own commands, layout and deploy step
60
+ AGENTS.md where an agent finds the framework docs; CLAUDE.md imports it
47
61
  public/ favicon.svg, robots.txt
48
- src/routes.ts one page, a 404 and a 500, with the other route kinds commented
49
- src/server.ts AppEnv, request-id middleware, error reporting, /api/health, redirects, AppType
50
- src/actions.ts a 'use server' action, called from a form that works without JavaScript
51
- src/components/ layout, home, greet-form ('use client'), 404, 500
52
- src/lib/env.ts both sides of the PUBLIC_ boundary in one place
62
+ src/routes.ts one page, a 404 and a 500
63
+ src/server.ts error reporting, trailing-slash and old-path redirects, AppType
64
+ src/components/ layout, home, 404, 500
53
65
  src/styles.css element-level CSS, or the Tailwind entry
66
+ src/env.d.ts the CSS-import declaration the compiler needs
67
+ pnpm-workspace.yaml pnpm only: which dependency install scripts this app runs (none of them)
54
68
  ```
55
69
 
56
- Then, if the dependencies were installed, the scaffold is run through its own formatter so a fresh
57
- project passes its own `format:check` rather than reporting a diff nobody made.
70
+ Scaffolding runs the install and nothing else no formatter, no linter. The templates are written to satisfy
71
+ every formatter option at its configured width, so a fresh project passes its own `format:check` without a
72
+ write pass first.
58
73
 
59
74
  `react` and `react-dom` are pinned **exactly**, at the versions the framework is tested against, and those
60
75
  pins are generated from rshono's own manifest. That is not tidiness: the RSC runtime reaches into React's
61
76
  internals, and an app installed with npm or bun has no workspace overrides to keep a single copy of it.
62
77
 
78
+ ## Two things worth knowing
79
+
80
+ **The ESLint preset pins TypeScript 6.** Linting TypeScript with ESLint means `typescript-eslint`, which reads
81
+ the compiler API directly rather than through a stable interface, so its peer range is
82
+ `typescript >=4.8.4 <6.1.0` — below the TypeScript rshono is built and tested against. An app that chooses
83
+ ESLint therefore gets `typescript ~6.0.3`, the newest that range allows: `npm install` would otherwise fail
84
+ outright on the conflict, and forcing past it hands you a linter running against a compiler API it was never
85
+ built for. The framework's declarations compile identically under either version, which is what makes this the
86
+ app's pin and not the framework's — every other preset leaves TypeScript alone. What you trade for type-aware
87
+ rules is a compiler one major behind, and the JavaScript implementation rather than the native one, so
88
+ `typecheck` on a large app is several times slower. When upstream widens the range, the pin in
89
+ `features/quality.ts` is the only thing to delete.
90
+
91
+ **Tailwind is four packages, a `postcss.config.mjs` and one rule in `rshono.config.ts`.** rshono compiles CSS
92
+ natively and has no PostCSS in it — that is deliberate, and it means an app that wants a plugin chain brings
93
+ its own, through the `rspack` hook. The overlay writes all of it, with a comment saying what to delete to go
94
+ back to plain CSS.
95
+
63
96
  ## Adding an option
64
97
 
65
98
  Every difference between two scaffolds is a `Feature` — files to overlay, dependencies, scripts,
@@ -68,38 +101,35 @@ edits and no new machinery:
68
101
 
69
102
  1. A `Feature` in `src/features/` — `templates/<id>` for the files it brings, plus whatever it adds to the
70
103
  manifest.
71
- 2. The template directory itself, as **real files**. They are copied over the base, so an overlay replaces
72
- a file rather than patching it, and template files stay valid TypeScript that an editor can check.
73
- `_name` becomes `.name` on write, because npm strips a literal `.gitignore` out of a published tarball.
104
+ 2. The template directory itself, as **real files**. They are copied over the base, so an overlay replaces a
105
+ file rather than patching it, and template files stay valid TypeScript that an editor can check. `_name`
106
+ becomes `.name` on write, because npm strips a literal `.gitignore` out of a published tarball.
74
107
  3. A prompt in `src/cli.ts`, if it deserves a question of its own — and a flag, which it always does.
75
108
 
76
- `plan(answers)` is pure: answers in, a `Map` of path → contents out, no directory touched. That is what
77
- makes the whole matrix of options testable in milliseconds (`test/plan.test.mjs`) and `--dry-run` free. It
78
- is also exported, for a tool that wants to scaffold without the prompts:
109
+ `plan(answers, pm)` is pure: answers in, a `Map` of path → contents out, no directory touched. That is what
110
+ makes the whole matrix of options testable in milliseconds (`test/plan.test.mjs`) and `--dry-run` free. It is
111
+ also exported, for a tool that wants to scaffold without the prompts:
79
112
 
80
113
  ```ts
81
114
  import { plan, writePlan } from '@rshono/create';
82
115
  ```
83
116
 
84
- ## Two things worth knowing
85
-
86
- **There is no ESLint option.** Linting TypeScript with ESLint means `typescript-eslint`, whose peer range is
87
- `typescript >=4.8.4 <6.1.0`; rshono is built and tested against TypeScript 7. `npm install` fails outright
88
- on the conflict, and forcing past it would hand you a linter running against a compiler API it was never
89
- built for. When upstream widens the range, ESLint becomes one more entry in `features/quality.ts`.
90
-
91
- **Tailwind is four packages, a `postcss.config.mjs` and one rule in `rshono.config.ts`.** rshono compiles
92
- CSS natively and has no PostCSS in it — that is deliberate, and it means an app that wants a plugin chain
93
- brings its own, through the `rspack` hook. The overlay writes all of it, with a comment saying what to
94
- delete to go back to plain CSS.
95
-
96
117
  ## Development
97
118
 
98
119
  ```bash
99
120
  pnpm --filter @rshono/create build # codegen, then one bundled dist/cli.mjs with no runtime deps
100
- pnpm --filter @rshono/create test # the plan matrix — fast, no I/O
121
+ pnpm --filter @rshono/create test # builds, then the plan matrix and the CLI seconds, no installs
101
122
  CREATE_RSHONO_E2E=1 pnpm --filter @rshono/create test # also: pack, install and build real apps
102
123
  ```
103
124
 
104
- `@clack/prompts` (MIT) is bundled rather than depended on, so `npm create` downloads one tarball before it
105
- can ask its first question.
125
+ `plan.test.mjs` is the fast one the whole matrix of answers in memory, no directory touched.
126
+ `cli.test.mjs` spawns the real bin against temp directories, which is where argument parsing and the refusal
127
+ to overwrite somebody's files are checked. `e2e.test.mjs` is the opt-in one, and the only one that installs
128
+ anything.
129
+
130
+ `src/generated/framework.ts` — the rshono version, the Node range, the dependency pins and the deploy target
131
+ list — is written by `scripts/codegen.mjs` from `packages/core`, so `pnpm --filter @rshono/create codegen` is
132
+ what picks up a change there.
133
+
134
+ `@clack/prompts` (MIT) is bundled rather than depended on, so `npx @rshono/create` downloads one tarball
135
+ before it can ask its first question.
@@ -3,7 +3,8 @@
3
3
  // parse and run on whatever Node the user happens to have. The CLI itself is a bundle — its imports
4
4
  // are evaluated before any statement in it, so a version check *inside* it would be too late to
5
5
  // produce anything friendlier than a stack trace.
6
- var MINIMUM = [22, 1, 0];
6
+ // Kept in step with `engines.node` in @rshono/core's manifest, which is what a scaffolded app pins.
7
+ var MINIMUM = [22, 18, 0];
7
8
 
8
9
  var current = process.versions.node.split('.').map(Number);
9
10
  var older = false;
@@ -20,8 +21,9 @@ if (older) {
20
21
  ' or newer — you are on ' +
21
22
  process.versions.node +
22
23
  '.\n' +
23
- 'rshono itself requires it too (worker threads, process.loadEnvFile, Promise.withResolvers),\n' +
24
- 'so scaffolding on this version would produce an app that cannot start.\n',
24
+ 'rshono itself requires it (native TypeScript stripping loads rshono.config.ts, and the dev\n' +
25
+ 'server needs process.loadEnvFile and Promise.withResolvers), so scaffolding on this version\n' +
26
+ 'would produce an app that cannot start.\n',
25
27
  );
26
28
  process.exit(1);
27
29
  }