# Publishing WrNexus to npm

All 39 `@wrnexus/*` packages are built and published to the **public npm registry**
(`registry.npmjs.org`), then installed on any machine with **Bun**.

## Prerequisites

The `@wrnexus/*` packages are **scoped**, so the `wrnexus` npm **organization** must
exist and you must be a member with publish rights (a username scope like
`@clintchiz` would work without an org, but the packages are named `@wrnexus/*`).

1. Create the org once at <https://www.npmjs.com/org/create> (name: `wrnexus`).
   - A **free** org can publish unlimited **public** packages.
   - To publish **private** (`restricted`) packages first and flip them public
     later, the org needs a paid **Teams** plan (private scoped packages require it).
2. `npm login` (registry `https://registry.npmjs.org/`).

The repo `.npmrc` points the scope at public npm:

```
@wrnexus:registry=https://registry.npmjs.org/
```

## Mandatory release workflow

Do not publish packages with ad-hoc `npm publish` commands during a normal release. The
repository release commands enforce the complete framework + migration + documentation
workflow.

Every release must have an entry in `packages/cli/src/update.ts`'s `MIGRATIONS` list. The
entry must be idempotent and conservative. If a release requires no project file change,
add a documented no-op migration entry so that the decision is explicit and reviewable.

### 1. Prepare

Align every `packages/*/package.json` version, add the update migration and tests, then run:

```bash
bun run release:prepare
```

This command refuses to prepare a release when versions differ or migration coverage is
missing. It runs the complete framework check, builds all publish artifacts, and verifies
that every staged manifest uses the aligned version and `restricted` access.

Review the generated `.publish` changes, then commit and push the framework repository.
The publish step will refuse to run from an uncommitted or unpushed framework checkout.

### 2. Publish privately and update documentation

```bash
bun run release:private
```

The command performs the remaining release as one guarded workflow:

1. Rebuild and validate all private package artifacts from the pushed commit.
2. Publish every missing `@wrnexus/*` package in dependency order. Already-published
   packages are verified and skipped, so an interrupted release can be resumed safely.
3. Confirm every package is private and run the newly published CLI updater, including its
   migrations, against `D:\Company\wrnexusjs`. The updater's immediate project check is
   deferred because its generated docs inputs are rebuilt in the next step.
4. Align every docs-site dependency, regenerate package pages twice, update
   `public/llms.txt`, `public/llms-full.txt`, the sitemap, and the documentation index.
5. Run the authoritative docs-site check and production build, verify that
   `public/llms.txt` contains the current version and every framework package, then commit
   and push the docs repository.

If the documentation checkout lives elsewhere, set `WRNEXUS_DOCS_ROOT` before running the
publish command. Both repositories must start clean and synchronized with their active
remote branches.

Only use the individual commands printed by `scripts/publish-packages.ts` for diagnosed
recovery. Finish recovery by rerunning `bun run release:private`; it is the authoritative
completion check.

## Publishing implementation

The packages ship raw TypeScript in the repo (`main`/`exports` → `src/*.ts`), so
they are **built** for publishing. `scripts/publish-packages.ts` builds each
package with [tsup](https://tsup.egoist.dev) (bundled JS + a single `.d.ts`) and
**stages** a publishable copy under `.publish/<name>/` with a rewritten manifest:

- `main`/`module`/`types`/`exports`/`bin` point at `./dist/*`
- `workspace:*` deps → `^<version>`
- `private` removed; `license` → `MIT`; `publishConfig` → `{ registry, access }`
- runtime assets copied (`@wrnexus/ui` → `components/`, `ui.css`)

The dev `package.json` (pointing at `src/`) is **never modified**, so in-repo dev
and tests keep working.

### Private staging details

By default the lower-level staging script creates **`restricted`** (private) manifests.
It is called by the mandatory release commands and requires the `wrnexus` org on a paid
Teams plan.

```bash
# Lower-level recovery/debug command only
bun run scripts/publish-packages.ts

# Publish (deps first). The script prints the exact order + --access flag; e.g.
npm publish .publish/core --access restricted
npm publish .publish/compiler --access restricted
# … through …
npm publish .publish/cli --access restricted
```

When an approved release is ready to become public, **flip every package to public** (no
republish needed):

```bash
npm access public @wrnexus/core
npm access public @wrnexus/compiler
# … the script prints the full list …
```

### Public staging for an explicitly approved public release

To stage public manifests from the start (free org is enough):

```bash
WRNEXUS_NPM_ACCESS=public bun run scripts/publish-packages.ts
npm publish .publish/core --access public
# …
```

Bump `version` in each `packages/*/package.json` before republishing (npm rejects a
duplicate version).

## Consume on another machine (needs Bun)

```bash
mkdir my-wrn-app && cd my-wrn-app

# Scaffold via the CLI
npm i @wrnexus/cli
bunx wrnexus create app
cd app                       # scaffolds with @wrnexus/* deps declared
bun install                  # pulls @wrnexus/core, styles, validation, db, cli
bun run dev                  # or: bun run build && bun dist/server.js
```

While the packages are still **private**, the consuming machine must be logged in
to npm (`npm login`) as a user with read access to the `wrnexus` org. Once public,
no auth is needed.

`wrnexus create` scaffolds an app that already declares its `@wrnexus/*` runtime
dependencies and a dev-dependency on `@wrnexus/cli`, so `bun install` + `bun run dev`
works standalone.

> Everything runs under **Bun** (the framework uses `Bun.serve`, `bun:sqlite`,
> `Bun.password`, `Bun.build`, …). Node is not a supported runtime.
