@dashai/cli 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -22
- package/dist/bin.js +2209 -337
- package/dist/bin.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Status
|
|
8
8
|
|
|
9
|
-
`0.5.x` — full author workflow + **Query Plane v1 author tooling** + **P7 cross-module-action observability** (shipped 2026-05-20) + **BaaS Phase 1 deploy loop** (`api-keys`, `env export`, `--deploy-target`; shipped 2026-05-24). Commands: `login`, `logout`, `profile`, `workspace`, `init` / `module init` (incl. `--custom`, `--deploy-target railway|vercel|fly`) / `connect-git` / `generate` / `dev` / `validate` / `list` / `publish` / `diff` / `pull-data` / `clone` / `query-log` / `action-log`, plus `query` (run AST queries against the local module), `pull` (sync canonical manifest from backend), `api-keys list|create|revoke`, `env export`, and `deps add` / `list` / `remove` / `check
|
|
9
|
+
`0.5.x` — full author workflow + **Query Plane v1 author tooling** + **P7 cross-module-action observability** (shipped 2026-05-20) + **BaaS Phase 1 deploy loop** (`api-keys`, `env export`, `--deploy-target`; shipped 2026-05-24). Commands: `login`, `logout`, `profile`, `workspace`, `init` / `module init` (incl. `--custom`, `--deploy-target railway|vercel|fly`) / `connect-git` / `generate` / `dev` / `validate` / `list` / `publish` / `diff` / `pull-data` / `clone` / `query-log` / `action-log`, plus `query` (run AST queries against the local module), `pull` (sync canonical manifest from backend), `api-keys list|create|revoke`, `origins list|add|remove` (SSO callback allowlist), `env export`, and `deps` (live connect status) / `add` / `list` / `remove` / `check` / `bind` / `unbind` (cross-module dependency connect lifecycle).
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -85,9 +85,11 @@ One-command local dev loop — collapses the historical two-terminal flow into a
|
|
|
85
85
|
1. `dashwise module dev` — manifest watcher + SDK regen
|
|
86
86
|
2. `next dev` — Next.js dev server (via the project's `dev:next` script if defined, else `npx next dev`)
|
|
87
87
|
|
|
88
|
-
Both children inherit a pre-populated env with `DASHWISE_API_URL
|
|
88
|
+
Both children inherit a pre-populated env with the Phase 2 two-var contract (`DASHWISE_API_URL` + `DASHWISE_API_KEY`, plus a `NEXT_PUBLIC_DASHWISE_API_URL` mirror) automatically resolved from your saved CLI config (`~/.config/dashwise/auth.json`). No more copying credentials into `.env.local` by hand.
|
|
89
89
|
|
|
90
|
-
**
|
|
90
|
+
**Two-var contract:** when the current module has been provisioned via `dashwise init` / `dashwise module register`, the per-module scoped `dwk_` API key cached at `~/.config/dashwise/auth.json#modules[<slug>]` is injected as `DASHWISE_API_KEY` into both children. The key resolves the install server-side, so the SDK hits the install-agnostic `/api/module-api` — there is no `DASHWISE_INSTALLATION_ID`. `DASHWISE_API_TOKEN` (your CLI bearer), `DASHWISE_RUNTIME_TOKEN` (retired), and `DASHWISE_DEV_SESSION_ID` are **not** injected into the children — the scoped key is the only data-plane credential, and the scaffold's sign-in route uses it (via `/api/module-api/sso/start-url`) for SSO too. The pre-flight banner prints which auth source is in use.
|
|
91
|
+
|
|
92
|
+
**Self-heal:** if your `auth.json` still has a legacy `runtimeToken` (pre-identity-collapse), `dashwise dev` mints a `dwk_` key via `POST /api/installations/:id/api-keys`, rewrites the entry, and tells you. If the install is gone, it points you to `dashwise init <slug> --force`.
|
|
91
93
|
|
|
92
94
|
If the manifest's slug isn't in `auth.json#modules`, `dashwise dev` still starts (SSO + watcher work fine), but it prints a one-line warning that data-plane calls (db, qb) will 401 — pointing you to re-run `dashwise init <slug> --force` to provision.
|
|
93
95
|
|
|
@@ -95,13 +97,13 @@ Output from both children is line-prefixed (`[sdk]` cyan, `[next]` magenta) so a
|
|
|
95
97
|
|
|
96
98
|
Flags:
|
|
97
99
|
- `--dir <path>` — Project root (default: current directory).
|
|
98
|
-
- `--installation-id <id>` —
|
|
100
|
+
- `--installation-id <id>` — Run against an already-installed module (skips dev-session registration and uses prod-mode SSO against a real installed module). The id is used by `dashwise dev` internally, not injected into the child env.
|
|
99
101
|
- `--api-url <url>` — Override `DASHWISE_API_URL` (default: saved config value).
|
|
100
102
|
- `--port <number>` — Port for `next dev` (default: Next picks 3000 / next free).
|
|
101
103
|
- `--sdk-only` — Run only the manifest watcher; skip `next dev`.
|
|
102
104
|
- `--next-only` — Run only `next dev`; skip the watcher.
|
|
103
105
|
|
|
104
|
-
Requires `dashwise login` first — the command refuses to start if no token is resolvable. The
|
|
106
|
+
Requires `dashwise login` first — the command refuses to start if no token is resolvable. The `DASHWISE_API_KEY` injection requires `dashwise init <slug>` (or `dashwise module register`); the dev session SSO setup works without it.
|
|
105
107
|
|
|
106
108
|
### `dashwise init [slug]` / `dashwise module init [slug]`
|
|
107
109
|
|
|
@@ -123,7 +125,7 @@ Flags:
|
|
|
123
125
|
- `--no-provision` — Skip the `POST /api/installations/dev` step (HH-CC-LDI-6). Local scaffold is still written, but the module won't have a backing dev installation — `dashwise dev` data-plane calls will fail with `UnauthenticatedError` until you re-run `dashwise init --force` or (once it ships) `dashwise module provision-dev-install`.
|
|
124
126
|
- `--deploy-target railway|vercel|fly` (HH-CC-P1-D2) — Emit a platform deploy config file alongside the scaffold (`railway.json`, `vercel.json`, or `fly.toml`). Default: none (clean repo). Pair with `dashwise env export --format <platform>` to push env vars after provisioning. See [`docs/deploying.md`](../../docs/deploying.md) for the full deploy walkthrough.
|
|
125
127
|
|
|
126
|
-
**Provisioning behavior (HH-CC-LDI-6):** by default, after the local scaffold is written, `dashwise init` provisions a real local-dev installation by calling `POST /api/installations/dev`. The returned
|
|
128
|
+
**Provisioning behavior (HH-CC-LDI-6):** by default, after the local scaffold is written, `dashwise init` provisions a real local-dev installation by calling `POST /api/installations/dev`. The returned scoped `dwk_` API key (default 90-day expiry) is cached in `~/.config/dashwise/auth.json#modules[<slug>]` where `@dashai/sdk`'s `createDevClient({ moduleSlug })` reads it on every dev-server boot. On a `kind='local'` install the key grants self-access to your own tables, so a table you create is instantly queryable. Provisioning failures are surfaced as warnings; the local scaffold remains usable so you can retry later.
|
|
127
129
|
|
|
128
130
|
### `dashwise module connect-git <repo-url>`
|
|
129
131
|
|
|
@@ -195,7 +197,7 @@ Tear down the local-dev installation for the current module. Calls `DELETE /api/
|
|
|
195
197
|
dashwise module destroy-dev-install
|
|
196
198
|
```
|
|
197
199
|
|
|
198
|
-
Local `module.json` is preserved — only the cached
|
|
200
|
+
Local `module.json` is preserved — only the cached API key + install id get cleared. Re-run `dashwise init <slug> --force` to provision a fresh install.
|
|
199
201
|
|
|
200
202
|
Flags:
|
|
201
203
|
- `--dir <path>` — Project root (default: current directory).
|
|
@@ -209,7 +211,7 @@ Errors map to user-friendly messages: `INSTALLATION_NOT_FOUND` (already destroye
|
|
|
209
211
|
Destroy + re-provision the local-dev install in a single command. Useful for:
|
|
210
212
|
|
|
211
213
|
- Nuking accumulated test data
|
|
212
|
-
- Refreshing a compromised
|
|
214
|
+
- Refreshing a compromised API key
|
|
213
215
|
- Recovering from a wedged schema state
|
|
214
216
|
|
|
215
217
|
```bash
|
|
@@ -297,7 +299,7 @@ Flags:
|
|
|
297
299
|
- `--json` — Compact JSON output (no pretty-print).
|
|
298
300
|
- `--dir <path>` — Project root (default: current directory).
|
|
299
301
|
|
|
300
|
-
Pre-reqs: `dashwise module generate` must have run (the SDK reads `node_modules/@dashai/generated`). `DASHWISE_API_URL
|
|
302
|
+
Pre-reqs: `dashwise module generate` must have run (the SDK reads `node_modules/@dashai/generated`). `DASHWISE_API_URL` + `DASHWISE_API_KEY` must be set (the scaffold's `.env.local` is loaded automatically; `dashwise dev` injects both).
|
|
301
303
|
|
|
302
304
|
### `dashwise pull` (HH-CC-P1-E2)
|
|
303
305
|
|
|
@@ -317,36 +319,50 @@ Flags:
|
|
|
317
319
|
|
|
318
320
|
### `dashwise api-keys list|create|revoke` (HH-CC-P1-C4)
|
|
319
321
|
|
|
320
|
-
Mint long-lived
|
|
322
|
+
Mint long-lived credentials for an install. Used by self-hosted deploys (Railway / Vercel / Fly / your own infra). Same `dwk_` key kind `dashwise init` mints for local dev, but you mint a separate one per environment. The key format is `dwk_<43-char-base64url>`; the backend stores only a `sha256` hash so the plaintext is shown exactly once at `create`.
|
|
321
323
|
|
|
322
324
|
```sh
|
|
323
|
-
# Mint a key. Plaintext appears on stdout — copy it now.
|
|
325
|
+
# Mint a full-access key. Plaintext appears on stdout — copy it now.
|
|
324
326
|
dashwise api-keys create production
|
|
325
327
|
|
|
326
328
|
# Script-friendly: capture the raw key with no other chatter.
|
|
327
329
|
KEY=$(dashwise api-keys create ci --raw-only)
|
|
328
330
|
|
|
329
|
-
#
|
|
331
|
+
# Least-privilege (scoped) key — any --grant flips it to default-deny.
|
|
332
|
+
dashwise api-keys create readonly --grant module:tasks:read
|
|
333
|
+
dashwise api-keys create writer \
|
|
334
|
+
--grant module:tasks:read,create \
|
|
335
|
+
--grant datahub:table=12:read
|
|
336
|
+
|
|
337
|
+
# Expire the key after N days.
|
|
338
|
+
dashwise api-keys create temp --grant module:tasks:read --expires 30
|
|
339
|
+
|
|
340
|
+
# List all keys for the current install (shows each key's grants).
|
|
330
341
|
dashwise api-keys list
|
|
331
342
|
|
|
332
343
|
# Revoke. Irreversible. Effective on the next request.
|
|
333
344
|
dashwise api-keys revoke <key-id>
|
|
334
345
|
```
|
|
335
346
|
|
|
347
|
+
Create flags:
|
|
348
|
+
- `--grant <spec>` (repeatable) — `module:<tableSlug>:<ops>`, `datahub:table=<id>:<ops>`, `datahub:app=<id>:<ops>`, or `datahub:workspace:<ops>`, where `<ops>` is a comma list of `create,read,update,delete`. Any grant mints a scoped (default-deny) key; minting scoped keys (or any key on a non-local install) requires workspace-admin.
|
|
349
|
+
- `--expires <days>` — days until the key expires (default: never).
|
|
350
|
+
- `--raw-only` — print only the plaintext key on stdout (for shell capture).
|
|
351
|
+
|
|
336
352
|
The install is resolved from the cached entry in `~/.config/dashwise/auth.json#modules[<slug>]` (keyed by `module.json#module.slug`). Run from inside the module directory, or pass `--dir <path>`.
|
|
337
353
|
|
|
338
354
|
Pairs with `dashwise env export --key dwk_...` to push the key into a deploy platform without ever copy-pasting it through a shell history.
|
|
339
355
|
|
|
340
356
|
### `dashwise env export` (HH-CC-P1-D1)
|
|
341
357
|
|
|
342
|
-
Emit the
|
|
358
|
+
Emit the Phase 2 two-var contract every self-hosted deploy needs:
|
|
343
359
|
|
|
344
360
|
| Var | Source |
|
|
345
361
|
|---|---|
|
|
346
362
|
| `DASHWISE_API_URL` | CLI config (`apiUrl`). |
|
|
347
|
-
| `
|
|
348
|
-
|
|
349
|
-
|
|
363
|
+
| `DASHWISE_API_KEY` | Placeholder by default; pass `--key dwk_...` to inline an existing key, or `--new-key <name>` to mint one in-flight. Resolves the install server-side. |
|
|
364
|
+
|
|
365
|
+
`DASHWISE_INSTALLATION_ID` is NOT emitted (the key binds the install) and `NEXT_PUBLIC_DASHWISE_API_URL` is NOT emitted (the scaffold's `next.config` derives it from `DASHWISE_API_URL`).
|
|
350
366
|
|
|
351
367
|
Five output formats — `env`, `json`, `railway`, `vercel`, `fly`. The platform-specific ones wrap each var in the matching CLI invocation (`railway variables set …`, `vercel env add …`, `fly secrets set …`) so the output is directly pipeable into `sh`.
|
|
352
368
|
|
|
@@ -369,6 +385,22 @@ Flags:
|
|
|
369
385
|
- `--new-key <name>` — Mint a new API key and inline its plaintext.
|
|
370
386
|
- `--dir <path>` — Project root.
|
|
371
387
|
|
|
388
|
+
### `dashwise origins list|add|remove`
|
|
389
|
+
|
|
390
|
+
Manage the current module install's SSO callback-origin allowlist. The scaffold's `/api/auth/sign-in` route sends its own public origin as the SSO `callback_url`; the backend only accepts an origin that's on the install's allowlist. `kind='local'` installs (what `dashwise init` provisions) allow `http://localhost:<any-port>` implicitly, so **local dev needs no config**. A deployed custom domain must be added here.
|
|
391
|
+
|
|
392
|
+
```sh
|
|
393
|
+
dashwise origins list # show the allowlist
|
|
394
|
+
dashwise origins add https://app.example.com # add a deployed domain (https:// for non-localhost)
|
|
395
|
+
dashwise origins remove https://app.example.com
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Workspace-admin operation (uses your CLI login bearer). The install id is resolved from `~/.config/dashwise/auth.json#modules[<slug>]` — you never type it. `add` / `remove` do a client-side read-modify-write against the backend's `GET` (read) + `PUT` (full-replace) endpoints.
|
|
399
|
+
|
|
400
|
+
Flags:
|
|
401
|
+
- `--dir <path>` — Project root.
|
|
402
|
+
- `--json` (list only) — Emit a JSON array of origins.
|
|
403
|
+
|
|
372
404
|
### `dashwise module query-log`
|
|
373
405
|
|
|
374
406
|
Read the per-module SDK query log (each cross-module / `.execute()` / `.stream()` / `.explain()` dispatch writes a row to `module_query_log` server-side). Workspace-member-scoped on the backend.
|
|
@@ -419,7 +451,7 @@ Flags:
|
|
|
419
451
|
|
|
420
452
|
Schema-mutation commands for the current module — add or drop tables, add/remove/retype fields in the dev installation. Each command:
|
|
421
453
|
|
|
422
|
-
1. Calls the LDI-4 REST endpoint at `/api/installations/:id/schema/...` using the
|
|
454
|
+
1. Calls the LDI-4 REST endpoint at `/api/installations/:id/schema/...` using the scoped `dwk_` API key cached by `dashwise init` (on a `kind='local'` install the backend allows the developer to mutate their own schema; C3).
|
|
423
455
|
2. Asks the backend to apply the change (manifest + physical Postgres tables update atomically server-side).
|
|
424
456
|
3. Calls `GET /api/installations/:id/schema` to fetch the new manifest.
|
|
425
457
|
4. Writes the response to local `module.json`.
|
|
@@ -507,18 +539,47 @@ Errors: 404 `TABLE_NOT_FOUND` / `FIELD_NOT_FOUND`.
|
|
|
507
539
|
|
|
508
540
|
### `dashwise deps`
|
|
509
541
|
|
|
510
|
-
Manage cross-module dependencies
|
|
542
|
+
Manage cross-module dependencies — both the declaration (in `module.json#dependencies`) and the **connect lifecycle** (whether each declared dep is actually wired to a provider installation).
|
|
511
543
|
|
|
512
|
-
|
|
544
|
+
#### Park-not-reject — how deps connect
|
|
513
545
|
|
|
514
|
-
|
|
546
|
+
A dependency is *declared* in your manifest but only *connected* once a compatible provider is installed in the workspace and bound. When a dep can't bind — no provider installed yet, a version mismatch, a table/action the provider doesn't expose — the backend **parks** it (`status='unbound'`) instead of failing the install. Runtime reads against a parked dep return `DEP_UNBOUND` (the SDK surfaces this as `DepUnboundError` so your app can render a "connect your provider" state).
|
|
515
547
|
|
|
516
|
-
|
|
548
|
+
**Both install orders work.** You can install the consumer first (its deps park until the provider shows up) or the provider first (the consumer's deps resolve immediately at install). A parked dep auto-connects when its provider is later installed; you can also connect it by hand with `dashwise deps bind`.
|
|
517
549
|
|
|
518
|
-
**`dashwise deps
|
|
550
|
+
**`dashwise deps`** (no subcommand) — Show the **live connect status** of every declared dep on your installation: a `resolved` / `unbound` chip, the version range, the bound provider's install id + version (when resolved), and the park reason (when unbound). This is the backend's per-installation truth — the thing that decides whether a runtime dep read succeeds or 409s. Requires a provisioned dev install (`dashwise init`). Workspace-member. `--json` for piping.
|
|
551
|
+
|
|
552
|
+
```
|
|
553
|
+
$ dashwise deps
|
|
554
|
+
ℹ Cross-module dependencies for my-app (2 declared, 1 unbound):
|
|
555
|
+
|
|
556
|
+
● resolved crm@^1.2.0
|
|
557
|
+
provider: install #88 @ v1.3.0
|
|
558
|
+
|
|
559
|
+
○ unbound billing@^2.0.0
|
|
560
|
+
reason: MISSING_DEPENDENCY
|
|
561
|
+
|
|
562
|
+
ℹ Connect a parked dep with `dashwise deps bind <provider-slug>` once its provider is installed.
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
**`dashwise deps add <provider-slug>`** — Add a dep to `module.json`. Interactive in a TTY (fetches the provider's published `exposes` block, multi-select tables + fields, prompts for the required `purpose` string); non-interactive when `--table` + `--fields` + `--purpose` are all passed. You can declare a dependency on an **unpublished same-workspace provider** — the backend resolves it against the provider's draft manifest; the CLI surfaces whatever answer the backend gives (it doesn't pre-validate beyond the manifest's schema shape). After writing the manifest, `deps add` shows the resulting **resolve / park status** for the new dep (the manifest is reconciled server-side on the next push, e.g. via `dashwise dev`).
|
|
566
|
+
|
|
567
|
+
Flags: `--table <slug>`, `--fields <comma-list>`, `--purpose <text>`, `--version <semver-range>`, `-y/--yes`, `--dir <path>`.
|
|
568
|
+
|
|
569
|
+
**`dashwise deps bind <provider-slug> [--installation <id>]`** — (Re-)connect a parked dependency to its provider installation. Re-runs single-dep resolution and snapshots the contract; on success, runtime reads succeed. If it can't bind, the command exits 1 with the **park reason** (`MISSING_DEPENDENCY`, `DEPENDENCY_VERSION_MISMATCH`, `EXPOSES_MISSING`, `EXPOSES_PRIVATE`, `ACTION_NOT_EXPOSED`, `PROVIDER_NOT_PRODUCTION`, …) and the dep stays unbound. Pass `--installation <id>` to disambiguate when the workspace has more than one candidate install of the provider. Workspace-admin.
|
|
570
|
+
|
|
571
|
+
**`dashwise deps unbind <provider-slug>`** — Disconnect a bound dependency: NULLs the provider ref + contract snapshot and parks the dep (reason `MANUALLY_UNBOUND`). Runtime reads then return `DEP_UNBOUND` until you bind it again. Workspace-admin.
|
|
572
|
+
|
|
573
|
+
**`dashwise deps list`** — Print the *local manifest's* declared deps as column-aligned text (provider slug, version range, tables, purpose). Offline; reads `module.json` only (contrast with the bare `dashwise deps`, which shows live backend connect status). `--json` for piping.
|
|
574
|
+
|
|
575
|
+
**`dashwise deps remove <provider-slug>`** — Drop a dep entry from the manifest (local edit).
|
|
519
576
|
|
|
520
577
|
**`dashwise deps check`** — Verify each declared dep still resolves against a currently-published provider (online command; requires backend reachability). Exits 1 on drift. Reported codes: `PROVIDER_NOT_FOUND`, `NO_MATCHING_VERSION`, `FIELD_NOT_EXPOSED`, `OP_NOT_ALLOWED`. `--json` available for CI integrations.
|
|
521
578
|
|
|
579
|
+
> **`deps` vs `deps list` vs `deps check`:** bare `dashwise deps` reads the **backend's live connect state** for your install (resolved/unbound). `deps list` reads your **local manifest** offline. `deps check` probes **published providers** for manifest drift. Use `deps` to answer "will my cross-module reads work right now?"; `bind` / `unbind` to change that.
|
|
580
|
+
|
|
581
|
+
Auth + install resolution for the online subcommands (`deps`, `bind`, `unbind`) mirror `dashwise origins`: they use your CLI login bearer (bind/unbind need workspace-admin) and resolve the install id from `~/.config/dashwise/auth.json#modules[<slug>]` — you never type it.
|
|
582
|
+
|
|
522
583
|
### Module dev loop
|
|
523
584
|
|
|
524
585
|
```bash
|