@tinycld/bootstrap 1.1.0 → 2.0.0
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 +82 -38
- package/dist/args.js +16 -3
- package/dist/args.js.map +1 -1
- package/dist/assemble-workspace.js +175 -0
- package/dist/assemble-workspace.js.map +1 -0
- package/dist/index.js +71 -8
- package/dist/index.js.map +1 -1
- package/dist/link-package.js +10 -9
- package/dist/link-package.js.map +1 -1
- package/package.json +3 -2
- package/templates/shared/.github/workflows/ci.yml +23 -25
- package/templates/shared/README.md +9 -8
- package/templates/workspace/.go-version +1 -0
- package/templates/workspace/.node-version +1 -0
- package/templates/workspace/tests/expo-clipboard-stub.ts +20 -0
- package/templates/workspace/tests/expo-router-stub.ts +48 -0
- package/templates/workspace/tests/lucide-react-native-stub.cjs +73 -0
- package/templates/workspace/tests/tinycld.packages.test.ts +54 -0
- package/templates/workspace/tests/unit-setup.ts +55 -0
- package/templates/workspace/tinycld.packages.ts +75 -0
- package/templates/workspace/vitest.config.ts +104 -0
- package/dist/bootstrap-tooling.js +0 -149
- package/dist/bootstrap-tooling.js.map +0 -1
- package/dist/link-core.js +0 -99
- package/dist/link-core.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,23 +1,56 @@
|
|
|
1
1
|
# @tinycld/bootstrap
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@tinycld/bootstrap` does two jobs:
|
|
4
|
+
|
|
5
|
+
- **`--new <slug>`** — scaffold a new feature package (manifest, CI workflow, sample screens, seed, migrations, optionally a Go server).
|
|
6
|
+
- **`--assemble-only`** — assemble a workspace root in the current directory by cloning the [`app`](https://github.com/tinycld/app) shell, the [`core`](https://github.com/tinycld/core) library, and any features named with `--with <slug>`.
|
|
4
7
|
|
|
5
8
|
Modeled after [`create-vite`](https://github.com/vitejs/vite/tree/main/packages/create-vite): tiny CLI, templates embedded in the published npm package, no runtime network fetch.
|
|
6
9
|
|
|
7
10
|
## Requirements
|
|
8
11
|
|
|
9
|
-
- **[npm](https://docs.npmjs.com/)**
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
+
- **[npm](https://docs.npmjs.com/)** on Node ≥ 24 (the package's `engines.node` is `>=24`; older Node may work but is unsupported).
|
|
13
|
+
- `git` (always) and `gh` (only for the suggested "initial push" next-step) on `$PATH`.
|
|
14
|
+
|
|
15
|
+
The two modes are independent — scaffold mode does not require a pre-existing workspace, and assemble mode does not require a scaffolded package. They compose: a common flow is `--assemble-only` once to set up `~/code/tinycld/`, then `--new <slug>` from inside that workspace to add a feature.
|
|
16
|
+
|
|
17
|
+
## Assemble a workspace (`--assemble-only`)
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
mkdir ~/code/tinycld && cd ~/code/tinycld
|
|
21
|
+
npx @tinycld/bootstrap@latest --assemble-only --with mail --with contacts
|
|
22
|
+
npm install # links members + runs the generator (postinstall)
|
|
23
|
+
cd app && npm run dev
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The CLI writes the workspace coordination files (`package.json`, `tinycld.packages.ts`, `vitest.config.ts`, shared test stubs, the `package-scripts/` CLI) from embedded templates, then clones `app` + `core` as siblings. Each `--with <slug>` adds one feature sibling. `app` and `core` are always cloned; everything else is opt-in.
|
|
27
|
+
|
|
28
|
+
`--with name@ref` pins a clone to a tag, branch, or commit:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npx @tinycld/bootstrap@latest --assemble-only \
|
|
32
|
+
--with app@v1.2.0 --with core@v1.2.0 --with mail@v0.3.1
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Skipped if the target directory already exists, so re-running is safe.
|
|
12
36
|
|
|
13
|
-
|
|
37
|
+
Set `TINYCLD_REPO_BASE` to clone over HTTPS instead of the default SSH (`git@github.com:tinycld`). CI uses this:
|
|
14
38
|
|
|
15
39
|
```sh
|
|
16
|
-
|
|
40
|
+
TINYCLD_REPO_BASE=https://github.com/tinycld \
|
|
41
|
+
npx @tinycld/bootstrap@latest --assemble-only --with mail
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Scaffold a new package (`--new`)
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
npx @tinycld/bootstrap --new my-feature
|
|
17
48
|
```
|
|
18
49
|
|
|
19
50
|
You'll be walked through an interactive prompt. The positional argument (`my-feature`) is the **slug** — kebab-case, 3–40 chars, becomes `@tinycld/my-feature`, the URL segment `/a/<orgSlug>/my-feature/`, and the Go module `tinycld.org/packages/my-feature`. Leave it off to be asked for it.
|
|
20
51
|
|
|
52
|
+
If `--new` runs from inside an existing workspace root (`app/` and `core/` siblings detected), the new package is scaffolded as a sibling and the link step adds it to the workspace `package.json`. Otherwise the CLI creates a wrapper directory `./tinycld-<slug>/` with the package at `./tinycld-<slug>/<slug>/`, assembles a workspace around it (cloning `app` + `core`), and links — leaving you a self-contained, runnable workspace.
|
|
53
|
+
|
|
21
54
|
### Prompts
|
|
22
55
|
|
|
23
56
|
| Prompt | Example | Notes |
|
|
@@ -31,15 +64,18 @@ You'll be walked through an interactive prompt. The positional argument (`my-fea
|
|
|
31
64
|
| **Keyboard shortcut** (full only) | `f` | Single lowercase letter, or blank. |
|
|
32
65
|
| **Include a Go server?** (full only) | `y` / `n` | If no, `server/` and the manifest's `server` field are omitted. |
|
|
33
66
|
| **Target directory** | `./my-feature` | Default creates the new repo as a child of the current directory. Must not exist or must be empty. |
|
|
34
|
-
| **Link into the
|
|
67
|
+
| **Link into the workspace?** | `y` / `n` | After scaffolding, the CLI adds the package to the workspace `package.json`'s `workspaces` array and runs `npm install` at the workspace root. If cwd isn't a workspace root, it assembles one (cloning `app` + `core`) first. Suppress with `--no-link`. |
|
|
35
68
|
|
|
36
69
|
### Flags (non-interactive use)
|
|
37
70
|
|
|
38
71
|
Every prompt has a corresponding flag. Pass `--yes` (or `-y`) to accept all defaults and skip everything that wasn't given a flag — useful for scripted scaffolding.
|
|
39
72
|
|
|
40
|
-
| Flag | Maps to
|
|
73
|
+
| Flag | Maps to | Notes |
|
|
41
74
|
|---|---|---|
|
|
42
|
-
|
|
|
75
|
+
| `--new` | Mode selector | Required for scaffold mode. Mutually exclusive with `--assemble-only`. |
|
|
76
|
+
| `--assemble-only` | Mode selector | Required for workspace-assembly mode. Mutually exclusive with `--new`. |
|
|
77
|
+
| `--with <slug>` | Assemble-only | Repeatable. Each adds one feature sibling. Accepts `--with name@ref` to pin to a tag/branch/commit. |
|
|
78
|
+
| *(positional)* | Package slug (scaffold) | First non-flag argument. Pair with `--new` to set the slug non-interactively. |
|
|
43
79
|
| `--name <s>` | Human-readable name | Defaults to title-cased slug. |
|
|
44
80
|
| `--description <s>` | Description | |
|
|
45
81
|
| `--preset <full\|settings-only>` | Preset | |
|
|
@@ -48,19 +84,19 @@ Every prompt has a corresponding flag. Pass `--yes` (or `-y`) to accept all defa
|
|
|
48
84
|
| `--shortcut <c>` | Keyboard shortcut | Single lowercase letter. |
|
|
49
85
|
| `--server` / `--no-server` | Include a Go server | Full preset only. |
|
|
50
86
|
| `--target <dir>` | Target directory | Default `./<slug>`. |
|
|
51
|
-
| `--link` / `--no-link` | Link into the
|
|
87
|
+
| `--link` / `--no-link` | Link into the workspace | Forces the post-scaffold link step on or off, skipping the prompt. |
|
|
52
88
|
| `--yes`, `-y` | — | Accept all defaults; with `--no-link`, fully non-interactive. |
|
|
53
89
|
|
|
54
90
|
Example, fully non-interactive:
|
|
55
91
|
|
|
56
92
|
```sh
|
|
57
|
-
npx @tinycld/bootstrap my-feature \
|
|
93
|
+
npx @tinycld/bootstrap --new my-feature \
|
|
58
94
|
--yes --no-link \
|
|
59
95
|
--description "Tracks widgets across the org" \
|
|
60
96
|
--preset full --icon box --nav-order 25 --shortcut w
|
|
61
97
|
```
|
|
62
98
|
|
|
63
|
-
`--help` is not wired (yet) — run `npx @tinycld/bootstrap` with no argv to
|
|
99
|
+
`--help` is not wired (yet) — run `npx @tinycld/bootstrap` with no argv to get a usage summary listing both modes.
|
|
64
100
|
|
|
65
101
|
## Presets
|
|
66
102
|
|
|
@@ -75,16 +111,16 @@ Matches the shape of `@tinycld/contacts`, `@tinycld/mail`, `@tinycld/calendar`,
|
|
|
75
111
|
|
|
76
112
|
```
|
|
77
113
|
my-feature/
|
|
78
|
-
├── .github/workflows/ci.yml #
|
|
114
|
+
├── .github/workflows/ci.yml # assembles the workspace via bootstrap --assemble-only, runs tinycld-pkg check + test:e2e
|
|
79
115
|
├── .gitignore # node_modules, *.tsbuildinfo, lockfiles, .DS_Store
|
|
80
116
|
├── README.md # developer-facing onboarding for this package
|
|
81
117
|
├── manifest.ts # name, slug, routes, nav, collections, seed, server, ...
|
|
82
118
|
├── package.json # @tinycld/my-feature, peer deps, scripts, exports map
|
|
83
|
-
├── tsconfig.json # extends ../
|
|
119
|
+
├── tsconfig.json # extends ../app/tsconfig.package-base.json
|
|
84
120
|
├── pb-migrations/
|
|
85
121
|
│ └── 1800000000_create_my-feature.js # creates my_feature_items collection
|
|
86
122
|
├── server/
|
|
87
|
-
│ ├── go.mod # module tinycld.org/packages/my-feature; replaces tinycld.org/core → ../../
|
|
123
|
+
│ ├── go.mod # module tinycld.org/packages/my-feature; replaces tinycld.org/core → ../../core/server
|
|
88
124
|
│ └── register.go # func Register(app) hook for server-side wiring
|
|
89
125
|
├── tests/
|
|
90
126
|
│ └── manifest.test.ts # vitest smoke test of manifest shape
|
|
@@ -131,7 +167,7 @@ my-service/
|
|
|
131
167
|
|
|
132
168
|
## Manifest fields
|
|
133
169
|
|
|
134
|
-
The scaffolded `manifest.ts` is the single source of truth for what a package contributes. Templates only fill in the fields appropriate for the chosen preset; the full reference (every field, when to use it) lives in [
|
|
170
|
+
The scaffolded `manifest.ts` is the single source of truth for what a package contributes. Templates only fill in the fields appropriate for the chosen preset; the full reference (every field, when to use it) lives in the [manifest schema docs](https://tinycld.org/docs/reference/manifest-schema). Quick summary:
|
|
135
171
|
|
|
136
172
|
| Field | Meaning |
|
|
137
173
|
|---|---|
|
|
@@ -150,7 +186,7 @@ All path-shaped fields use **short subpaths** (`'screens'`, `'sidebar'`, `'colle
|
|
|
150
186
|
|
|
151
187
|
## After scaffolding
|
|
152
188
|
|
|
153
|
-
If you accepted the link-into-
|
|
189
|
+
If you accepted the link-into-workspace prompt, the package is already a workspace member and `npm install` has run. Otherwise the CLI prints next-steps you can copy verbatim:
|
|
154
190
|
|
|
155
191
|
```sh
|
|
156
192
|
# 1. Initialize git and push to GitHub
|
|
@@ -160,43 +196,51 @@ git add .
|
|
|
160
196
|
git commit -m 'chore: initial scaffold'
|
|
161
197
|
gh repo create tinycld/my-feature --public --source=. --push
|
|
162
198
|
|
|
163
|
-
# 2. Link into the
|
|
164
|
-
cd
|
|
165
|
-
|
|
199
|
+
# 2. Link into the workspace (add as a member, then install)
|
|
200
|
+
cd ..
|
|
201
|
+
# ensure "my-feature" is listed in the workspace package.json's "workspaces" array, then:
|
|
202
|
+
npm install
|
|
166
203
|
|
|
167
|
-
# 3. Verify (
|
|
168
|
-
|
|
204
|
+
# 3. Verify (scoped to this member)
|
|
205
|
+
cd my-feature
|
|
206
|
+
npx tinycld-pkg check
|
|
169
207
|
```
|
|
170
208
|
|
|
171
|
-
Once linked, the app shell's generator wires your manifest in automatically: routes appear at `/a/<orgSlug>/my-feature/**`, the sidebar renders, the settings panel shows up, migrations get picked up by PocketBase
|
|
209
|
+
Once linked, the app shell's generator wires your manifest in automatically: routes appear at `/a/<orgSlug>/my-feature/**`, the sidebar renders, the settings panel shows up, migrations get picked up by PocketBase. No further changes to `app/` or `core/` are needed.
|
|
172
210
|
|
|
173
|
-
> ⚠️ **`
|
|
211
|
+
> ⚠️ **`app/metro.config.cjs` watches the workspace root**, but Expo's resolver caches package metadata at boot. If you add a new sibling while `npm run dev` is already running, restart it (Ctrl-C, then `npm run dev`) so the new member is picked up. CI is fine — it always starts fresh.
|
|
174
212
|
|
|
175
213
|
### Day-to-day development
|
|
176
214
|
|
|
177
|
-
Most work happens **inside
|
|
215
|
+
Most work happens **from inside the package** with the workspace assembled around it:
|
|
216
|
+
|
|
217
|
+
```sh
|
|
218
|
+
cd my-feature
|
|
219
|
+
npx tinycld-pkg check # biome + tsc + vitest, scoped to this member
|
|
220
|
+
npx tinycld-pkg test # vitest only
|
|
221
|
+
npx tinycld-pkg test:e2e # playwright for this member
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
To run the app itself, drop into the app shell:
|
|
178
225
|
|
|
179
226
|
```sh
|
|
180
|
-
cd ../
|
|
181
|
-
npm run
|
|
182
|
-
npm run checks
|
|
183
|
-
npm run test:unit # vitest, includes your tests/ via the packages glob
|
|
227
|
+
cd ../app
|
|
228
|
+
npm run dev # expo + pocketbase, fronted by a single-port dev proxy
|
|
229
|
+
npm run checks # biome + tsc, ecosystem-wide
|
|
184
230
|
```
|
|
185
231
|
|
|
186
|
-
Hot reload picks up changes in your package the same way as core code, since
|
|
232
|
+
Hot reload picks up changes in your package the same way as core code, since members are symlinked.
|
|
187
233
|
|
|
188
234
|
### Running the scaffolded package's own CI locally
|
|
189
235
|
|
|
190
|
-
The package's `.github/workflows/ci.yml`
|
|
236
|
+
The package's `.github/workflows/ci.yml` mirrors what GitHub Actions runs:
|
|
191
237
|
|
|
192
|
-
1.
|
|
193
|
-
2. `npm install`
|
|
194
|
-
3. `
|
|
195
|
-
4.
|
|
196
|
-
5. **Typecheck from inside `tinycld/`** (`npm run typecheck`) — the app shell's tsconfig pulls in `expo`'s base, `uniwind` global type augments (which add `className` to RN components), and the live `~/types/pbSchema` generated from PocketBase. A standalone `tsc` invocation inside the package can't see those.
|
|
197
|
-
6. Run unit tests from the package (vitest discovers them via the `packages/@*/*/tests/**` glob in `tinycld/vitest.config.ts`).
|
|
238
|
+
1. Assemble a workspace via `npx @tinycld/bootstrap --assemble-only`. The job has `--with <this-pkg>@<sha>` so it lands the exact commit under test.
|
|
239
|
+
2. `npm install` at the workspace root (this also runs the package generator via the postinstall hook).
|
|
240
|
+
3. `npx tinycld-pkg check` from inside the package directory — runs biome (scoped), tsc, and vitest.
|
|
241
|
+
4. `npx tinycld-pkg test:e2e` if the package ships Playwright specs under `tests/`.
|
|
198
242
|
|
|
199
|
-
|
|
243
|
+
Biome lives only in `app/biome.json` (one config across every member). There is no `biome.json` in the scaffolded package repo. Typecheck runs against the app shell's tsconfig via `tinycld-pkg`, so the `expo` base, `uniwind` global augments, and the live `pbSchema` types are all in scope.
|
|
200
244
|
|
|
201
245
|
## Import conventions the templates assume
|
|
202
246
|
|
package/dist/args.js
CHANGED
|
@@ -13,8 +13,14 @@ export class ArgParseError extends Error {
|
|
|
13
13
|
}
|
|
14
14
|
const STRING_FLAGS = new Set(['name', 'description', 'preset', 'icon', 'shortcut', 'target']);
|
|
15
15
|
const NUMBER_FLAGS = new Set(['nav-order']);
|
|
16
|
-
const BOOL_FLAGS = new Set(['server', 'link', 'yes', '
|
|
16
|
+
const BOOL_FLAGS = new Set(['server', 'link', 'yes', 'new', 'assemble-only']);
|
|
17
17
|
const BOOL_ALIASES = { y: 'yes' };
|
|
18
|
+
// Removed in v2. Surface a targeted error so users who hit these (from old
|
|
19
|
+
// docs, old CI workflows, or muscle memory) get an actionable message instead
|
|
20
|
+
// of the generic "unknown flag" / "missing value" they'd otherwise see.
|
|
21
|
+
const REMOVED_FLAGS = {
|
|
22
|
+
tooling: '`--tooling` was removed in v2. Use `--assemble-only` instead.',
|
|
23
|
+
};
|
|
18
24
|
export function parseArgs(argv) {
|
|
19
25
|
const out = {};
|
|
20
26
|
const positionals = [];
|
|
@@ -32,6 +38,10 @@ export function parseArgs(argv) {
|
|
|
32
38
|
const isNegated = rawName.startsWith('no-');
|
|
33
39
|
const baseName = isNegated ? rawName.slice(3) : rawName;
|
|
34
40
|
const canonical = BOOL_ALIASES[baseName] ?? baseName;
|
|
41
|
+
if (canonical in REMOVED_FLAGS) {
|
|
42
|
+
issues.push({ flag: canonical, reason: REMOVED_FLAGS[canonical] ?? 'removed' });
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
35
45
|
if (BOOL_FLAGS.has(canonical)) {
|
|
36
46
|
if (inlineValue !== undefined) {
|
|
37
47
|
issues.push({ flag: canonical, reason: 'boolean flag takes no value' });
|
|
@@ -122,8 +132,11 @@ function setBool(out, name, value) {
|
|
|
122
132
|
case 'yes':
|
|
123
133
|
out.yes = value;
|
|
124
134
|
break;
|
|
125
|
-
case '
|
|
126
|
-
out.
|
|
135
|
+
case 'new':
|
|
136
|
+
out.new = value;
|
|
137
|
+
break;
|
|
138
|
+
case 'assemble-only':
|
|
139
|
+
out.assembleOnly = value;
|
|
127
140
|
break;
|
|
128
141
|
}
|
|
129
142
|
}
|
package/dist/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, relative } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
// All feature members that exist in the ecosystem. The workspace manifest lists
|
|
6
|
+
// ALL of them (npm tolerates absent dirs), so a partial checkout still installs.
|
|
7
|
+
// But --assemble-only CLONES only app+core+requested — we do NOT force-clone all.
|
|
8
|
+
const ALL_FEATURES = ['contacts', 'mail', 'calendar', 'drive', 'calc', 'text', 'google-takeout-import'];
|
|
9
|
+
// app + core are always cloned by assemble-only mode (the minimum viable
|
|
10
|
+
// workspace); the clone set in assembleWorkspace seeds them directly (pinnable
|
|
11
|
+
// via appRef/coreRef). package-scripts (the tinycld-pkg CLI) now lives INSIDE
|
|
12
|
+
// the app member at app/package-scripts, so it arrives with the app clone and
|
|
13
|
+
// is never cloned separately.
|
|
14
|
+
// Listed in the manifest workspaces array (everything that could exist). The
|
|
15
|
+
// nested member path app/package-scripts is a valid npm workspace entry.
|
|
16
|
+
const ALL_MEMBERS = ['app', 'app/package-scripts', 'core', ...ALL_FEATURES];
|
|
17
|
+
/**
|
|
18
|
+
* Write (or merge into) a workspace-root package.json + .npmrc in `dir`.
|
|
19
|
+
*
|
|
20
|
+
* When `dir/package.json` already exists (e.g. provided by the workspace clone),
|
|
21
|
+
* we preserve its fields and only enforce the two things bootstrap owns:
|
|
22
|
+
* the complete `workspaces` list (so later --with clones need no manifest edit)
|
|
23
|
+
* and the `postinstall` script. All other fields — devDependencies, engines,
|
|
24
|
+
* volta, extra scripts, etc. — survive as-is.
|
|
25
|
+
*
|
|
26
|
+
* When no package.json exists yet (workspace clone was skipped), the full
|
|
27
|
+
* generated defaults are written, matching the previous behaviour.
|
|
28
|
+
*
|
|
29
|
+
* The workspaces array ALWAYS lists every possible member — npm ignores entries
|
|
30
|
+
* whose dirs are absent, so a partial checkout installs fine.
|
|
31
|
+
*
|
|
32
|
+
* .npmrc is written only when one does not already exist, for the same reason.
|
|
33
|
+
*/
|
|
34
|
+
export function writeWorkspaceManifest(dir) {
|
|
35
|
+
const pkgPath = join(dir, 'package.json');
|
|
36
|
+
let existing = {};
|
|
37
|
+
if (existsSync(pkgPath)) {
|
|
38
|
+
try {
|
|
39
|
+
existing = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Unparseable existing file — start from defaults
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const existingScripts = typeof existing.scripts === 'object' && existing.scripts !== null
|
|
46
|
+
? existing.scripts
|
|
47
|
+
: {};
|
|
48
|
+
const pkg = {
|
|
49
|
+
name: '@tinycld/workspace',
|
|
50
|
+
version: '0.0.0',
|
|
51
|
+
private: true,
|
|
52
|
+
type: 'module',
|
|
53
|
+
...existing,
|
|
54
|
+
// Always enforce the canonical workspaces list and postinstall script.
|
|
55
|
+
workspaces: [...ALL_MEMBERS],
|
|
56
|
+
scripts: {
|
|
57
|
+
...existingScripts,
|
|
58
|
+
postinstall: 'cd app && npm run packages:generate && npm run assets:copy-pdfjs',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 4)}\n`);
|
|
62
|
+
const npmrcPath = join(dir, '.npmrc');
|
|
63
|
+
if (!existsSync(npmrcPath)) {
|
|
64
|
+
writeFileSync(npmrcPath, 'legacy-peer-deps=true\n');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resolve the workspace-template dir relative to this module. Published builds
|
|
69
|
+
* have `dist/assemble-workspace.js` next to `templates/`; dev has
|
|
70
|
+
* `src/assemble-workspace.ts` under the same parent. Both → `../templates/workspace`.
|
|
71
|
+
*/
|
|
72
|
+
function resolveWorkspaceTemplateDir() {
|
|
73
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
74
|
+
return join(here, '..', 'templates', 'workspace');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Copy the workspace-root scaffolding (tinycld.packages.ts, vitest.config.ts,
|
|
78
|
+
* tests/ stubs) from bootstrap's templates/workspace/ into `dir`. These files
|
|
79
|
+
* are pure scaffolding the workspace ROOT needs but that no longer lives in a
|
|
80
|
+
* committed workspace repo — bootstrap is their source of truth.
|
|
81
|
+
*
|
|
82
|
+
* Never overwrites an existing file: a real workspace checkout, or a CI lane
|
|
83
|
+
* that supplied its own copy, keeps what it has (same non-destructive ethos as
|
|
84
|
+
* the member clones). Returns the relative paths actually written.
|
|
85
|
+
*/
|
|
86
|
+
export function copyWorkspaceTemplate(dir, templateDir = resolveWorkspaceTemplateDir()) {
|
|
87
|
+
if (!existsSync(templateDir))
|
|
88
|
+
return [];
|
|
89
|
+
const written = [];
|
|
90
|
+
const walk = (src) => {
|
|
91
|
+
for (const entry of readdirSync(src)) {
|
|
92
|
+
const srcPath = join(src, entry);
|
|
93
|
+
const rel = relative(templateDir, srcPath);
|
|
94
|
+
const dstPath = join(dir, rel);
|
|
95
|
+
if (statSync(srcPath).isDirectory()) {
|
|
96
|
+
walk(srcPath);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (existsSync(dstPath))
|
|
100
|
+
continue; // never overwrite
|
|
101
|
+
mkdirSync(dirname(dstPath), { recursive: true });
|
|
102
|
+
cpSync(srcPath, dstPath);
|
|
103
|
+
written.push(rel);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
walk(templateDir);
|
|
107
|
+
return written;
|
|
108
|
+
}
|
|
109
|
+
/** Split a member spec `name@ref` into its parts. No `@` → no ref (clone HEAD). */
|
|
110
|
+
function splitRef(spec) {
|
|
111
|
+
const at = spec.indexOf('@');
|
|
112
|
+
if (at === -1)
|
|
113
|
+
return { name: spec };
|
|
114
|
+
return { name: spec.slice(0, at), ref: spec.slice(at + 1) || undefined };
|
|
115
|
+
}
|
|
116
|
+
function realClone(url, dest, ref) {
|
|
117
|
+
const args = ['clone', '--depth', '1'];
|
|
118
|
+
if (ref)
|
|
119
|
+
args.push('--branch', ref);
|
|
120
|
+
args.push(url, dest);
|
|
121
|
+
const r = spawnSync('git', args, { stdio: 'inherit' });
|
|
122
|
+
return r.status === 0;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Assemble a workspace skeleton at opts.root: write the canonical root manifest
|
|
126
|
+
* (writeWorkspaceManifest) + lay down the root scaffolding (copyWorkspaceTemplate:
|
|
127
|
+
* tinycld.packages.ts, vitest.config.ts, tests/ stubs, version files), then clone
|
|
128
|
+
* ONLY app + core + the explicitly-requested feature members (skipping any
|
|
129
|
+
* already present — e.g. a CI-checked-out member). There is NO workspace
|
|
130
|
+
* meta-repo clone: bootstrap is the source of all root scaffolding.
|
|
131
|
+
* Unknown member names throw. Returns the members that ended up present. Does
|
|
132
|
+
* NOT run npm install (the caller / CI controls that, since it may want a
|
|
133
|
+
* clean `npm ci`).
|
|
134
|
+
*/
|
|
135
|
+
export function assembleWorkspace(opts) {
|
|
136
|
+
// Each requested member may be `name` or `name@ref`. Validate the NAME part.
|
|
137
|
+
const requested = (opts.members ?? []).map(splitRef);
|
|
138
|
+
const unknown = requested.filter((m) => !ALL_FEATURES.includes(m.name));
|
|
139
|
+
if (unknown.length > 0) {
|
|
140
|
+
throw new Error(`Unknown feature member(s): ${unknown.map((m) => m.name).join(', ')}. Known: ${ALL_FEATURES.join(', ')}`);
|
|
141
|
+
}
|
|
142
|
+
const repoBase = opts.repoBase ?? 'git@github.com:tinycld';
|
|
143
|
+
const clone = opts.clone ?? realClone;
|
|
144
|
+
const present = [];
|
|
145
|
+
// Write the canonical root manifest (workspaces list + postinstall), then
|
|
146
|
+
// lay down the root scaffolding bootstrap owns (tinycld.packages.ts,
|
|
147
|
+
// vitest.config.ts, tests/ stubs, .node-version, .go-version). Both are
|
|
148
|
+
// non-destructive: anything already present (a real workspace checkout, or
|
|
149
|
+
// a CI lane that supplied its own) is left as-is.
|
|
150
|
+
writeWorkspaceManifest(opts.root);
|
|
151
|
+
copyWorkspaceTemplate(opts.root);
|
|
152
|
+
// Build the clone set keyed by member NAME so a member passed both bare and
|
|
153
|
+
// with an @ref dedupes to one clone (the ref-bearing entry wins). app+core
|
|
154
|
+
// are always cloned and pinnable via appRef/coreRef.
|
|
155
|
+
const refByName = new Map();
|
|
156
|
+
refByName.set('app', opts.appRef);
|
|
157
|
+
refByName.set('core', opts.coreRef);
|
|
158
|
+
for (const { name, ref } of requested) {
|
|
159
|
+
// A later ref overrides an earlier bare entry; a bare entry never clears
|
|
160
|
+
// an existing ref.
|
|
161
|
+
if (ref !== undefined || !refByName.has(name))
|
|
162
|
+
refByName.set(name, ref);
|
|
163
|
+
}
|
|
164
|
+
for (const [name, ref] of refByName) {
|
|
165
|
+
const dest = join(opts.root, name);
|
|
166
|
+
if (existsSync(join(dest, '.git')) || existsSync(join(dest, 'package.json'))) {
|
|
167
|
+
present.push(name);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (clone(`${repoBase}/${name}.git`, dest, ref))
|
|
171
|
+
present.push(name);
|
|
172
|
+
}
|
|
173
|
+
return present;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=assemble-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assemble-workspace.js","sourceRoot":"","sources":["../src/assemble-workspace.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,19 +5,41 @@ import { pathToFileURL } from 'node:url';
|
|
|
5
5
|
import { intro, outro } from '@clack/prompts';
|
|
6
6
|
import pc from 'picocolors';
|
|
7
7
|
import { ArgParseError, parseArgs } from "./args.js";
|
|
8
|
-
import {
|
|
8
|
+
import { assembleWorkspace } from "./assemble-workspace.js";
|
|
9
9
|
import { copyTemplate, resolveTemplatesRoot } from "./copy-template.js";
|
|
10
10
|
import { detectLayout } from "./layout.js";
|
|
11
11
|
import { offerLinkPackage } from "./link-package.js";
|
|
12
12
|
import { runPrompts } from "./prompts.js";
|
|
13
|
-
export function
|
|
13
|
+
export function runAssembleOnly(opts) {
|
|
14
14
|
const root = opts.root ?? process.cwd();
|
|
15
|
+
// app + core are always-cloned members, not features, so they can't ride the
|
|
16
|
+
// `members` list through assembleWorkspace's feature validation. Accept them
|
|
17
|
+
// in the SAME `--with name@ref` surface for a uniform pinned invocation
|
|
18
|
+
// (`--with app@v1 --with core@v2 --with mail@v3`) by peeling app@ref/core@ref
|
|
19
|
+
// out of `members` into appRef/coreRef. An explicit opts.appRef/coreRef wins.
|
|
20
|
+
let appRef = opts.appRef;
|
|
21
|
+
let coreRef = opts.coreRef;
|
|
22
|
+
const features = [];
|
|
23
|
+
for (const spec of opts.members ?? []) {
|
|
24
|
+
const at = spec.indexOf('@');
|
|
25
|
+
const name = at === -1 ? spec : spec.slice(0, at);
|
|
26
|
+
const ref = at === -1 ? undefined : spec.slice(at + 1) || undefined;
|
|
27
|
+
if (name === 'app')
|
|
28
|
+
appRef = appRef ?? ref;
|
|
29
|
+
else if (name === 'core')
|
|
30
|
+
coreRef = coreRef ?? ref;
|
|
31
|
+
else
|
|
32
|
+
features.push(spec);
|
|
33
|
+
}
|
|
15
34
|
// Honor TINYCLD_REPO_BASE (CI sets it to an HTTPS base since runners have no
|
|
16
35
|
// SSH key). Listed first so an explicit opts.repoBase still wins via spread;
|
|
17
|
-
// when neither is set,
|
|
18
|
-
const present =
|
|
36
|
+
// when neither is set, assembleWorkspace falls back to its SSH default.
|
|
37
|
+
const present = assembleWorkspace({
|
|
19
38
|
repoBase: process.env.TINYCLD_REPO_BASE,
|
|
20
39
|
...opts,
|
|
40
|
+
members: features,
|
|
41
|
+
appRef,
|
|
42
|
+
coreRef,
|
|
21
43
|
root,
|
|
22
44
|
});
|
|
23
45
|
// Mandatory members must clone — a missing app/core means a broken workspace.
|
|
@@ -29,7 +51,9 @@ export function runToolingMode(opts) {
|
|
|
29
51
|
console.log(`Workspace skeleton ready at ${root} (members: ${present.join(', ')})`);
|
|
30
52
|
}
|
|
31
53
|
async function main() {
|
|
32
|
-
|
|
54
|
+
// Parse + mode-resolve BEFORE opening a clack session — anything that exits
|
|
55
|
+
// early (parse error, usage, mutex error) prints plainly and avoids the
|
|
56
|
+
// dangling `┌ @tinycld/bootstrap` banner with no matching footer.
|
|
33
57
|
let args;
|
|
34
58
|
try {
|
|
35
59
|
args = parseArgs(process.argv.slice(2));
|
|
@@ -44,9 +68,15 @@ async function main() {
|
|
|
44
68
|
}
|
|
45
69
|
throw err;
|
|
46
70
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
71
|
+
const mode = resolveMode(args);
|
|
72
|
+
if (mode === 'usage') {
|
|
73
|
+
printUsage();
|
|
74
|
+
process.exit(2);
|
|
75
|
+
}
|
|
76
|
+
intro(pc.bold(pc.cyan('@tinycld/bootstrap')));
|
|
77
|
+
if (mode === 'assemble-only') {
|
|
78
|
+
runAssembleOnly({ root: process.cwd(), members: args.with });
|
|
79
|
+
outro(pc.green(composeAssembleOutro(args.with)));
|
|
50
80
|
return;
|
|
51
81
|
}
|
|
52
82
|
const answers = await runPrompts(args);
|
|
@@ -67,6 +97,39 @@ async function main() {
|
|
|
67
97
|
const layout = detectLayoutFromTarget(answers.targetDir, answers.slug);
|
|
68
98
|
printNextSteps({ slug: answers.slug, relTarget, linked, layout });
|
|
69
99
|
}
|
|
100
|
+
export function composeAssembleOutro(members) {
|
|
101
|
+
const extras = members?.length ? `, ${members.join(', ')}` : '';
|
|
102
|
+
return `Workspace assembled (app + core${extras}). Run \`npm install\` at the root.`;
|
|
103
|
+
}
|
|
104
|
+
export function resolveMode(args) {
|
|
105
|
+
if (args.assembleOnly && args.new) {
|
|
106
|
+
console.error(pc.red('Bad arguments: --assemble-only and --new are mutually exclusive.'));
|
|
107
|
+
return 'usage';
|
|
108
|
+
}
|
|
109
|
+
if (args.assembleOnly)
|
|
110
|
+
return 'assemble-only';
|
|
111
|
+
if (args.new)
|
|
112
|
+
return 'new';
|
|
113
|
+
return 'usage';
|
|
114
|
+
}
|
|
115
|
+
function printUsage() {
|
|
116
|
+
const lines = [
|
|
117
|
+
'',
|
|
118
|
+
`${pc.bold('@tinycld/bootstrap')} — scaffolder + workspace assembler`,
|
|
119
|
+
'',
|
|
120
|
+
pc.bold('Modes (one is required):'),
|
|
121
|
+
` ${pc.cyan('--new <slug>')} Scaffold a new feature package.`,
|
|
122
|
+
` ${pc.cyan('--assemble-only')} Assemble a workspace root (clones app + core + --with features).`,
|
|
123
|
+
'',
|
|
124
|
+
pc.bold('Examples:'),
|
|
125
|
+
' npx @tinycld/bootstrap --new my-feature',
|
|
126
|
+
' npx @tinycld/bootstrap --assemble-only --with mail --with contacts',
|
|
127
|
+
'',
|
|
128
|
+
pc.dim('Full reference: https://tinycld.org/docs/reference/cli'),
|
|
129
|
+
'',
|
|
130
|
+
];
|
|
131
|
+
console.log(lines.join('\n'));
|
|
132
|
+
}
|
|
70
133
|
function detectLayoutFromTarget(targetDir, slug) {
|
|
71
134
|
// If cwd is itself a workspace root and target is a direct child of it,
|
|
72
135
|
// we're in attach mode. Otherwise the scaffolder created a wrapper under
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,MAAM,YAAY,CAAA;AAC3B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|