@dashai/cli 0.5.0 → 0.5.1
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 +78 -6
- package/dist/bin.js +139 -11
- package/dist/bin.js.map +1 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Status
|
|
8
8
|
|
|
9
|
-
`0.
|
|
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`.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -103,23 +103,25 @@ Flags:
|
|
|
103
103
|
|
|
104
104
|
Requires `dashwise login` first — the command refuses to start if no token is resolvable. The runtime-token injection requires `dashwise init <slug>` (LDI-6); the dev session SSO setup works without it.
|
|
105
105
|
|
|
106
|
-
### `dashwise module init [slug]`
|
|
106
|
+
### `dashwise init [slug]` / `dashwise module init [slug]`
|
|
107
107
|
|
|
108
|
-
Scaffold a new DashWise module in a fresh directory. Two flavors:
|
|
108
|
+
Scaffold a new DashWise module in a fresh directory. `dashwise init` is a top-level alias for `dashwise module init` — both accept the same flags. Two flavors:
|
|
109
109
|
|
|
110
|
-
**
|
|
110
|
+
**Custom** (default since 2026-05-18) — full Next.js App Router app with SDK auth wired in (machine runtime, lands on Fly Machines once P7 ships). Files: `module.json`, `package.json`, `tsconfig.json`, `next.config.mjs`, `next-env.d.ts`, `middleware.ts` (uses `@dashai/sdk/auth/middleware`), `app/layout.tsx`, `app/page.tsx`, `app/dashboard/page.tsx` (auth-gated Server Component example), three `app/api/auth/*` route handlers, shadcn primitives + a `globals.css`, plus `CLAUDE.md` / `spec.md` / `agent-log.md` agent-facing docs. `module.json` carries `module_kind: 'custom'` + `runtime.kind: 'machine'`.
|
|
111
111
|
|
|
112
|
-
**
|
|
112
|
+
**Hand-authored** (`--simple`) — the legacy simple module-runtime app (isolate runtime). 10 files total: no middleware, no `/api/auth/*`, no dashboard. Suitable for public viewers / demo modules that don't need SSO.
|
|
113
113
|
|
|
114
114
|
Flags:
|
|
115
115
|
- `--dir <path>` — Target directory (default `./<slug>`).
|
|
116
116
|
- `--name <name>` — Human-readable module name (default: derived from slug).
|
|
117
117
|
- `--force` — Overwrite an existing non-empty directory.
|
|
118
|
-
- `--
|
|
118
|
+
- `--simple` — Use the legacy minimal scaffold (hand-authored, no Next.js auth wiring).
|
|
119
|
+
- `--custom` — *[Deprecated alias — kept for back-compat.]* Equivalent to the default. Will be removed in a future major version.
|
|
119
120
|
- `--git <url>` — Initial Git repository URL. Written to `module.json#repository.url`.
|
|
120
121
|
- `--description <text>` — Module description forwarded to the backend when provisioning the dev installation (HH-CC-LDI-6). No effect under `--no-provision`.
|
|
121
122
|
- `--workspace <slug-or-id>` — Target workspace for the dev installation (HH-CC-LDI-6). When omitted in a TTY, the CLI prompts; auto-picked if your account has one workspace; in non-interactive mode with multiple workspaces, errors with the list.
|
|
122
123
|
- `--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
|
+
- `--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.
|
|
123
125
|
|
|
124
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 runtime token (90-day JWT) is cached in `~/.config/dashwise/auth.json#modules[<slug>]` where `@dashai/sdk`'s `createDevClient({ moduleSlug })` reads it on every dev-server boot. Provisioning failures are surfaced as warnings; the local scaffold remains usable so you can retry later.
|
|
125
127
|
|
|
@@ -297,6 +299,76 @@ Flags:
|
|
|
297
299
|
|
|
298
300
|
Pre-reqs: `dashwise module generate` must have run (the SDK reads `node_modules/@dashai/generated`). `DASHWISE_API_URL`, `DASHWISE_INSTALLATION_ID`, `DASHWISE_API_TOKEN` must be set (the scaffold's `.env.local` is loaded automatically).
|
|
299
301
|
|
|
302
|
+
### `dashwise pull` (HH-CC-P1-E2)
|
|
303
|
+
|
|
304
|
+
Fetch the canonical manifest from the backend and write it to local `module.json`. The inverse of `dashwise table create` / `field add` — useful after dashboard-side schema edits, DashAI mutations, or teammate-driven changes.
|
|
305
|
+
|
|
306
|
+
The backend (`GET /api/installations/:id/schema`) is the source of truth; `pull` materializes that locally. `dashwise dev`'s watcher polls this endpoint automatically, so most authors don't need to invoke `pull` manually.
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
$ dashwise pull
|
|
310
|
+
ℹ Backend at ab12cd34 — local at 9f8e7d6c. Writing module.json…
|
|
311
|
+
✓ module.json updated (3 tables, 18 fields).
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Flags:
|
|
315
|
+
- `--dir <path>` — Project root (default: current directory).
|
|
316
|
+
- `--dry-run` — Print the diff but don't write.
|
|
317
|
+
|
|
318
|
+
### `dashwise api-keys list|create|revoke` (HH-CC-P1-C4)
|
|
319
|
+
|
|
320
|
+
Mint long-lived production credentials for a `production` install. Used by self-hosted deploys (Railway / Vercel / Fly / your own infra) instead of the per-CLI-session runtime token. 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
|
+
|
|
322
|
+
```sh
|
|
323
|
+
# Mint a key. Plaintext appears on stdout — copy it now.
|
|
324
|
+
dashwise api-keys create production
|
|
325
|
+
|
|
326
|
+
# Script-friendly: capture the raw key with no other chatter.
|
|
327
|
+
KEY=$(dashwise api-keys create ci --raw-only)
|
|
328
|
+
|
|
329
|
+
# List all keys for the current install.
|
|
330
|
+
dashwise api-keys list
|
|
331
|
+
|
|
332
|
+
# Revoke. Irreversible. Effective on the next request.
|
|
333
|
+
dashwise api-keys revoke <key-id>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
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
|
+
|
|
338
|
+
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
|
+
|
|
340
|
+
### `dashwise env export` (HH-CC-P1-D1)
|
|
341
|
+
|
|
342
|
+
Emit the four env vars every self-hosted deploy needs:
|
|
343
|
+
|
|
344
|
+
| Var | Source |
|
|
345
|
+
|---|---|
|
|
346
|
+
| `DASHWISE_API_URL` | CLI config (`apiUrl`). |
|
|
347
|
+
| `NEXT_PUBLIC_DASHWISE_API_URL` | Same. |
|
|
348
|
+
| `DASHWISE_INSTALLATION_ID` | `~/.config/dashwise/auth.json#modules[<slug>].installationId` (the dev install cached at `dashwise init`). |
|
|
349
|
+
| `DASHWISE_API_KEY` | Placeholder by default; pass `--key dwk_...` to inline an existing key, or `--new-key <name>` to mint one in-flight. |
|
|
350
|
+
|
|
351
|
+
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
|
+
|
|
353
|
+
```sh
|
|
354
|
+
# .env syntax — copy/paste into a host that reads .env files.
|
|
355
|
+
dashwise env export --format env > .env.production
|
|
356
|
+
|
|
357
|
+
# Push straight into Railway.
|
|
358
|
+
dashwise env export --key dwk_... --format railway | sh
|
|
359
|
+
|
|
360
|
+
# Mint and inline a new key in one step.
|
|
361
|
+
dashwise env export --new-key prod --format vercel | sh
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Stdout carries only the env block (clean for piping); status chatter goes to stderr.
|
|
365
|
+
|
|
366
|
+
Flags:
|
|
367
|
+
- `--format env|json|railway|vercel|fly` — Output format. Default: `env`.
|
|
368
|
+
- `--key dwk_<...>` — Inline an existing API key.
|
|
369
|
+
- `--new-key <name>` — Mint a new API key and inline its plaintext.
|
|
370
|
+
- `--dir <path>` — Project root.
|
|
371
|
+
|
|
300
372
|
### `dashwise module query-log`
|
|
301
373
|
|
|
302
374
|
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.
|
package/dist/bin.js
CHANGED
|
@@ -4,7 +4,7 @@ import { tmpdir, platform, homedir } from 'os';
|
|
|
4
4
|
import { resolve, join, dirname, relative } from 'path';
|
|
5
5
|
import pc from 'picocolors';
|
|
6
6
|
import { intro, log, select, isCancel, cancel, spinner, outro, text, multiselect, confirm } from '@clack/prompts';
|
|
7
|
-
import { Command } from 'commander';
|
|
7
|
+
import { Command, Option } from 'commander';
|
|
8
8
|
import { spawn, spawnSync } from 'child_process';
|
|
9
9
|
import open from 'open';
|
|
10
10
|
import * as tar from 'tar';
|
|
@@ -394,6 +394,9 @@ var init_output = __esm({
|
|
|
394
394
|
});
|
|
395
395
|
|
|
396
396
|
// src/lib/scaffold.ts
|
|
397
|
+
function isDeployTarget(value) {
|
|
398
|
+
return DEPLOY_TARGETS.includes(value);
|
|
399
|
+
}
|
|
397
400
|
function manifestJson(opts) {
|
|
398
401
|
const kind = opts.kind ?? "hand_authored";
|
|
399
402
|
const manifest = {
|
|
@@ -1017,6 +1020,7 @@ function appApiAuthSignInTs() {
|
|
|
1017
1020
|
// the DashWise FE \`/login?return_to=...\` automatically \u2014 you don't
|
|
1018
1021
|
// need to handle the "user not logged in" case here.
|
|
1019
1022
|
import { NextResponse } from 'next/server';
|
|
1023
|
+
import { getPublicOrigin } from '@/lib/request-origin';
|
|
1020
1024
|
|
|
1021
1025
|
export function GET(request: Request) {
|
|
1022
1026
|
const url = new URL(request.url);
|
|
@@ -1042,8 +1046,10 @@ export function GET(request: Request) {
|
|
|
1042
1046
|
|
|
1043
1047
|
// Absolute URL for return_to so the backend knows which host to
|
|
1044
1048
|
// bounce back to (the callback path is fixed at /api/auth/callback
|
|
1045
|
-
// by SDK convention).
|
|
1046
|
-
|
|
1049
|
+
// by SDK convention). \`getPublicOrigin\` reads \`X-Forwarded-Host\`
|
|
1050
|
+
// when present so the redirect URL points at the public domain,
|
|
1051
|
+
// not the internal Node origin behind reverse proxies.
|
|
1052
|
+
const moduleOrigin = getPublicOrigin(request);
|
|
1047
1053
|
const absoluteReturnTo = \`\${moduleOrigin}\${returnTo}\`;
|
|
1048
1054
|
|
|
1049
1055
|
let ssoStart;
|
|
@@ -1077,12 +1083,17 @@ function appApiAuthCallbackTs() {
|
|
|
1077
1083
|
// (e.g. \`access_denied\`, \`server_error\`, \`invalid_request\`).
|
|
1078
1084
|
import { NextResponse } from 'next/server';
|
|
1079
1085
|
import { exchangeCode } from '@dashai/sdk/auth/server';
|
|
1086
|
+
import { getPublicOrigin } from '@/lib/request-origin';
|
|
1080
1087
|
|
|
1081
1088
|
export async function GET(request: Request) {
|
|
1082
1089
|
const url = new URL(request.url);
|
|
1090
|
+
// Resolve the public origin once \u2014 all redirects below are
|
|
1091
|
+
// back to this module, and behind a reverse proxy url.origin is
|
|
1092
|
+
// the internal Node origin (localhost:<PORT>), not the public host.
|
|
1093
|
+
const publicOrigin = getPublicOrigin(request);
|
|
1083
1094
|
const error = url.searchParams.get('error');
|
|
1084
1095
|
if (error) {
|
|
1085
|
-
const target = new URL('/sign-in-error',
|
|
1096
|
+
const target = new URL('/sign-in-error', publicOrigin);
|
|
1086
1097
|
target.searchParams.set('code', error);
|
|
1087
1098
|
const description = url.searchParams.get('error_description');
|
|
1088
1099
|
if (description) target.searchParams.set('description', description);
|
|
@@ -1091,19 +1102,19 @@ export async function GET(request: Request) {
|
|
|
1091
1102
|
const code = url.searchParams.get('code');
|
|
1092
1103
|
const returnTo = url.searchParams.get('return_to') ?? '/';
|
|
1093
1104
|
if (!code) {
|
|
1094
|
-
const target = new URL('/sign-in-error',
|
|
1105
|
+
const target = new URL('/sign-in-error', publicOrigin);
|
|
1095
1106
|
target.searchParams.set('code', 'missing_code');
|
|
1096
1107
|
return NextResponse.redirect(target);
|
|
1097
1108
|
}
|
|
1098
1109
|
try {
|
|
1099
1110
|
await exchangeCode(code); // sets the dashwise.session cookie
|
|
1100
1111
|
} catch (err) {
|
|
1101
|
-
const target = new URL('/sign-in-error',
|
|
1112
|
+
const target = new URL('/sign-in-error', publicOrigin);
|
|
1102
1113
|
target.searchParams.set('code', 'exchange_failed');
|
|
1103
1114
|
target.searchParams.set('description', (err as Error).message);
|
|
1104
1115
|
return NextResponse.redirect(target);
|
|
1105
1116
|
}
|
|
1106
|
-
return NextResponse.redirect(new URL(returnTo,
|
|
1117
|
+
return NextResponse.redirect(new URL(returnTo, publicOrigin));
|
|
1107
1118
|
}
|
|
1108
1119
|
`;
|
|
1109
1120
|
}
|
|
@@ -1116,10 +1127,14 @@ function appApiAuthSignOutTs() {
|
|
|
1116
1127
|
// to follow with GET (not re-POST), landing on the public '/' page.
|
|
1117
1128
|
import { NextResponse } from 'next/server';
|
|
1118
1129
|
import { signOut } from '@dashai/sdk/auth/server';
|
|
1130
|
+
import { getPublicOrigin } from '@/lib/request-origin';
|
|
1119
1131
|
|
|
1120
1132
|
export async function POST(request: Request) {
|
|
1121
1133
|
await signOut();
|
|
1122
|
-
|
|
1134
|
+
// Build the redirect against the public origin so we don't land
|
|
1135
|
+
// the user on \`http://localhost:<PORT>/\` when running behind a
|
|
1136
|
+
// reverse proxy (Railway/Vercel/Fly).
|
|
1137
|
+
return NextResponse.redirect(new URL('/', getPublicOrigin(request)), 303);
|
|
1123
1138
|
}
|
|
1124
1139
|
`;
|
|
1125
1140
|
}
|
|
@@ -1293,6 +1308,36 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1293
1308
|
}
|
|
1294
1309
|
`;
|
|
1295
1310
|
}
|
|
1311
|
+
function libRequestOriginTs() {
|
|
1312
|
+
return `/**
|
|
1313
|
+
* Resolve the **public** origin of an incoming request.
|
|
1314
|
+
*
|
|
1315
|
+
* Behind a reverse proxy (Railway, Vercel, Fly, Cloudflare, an
|
|
1316
|
+
* nginx in front of a Node container, etc.) \`new URL(request.url)\`
|
|
1317
|
+
* reports the *internal* origin the Node process is bound to \u2014
|
|
1318
|
+
* usually \`http://localhost:<PORT>\` \u2014 not the public URL the
|
|
1319
|
+
* browser hit. The proxy preserves the public origin in
|
|
1320
|
+
* \`X-Forwarded-*\` headers; we read those first.
|
|
1321
|
+
*
|
|
1322
|
+
* Falls back to \`new URL(request.url).origin\` for local dev where
|
|
1323
|
+
* there's no proxy in front of Next.js.
|
|
1324
|
+
*
|
|
1325
|
+
* Both \`x-forwarded-proto\` and \`x-forwarded-host\` can be
|
|
1326
|
+
* comma-separated when multiple proxies chain; the leftmost entry
|
|
1327
|
+
* is the original client-facing one per RFC 7239 conventions.
|
|
1328
|
+
*/
|
|
1329
|
+
export function getPublicOrigin(request: Request): string {
|
|
1330
|
+
const forwardedProto = request.headers.get('x-forwarded-proto');
|
|
1331
|
+
const forwardedHost = request.headers.get('x-forwarded-host');
|
|
1332
|
+
if (forwardedProto && forwardedHost) {
|
|
1333
|
+
const proto = forwardedProto.split(',')[0].trim();
|
|
1334
|
+
const host = forwardedHost.split(',')[0].trim();
|
|
1335
|
+
return \`\${proto}://\${host}\`;
|
|
1336
|
+
}
|
|
1337
|
+
return new URL(request.url).origin;
|
|
1338
|
+
}
|
|
1339
|
+
`;
|
|
1340
|
+
}
|
|
1296
1341
|
function componentsUiButtonTsx() {
|
|
1297
1342
|
return `import * as React from "react";
|
|
1298
1343
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
@@ -1750,9 +1795,63 @@ Format (reverse chronological, newest first):
|
|
|
1750
1795
|
schema mutation.
|
|
1751
1796
|
`;
|
|
1752
1797
|
}
|
|
1753
|
-
|
|
1798
|
+
function railwayJson(_opts) {
|
|
1799
|
+
return JSON.stringify(
|
|
1800
|
+
{
|
|
1801
|
+
$schema: "https://railway.com/railway.schema.json",
|
|
1802
|
+
build: {
|
|
1803
|
+
builder: "NIXPACKS"
|
|
1804
|
+
},
|
|
1805
|
+
deploy: {
|
|
1806
|
+
restartPolicyType: "ON_FAILURE",
|
|
1807
|
+
restartPolicyMaxRetries: 3
|
|
1808
|
+
}
|
|
1809
|
+
},
|
|
1810
|
+
null,
|
|
1811
|
+
2
|
|
1812
|
+
) + "\n";
|
|
1813
|
+
}
|
|
1814
|
+
function vercelJson(_opts) {
|
|
1815
|
+
return JSON.stringify(
|
|
1816
|
+
{
|
|
1817
|
+
$schema: "https://openapi.vercel.sh/vercel.json",
|
|
1818
|
+
framework: "nextjs"
|
|
1819
|
+
},
|
|
1820
|
+
null,
|
|
1821
|
+
2
|
|
1822
|
+
) + "\n";
|
|
1823
|
+
}
|
|
1824
|
+
function flyToml(opts) {
|
|
1825
|
+
return `# fly.toml \u2014 generated by \`dashwise init --deploy-target fly\`.
|
|
1826
|
+
# Run \`fly launch --no-deploy --copy-config\` to register this app with
|
|
1827
|
+
# Fly; the launcher will read this file and prompt for anything missing.
|
|
1828
|
+
#
|
|
1829
|
+
# Edit \`app\` if the slug is already taken globally on fly.io.
|
|
1830
|
+
# Edit \`primary_region\` for non-US-East deploys (https://fly.io/docs/reference/regions/).
|
|
1831
|
+
|
|
1832
|
+
app = "${opts.slug}"
|
|
1833
|
+
primary_region = "iad"
|
|
1834
|
+
|
|
1835
|
+
[build]
|
|
1836
|
+
|
|
1837
|
+
[http_service]
|
|
1838
|
+
internal_port = 3000
|
|
1839
|
+
force_https = true
|
|
1840
|
+
auto_stop_machines = "stop"
|
|
1841
|
+
auto_start_machines = true
|
|
1842
|
+
min_machines_running = 0
|
|
1843
|
+
processes = ["app"]
|
|
1844
|
+
|
|
1845
|
+
[[vm]]
|
|
1846
|
+
cpu_kind = "shared"
|
|
1847
|
+
cpus = 1
|
|
1848
|
+
memory_mb = 256
|
|
1849
|
+
`;
|
|
1850
|
+
}
|
|
1851
|
+
var DEPLOY_TARGETS, SCAFFOLD_DEFAULT_API_URL;
|
|
1754
1852
|
var init_scaffold = __esm({
|
|
1755
1853
|
"src/lib/scaffold.ts"() {
|
|
1854
|
+
DEPLOY_TARGETS = ["railway", "vercel", "fly"];
|
|
1756
1855
|
SCAFFOLD_DEFAULT_API_URL = "http://localhost:3000";
|
|
1757
1856
|
}
|
|
1758
1857
|
});
|
|
@@ -1854,6 +1953,12 @@ async function moduleInitCommand(slugArg, options) {
|
|
|
1854
1953
|
);
|
|
1855
1954
|
return 1;
|
|
1856
1955
|
}
|
|
1956
|
+
if (options.deployTarget !== void 0 && !isDeployTarget(options.deployTarget)) {
|
|
1957
|
+
fail(
|
|
1958
|
+
`Invalid --deploy-target ${code(options.deployTarget)} \u2014 must be one of ${DEPLOY_TARGETS.map((t) => code(t)).join(", ")}.`
|
|
1959
|
+
);
|
|
1960
|
+
return 1;
|
|
1961
|
+
}
|
|
1857
1962
|
const kind = options.simple ? "hand_authored" : "custom";
|
|
1858
1963
|
const scaffoldOpts = {
|
|
1859
1964
|
slug,
|
|
@@ -1886,6 +1991,7 @@ async function moduleInitCommand(slugArg, options) {
|
|
|
1886
1991
|
["postcss.config.mjs", postcssConfigMjs()],
|
|
1887
1992
|
["app/globals.css", globalsCss()],
|
|
1888
1993
|
["lib/utils.ts", libUtilsTs()],
|
|
1994
|
+
["lib/request-origin.ts", libRequestOriginTs()],
|
|
1889
1995
|
["components/theme-provider.tsx", componentsThemeProviderTsx()],
|
|
1890
1996
|
["components/ui/button.tsx", componentsUiButtonTsx()],
|
|
1891
1997
|
["components/ui/card.tsx", componentsUiCardTsx()],
|
|
@@ -1904,6 +2010,19 @@ async function moduleInitCommand(slugArg, options) {
|
|
|
1904
2010
|
["app/page.tsx", appPageTsx(scaffoldOpts)]
|
|
1905
2011
|
);
|
|
1906
2012
|
}
|
|
2013
|
+
if (options.deployTarget !== void 0) {
|
|
2014
|
+
switch (options.deployTarget) {
|
|
2015
|
+
case "railway":
|
|
2016
|
+
files.push(["railway.json", railwayJson()]);
|
|
2017
|
+
break;
|
|
2018
|
+
case "vercel":
|
|
2019
|
+
files.push(["vercel.json", vercelJson()]);
|
|
2020
|
+
break;
|
|
2021
|
+
case "fly":
|
|
2022
|
+
files.push(["fly.toml", flyToml(scaffoldOpts)]);
|
|
2023
|
+
break;
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
1907
2026
|
for (const [relPath, content] of files) {
|
|
1908
2027
|
const absPath = join(dir, relPath);
|
|
1909
2028
|
const parentDir = join(absPath, "..");
|
|
@@ -5243,6 +5362,9 @@ function surfacePullFailure(err) {
|
|
|
5243
5362
|
return 1;
|
|
5244
5363
|
}
|
|
5245
5364
|
|
|
5365
|
+
// src/bin.ts
|
|
5366
|
+
init_scaffold();
|
|
5367
|
+
|
|
5246
5368
|
// src/commands/api-keys.ts
|
|
5247
5369
|
init_api_client();
|
|
5248
5370
|
init_config();
|
|
@@ -6253,6 +6375,11 @@ var initOptions = (cmd) => cmd.option("--dir <path>", "Override the target direc
|
|
|
6253
6375
|
).option(
|
|
6254
6376
|
"--no-provision",
|
|
6255
6377
|
"Skip the `POST /api/installations/dev` step. Local scaffold is still written; you can provision later by re-running `dashwise init --force` (or, once it ships, `dashwise module provision-dev-install`)."
|
|
6378
|
+
).addOption(
|
|
6379
|
+
new Option(
|
|
6380
|
+
"--deploy-target <platform>",
|
|
6381
|
+
"Emit a platform deploy config file alongside the scaffold (railway.json | vercel.json | fly.toml). Default: none (clean repo). Pair with `dashwise env export --format <platform>` to push env vars after provisioning."
|
|
6382
|
+
).choices([...DEPLOY_TARGETS])
|
|
6256
6383
|
);
|
|
6257
6384
|
var initAction = async (slugArg, cmdOpts) => {
|
|
6258
6385
|
process.exitCode = await moduleInitCommand(slugArg, {
|
|
@@ -6264,7 +6391,8 @@ var initAction = async (slugArg, cmdOpts) => {
|
|
|
6264
6391
|
...cmdOpts.git !== void 0 ? { git: cmdOpts.git } : {},
|
|
6265
6392
|
...cmdOpts.description !== void 0 ? { description: cmdOpts.description } : {},
|
|
6266
6393
|
...cmdOpts.workspace !== void 0 ? { workspace: cmdOpts.workspace } : {},
|
|
6267
|
-
...cmdOpts.provision !== void 0 ? { provision: cmdOpts.provision } : {}
|
|
6394
|
+
...cmdOpts.provision !== void 0 ? { provision: cmdOpts.provision } : {},
|
|
6395
|
+
...cmdOpts.deployTarget !== void 0 ? { deployTarget: cmdOpts.deployTarget } : {}
|
|
6268
6396
|
});
|
|
6269
6397
|
};
|
|
6270
6398
|
initOptions(
|
|
@@ -6651,7 +6779,7 @@ fieldCmd.command("set-type <table-slug> <field-slug> <new-type>").description(
|
|
|
6651
6779
|
}
|
|
6652
6780
|
})();
|
|
6653
6781
|
function getVersion() {
|
|
6654
|
-
return "0.5.
|
|
6782
|
+
return "0.5.1";
|
|
6655
6783
|
}
|
|
6656
6784
|
function parseIntOption(value) {
|
|
6657
6785
|
const n = Number.parseInt(value, 10);
|