Compare commits
2 Commits
1ba1c2a32a
...
4c0fe528dc
| Author | SHA1 | Date | |
|---|---|---|---|
| 4c0fe528dc | |||
| 7e703c93b1 |
@@ -116,7 +116,7 @@ jobs:
|
|||||||
|
|
||||||
# Pass 1: stamp every manifest before anything is packed. `pnpm
|
# Pass 1: stamp every manifest before anything is packed. `pnpm
|
||||||
# publish` substitutes `workspace:*` with the version the linked
|
# publish` substitutes `workspace:*` with the version the linked
|
||||||
# package declares at pack time, so nopy-cube has to be carrying its
|
# package declares at pack time, so nopy-cubes has to be carrying its
|
||||||
# snapshot version by the time nopy is packed.
|
# snapshot version by the time nopy is packed.
|
||||||
for dir in $dirs; do
|
for dir in $dirs; do
|
||||||
base=$(node -p "require('./${dir}/package.json').version")
|
base=$(node -p "require('./${dir}/package.json').version")
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Tag-driven release of a single package.
|
# Tag-driven release of a single package.
|
||||||
#
|
#
|
||||||
# git tag nopy-v1.2.0 && git push origin nopy-v1.2.0
|
# git tag nopy-v1.2.0 && git push origin nopy-v1.2.0
|
||||||
# git tag nopy-cube-v1.2.0 && git push origin nopy-cube-v1.2.0
|
# git tag nopy-cubes-v1.2.0 && git push origin nopy-cubes-v1.2.0
|
||||||
# git tag keyman-v1.2.0 && git push origin keyman-v1.2.0
|
# git tag keyman-v1.2.0 && git push origin keyman-v1.2.0
|
||||||
#
|
#
|
||||||
# The tag is the source of truth for *which* package ships; package.json is the
|
# The tag is the source of truth for *which* package ships; package.json is the
|
||||||
# source of truth for the version, and the two must agree or the run fails.
|
# source of truth for the version, and the two must agree or the run fails.
|
||||||
#
|
#
|
||||||
# Packages that link to each other release dependency-first — `nopy-cube` before
|
# Packages that link to each other release dependency-first — `nopy-cubes` before
|
||||||
# `nopy` — because the linked version is resolved at pack time. The run refuses
|
# `nopy` — because the linked version is resolved at pack time. The run refuses
|
||||||
# to publish otherwise.
|
# to publish otherwise.
|
||||||
# A version with a prerelease part (1.2.0-rc.1) publishes under `next` instead
|
# A version with a prerelease part (1.2.0-rc.1) publishes under `next` instead
|
||||||
@@ -135,7 +135,7 @@ jobs:
|
|||||||
# package declares at this commit. If that version is not on the
|
# package declares at this commit. If that version is not on the
|
||||||
# registry yet, the release installs to a broken tree — and npmjs
|
# registry yet, the release installs to a broken tree — and npmjs
|
||||||
# only lets you unpublish for 72 hours. Release the dependency first:
|
# only lets you unpublish for 72 hours. Release the dependency first:
|
||||||
# nopy-cube, then nopy, then any bundle.
|
# nopy-cubes, then nopy, then any bundle.
|
||||||
#
|
#
|
||||||
# npmjs only: it is the irreversible one, and it needs no credentials
|
# npmjs only: it is the irreversible one, and it needs no credentials
|
||||||
# to read, which this step does not have yet.
|
# to read, which this step does not have yet.
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"hosts": [],
|
"hosts": [],
|
||||||
"cubeDirs": [],
|
"cubeDirs": [],
|
||||||
"cubePackages": ["@bitsquare/cubes-core"],
|
"cubePackages": ["@bitsquare/nopy-cubes-core"],
|
||||||
"env": {},
|
"env": {},
|
||||||
"log": {
|
"log": {
|
||||||
"verbosity": "info",
|
"verbosity": "info",
|
||||||
|
|||||||
@@ -8,17 +8,17 @@ A pnpm workspace holding two independently published CLIs, the authoring package
|
|||||||
their deployment units are written against, and one bundle of those units:
|
their deployment units are written against, and one bundle of those units:
|
||||||
|
|
||||||
| Path | Package | Binary | Role |
|
| Path | Package | Binary | Role |
|
||||||
| --------------------- | ---------------------- | -------- | -------------------------------------------------------- |
|
| -------------------------- | ----------------------------- | -------- | -------------------------------------------------------- |
|
||||||
| `packages/nopy` | `@bitsquare/nopy` | `nopy` | interactive pyinfra script management and execution |
|
| `packages/nopy` | `@bitsquare/nopy` | `nopy` | interactive pyinfra script management and execution |
|
||||||
| `packages/keyman` | `@bitsquare/keyman` | `keyman` | SSH key management, shelling out to `age` / `ssh-keygen` |
|
| `packages/keyman` | `@bitsquare/keyman` | `keyman` | SSH key management, shelling out to `age` / `ssh-keygen` |
|
||||||
| `packages/nopy-cube` | `@bitsquare/nopy-cube` | — | the authoring surface a `manifest.mjs` imports |
|
| `packages/nopy-cubes` | `@bitsquare/nopy-cubes` | — | the authoring surface a `manifest.mjs` imports |
|
||||||
| `packages/cubes-core` | `@bitsquare/cubes-core`| — | the core cube bundle (22 cubes), no TypeScript |
|
| `packages/nopy-cubes-core` | `@bitsquare/nopy-cubes-core` | — | the core cube bundle (22 cubes), no TypeScript |
|
||||||
|
|
||||||
The root package is private; everything under `packages/` ships. `keyman` stands
|
The root package is private; everything under `packages/` ships. `keyman` stands
|
||||||
alone, but `nopy` and `cubes-core` both depend on `nopy-cube` (`workspace:*`), so
|
alone, but `nopy` and `nopy-cubes-core` both depend on `nopy-cubes` (`workspace:*`), so
|
||||||
publish order matters — see *Releasing*.
|
publish order matters — see *Releasing*.
|
||||||
|
|
||||||
`cubes-core` is consumed the way a third party would consume it: the root
|
`nopy-cubes-core` is consumed the way a third party would consume it: the root
|
||||||
`.nopyrc.json` names it in `cubePackages`, and the loader reads it out of
|
`.nopyrc.json` names it in `cubePackages`, and the loader reads it out of
|
||||||
`node_modules`. There is no `cubes/` directory at the repo root any more.
|
`node_modules`. There is no `cubes/` directory at the repo root any more.
|
||||||
|
|
||||||
@@ -76,11 +76,11 @@ locally and on the runner. Barrel files (`src/index.ts`, `src/cubes/index.ts`,
|
|||||||
`src/nopy.cubes.ts`) and the Commander argv wiring (`src/*.cli.ts`) are excluded;
|
`src/nopy.cubes.ts`) and the Commander argv wiring (`src/*.cli.ts`) are excluded;
|
||||||
adding logic to those files means moving it somewhere covered.
|
adding logic to those files means moving it somewhere covered.
|
||||||
|
|
||||||
nopy's vitest config aliases `@bitsquare/nopy-cube` to that package's **source**,
|
nopy's vitest config aliases `@bitsquare/nopy-cubes` to that package's **source**,
|
||||||
not to the workspace link (which points at a `dist` that only exists after a
|
not to the workspace link (which points at a `dist` that only exists after a
|
||||||
build), so the gate does not depend on build ordering and can never run against a
|
build), so the gate does not depend on build ordering and can never run against a
|
||||||
stale artefact. The same config excludes `**/nopy-cube/**` from coverage — without
|
stale artefact. The same config excludes `**/nopy-cubes/**` from coverage — without
|
||||||
it nopy's numbers absorb another package's files. `cubes-core` has no tests of its
|
it nopy's numbers absorb another package's files. `nopy-cubes-core` has no tests of its
|
||||||
own; the loader tests in nopy cover the contract it implements.
|
own; the loader tests in nopy cover the contract it implements.
|
||||||
|
|
||||||
The three TS packages set `pool: 'forks'` because tests use `process.chdir()` — most
|
The three TS packages set `pool: 'forks'` because tests use `process.chdir()` — most
|
||||||
@@ -184,15 +184,15 @@ items 6 and 7.
|
|||||||
A cube directory holds `manifest.mjs` + `deploy.py`; anything else in it is
|
A cube directory holds `manifest.mjs` + `deploy.py`; anything else in it is
|
||||||
ignored by the loader but reachable from the script, which runs with the cube
|
ignored by the loader but reachable from the script, which runs with the cube
|
||||||
directory as its cwd. Manifests are ESM, import `Manifest` from
|
directory as its cwd. Manifests are ESM, import `Manifest` from
|
||||||
`@bitsquare/nopy-cube`, and declare `id`, `name`, a Zod `schema` (each field
|
`@bitsquare/nopy-cubes`, and declare `id`, `name`, a Zod `schema` (each field
|
||||||
`.describe()`d — the description is the prompt label — and `.default()`ed), plus
|
`.describe()`d — the description is the prompt label — and `.default()`ed), plus
|
||||||
optional `secrets`/`dependencies`/`before`/`after`.
|
optional `secrets`/`dependencies`/`before`/`after`.
|
||||||
|
|
||||||
Import from **`@bitsquare/nopy-cube`**, not `@bitsquare/nopy`. The authoring
|
Import from **`@bitsquare/nopy-cubes`**, not `@bitsquare/nopy`. The authoring
|
||||||
surface is types and a factory, with zod as its only peer — no CLI, no prompts,
|
surface is types and a factory, with zod as its only peer — no CLI, no prompts,
|
||||||
no process spawning — so a bundle can depend on it without dragging the CLI in.
|
no process spawning — so a bundle can depend on it without dragging the CLI in.
|
||||||
`@bitsquare/nopy` re-exports all of it (`cubes.Manifest`, `cubes.uniqid`, …), so
|
`@bitsquare/nopy` re-exports all of it (`cubes.Manifest`, `cubes.uniqid`, …), so
|
||||||
the older form still works; every cube in `packages/cubes-core` has been moved to
|
the older form still works; every cube in `packages/nopy-cubes-core` has been moved to
|
||||||
the new one.
|
the new one.
|
||||||
|
|
||||||
Manifests are resolved by ordinary Node resolution **from the manifest's own
|
Manifests are resolved by ordinary Node resolution **from the manifest's own
|
||||||
@@ -200,7 +200,7 @@ directory**, which used to mean a hand-written local cube failed with
|
|||||||
`ERR_MODULE_NOT_FOUND` unless you linked the package. `cubes/resolve-hook.mjs`
|
`ERR_MODULE_NOT_FOUND` unless you linked the package. `cubes/resolve-hook.mjs`
|
||||||
retires that: `loadCubes()` registers a `module.register()` resolve hook that
|
retires that: `loadCubes()` registers a `module.register()` resolve hook that
|
||||||
tries normal resolution *first* and only on failure falls back to resolving
|
tries normal resolution *first* and only on failure falls back to resolving
|
||||||
`@bitsquare/nopy-cube`, `@bitsquare/nopy` and `zod` from the running CLI's own
|
`@bitsquare/nopy-cubes`, `@bitsquare/nopy` and `zod` from the running CLI's own
|
||||||
`node_modules`. Ordinary-resolution-first is the load-bearing part — a cube that
|
`node_modules`. Ordinary-resolution-first is the load-bearing part — a cube that
|
||||||
ships its own zod keeps it. The hook is a convenience, never load-bearing:
|
ships its own zod keeps it. The hook is a convenience, never load-bearing:
|
||||||
registration is wrapped in a `try`, and a bundle installed properly never reaches
|
registration is wrapped in a `try`, and a bundle installed properly never reaches
|
||||||
@@ -242,7 +242,7 @@ The install command uses `--@bitsquare:registry=<url>`, never `--registry`:
|
|||||||
Gitea serves the `@bitsquare` scope and does **not** proxy npmjs, so a global
|
Gitea serves the `@bitsquare` scope and does **not** proxy npmjs, so a global
|
||||||
`--registry` would send every transitive dependency to a registry that has never
|
`--registry` would send every transitive dependency to a registry that has never
|
||||||
heard of them. Verified — `npm i -g @bitsquare/nopy@main --@bitsquare:registry=…`
|
heard of them. Verified — `npm i -g @bitsquare/nopy@main --@bitsquare:registry=…`
|
||||||
pulls `nopy-cube` from Gitea and the other 55 packages from npmjs. pnpm accepts
|
pulls `nopy-cubes` from Gitea and the other 55 packages from npmjs. pnpm accepts
|
||||||
the same flag; the `npm_config_@bitsquare:registry` env var does not work with
|
the same flag; the `npm_config_@bitsquare:registry` env var does not work with
|
||||||
pnpm and is not used.
|
pnpm and is not used.
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ Three things the `workspace:*` links added, all of them non-obvious:
|
|||||||
`workspace:` range survived into a tarball. It runs in both publish workflows.
|
`workspace:` range survived into a tarball. It runs in both publish workflows.
|
||||||
Note `pnpm pack` has no `--ignore-scripts` flag, so `prepack` does rebuild —
|
Note `pnpm pack` has no `--ignore-scripts` flag, so `prepack` does rebuild —
|
||||||
which means the artefact under test is the one publish ships.
|
which means the artefact under test is the one publish ships.
|
||||||
- **Order.** `packages/*/` sorts `nopy` before `nopy-cube`, which is backwards.
|
- **Order.** `packages/*/` sorts `nopy` before `nopy-cubes`, which is backwards.
|
||||||
`scripts/publish-order.mjs` topologically sorts over the `workspace:` edges;
|
`scripts/publish-order.mjs` topologically sorts over the `workspace:` edges;
|
||||||
the snapshot workflow stamps *every* version first and only then publishes in
|
the snapshot workflow stamps *every* version first and only then publishes in
|
||||||
that order, because `pnpm publish` reads the linked package's version at pack
|
that order, because `pnpm publish` reads the linked package's version at pack
|
||||||
@@ -347,9 +347,9 @@ currently have no effect. Treat `docs/REFACTORING.md` as a plan, not a record.
|
|||||||
The publish lane has now run against the Gitea registry: all four packages are
|
The publish lane has now run against the Gitea registry: all four packages are
|
||||||
there under `@main`, and `pnpm run try:snapshot` installs them into a throwaway
|
there under `@main`, and `pnpm run try:snapshot` installs them into a throwaway
|
||||||
project with npm and runs the binary. The npmjs lane has only ever published
|
project with npm and runs the binary. The npmjs lane has only ever published
|
||||||
`@bitsquare/nopy`; `keyman`, `nopy-cube` and `cubes-core` have never been
|
`@bitsquare/nopy`; `keyman`, `nopy-cubes` and `nopy-cubes-core` have never been
|
||||||
released there, so the *check linked deps are released* guard in `release.yml`
|
released there, so the *check linked deps are released* guard in `release.yml`
|
||||||
will stop the first `nopy` release until `nopy-cube` ships.
|
will stop the first `nopy` release until `nopy-cubes` ships.
|
||||||
|
|
||||||
Nothing checks that a bundle and the CLI reading it are compatible versions;
|
Nothing checks that a bundle and the CLI reading it are compatible versions;
|
||||||
`nopy.engines` was considered and deferred. `docs/CUBE-PACKAGES.md` is where all
|
`nopy.engines` was considered and deferred. `docs/CUBE-PACKAGES.md` is where all
|
||||||
|
|||||||
+1
-1
@@ -206,7 +206,7 @@ Two pairs are inverted, and both have consequences:
|
|||||||
> to deploy a cube whose required key nothing supplied. Verified against all 22
|
> to deploy a cube whose required key nothing supplied. Verified against all 22
|
||||||
> cubes in `cubes/`: 19 build a complete `-D` run, the 3 below abort by name.
|
> cubes in `cubes/`: 19 build a complete `-D` run, the 3 below abort by name.
|
||||||
>
|
>
|
||||||
> Re-measured against the 25 cubes now in `packages/cubes-core/cubes`: 20 build a
|
> Re-measured against the 25 cubes now in `packages/nopy-cubes-core/cubes`: 20 build a
|
||||||
> complete `-D` run and 5 abort by name. Two of the additions are deliberate —
|
> complete `-D` run and 5 abort by name. Two of the additions are deliberate —
|
||||||
> `user:add` lost its `PUBKEY` default (it was a specific personal key), and
|
> `user:add` lost its `PUBKEY` default (it was a specific personal key), and
|
||||||
> `ssh:keygen` inherits that failure because it declares `dependencies: () =>
|
> `ssh:keygen` inherits that failure because it declares `dependencies: () =>
|
||||||
|
|||||||
+23
-23
@@ -28,8 +28,8 @@ shipped. If you only want to cut a release, jump to
|
|||||||
| --------------------- | ----------------------- | -------- | ------------------------ |
|
| --------------------- | ----------------------- | -------- | ------------------------ |
|
||||||
| `packages/nopy` | `@bitsquare/nopy` | `nopy` | CLI |
|
| `packages/nopy` | `@bitsquare/nopy` | `nopy` | CLI |
|
||||||
| `packages/keyman` | `@bitsquare/keyman` | `keyman` | CLI |
|
| `packages/keyman` | `@bitsquare/keyman` | `keyman` | CLI |
|
||||||
| `packages/nopy-cube` | `@bitsquare/nopy-cube` | — | library (cube authoring) |
|
| `packages/nopy-cubes` | `@bitsquare/nopy-cubes` | — | library (cube authoring) |
|
||||||
| `packages/cubes-core` | `@bitsquare/cubes-core` | — | cube bundle (no build) |
|
| `packages/nopy-cubes-core` | `@bitsquare/nopy-cubes-core` | — | cube bundle (no build) |
|
||||||
|
|
||||||
All are ESM and declare `engines.node >= 22`. The two CLIs expose a single
|
All are ESM and declare `engines.node >= 22`. The two CLIs expose a single
|
||||||
executable through `bin`, so `npm install -g` puts `nopy` / `keyman` on the
|
executable through `bin`, so `npm install -g` puts `nopy` / `keyman` on the
|
||||||
@@ -37,7 +37,7 @@ executable through `bin`, so `npm install -g` puts `nopy` / `keyman` on the
|
|||||||
|
|
||||||
The tarball contents are pinned by `files` — for the three TypeScript packages
|
The tarball contents are pinned by `files` — for the three TypeScript packages
|
||||||
that is `["dist", "README.md", "LICENSE"]`, so sources and tests are not shipped.
|
that is `["dist", "README.md", "LICENSE"]`, so sources and tests are not shipped.
|
||||||
`cubes-core` ships `["cubes", "!cubes/**/*.log", "README.md", "LICENSE"]`: the
|
`nopy-cubes-core` ships `["cubes", "!cubes/**/*.log", "README.md", "LICENSE"]`: the
|
||||||
negation matters, because a cube that has been run leaves a `pyinfra-debug.log`
|
negation matters, because a cube that has been run leaves a `pyinfra-debug.log`
|
||||||
next to its `deploy.py`, and `.gitignore` does not filter an npm tarball.
|
next to its `deploy.py`, and `.gitignore` does not filter an npm tarball.
|
||||||
`publishConfig.access: "public"` is what makes a scoped package publishable to
|
`publishConfig.access: "public"` is what makes a scoped package publishable to
|
||||||
@@ -45,7 +45,7 @@ npmjs without an extra flag; the workflows pass `--access public` anyway.
|
|||||||
|
|
||||||
### Dependencies between them
|
### Dependencies between them
|
||||||
|
|
||||||
`keyman` stands alone. `nopy` and `cubes-core` both depend on `nopy-cube` through
|
`keyman` stands alone. `nopy` and `nopy-cubes-core` both depend on `nopy-cubes` through
|
||||||
`workspace:*`, which drives three rules the rest of this document keeps coming
|
`workspace:*`, which drives three rules the rest of this document keeps coming
|
||||||
back to:
|
back to:
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ back to:
|
|||||||
through verbatim and the install fails with `EUNSUPPORTEDPROTOCOL`. `pnpm
|
through verbatim and the install fails with `EUNSUPPORTEDPROTOCOL`. `pnpm
|
||||||
pack` and `pnpm publish` substitute the concrete version at pack time. Both
|
pack` and `pnpm publish` substitute the concrete version at pack time. Both
|
||||||
workflows use `pnpm publish --ignore-scripts --no-git-checks`.
|
workflows use `pnpm publish --ignore-scripts --no-git-checks`.
|
||||||
2. **`nopy-cube` publishes before anything that depends on it.**
|
2. **`nopy-cubes` publishes before anything that depends on it.**
|
||||||
`node scripts/publish-order.mjs` prints the publishable directories in
|
`node scripts/publish-order.mjs` prints the publishable directories in
|
||||||
dependency order — note that plain alphabetical `packages/*/` gets this
|
dependency order — note that plain alphabetical `packages/*/` gets this
|
||||||
backwards, putting `nopy` first.
|
backwards, putting `nopy` first.
|
||||||
@@ -124,7 +124,7 @@ The publish step is **two passes** over `node scripts/publish-order.mjs`: the
|
|||||||
first stamps the snapshot version into every manifest with `npm pkg set`, the
|
first stamps the snapshot version into every manifest with `npm pkg set`, the
|
||||||
second publishes. They cannot be one loop — `pnpm publish` reads a linked
|
second publishes. They cannot be one loop — `pnpm publish` reads a linked
|
||||||
package's version out of its manifest at pack time, so stamping and publishing
|
package's version out of its manifest at pack time, so stamping and publishing
|
||||||
one package at a time would bake the *old* `nopy-cube` version into `nopy`'s
|
one package at a time would bake the *old* `nopy-cubes` version into `nopy`'s
|
||||||
tarball.
|
tarball.
|
||||||
|
|
||||||
### `release.yml`
|
### `release.yml`
|
||||||
@@ -144,7 +144,7 @@ the whole gate.
|
|||||||
*Check linked deps are released* asks npmjs whether every `workspace:` dependency
|
*Check linked deps are released* asks npmjs whether every `workspace:` dependency
|
||||||
of the package being released already exists at the version pnpm is about to
|
of the package being released already exists at the version pnpm is about to
|
||||||
bake in (`scripts/linked-deps.mjs` → `npm view`). Tagging `nopy-v1.3.0` while
|
bake in (`scripts/linked-deps.mjs` → `npm view`). Tagging `nopy-v1.3.0` while
|
||||||
`@bitsquare/nopy-cube@1.1.0` is still unpublished would otherwise ship a tarball
|
`@bitsquare/nopy-cubes@1.1.0` is still unpublished would otherwise ship a tarball
|
||||||
nobody can install, and npmjs only lets you unpublish for 72 hours. The check is
|
nobody can install, and npmjs only lets you unpublish for 72 hours. The check is
|
||||||
npmjs-only: it runs before any credentials are written, and npmjs is the registry
|
npmjs-only: it runs before any credentials are written, and npmjs is the registry
|
||||||
where the mistake is permanent.
|
where the mistake is permanent.
|
||||||
@@ -253,26 +253,26 @@ the same way:
|
|||||||
```sh
|
```sh
|
||||||
git tag nopy-v1.2.0
|
git tag nopy-v1.2.0
|
||||||
git tag keyman-v1.2.0
|
git tag keyman-v1.2.0
|
||||||
git tag nopy-cube-v1.2.0
|
git tag nopy-cubes-v1.2.0
|
||||||
git tag cubes-core-v1.2.0
|
git tag nopy-cubes-core-v1.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Ordering when more than one package changed
|
### Ordering when more than one package changed
|
||||||
|
|
||||||
Tags are independent, but the dependency graph is not. If a release touches
|
Tags are independent, but the dependency graph is not. If a release touches
|
||||||
`nopy-cube` *and* something that depends on it, release them in this order,
|
`nopy-cubes` *and* something that depends on it, release them in this order,
|
||||||
waiting for each run to go green:
|
waiting for each run to go green:
|
||||||
|
|
||||||
```
|
```
|
||||||
nopy-cube → nopy, cubes-core (these two are independent of each other)
|
nopy-cubes → nopy, nopy-cubes-core (these two are independent of each other)
|
||||||
```
|
```
|
||||||
|
|
||||||
Release `nopy` first and the run stops at the *check linked deps* step, telling
|
Release `nopy` first and the run stops at the *check linked deps* step, telling
|
||||||
you the `nopy-cube` version it wanted is not on npmjs. That is the guard working;
|
you the `nopy-cubes` version it wanted is not on npmjs. That is the guard working;
|
||||||
release `nopy-cube`, then re-tag. `node scripts/publish-order.mjs` prints the
|
release `nopy-cubes`, then re-tag. `node scripts/publish-order.mjs` prints the
|
||||||
order if you would rather not reason about it.
|
order if you would rather not reason about it.
|
||||||
|
|
||||||
Bumping `nopy-cube` means bumping the packages that depend on it in the same
|
Bumping `nopy-cubes` means bumping the packages that depend on it in the same
|
||||||
change — the `workspace:*` range resolves to whatever version is in the workspace
|
change — the `workspace:*` range resolves to whatever version is in the workspace
|
||||||
at pack time, so their next release picks it up whether or not you meant it to.
|
at pack time, so their next release picks it up whether or not you meant it to.
|
||||||
|
|
||||||
@@ -387,12 +387,12 @@ npm install -g @bitsquare/nopy @bitsquare/keyman
|
|||||||
```
|
```
|
||||||
|
|
||||||
The other two go into a project. A cube bundle is a dev dependency of whatever
|
The other two go into a project. A cube bundle is a dev dependency of whatever
|
||||||
repo describes your infrastructure; `nopy-cube` is only needed if you are writing
|
repo describes your infrastructure; `nopy-cubes` is only needed if you are writing
|
||||||
cubes of your own:
|
cubes of your own:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm add -D @bitsquare/cubes-core # then name it in .nopyrc.json cubePackages
|
pnpm add -D @bitsquare/nopy-cubes-core # then name it in .nopyrc.json cubePackages
|
||||||
pnpm add -D @bitsquare/nopy-cube zod # authoring your own manifests
|
pnpm add -D @bitsquare/nopy-cubes zod # authoring your own manifests
|
||||||
```
|
```
|
||||||
|
|
||||||
From the Gitea registry, which holds every snapshot plus a mirror of every
|
From the Gitea registry, which holds every snapshot plus a mirror of every
|
||||||
@@ -525,9 +525,9 @@ pnpm run try:snapshot -- --keep # keep the directory
|
|||||||
|
|
||||||
`scripts/try-snapshot.mjs` builds a throwaway project in a temp directory,
|
`scripts/try-snapshot.mjs` builds a throwaway project in a temp directory,
|
||||||
points the `@bitsquare` scope at the registry, installs `@bitsquare/nopy` and
|
points the `@bitsquare` scope at the registry, installs `@bitsquare/nopy` and
|
||||||
`@bitsquare/cubes-core` at that tag, and then:
|
`@bitsquare/nopy-cubes-core` at that tag, and then:
|
||||||
|
|
||||||
- asserts the installed `nopy` declares a **concrete** `nopy-cube` version
|
- asserts the installed `nopy` declares a **concrete** `nopy-cubes` version
|
||||||
rather than a leaked `workspace:*` range;
|
rather than a leaked `workspace:*` range;
|
||||||
- prints the three resolved versions, so you can see which commit you are on;
|
- prints the three resolved versions, so you can see which commit you are on;
|
||||||
- runs `nopy --version`;
|
- runs `nopy --version`;
|
||||||
@@ -662,13 +662,13 @@ Use **npm**, not pnpm: npm is the one that rejects a leaked `workspace:` range,
|
|||||||
so a clean install here is the real proof.
|
so a clean install here is the real proof.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm --filter @bitsquare/nopy-cube pack --pack-destination /tmp/tgz
|
pnpm --filter @bitsquare/nopy-cubes pack --pack-destination /tmp/tgz
|
||||||
pnpm --filter @bitsquare/nopy pack --pack-destination /tmp/tgz
|
pnpm --filter @bitsquare/nopy pack --pack-destination /tmp/tgz
|
||||||
pnpm --filter @bitsquare/cubes-core pack --pack-destination /tmp/tgz
|
pnpm --filter @bitsquare/nopy-cubes-core pack --pack-destination /tmp/tgz
|
||||||
|
|
||||||
mkdir /tmp/try && cd /tmp/try && npm init -y
|
mkdir /tmp/try && cd /tmp/try && npm init -y
|
||||||
npm install /tmp/tgz/*.tgz
|
npm install /tmp/tgz/*.tgz
|
||||||
echo '{"hosts":["h"],"cubePackages":["@bitsquare/cubes-core"]}' > .nopyrc.json
|
echo '{"hosts":["h"],"cubePackages":["@bitsquare/nopy-cubes-core"]}' > .nopyrc.json
|
||||||
./node_modules/.bin/nopy install -l session.json -P -D
|
./node_modules/.bin/nopy install -l session.json -P -D
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -713,7 +713,7 @@ pnpm run registry:status
|
|||||||
| Snapshot workflow green, nothing installable | Snapshots are only on Gitea and only under `@main`. Point the scope at the Gitea registry. |
|
| Snapshot workflow green, nothing installable | Snapshots are only on Gitea and only under `@main`. Point the scope at the Gitea registry. |
|
||||||
| The release workflow did not trigger | The tag must match `*-v*` and must be pushed (`git push origin <tag>`), not just created. |
|
| The release workflow did not trigger | The tag must match `*-v*` and must be pushed (`git push origin <tag>`), not just created. |
|
||||||
| `EUNSUPPORTEDPROTOCOL` / `Unsupported URL Type "workspace:"` on install | A `workspace:` range reached a tarball — something published with `npm publish` instead of `pnpm publish`. `verify-pack.mjs` exists to catch this before it ships. |
|
| `EUNSUPPORTEDPROTOCOL` / `Unsupported URL Type "workspace:"` on install | A `workspace:` range reached a tarball — something published with `npm publish` instead of `pnpm publish`. `verify-pack.mjs` exists to catch this before it ships. |
|
||||||
| `... is not published yet on npmjs` before the gate runs | Releasing a package before its `nopy-cube` dependency. Tag and release `nopy-cube` first, then re-tag. |
|
| `... is not published yet on npmjs` before the gate runs | Releasing a package before its `nopy-cubes` dependency. Tag and release `nopy-cubes` first, then re-tag. |
|
||||||
| `verify-pack.mjs` fails locally with a build error | `pnpm pack` runs `prepack`, so a broken build fails the check. Fix the build; there is no skip flag. |
|
| `verify-pack.mjs` fails locally with a build error | `pnpm pack` runs `prepack`, so a broken build fails the check. Fix the build; there is no skip flag. |
|
||||||
|
|
||||||
## Recovering from a bad publish
|
## Recovering from a bad publish
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^2.5.5",
|
"@biomejs/biome": "^2.5.5",
|
||||||
"@bitsquare/cubes-core": "workspace:*",
|
"@bitsquare/nopy-cubes-core": "workspace:*",
|
||||||
"@logtape/logtape": "^2.2.4",
|
"@logtape/logtape": "^2.2.4",
|
||||||
"@types/node": "^26.1.1",
|
"@types/node": "^26.1.1",
|
||||||
"simple-git-hooks": "^2.13.1",
|
"simple-git-hooks": "^2.13.1",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# @bitsquare/cubes-core
|
# @bitsquare/nopy-cubes-core
|
||||||
|
|
||||||
The core cube bundle for [nopy](https://www.npmjs.com/package/@bitsquare/nopy):
|
The core cube bundle for [nopy](https://www.npmjs.com/package/@bitsquare/nopy):
|
||||||
base packages, users, SSH, firewalling, networking, web serving and runtimes.
|
base packages, users, SSH, firewalling, networking, web serving and runtimes.
|
||||||
@@ -6,7 +6,7 @@ base packages, users, SSH, firewalling, networking, web serving and runtimes.
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm add -D @bitsquare/cubes-core
|
pnpm add -D @bitsquare/nopy-cubes-core
|
||||||
```
|
```
|
||||||
|
|
||||||
Then name it in `.nopyrc.json`:
|
Then name it in `.nopyrc.json`:
|
||||||
@@ -14,7 +14,7 @@ Then name it in `.nopyrc.json`:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"hosts": ["web-1"],
|
"hosts": ["web-1"],
|
||||||
"cubePackages": ["@bitsquare/cubes-core"]
|
"cubePackages": ["@bitsquare/nopy-cubes-core"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
id: 'admin:cockpit',
|
id: 'admin:cockpit',
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest, uniqid } from '@bitsquare/nopy-cube';
|
import { Manifest, uniqid } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
+1
-1
@@ -12,7 +12,7 @@ Configures system keyboard layout permanently by updating `/etc/default/keyboard
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
name: 'My Host Setup',
|
name: 'My Host Setup',
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
id: 'armor:fail2ban',
|
id: 'armor:fail2ban',
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
// [agnt://cogen/cogen/network-wifi-connection-1]{cartridge: "ansiblings/cubes", action: "generated", status: "generated"}
|
// [agnt://cogen/cogen/network-wifi-connection-1]{cartridge: "ansiblings/cubes", action: "generated", status: "generated"}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest, uniqid } from '@bitsquare/nopy-cube';
|
import { Manifest, uniqid } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
// [agnt://cogen/cogen/user-edit-1]{cartridge: "ansiblings/cubes", action: "generated", status: "generated"}
|
// [agnt://cogen/cogen/user-edit-1]{cartridge: "ansiblings/cubes", action: "generated", status: "generated"}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@bitsquare/cubes-core",
|
"name": "@bitsquare/nopy-cubes-core",
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"description": "The core nopy cube bundle: apt, users, ssh, networking, services and runtimes.",
|
"description": "The core nopy cube bundle: apt, users, ssh, networking, services and runtimes.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -15,9 +15,9 @@
|
|||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://gitea.bitsquare.dev/BitSquare/ansiblings.git",
|
"url": "git+https://gitea.bitsquare.dev/BitSquare/ansiblings.git",
|
||||||
"directory": "packages/cubes-core"
|
"directory": "packages/nopy-cubes-core"
|
||||||
},
|
},
|
||||||
"homepage": "https://gitea.bitsquare.dev/BitSquare/ansiblings/src/branch/main/packages/cubes-core",
|
"homepage": "https://gitea.bitsquare.dev/BitSquare/ansiblings/src/branch/main/packages/nopy-cubes-core",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitea.bitsquare.dev/BitSquare/ansiblings/issues"
|
"url": "https://gitea.bitsquare.dev/BitSquare/ansiblings/issues"
|
||||||
},
|
},
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bitsquare/nopy-cube": "workspace:*",
|
"@bitsquare/nopy-cubes": "workspace:*",
|
||||||
"zod": "^4.4.3"
|
"zod": "^4.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# @bitsquare/nopy-cube
|
# @bitsquare/nopy-cubes
|
||||||
|
|
||||||
The authoring surface for [nopy](https://www.npmjs.com/package/@bitsquare/nopy)
|
The authoring surface for [nopy](https://www.npmjs.com/package/@bitsquare/nopy)
|
||||||
cubes — the `Manifest` factory, the `Cube` class, and the types around them.
|
cubes — the `Manifest` factory, the `Cube` class, and the types around them.
|
||||||
@@ -12,7 +12,7 @@ re-exports everything here, so a manifest that already imports from
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm add @bitsquare/nopy-cube zod
|
pnpm add @bitsquare/nopy-cubes zod
|
||||||
```
|
```
|
||||||
|
|
||||||
`zod` is a **peer dependency** on purpose: the manifest, the schema it builds and
|
`zod` is a **peer dependency** on purpose: the manifest, the schema it builds and
|
||||||
@@ -22,7 +22,7 @@ the `Manifest` factory should all see the same copy.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
// cubes/net/tailscale/manifest.mjs
|
// cubes/net/tailscale/manifest.mjs
|
||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@bitsquare/nopy-cube",
|
"name": "@bitsquare/nopy-cubes",
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"description": "Authoring types for nopy cubes: the Manifest factory and the Cube contract.",
|
"description": "Authoring types for nopy cubes: the Manifest factory and the Cube contract.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -14,9 +14,9 @@
|
|||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://gitea.bitsquare.dev/BitSquare/ansiblings.git",
|
"url": "git+https://gitea.bitsquare.dev/BitSquare/ansiblings.git",
|
||||||
"directory": "packages/nopy-cube"
|
"directory": "packages/nopy-cubes"
|
||||||
},
|
},
|
||||||
"homepage": "https://gitea.bitsquare.dev/BitSquare/ansiblings/src/branch/main/packages/nopy-cube",
|
"homepage": "https://gitea.bitsquare.dev/BitSquare/ansiblings/src/branch/main/packages/nopy-cubes",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitea.bitsquare.dev/BitSquare/ansiblings/issues"
|
"url": "https://gitea.bitsquare.dev/BitSquare/ansiblings/issues"
|
||||||
},
|
},
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @bitsquare/nopy-cube — the authoring surface for nopy cubes.
|
* @bitsquare/nopy-cubes — the authoring surface for nopy cubes.
|
||||||
*
|
*
|
||||||
* Everything a `manifest.mjs` needs and nothing else: no CLI, no prompts, no
|
* Everything a `manifest.mjs` needs and nothing else: no CLI, no prompts, no
|
||||||
* process spawning. `@bitsquare/nopy` re-exports all of it, so a manifest can
|
* process spawning. `@bitsquare/nopy` re-exports all of it, so a manifest can
|
||||||
@@ -164,7 +164,7 @@ Uses `.nopyrc.json` files (project-level or home directory) containing:
|
|||||||
{
|
{
|
||||||
"hosts": ["host1.example.com", "host2.example.com"],
|
"hosts": ["host1.example.com", "host2.example.com"],
|
||||||
"cubeDirs": ["./cubes", "../shared-cubes"],
|
"cubeDirs": ["./cubes", "../shared-cubes"],
|
||||||
"cubePackages": ["@bitsquare/cubes-core"],
|
"cubePackages": ["@bitsquare/nopy-cubes-core"],
|
||||||
"env": {
|
"env": {
|
||||||
"SHARED_VAR": "value"
|
"SHARED_VAR": "value"
|
||||||
},
|
},
|
||||||
@@ -314,11 +314,11 @@ A cube package is an ordinary npm package that ships its cubes in a `cubes/` dir
|
|||||||
Install it and name it — nothing needs linking or copying:
|
Install it and name it — nothing needs linking or copying:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm add -D @bitsquare/cubes-core
|
pnpm add -D @bitsquare/nopy-cubes-core
|
||||||
```
|
```
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "cubePackages": ["@bitsquare/cubes-core"] }
|
{ "cubePackages": ["@bitsquare/nopy-cubes-core"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
Naming a package is a statement that cubes are expected from it, so anything wrong is an error that aborts the run rather than a silent skip: the package is not installed, it has neither a `cubes/` directory nor a `nopy.cubes` override, its `nopy.cubes` is malformed, or an entry points at a directory that does not exist or lies outside the package.
|
Naming a package is a statement that cubes are expected from it, so anything wrong is an error that aborts the run rather than a silent skip: the package is not installed, it has neither a `cubes/` directory nor a `nopy.cubes` override, its `nopy.cubes` is malformed, or an entry points at a directory that does not exist or lies outside the package.
|
||||||
@@ -341,11 +341,11 @@ The cubes live in a separate bundle, installed into whichever project describes
|
|||||||
your infrastructure and named in its `.nopyrc.json`:
|
your infrastructure and named in its `.nopyrc.json`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm add -D @bitsquare/cubes-core
|
pnpm add -D @bitsquare/nopy-cubes-core
|
||||||
```
|
```
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "hosts": ["your-host"], "cubePackages": ["@bitsquare/cubes-core"] }
|
{ "hosts": ["your-host"], "cubePackages": ["@bitsquare/nopy-cubes-core"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Channels
|
#### Channels
|
||||||
|
|||||||
+14
-14
@@ -1,7 +1,7 @@
|
|||||||
# Nopy API Reference
|
# Nopy API Reference
|
||||||
|
|
||||||
The public surface of **`@bitsquare/nopy`** (the CLI and its library exports) and
|
The public surface of **`@bitsquare/nopy`** (the CLI and its library exports) and
|
||||||
of **`@bitsquare/nopy-cube`** (the authoring package a `manifest.mjs` imports).
|
of **`@bitsquare/nopy-cubes`** (the authoring package a `manifest.mjs` imports).
|
||||||
|
|
||||||
Everything below was checked against the source. Where the code does something a
|
Everything below was checked against the source. Where the code does something a
|
||||||
reader would not expect — a field that is always empty, a function nothing calls
|
reader would not expect — a field that is always empty, a function nothing calls
|
||||||
@@ -10,14 +10,14 @@ reader would not expect — a field that is always empty, a function nothing cal
|
|||||||
|
|
||||||
If you are writing cubes rather than calling nopy from code, you want
|
If you are writing cubes rather than calling nopy from code, you want
|
||||||
[CUBE-BUNDLES.md](CUBE-BUNDLES.md) and [HOOKS.md](HOOKS.md); only the
|
[CUBE-BUNDLES.md](CUBE-BUNDLES.md) and [HOOKS.md](HOOKS.md); only the
|
||||||
[Authoring API](#authoring-api-bitsquarenopy-cube) section here applies to you.
|
[Authoring API](#authoring-api-bitsquarenopy-cubes) section here applies to you.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Two packages](#two-packages)
|
- [Two packages](#two-packages)
|
||||||
- [Authoring API (`@bitsquare/nopy-cube`)](#authoring-api-bitsquarenopy-cube)
|
- [Authoring API (`@bitsquare/nopy-cubes`)](#authoring-api-bitsquarenopy-cubes)
|
||||||
- [Main Module](#main-module)
|
- [Main Module](#main-module)
|
||||||
- [Cubes Module](#cubes-module)
|
- [Cubes Module](#cubes-module)
|
||||||
- [Variables Module](#variables-module)
|
- [Variables Module](#variables-module)
|
||||||
@@ -38,15 +38,15 @@ If you are writing cubes rather than calling nopy from code, you want
|
|||||||
|
|
||||||
| Package | Contains | Depends on |
|
| Package | Contains | Depends on |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `@bitsquare/nopy-cube` | `Manifest`, `Cube`, `Hook`, `uniqid`, the zod helpers | zod (peer) |
|
| `@bitsquare/nopy-cubes` | `Manifest`, `Cube`, `Hook`, `uniqid`, the zod helpers | zod (peer) |
|
||||||
| `@bitsquare/nopy` | the CLI, the loader, config, sessions, execution | `@bitsquare/nopy-cube` |
|
| `@bitsquare/nopy` | the CLI, the loader, config, sessions, execution | `@bitsquare/nopy-cubes` |
|
||||||
|
|
||||||
A `manifest.mjs` should import from **`@bitsquare/nopy-cube`**: it is types and a
|
A `manifest.mjs` should import from **`@bitsquare/nopy-cubes`**: it is types and a
|
||||||
factory with no CLI, no prompts and no process spawning, so a cube bundle can
|
factory with no CLI, no prompts and no process spawning, so a cube bundle can
|
||||||
depend on it without pulling the whole tool into its dependency graph.
|
depend on it without pulling the whole tool into its dependency graph.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { Manifest } from '@bitsquare/nopy-cube'; // prefer this
|
import { Manifest } from '@bitsquare/nopy-cubes'; // prefer this
|
||||||
import { cubes } from '@bitsquare/nopy'; // cubes.Manifest — still supported
|
import { cubes } from '@bitsquare/nopy'; // cubes.Manifest — still supported
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ compatibility; it also carries a `cubes.load` alias for `loadCubes`.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Authoring API (`@bitsquare/nopy-cube`)
|
## Authoring API (`@bitsquare/nopy-cubes`)
|
||||||
|
|
||||||
### `Manifest(opts)`
|
### `Manifest(opts)`
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ Factory for a cube manifest. `name` is the only required option; everything else
|
|||||||
is filled in.
|
is filled in.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
@@ -85,7 +85,7 @@ Defaults applied by the factory: `id: ''`, `schema: z.object({})`,
|
|||||||
`createManifest` and `manifest` are exported as identical aliases.
|
`createManifest` and `manifest` are exported as identical aliases.
|
||||||
`ManifestFactory` is a third alias, marked `@deprecated` — and it is not
|
`ManifestFactory` is a third alias, marked `@deprecated` — and it is not
|
||||||
re-exported through `@bitsquare/nopy`, so it is only reachable from
|
re-exported through `@bitsquare/nopy`, so it is only reachable from
|
||||||
`@bitsquare/nopy-cube` directly.
|
`@bitsquare/nopy-cubes` directly.
|
||||||
|
|
||||||
#### `Manifest<Schema>` (interface)
|
#### `Manifest<Schema>` (interface)
|
||||||
|
|
||||||
@@ -336,7 +336,7 @@ for callers that only want to display what was found.
|
|||||||
|
|
||||||
`loadCubes()` also registers the resolve hook (`cubes/resolve-hook.mjs`) before
|
`loadCubes()` also registers the resolve hook (`cubes/resolve-hook.mjs`) before
|
||||||
importing anything. The hook tries ordinary Node resolution first and only on
|
importing anything. The hook tries ordinary Node resolution first and only on
|
||||||
failure falls back to resolving `@bitsquare/nopy-cube`, `@bitsquare/nopy` and
|
failure falls back to resolving `@bitsquare/nopy-cubes`, `@bitsquare/nopy` and
|
||||||
`zod` from the running CLI's own `node_modules` — so a hand-written cube in a
|
`zod` from the running CLI's own `node_modules` — so a hand-written cube in a
|
||||||
directory with no `node_modules` loads, while a cube shipping its own zod keeps
|
directory with no `node_modules` loads, while a cube shipping its own zod keeps
|
||||||
it. Registration is best-effort: it is a convenience, never load-bearing.
|
it. Registration is best-effort: it is a convenience, never load-bearing.
|
||||||
@@ -811,7 +811,7 @@ type ResolutionConfig = { [K in keyof NopyConfig]?: ResolutionStrategy };
|
|||||||
### `CubePackageRef`
|
### `CubePackageRef`
|
||||||
|
|
||||||
A package named in `cubePackages`, paired with where it was named. In the file an
|
A package named in `cubePackages`, paired with where it was named. In the file an
|
||||||
entry is just a string (`"@bitsquare/cubes-core"`); `loadConfig()` normalises it.
|
entry is just a string (`"@bitsquare/nopy-cubes-core"`); `loadConfig()` normalises it.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface CubePackageRef {
|
interface CubePackageRef {
|
||||||
@@ -848,7 +848,7 @@ objects deep-merge, primitives are replaced. `override` replaces outright.
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"hosts": ["local-host"],
|
"hosts": ["local-host"],
|
||||||
"cubePackages": ["@bitsquare/cubes-core"],
|
"cubePackages": ["@bitsquare/nopy-cubes-core"],
|
||||||
"resolution": { "hosts": "override" }
|
"resolution": { "hosts": "override" }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -1111,7 +1111,7 @@ working directory. The prefixed forms `<name>.manifest.mjs` and
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// manifest.mjs
|
// manifest.mjs
|
||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ what changes once a cube lives in `node_modules` instead of in your own tree.
|
|||||||
If you only want to *use* a published bundle, you need one line of config:
|
If you only want to *use* a published bundle, you need one line of config:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "cubePackages": ["@bitsquare/cubes-core"] }
|
{ "cubePackages": ["@bitsquare/nopy-cubes-core"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
The rest of this document is for writing one.
|
The rest of this document is for writing one.
|
||||||
@@ -39,7 +39,7 @@ and imports each `manifest.mjs` directly.
|
|||||||
└── deploy.py
|
└── deploy.py
|
||||||
```
|
```
|
||||||
|
|
||||||
`@bitsquare/cubes-core` in this repository is the worked example, and is consumed
|
`@bitsquare/nopy-cubes-core` in this repository is the worked example, and is consumed
|
||||||
by this repository through exactly the mechanism described here — it is not
|
by this repository through exactly the mechanism described here — it is not
|
||||||
special-cased.
|
special-cased.
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ special-cased.
|
|||||||
"files": ["cubes", "!cubes/**/*.log", "README.md", "LICENSE"],
|
"files": ["cubes", "!cubes/**/*.log", "README.md", "LICENSE"],
|
||||||
"publishConfig": { "access": "public" },
|
"publishConfig": { "access": "public" },
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bitsquare/nopy-cube": "^1.0.0",
|
"@bitsquare/nopy-cubes": "^1.0.0",
|
||||||
"zod": "^4.4.3"
|
"zod": "^4.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ not behave the way you expect.
|
|||||||
leaves a `pyinfra-debug.log` next to its `deploy.py`, and `.gitignore` has no
|
leaves a `pyinfra-debug.log` next to its `deploy.py`, and `.gitignore` has no
|
||||||
effect on what npm packs. Check with `npm pack --dry-run` before publishing.
|
effect on what npm packs. Check with `npm pack --dry-run` before publishing.
|
||||||
|
|
||||||
**Dependencies** are `@bitsquare/nopy-cube` and `zod`, both real dependencies
|
**Dependencies** are `@bitsquare/nopy-cubes` and `zod`, both real dependencies
|
||||||
rather than peers — a bundle is a leaf, and the copies it gets are the copies its
|
rather than peers — a bundle is a leaf, and the copies it gets are the copies its
|
||||||
manifests use. Do **not** depend on `@bitsquare/nopy`: the CLI is what installs
|
manifests use. Do **not** depend on `@bitsquare/nopy`: the CLI is what installs
|
||||||
your bundle, not the other way round, and depending on it invites two copies of
|
your bundle, not the other way round, and depending on it invites two copies of
|
||||||
@@ -101,7 +101,7 @@ directory as its working directory.
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// cubes/nginx/manifest.mjs
|
// cubes/nginx/manifest.mjs
|
||||||
import { Manifest } from '@bitsquare/nopy-cube';
|
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export default Manifest({
|
export default Manifest({
|
||||||
@@ -127,7 +127,7 @@ SERVER_NAME = host.data.SERVER_NAME
|
|||||||
apt.packages(name='Install nginx', packages=['nginx'], _sudo=True)
|
apt.packages(name='Install nginx', packages=['nginx'], _sudo=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
Import **`@bitsquare/nopy-cube`**, not `@bitsquare/nopy`. It is types and a
|
Import **`@bitsquare/nopy-cubes`**, not `@bitsquare/nopy`. It is types and a
|
||||||
factory with zod as its only peer — no CLI, no prompts, no process spawning — so
|
factory with zod as its only peer — no CLI, no prompts, no process spawning — so
|
||||||
your bundle stays a leaf. (`@bitsquare/nopy` re-exports the same surface as
|
your bundle stays a leaf. (`@bitsquare/nopy` re-exports the same surface as
|
||||||
`cubes.Manifest`, which is what older manifests use. It still works; it just
|
`cubes.Manifest`, which is what older manifests use. It still works; it just
|
||||||
@@ -214,10 +214,10 @@ the cube scan itself.
|
|||||||
|
|
||||||
**How a manifest finds its imports.** Ordinary Node resolution, from the
|
**How a manifest finds its imports.** Ordinary Node resolution, from the
|
||||||
manifest's own directory. An installed bundle has its own `node_modules` with
|
manifest's own directory. An installed bundle has its own `node_modules` with
|
||||||
`@bitsquare/nopy-cube` and `zod` in it, so this just works. A hand-written cube
|
`@bitsquare/nopy-cubes` and `zod` in it, so this just works. A hand-written cube
|
||||||
sitting in a directory with no `node_modules` would historically fail with
|
sitting in a directory with no `node_modules` would historically fail with
|
||||||
`ERR_MODULE_NOT_FOUND`; nopy now registers a resolve hook that catches exactly
|
`ERR_MODULE_NOT_FOUND`; nopy now registers a resolve hook that catches exactly
|
||||||
that case and falls back to resolving `@bitsquare/nopy-cube`, `@bitsquare/nopy`
|
that case and falls back to resolving `@bitsquare/nopy-cubes`, `@bitsquare/nopy`
|
||||||
and `zod` from the running CLI. Normal resolution is always tried first, so a
|
and `zod` from the running CLI. Normal resolution is always tried first, so a
|
||||||
cube that ships its own zod keeps it. Treat the hook as a convenience for local
|
cube that ships its own zod keeps it. Treat the hook as a convenience for local
|
||||||
cubes — a published bundle must declare its dependencies properly.
|
cubes — a published bundle must declare its dependencies properly.
|
||||||
@@ -272,6 +272,6 @@ For how this repository releases its own packages, see
|
|||||||
| `'…' does not exist in …` | A `nopy.cubes` entry pointing at a directory the tarball does not contain. |
|
| `'…' does not exist in …` | A `nopy.cubes` entry pointing at a directory the tarball does not contain. |
|
||||||
| `'…' points outside the package` | A `nopy.cubes` entry escaping the package root. Not allowed. |
|
| `'…' points outside the package` | A `nopy.cubes` entry escaping the package root. Not allowed. |
|
||||||
| `Duplicate cube id 'X' from N sources:` | Two or more cubes claiming one id; the message lists each source. Rename one — there is no precedence rule to lean on. |
|
| `Duplicate cube id 'X' from N sources:` | Two or more cubes claiming one id; the message lists each source. Rename one — there is no precedence rule to lean on. |
|
||||||
| `ERR_MODULE_NOT_FOUND` for `zod` or `@bitsquare/nopy-cube` | The bundle did not declare them as dependencies. The resolve-hook fallback covers loose local cubes, not published packages. |
|
| `ERR_MODULE_NOT_FOUND` for `zod` or `@bitsquare/nopy-cubes` | The bundle did not declare them as dependencies. The resolve-hook fallback covers loose local cubes, not published packages. |
|
||||||
| `Invalid manifest in …: 'secrets' names X, which is not in the schema` | A `secrets` entry with no matching schema key — usually a typo or a renamed field. |
|
| `Invalid manifest in …: 'secrets' names X, which is not in the schema` | A `secrets` entry with no matching schema key — usually a typo or a renamed field. |
|
||||||
| Cubes work linked, fail installed | Almost always a write into the cube's own directory, or a file missing from `files`. |
|
| Cubes work linked, fail installed | Almost always a write into the cube's own directory, or a file missing from `files`. |
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Status: **All six phases have landed. This document is now a record, not a plan.**
|
Status: **All six phases have landed. This document is now a record, not a plan.**
|
||||||
The one thing still unproven is the publish lane against a real registry — see
|
The one thing still unproven is the publish lane against a real registry — see
|
||||||
*Risks*.
|
*Risks*.
|
||||||
`cubePackages` resolves and loads end to end, `@bitsquare/nopy-cube` exists and
|
`cubePackages` resolves and loads end to end, `@bitsquare/nopy-cubes` exists and
|
||||||
the publish lane can ship a linked package. What is missing is a bundle to point
|
the publish lane can ship a linked package. What is missing is a bundle to point
|
||||||
`cubePackages` at.
|
`cubePackages` at.
|
||||||
|
|
||||||
@@ -35,8 +35,8 @@ and have its cubes show up in `nopy` alongside local ones.
|
|||||||
| Duplicate cube ids across sources | **Hard error.** No precedence, no shadowing. Mitigation is a good error message, not a fallback. |
|
| Duplicate cube ids across sources | **Hard error.** No precedence, no shadowing. Mitigation is a good error message, not a fallback. |
|
||||||
| Id format | Unchanged, flat. The id is the session key (`dependencies.ts:135`); changing it breaks `--repeat-last` and `--history`. |
|
| Id format | Unchanged, flat. The id is the session key (`dependencies.ts:135`); changing it breaks `--repeat-last` and `--history`. |
|
||||||
| Discovery | Explicit `cubePackages` list in `.nopyrc.json`. |
|
| Discovery | Explicit `cubePackages` list in `.nopyrc.json`. |
|
||||||
| Migrate in-repo `cubes/` | Yes — `packages/cubes-core`, as the proof of concept. |
|
| Migrate in-repo `cubes/` | Yes — `packages/nopy-cubes-core`, as the proof of concept. |
|
||||||
| Split an authoring package (`@bitsquare/nopy-cube`) | **Yes.** Bundles take a regular dependency on it; `@bitsquare/nopy` re-exports it for backwards compatibility. See *Phase 4*. |
|
| Split an authoring package (`@bitsquare/nopy-cubes`) | **Yes.** Bundles take a regular dependency on it; `@bitsquare/nopy` re-exports it for backwards compatibility. See *Phase 4*. |
|
||||||
|
|
||||||
## Current state
|
## Current state
|
||||||
|
|
||||||
@@ -142,9 +142,9 @@ A cube bundle is an npm package with a `nopy` field:
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"files": ["cubes", "README.md", "LICENSE"],
|
"files": ["cubes", "README.md", "LICENSE"],
|
||||||
"keywords": ["nopy", "nopy-cubes", "pyinfra"],
|
"keywords": ["nopy", "nopy-cubess", "pyinfra"],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bitsquare/nopy-cube": "^1.0.0",
|
"@bitsquare/nopy-cubes": "^1.0.0",
|
||||||
"zod": "^4.4.3"
|
"zod": "^4.4.3"
|
||||||
},
|
},
|
||||||
"publishConfig": { "access": "public" }
|
"publishConfig": { "access": "public" }
|
||||||
@@ -164,8 +164,8 @@ Rules:
|
|||||||
back. Finding no cube directory at all is still an error, not a silent skip:
|
back. Finding no cube directory at all is still an error, not a silent skip:
|
||||||
listing a package means the user expects cubes from it.
|
listing a package means the user expects cubes from it.
|
||||||
- Both dependencies are **regular dependencies, not peers**, and both are
|
- Both dependencies are **regular dependencies, not peers**, and both are
|
||||||
load-bearing: a manifest imports `Manifest` from `@bitsquare/nopy-cube` and `z`
|
load-bearing: a manifest imports `Manifest` from `@bitsquare/nopy-cubes` and `z`
|
||||||
from `zod`. `@bitsquare/nopy-cube` peer-depends on zod, so the bundle's copy is
|
from `zod`. `@bitsquare/nopy-cubes` peer-depends on zod, so the bundle's copy is
|
||||||
the one everybody uses — see Phase 4.
|
the one everybody uses — see Phase 4.
|
||||||
- The package needs no `exports` entry for this to work — resolution reads
|
- The package needs no `exports` entry for this to work — resolution reads
|
||||||
`package.json` off disk (Phase 2), so the `exports` map is irrelevant.
|
`package.json` off disk (Phase 2), so the `exports` map is irrelevant.
|
||||||
@@ -306,7 +306,7 @@ The duplicate error carries both sources and is order-independent (Phase 0.2):
|
|||||||
|
|
||||||
```
|
```
|
||||||
Duplicate cube id 'apt:essentials' from 2 sources:
|
Duplicate cube id 'apt:essentials' from 2 sources:
|
||||||
package @bitsquare/cubes-core /…/node_modules/@bitsquare/cubes-core/cubes/apt/essentials
|
package @bitsquare/nopy-cubes-core /…/node_modules/@bitsquare/nopy-cubes-core/cubes/apt/essentials
|
||||||
directory /repo/packages/nopy/cubes/apt/essentials
|
directory /repo/packages/nopy/cubes/apt/essentials
|
||||||
Rename one of them, or remove a source from .nopyrc.json.
|
Rename one of them, or remove a source from .nopyrc.json.
|
||||||
```
|
```
|
||||||
@@ -317,7 +317,7 @@ claim the same id they are mutually exclusive, and the fix is upstream.
|
|||||||
Surface the source in the interactive picker and in `--json` output so a user can
|
Surface the source in the interactive picker and in `--json` output so a user can
|
||||||
see where a cube came from before running it.
|
see where a cube came from before running it.
|
||||||
|
|
||||||
## Phase 4 — `@bitsquare/nopy-cube`, the authoring package — **done**
|
## Phase 4 — `@bitsquare/nopy-cubes`, the authoring package — **done**
|
||||||
|
|
||||||
The problem: a manifest does `import { cubes } from '@bitsquare/nopy'`, resolved
|
The problem: a manifest does `import { cubes } from '@bitsquare/nopy'`, resolved
|
||||||
by ordinary Node resolution from the manifest's own directory. From inside
|
by ordinary Node resolution from the manifest's own directory. From inside
|
||||||
@@ -329,7 +329,7 @@ is plain, boring, spec-compliant Node with no loader tricks in the critical path
|
|||||||
|
|
||||||
### The package
|
### The package
|
||||||
|
|
||||||
`packages/nopy-cube` — the `Manifest` factory, the `Cube` class, and the types
|
`packages/nopy-cubes` — the `Manifest` factory, the `Cube` class, and the types
|
||||||
from `cubes/types.ts`. No CLI, no `execa`, `inquirer`, `enquirer`, `zx`, or
|
from `cubes/types.ts`. No CLI, no `execa`, `inquirer`, `enquirer`, `zx`, or
|
||||||
`commander`. Today a cube manifest — a file that ships nothing but data — drags
|
`commander`. Today a cube manifest — a file that ships nothing but data — drags
|
||||||
the entire CLI in as a transitive dependency; this makes the authoring surface
|
the entire CLI in as a transitive dependency; this makes the authoring surface
|
||||||
@@ -338,7 +338,7 @@ moves independently of the CLI's.
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "@bitsquare/nopy-cube",
|
"name": "@bitsquare/nopy-cubes",
|
||||||
"version": "1.0.0-alpha0",
|
"version": "1.0.0-alpha0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": { ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" } },
|
"exports": { ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" } },
|
||||||
@@ -355,7 +355,7 @@ is still the right default.
|
|||||||
|
|
||||||
### Moving `cubes/types.ts`
|
### Moving `cubes/types.ts`
|
||||||
|
|
||||||
`@bitsquare/nopy` re-exports everything from `@bitsquare/nopy-cube` — through
|
`@bitsquare/nopy` re-exports everything from `@bitsquare/nopy-cubes` — through
|
||||||
`src/cubes/index.ts` and the `cubes` namespace in `src/nopy.cubes.ts`, both
|
`src/cubes/index.ts` and the `cubes` namespace in `src/nopy.cubes.ts`, both
|
||||||
already coverage-excluded barrels — so `import { cubes } from '@bitsquare/nopy'`
|
already coverage-excluded barrels — so `import { cubes } from '@bitsquare/nopy'`
|
||||||
in every existing manifest keeps working unchanged. Nothing in `cubes/` has to be
|
in every existing manifest keeps working unchanged. Nothing in `cubes/` has to be
|
||||||
@@ -368,7 +368,7 @@ and the alternative is a test-only dependency edge between the packages.
|
|||||||
|
|
||||||
Repo plumbing it took:
|
Repo plumbing it took:
|
||||||
|
|
||||||
- `tsconfig.base.json`: `"@bitsquare/nopy-cube": ["./packages/nopy-cube/src"]`.
|
- `tsconfig.base.json`: `"@bitsquare/nopy-cubes": ["./packages/nopy-cubes/src"]`.
|
||||||
- Root `tsconfig.json` and `packages/nopy/tsconfig.json`: the project reference.
|
- Root `tsconfig.json` and `packages/nopy/tsconfig.json`: the project reference.
|
||||||
This is the first reference edge in the repo, and it broke the gate
|
This is the first reference edge in the repo, and it broke the gate
|
||||||
immediately: **`tsc --build --noEmit` is not legal once a project has
|
immediately: **`tsc --build --noEmit` is not legal once a project has
|
||||||
@@ -377,12 +377,12 @@ Repo plumbing it took:
|
|||||||
`typecheck` script is now plain `tsc --build`. It still fails on a type error,
|
`typecheck` script is now plain `tsc --build`. It still fails on a type error,
|
||||||
and it now also proves the build works; the cost is that it writes `dist`,
|
and it now also proves the build works; the cost is that it writes `dist`,
|
||||||
which is gitignored.
|
which is gitignored.
|
||||||
- `packages/nopy/package.json`: `"@bitsquare/nopy-cube": "workspace:*"`.
|
- `packages/nopy/package.json`: `"@bitsquare/nopy-cubes": "workspace:*"`.
|
||||||
- `packages/nopy/vitest.config.ts`: a `resolve.alias` for `@bitsquare/nopy-cube`
|
- `packages/nopy/vitest.config.ts`: a `resolve.alias` for `@bitsquare/nopy-cubes`
|
||||||
pointing at `../nopy-cube/src/index.ts`. Without it the workspace link
|
pointing at `../nopy-cubes/src/index.ts`. Without it the workspace link
|
||||||
resolves through `exports` to `dist`, so `pnpm test` on a clean checkout would
|
resolves through `exports` to `dist`, so `pnpm test` on a clean checkout would
|
||||||
fail until something had built it, and a stale `dist` would silently be what
|
fail until something had built it, and a stale `dist` would silently be what
|
||||||
the tests ran against. The same config excludes `**/nopy-cube/**` from
|
the tests ran against. The same config excludes `**/nopy-cubes/**` from
|
||||||
coverage — the aliased files were being counted against nopy's thresholds.
|
coverage — the aliased files were being counted against nopy's thresholds.
|
||||||
- A `vitest.config.ts` for the new package with the same thresholds. It sits at
|
- A `vitest.config.ts` for the new package with the same thresholds. It sits at
|
||||||
100 % statements/functions/lines, 91 % branches.
|
100 % statements/functions/lines, 91 % branches.
|
||||||
@@ -391,14 +391,14 @@ Repo plumbing it took:
|
|||||||
|
|
||||||
This is the part that is easy to miss. `link-workspace-packages` is unset and
|
This is the part that is easy to miss. `link-workspace-packages` is unset and
|
||||||
pnpm 10+ defaults it to `false`, so a plain semver range would resolve
|
pnpm 10+ defaults it to `false`, so a plain semver range would resolve
|
||||||
`@bitsquare/nopy-cube` from the registry instead of linking the workspace copy —
|
`@bitsquare/nopy-cubes` from the registry instead of linking the workspace copy —
|
||||||
the dependency has to use `workspace:*`.
|
the dependency has to use `workspace:*`.
|
||||||
|
|
||||||
But **both workflows publish with `npm publish`**, and npm does not understand
|
But **both workflows publish with `npm publish`**, and npm does not understand
|
||||||
the `workspace:` protocol. `@bitsquare/nopy` would ship a manifest carrying
|
the `workspace:` protocol. `@bitsquare/nopy` would ship a manifest carrying
|
||||||
`"@bitsquare/nopy-cube": "workspace:*"`, which fails on install with
|
`"@bitsquare/nopy-cubes": "workspace:*"`, which fails on install with
|
||||||
`EUNSUPPORTEDPROTOCOL`. This has never mattered because the two current packages
|
`EUNSUPPORTEDPROTOCOL`. This has never mattered because the two current packages
|
||||||
do not depend on each other; `nopy → nopy-cube` is the first edge, and the PoC
|
do not depend on each other; `nopy → nopy-cubes` is the first edge, and the PoC
|
||||||
bundle in Phase 5 adds a second.
|
bundle in Phase 5 adds a second.
|
||||||
|
|
||||||
Pick one before publishing anything:
|
Pick one before publishing anything:
|
||||||
@@ -408,13 +408,13 @@ Pick one before publishing anything:
|
|||||||
workflows and pulls in pnpm's own lifecycle behaviour.
|
workflows and pulls in pnpm's own lifecycle behaviour.
|
||||||
- **Rewrite the range with `npm pkg set` before publishing**, extending the
|
- **Rewrite the range with `npm pkg set` before publishing**, extending the
|
||||||
pattern `publish-snapshot.yml` already uses for `version`. In `release.yml` one
|
pattern `publish-snapshot.yml` already uses for `version`. In `release.yml` one
|
||||||
package ships at a time, so it pins to whatever version `packages/nopy-cube/package.json`
|
package ships at a time, so it pins to whatever version `packages/nopy-cubes/package.json`
|
||||||
declares at that commit. In `publish-snapshot.yml` the loop needs to become two
|
declares at that commit. In `publish-snapshot.yml` the loop needs to become two
|
||||||
passes — compute every snapshot version first, then publish — so `nopy` can pin
|
passes — compute every snapshot version first, then publish — so `nopy` can pin
|
||||||
the exact `nopy-cube` snapshot from the same run.
|
the exact `nopy-cubes` snapshot from the same run.
|
||||||
|
|
||||||
**Measured, both directions.** `npm pack` in `packages/nopy` produces a tarball
|
**Measured, both directions.** `npm pack` in `packages/nopy` produces a tarball
|
||||||
whose manifest still reads `"@bitsquare/nopy-cube": "workspace:*"`; `pnpm pack`
|
whose manifest still reads `"@bitsquare/nopy-cubes": "workspace:*"`; `pnpm pack`
|
||||||
produces one that reads `"1.0.0-alpha0"`. So the failure was real and the fix
|
produces one that reads `"1.0.0-alpha0"`. So the failure was real and the fix
|
||||||
works.
|
works.
|
||||||
|
|
||||||
@@ -431,7 +431,7 @@ locally:
|
|||||||
in both workflows. Turns "npm would have shipped a broken manifest" from an
|
in both workflows. Turns "npm would have shipped a broken manifest" from an
|
||||||
install-time surprise into a red run.
|
install-time surprise into a red run.
|
||||||
- **`scripts/publish-order.mjs`** — topologically sorts the publishable packages.
|
- **`scripts/publish-order.mjs`** — topologically sorts the publishable packages.
|
||||||
`packages/*/` alphabetically puts `nopy` ahead of the `nopy-cube` it depends
|
`packages/*/` alphabetically puts `nopy` ahead of the `nopy-cubes` it depends
|
||||||
on; the snapshot workflow now iterates this instead.
|
on; the snapshot workflow now iterates this instead.
|
||||||
- **`scripts/linked-deps.mjs`** — lists a package's workspace links as
|
- **`scripts/linked-deps.mjs`** — lists a package's workspace links as
|
||||||
`<name> <version>`, resolved by package name rather than by directory.
|
`<name> <version>`, resolved by package name rather than by directory.
|
||||||
@@ -440,7 +440,7 @@ locally:
|
|||||||
|
|
||||||
`publish-snapshot.yml` also became two passes over the packages: stamp every
|
`publish-snapshot.yml` also became two passes over the packages: stamp every
|
||||||
version first, then publish. `pnpm publish` substitutes the version the linked
|
version first, then publish. `pnpm publish` substitutes the version the linked
|
||||||
package declares *at pack time*, so `nopy-cube` has to be carrying its snapshot
|
package declares *at pack time*, so `nopy-cubes` has to be carrying its snapshot
|
||||||
version before `nopy` is packed.
|
version before `nopy` is packed.
|
||||||
|
|
||||||
Still unverified: none of this has run against the Gitea registry. Worth a
|
Still unverified: none of this has run against the Gitea registry. Worth a
|
||||||
@@ -453,7 +453,7 @@ Independent of the split, and worth building anyway — it retires the
|
|||||||
where manifests import `@bitsquare/nopy` from a directory that has no link to it.
|
where manifests import `@bitsquare/nopy` from a directory that has no link to it.
|
||||||
|
|
||||||
With the split, the hook is a convenience rather than load-bearing: bundles
|
With the split, the hook is a convenience rather than load-bearing: bundles
|
||||||
resolve `@bitsquare/nopy-cube` through their own `node_modules` and never reach
|
resolve `@bitsquare/nopy-cubes` through their own `node_modules` and never reach
|
||||||
it.
|
it.
|
||||||
|
|
||||||
**The gotcha is bigger than CLAUDE.md says: it is two specifiers, not one.**
|
**The gotcha is bigger than CLAUDE.md says: it is two specifiers, not one.**
|
||||||
@@ -495,7 +495,7 @@ Constraints, as built:
|
|||||||
now `tsc && cp src/cubes/*.mjs dist/cubes/`. `files` already covers it via the
|
now `tsc && cp src/cubes/*.mjs dist/cubes/`. `files` already covers it via the
|
||||||
`dist` entry.
|
`dist` entry.
|
||||||
- It covers **three** specifiers, not the two the plan named: `zod`,
|
- It covers **three** specifiers, not the two the plan named: `zod`,
|
||||||
`@bitsquare/nopy`, and `@bitsquare/nopy-cube` — a hand-written local cube is
|
`@bitsquare/nopy`, and `@bitsquare/nopy-cubes` — a hand-written local cube is
|
||||||
as entitled to the new authoring package as to the old one. Subpaths count
|
as entitled to the new authoring package as to the old one. Subpaths count
|
||||||
(`@bitsquare/nopy/package.json`), anything else stays a hard failure.
|
(`@bitsquare/nopy/package.json`), anything else stays a hard failure.
|
||||||
|
|
||||||
@@ -509,80 +509,80 @@ therefore runs each case in a child process, and the first case asserts the
|
|||||||
linked, the built loader reads all 22 cubes under `cubes/` with zero errors. The
|
linked, the built loader reads all 22 cubes under `cubes/` with zero errors. The
|
||||||
`ERR_MODULE_NOT_FOUND` gotcha in `CLAUDE.md` is retired.
|
`ERR_MODULE_NOT_FOUND` gotcha in `CLAUDE.md` is retired.
|
||||||
|
|
||||||
## Phase 5 — proof of concept: `packages/cubes-core` — **done**
|
## Phase 5 — proof of concept: `packages/nopy-cubes-core` — **done**
|
||||||
|
|
||||||
Depends on Phase 4 shipping first — the bundle cannot declare
|
Depends on Phase 4 shipping first — the bundle cannot declare
|
||||||
`@bitsquare/nopy-cube` as a dependency until it exists, and the publish-lane fix
|
`@bitsquare/nopy-cubes` as a dependency until it exists, and the publish-lane fix
|
||||||
has to be in place before either package is published.
|
has to be in place before either package is published.
|
||||||
|
|
||||||
1. `git mv cubes packages/cubes-core/cubes` — preserves per-file history.
|
1. `git mv cubes packages/nopy-cubes-core/cubes` — preserves per-file history.
|
||||||
2. Add `packages/cubes-core/package.json` per the Phase 1 contract. Version
|
2. Add `packages/nopy-cubes-core/package.json` per the Phase 1 contract. Version
|
||||||
`1.0.0-alpha0`, tracking the current alpha train. Not private. Its
|
`1.0.0-alpha0`, tracking the current alpha train. Not private. Its
|
||||||
`@bitsquare/nopy-cube` dependency uses `workspace:*` in the repo, which is
|
`@bitsquare/nopy-cubes` dependency uses `workspace:*` in the repo, which is
|
||||||
exactly the case the Phase 4 publish fix has to handle.
|
exactly the case the Phase 4 publish fix has to handle.
|
||||||
Migrating the manifests' `import { cubes } from '@bitsquare/nopy'` to
|
Migrating the manifests' `import { cubes } from '@bitsquare/nopy'` to
|
||||||
`import { Manifest } from '@bitsquare/nopy-cube'` is optional — the re-export
|
`import { Manifest } from '@bitsquare/nopy-cubes'` is optional — the re-export
|
||||||
keeps the old form working — but doing it here is what proves the bundle
|
keeps the old form working — but doing it here is what proves the bundle
|
||||||
resolves without the CLI present at all.
|
resolves without the CLI present at all.
|
||||||
3. Root `.nopyrc.json`: **replace** `"cubeDirs": ["./cubes"]` with
|
3. Root `.nopyrc.json`: **replace** `"cubeDirs": ["./cubes"]` with
|
||||||
`"cubePackages": ["@bitsquare/cubes-core"]`. Replace, not add — keeping both
|
`"cubePackages": ["@bitsquare/nopy-cubes-core"]`. Replace, not add — keeping both
|
||||||
means every id resolves from two sources and the hard error fires on every
|
means every id resolves from two sources and the hard error fires on every
|
||||||
run.
|
run.
|
||||||
4. Root `package.json`: add `"@bitsquare/cubes-core": "workspace:*"` to
|
4. Root `package.json`: add `"@bitsquare/nopy-cubes-core": "workspace:*"` to
|
||||||
`devDependencies`, so pnpm symlinks it into the root `node_modules`. This is
|
`devDependencies`, so pnpm symlinks it into the root `node_modules`. This is
|
||||||
what makes the PoC exercise the real pnpm symlink resolution path rather than
|
what makes the PoC exercise the real pnpm symlink resolution path rather than
|
||||||
a plain directory.
|
a plain directory.
|
||||||
5. `packages/nopy/.nopyrc.json` keeps `"cubeDirs": ["./cubes"]` for its fixtures.
|
5. `packages/nopy/.nopyrc.json` keeps `"cubeDirs": ["./cubes"]` for its fixtures.
|
||||||
Config merges root-first, so running from `packages/nopy` now pulls in
|
Config merges root-first, so running from `packages/nopy` now pulls in
|
||||||
`@bitsquare/cubes-core` *and* the fixtures — which is exactly the collision
|
`@bitsquare/nopy-cubes-core` *and* the fixtures — which is exactly the collision
|
||||||
Phase 0.3 renames away.
|
Phase 0.3 renames away.
|
||||||
6. Workflow changes are limited to the publish-lane fix from Phase 4.
|
6. Workflow changes are limited to the publish-lane fix from Phase 4.
|
||||||
`publish-snapshot.yml` loops `for dir in packages/*/` and picks both new
|
`publish-snapshot.yml` loops `for dir in packages/*/` and picks both new
|
||||||
packages up automatically; `release.yml` resolves `packages/<pkg>` from the
|
packages up automatically; `release.yml` resolves `packages/<pkg>` from the
|
||||||
tag, so `cubes-core-v1.0.0` and `nopy-cube-v1.0.0` work as-is. Verify on the
|
tag, so `nopy-cubes-core-v1.0.0` and `nopy-cubes-v1.0.0` work as-is. Verify on the
|
||||||
first snapshot run that a package with no `build` script is skipped cleanly by
|
first snapshot run that a package with no `build` script is skipped cleanly by
|
||||||
`pnpm -r run build` (it is) and that publishing is happy with no lifecycle
|
`pnpm -r run build` (it is) and that publishing is happy with no lifecycle
|
||||||
scripts.
|
scripts.
|
||||||
7. No `tsconfig` reference for `cubes-core` — the bundle has no TypeScript. (The
|
7. No `tsconfig` reference for `nopy-cubes-core` — the bundle has no TypeScript. (The
|
||||||
`nopy-cube` references from Phase 4 are separate.)
|
`nopy-cubes` references from Phase 4 are separate.)
|
||||||
8. Biome already lints `cubes/**/*.mjs` from the root; only the path changes.
|
8. Biome already lints `cubes/**/*.mjs` from the root; only the path changes.
|
||||||
|
|
||||||
### What differed from the plan
|
### What differed from the plan
|
||||||
|
|
||||||
- **Step 2's optional migration was done.** All 22 manifests now import
|
- **Step 2's optional migration was done.** All 22 manifests now import
|
||||||
`{ Manifest }` from `@bitsquare/nopy-cube`, not `{ cubes }` from
|
`{ Manifest }` from `@bitsquare/nopy-cubes`, not `{ cubes }` from
|
||||||
`@bitsquare/nopy`. Optional for correctness, but it is the only version of the
|
`@bitsquare/nopy`. Optional for correctness, but it is the only version of the
|
||||||
PoC that proves anything: leaving the old import in place would have resolved
|
PoC that proves anything: leaving the old import in place would have resolved
|
||||||
through the CLI that happens to sit in the same tree.
|
through the CLI that happens to sit in the same tree.
|
||||||
- **`uniqid` had to move too.** Two manifests use it (`admin:hostname` bare,
|
- **`uniqid` had to move too.** Two manifests use it (`admin:hostname` bare,
|
||||||
`user:add` via `cubes.uniqid`), so `src/cubes/utils.ts` and its test went to
|
`user:add` via `cubes.uniqid`), so `src/cubes/utils.ts` and its test went to
|
||||||
`nopy-cube` alongside `types.ts`, and `uniqid` joined the authoring barrel.
|
`nopy-cubes` alongside `types.ts`, and `uniqid` joined the authoring barrel.
|
||||||
Otherwise one migrated manifest would still have been importing the CLI.
|
Otherwise one migrated manifest would still have been importing the CLI.
|
||||||
- **`files` needs a log exclusion.** Cubes that have been run leave a gitignored
|
- **`files` needs a log exclusion.** Cubes that have been run leave a gitignored
|
||||||
`pyinfra-debug.log` next to `deploy.py`; gitignore does not filter an npm
|
`pyinfra-debug.log` next to `deploy.py`; gitignore does not filter an npm
|
||||||
tarball. `"files": ["cubes", "!cubes/**/*.log", …]` does. Verified: 22
|
tarball. `"files": ["cubes", "!cubes/**/*.log", …]` does. Verified: 22
|
||||||
manifests, 22 deploy scripts, 0 logs in the packed artefact.
|
manifests, 22 deploy scripts, 0 logs in the packed artefact.
|
||||||
- **`verify-pack.mjs` picks the bundle up for free** — it walks every non-private
|
- **`verify-pack.mjs` picks the bundle up for free** — it walks every non-private
|
||||||
`packages/*`, so `cubes-core`'s `workspace:*` edge is checked like nopy's.
|
`packages/*`, so `nopy-cubes-core`'s `workspace:*` edge is checked like nopy's.
|
||||||
|
|
||||||
### Verifying the PoC — done
|
### Verifying the PoC — done
|
||||||
|
|
||||||
- **In-workspace:** the built loader, run from the repo root against the new
|
- **In-workspace:** the built loader, run from the repo root against the new
|
||||||
root `.nopyrc.json`, reads 22 cubes with 0 errors and reports
|
root `.nopyrc.json`, reads 22 cubes with 0 errors and reports
|
||||||
`source: { type: 'package', packageName: '@bitsquare/cubes-core', dir:
|
`source: { type: 'package', packageName: '@bitsquare/nopy-cubes-core', dir:
|
||||||
'…/node_modules/@bitsquare/cubes-core/cubes' }` — the pnpm symlink path, not a
|
'…/node_modules/@bitsquare/nopy-cubes-core/cubes' }` — the pnpm symlink path, not a
|
||||||
plain directory.
|
plain directory.
|
||||||
- **Out-of-workspace (the real test):** `pnpm pack` for `nopy-cube`, `nopy` and
|
- **Out-of-workspace (the real test):** `pnpm pack` for `nopy-cubes`, `nopy` and
|
||||||
`cubes-core`, then **`npm install`** of all three tarballs into a throwaway
|
`nopy-cubes-core`, then **`npm install`** of all three tarballs into a throwaway
|
||||||
directory with a `.nopyrc.json` naming only the bundle. npm is the strict test
|
directory with a `.nopyrc.json` naming only the bundle. npm is the strict test
|
||||||
here — it does not understand `workspace:`, so a leaked range fails the install
|
here — it does not understand `workspace:`, so a leaked range fails the install
|
||||||
outright. It installed clean, and the installed
|
outright. It installed clean, and the installed
|
||||||
`@bitsquare/nopy/package.json` carries `"@bitsquare/nopy-cube":
|
`@bitsquare/nopy/package.json` carries `"@bitsquare/nopy-cubes":
|
||||||
"1.0.0-alpha0"`. `nopy install -l session.json -P -D` then resolved
|
"1.0.0-alpha0"`. `nopy install -l session.json -P -D` then resolved
|
||||||
`apt:essentials` and printed a `--chdir` into
|
`apt:essentials` and printed a `--chdir` into
|
||||||
`node_modules/@bitsquare/cubes-core/cubes/apt/essentials`. Since the loader
|
`node_modules/@bitsquare/nopy-cubes-core/cubes/apt/essentials`. Since the loader
|
||||||
aborts on any manifest error and this run did not, all 22 manifests imported
|
aborts on any manifest error and this run did not, all 22 manifests imported
|
||||||
`@bitsquare/nopy-cube` and `zod` successfully from a tree containing no
|
`@bitsquare/nopy-cubes` and `zod` successfully from a tree containing no
|
||||||
workspace links.
|
workspace links.
|
||||||
|
|
||||||
Note for anyone repeating this: `-P` on its own is interactive, and a replay
|
Note for anyone repeating this: `-P` on its own is interactive, and a replay
|
||||||
@@ -592,15 +592,15 @@ has to be in place before either package is published.
|
|||||||
|
|
||||||
## Phase 6 — documentation — **done**
|
## Phase 6 — documentation — **done**
|
||||||
|
|
||||||
- `CLAUDE.md`: the repo table gains two rows (`packages/nopy-cube`,
|
- `CLAUDE.md`: the repo table gains two rows (`packages/nopy-cubes`,
|
||||||
`packages/cubes-core`) and loses the `cubes/` one; "The two packages do not
|
`packages/nopy-cubes-core`) and loses the `cubes/` one; "The two packages do not
|
||||||
depend on each other" is no longer true; the loader section in *nopy
|
depend on each other" is no longer true; the loader section in *nopy
|
||||||
architecture*; and the *Gotcha* paragraph, which the resolve hook retires.
|
architecture*; and the *Gotcha* paragraph, which the resolve hook retires.
|
||||||
- `packages/nopy/docs/CUBE-BUNDLES.md` (new): authoring guide — package shape,
|
- `packages/nopy/docs/CUBE-BUNDLES.md` (new): authoring guide — package shape,
|
||||||
read-only constraint, id collision policy, publishing.
|
read-only constraint, id collision policy, publishing.
|
||||||
- `packages/nopy/docs/API.md` + `README.md`: `cubePackages`.
|
- `packages/nopy/docs/API.md` + `README.md`: `cubePackages`.
|
||||||
- `README.PUBLISH.md`: `nopy-cube-v*` and `cubes-core-v*` as new tag prefixes,
|
- `README.PUBLISH.md`: `nopy-cubes-v*` and `nopy-cubes-core-v*` as new tag prefixes,
|
||||||
plus the ordering constraint — `nopy-cube` releases before anything that
|
plus the ordering constraint — `nopy-cubes` releases before anything that
|
||||||
depends on it.
|
depends on it.
|
||||||
|
|
||||||
Beyond the list: `CLAUDE.md` also needed the `typecheck` command corrected
|
Beyond the list: `CLAUDE.md` also needed the `typecheck` command corrected
|
||||||
@@ -649,7 +649,7 @@ the error is identical regardless of scan order (Phase 0.2).
|
|||||||
`tests/prompts.test.ts` — `coerceValue` against schemas built by a *different*
|
`tests/prompts.test.ts` — `coerceValue` against schemas built by a *different*
|
||||||
zod instance, so Phase 0.4 cannot silently regress to `instanceof`.
|
zod instance, so Phase 0.4 cannot silently regress to `instanceof`.
|
||||||
|
|
||||||
`packages/nopy-cube/` — its own `vitest.config.ts` at the same thresholds. The
|
`packages/nopy-cubes/` — its own `vitest.config.ts` at the same thresholds. The
|
||||||
`Manifest()` / `Manifest.create()` / `Cube.getDefaults()` cases move over from
|
`Manifest()` / `Manifest.create()` / `Cube.getDefaults()` cases move over from
|
||||||
`tests/cubes.factories.test.ts`; what stays behind is whatever tests the
|
`tests/cubes.factories.test.ts`; what stays behind is whatever tests the
|
||||||
re-export surface.
|
re-export surface.
|
||||||
@@ -678,7 +678,7 @@ against a fixture tree, under the existing `test:integration` script.
|
|||||||
publish time and only shows up when someone installs the package. Phase 4
|
publish time and only shows up when someone installs the package. Phase 4
|
||||||
fixes the lane; a `postpack` assertion that no dependency range starts with
|
fixes the lane; a `postpack` assertion that no dependency range starts with
|
||||||
`workspace:` would make it impossible to regress.
|
`workspace:` would make it impossible to regress.
|
||||||
7. **Three packages, three version lines.** `nopy-cube` is the contract, so a
|
7. **Three packages, three version lines.** `nopy-cubes` is the contract, so a
|
||||||
breaking change there ripples to every published bundle in the wild — which is
|
breaking change there ripples to every published bundle in the wild — which is
|
||||||
the point of versioning it separately, but it means the compatibility question
|
the point of versioning it separately, but it means the compatibility question
|
||||||
from risk 4 gets more pressing, not less.
|
from risk 4 gets more pressing, not less.
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
"test:watch": "vitest"
|
"test:watch": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bitsquare/nopy-cube": "workspace:*",
|
"@bitsquare/nopy-cubes": "workspace:*",
|
||||||
"@logtape/logtape": "^2.2.4",
|
"@logtape/logtape": "^2.2.4",
|
||||||
"commander": "^15.0.0",
|
"commander": "^15.0.0",
|
||||||
"enquirer": "^2.4.1",
|
"enquirer": "^2.4.1",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* @module cubes/dependencies
|
* @module cubes/dependencies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Cube, CubeVariables, HookContext } from '@bitsquare/nopy-cube';
|
import type { Cube, CubeVariables, HookContext } from '@bitsquare/nopy-cubes';
|
||||||
import { getLogger } from '@logtape/logtape';
|
import { getLogger } from '@logtape/logtape';
|
||||||
import type { Variables } from '../nopy.common.js';
|
import type { Variables } from '../nopy.common.js';
|
||||||
import type { NopyConfig } from '../nopy.config.js';
|
import type { NopyConfig } from '../nopy.config.js';
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export type {
|
|||||||
Hook,
|
Hook,
|
||||||
HookContext,
|
HookContext,
|
||||||
LoadResult,
|
LoadResult,
|
||||||
} from '@bitsquare/nopy-cube';
|
} from '@bitsquare/nopy-cubes';
|
||||||
export {
|
export {
|
||||||
Cube,
|
Cube,
|
||||||
createManifest,
|
createManifest,
|
||||||
@@ -26,7 +26,7 @@ export {
|
|||||||
uniqid,
|
uniqid,
|
||||||
zodInner,
|
zodInner,
|
||||||
zodKind,
|
zodKind,
|
||||||
} from '@bitsquare/nopy-cube';
|
} from '@bitsquare/nopy-cubes';
|
||||||
// Dependencies
|
// Dependencies
|
||||||
export { BuildContext } from './dependencies.js';
|
export { BuildContext } from './dependencies.js';
|
||||||
// Loader
|
// Loader
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import module from 'node:module';
|
import module from 'node:module';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { Cube, type CubeSource, type LoadResult, type Manifest } from '@bitsquare/nopy-cube';
|
import { Cube, type CubeSource, type LoadResult, type Manifest } from '@bitsquare/nopy-cubes';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { fs } from 'zx';
|
import { fs } from 'zx';
|
||||||
import { loadConfig } from '../nopy.config.js';
|
import { loadConfig } from '../nopy.config.js';
|
||||||
@@ -15,7 +15,7 @@ let hookRegistered = false;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs the fallback resolver that lets a manifest in a bare directory
|
* Installs the fallback resolver that lets a manifest in a bare directory
|
||||||
* import `@bitsquare/nopy-cube` or `zod` — see `resolve-hook.mjs`.
|
* import `@bitsquare/nopy-cubes` or `zod` — see `resolve-hook.mjs`.
|
||||||
*
|
*
|
||||||
* `module.register()` is process-global and cannot be undone, so this runs once
|
* `module.register()` is process-global and cannot be undone, so this runs once
|
||||||
* and only when cubes are about to be imported. Registration failing is not
|
* and only when cubes are about to be imported. Registration failing is not
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* A manifest is loaded with `import(manifestPath)`, so its imports resolve from
|
* A manifest is loaded with `import(manifestPath)`, so its imports resolve from
|
||||||
* its own directory. A cube sitting in an arbitrary `cubeDirs` entry — no
|
* its own directory. A cube sitting in an arbitrary `cubeDirs` entry — no
|
||||||
* package.json above it, no node_modules beside it — therefore cannot import
|
* package.json above it, no node_modules beside it — therefore cannot import
|
||||||
* `@bitsquare/nopy-cube` or `zod` at all, and the run dies on
|
* `@bitsquare/nopy-cubes` or `zod` at all, and the run dies on
|
||||||
* ERR_MODULE_NOT_FOUND before a single deploy is built.
|
* ERR_MODULE_NOT_FOUND before a single deploy is built.
|
||||||
*
|
*
|
||||||
* A published cube bundle never reaches this: it declares its own dependencies
|
* A published cube bundle never reaches this: it declares its own dependencies
|
||||||
@@ -25,7 +25,7 @@ import { pathToFileURL } from 'node:url';
|
|||||||
* be expected to install for itself. Anything else stays a hard failure — a
|
* be expected to install for itself. Anything else stays a hard failure — a
|
||||||
* cube that wants a library should depend on it.
|
* cube that wants a library should depend on it.
|
||||||
*/
|
*/
|
||||||
const FALLBACK_ROOTS = ['@bitsquare/nopy-cube', '@bitsquare/nopy', 'zod'];
|
const FALLBACK_ROOTS = ['@bitsquare/nopy-cubes', '@bitsquare/nopy', 'zod'];
|
||||||
|
|
||||||
/** @type {NodeRequire | undefined} */
|
/** @type {NodeRequire | undefined} */
|
||||||
let fallbackRequire;
|
let fallbackRequire;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* @module nopy.executor
|
* @module nopy.executor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { DependencySpec } from '@bitsquare/nopy-cube';
|
import type { DependencySpec } from '@bitsquare/nopy-cubes';
|
||||||
import { getLogger } from '@logtape/logtape';
|
import { getLogger } from '@logtape/logtape';
|
||||||
import { execa } from 'execa';
|
import { execa } from 'execa';
|
||||||
import { MASK } from './nopy.common.js';
|
import { MASK } from './nopy.common.js';
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user