rastack 0.0.54 → 0.0.56

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.
@@ -1,16 +1,20 @@
1
1
  /**
2
2
  * Pure core of `rastack dev` — the local, always-WASM development server.
3
3
  *
4
- * `rastack dev` boots the app + admin **in the browser** over the WebAssembly
5
- * engine (the same app-generic `rastack-api-core` the Lambda runs, fed the app's
4
+ * `rastack dev` runs **your app** in the browser over the WebAssembly engine
5
+ * (the same app-generic `rastack-api-core` the Lambda runs, fed the app's
6
6
  * compiled manifest). No native server, no cargo: a dependency-free static
7
- * server hands the browser the prebuilt wasm engine, the compiled schema, and
8
- * the committed Iceberg warehouse, and a bundled React admin drives it.
7
+ * server hands the browser the prebuilt wasm engine, the compiled schema, the
8
+ * committed Iceberg warehouse, and the developer's own app. It does **not**
9
+ * serve the admin console — that is a separate command, `rastack admin`.
10
+ *
11
+ * When the project has no app to serve, `dev` shows a Django-style welcome
12
+ * page (`renderWelcome`) so a fresh scaffold still boots to something friendly.
9
13
  *
10
14
  * Everything decidable without IO lives here (arg parsing, MIME types, locating
11
- * the wasm bundle, the HTML shell) so it is unit-tested without a socket or a
12
- * filesystem; `rastack-dev.ts` is the thin IO wrapper that compiles, resolves
13
- * the engine, and serves.
15
+ * the wasm bundle, resolving the app root, the HTML pages) so it is unit-tested
16
+ * without a socket or a filesystem; `rastack-dev.ts` is the thin IO wrapper that
17
+ * compiles, resolves the engine and the app, and serves.
14
18
  */
15
19
  export interface DevArgs {
16
20
  /** Where the TypeScript resource definitions live (compiled on start). */
@@ -19,6 +23,12 @@ export interface DevArgs {
19
23
  outDir: string;
20
24
  /** The committed Iceberg warehouse served to seed the browser engine. */
21
25
  warehouseDir: string;
26
+ /**
27
+ * Explicit app root to serve at `/` (its `index.html`). Empty when unset —
28
+ * the IO wrapper then probes `appRootCandidates`, falling back to the welcome
29
+ * page when none holds an `index.html`.
30
+ */
31
+ appDir: string;
22
32
  /** Port the dev server listens on. */
23
33
  port: number;
24
34
  /** Open the browser on start (false with `--no-open`). */
@@ -26,10 +36,21 @@ export interface DevArgs {
26
36
  }
27
37
  export declare const DEV_DEFAULTS: DevArgs;
28
38
  /**
29
- * Parse `rastack dev` args: `--port`, `--warehouse`, `--out`, `--no-open`, and a
30
- * single positional resources dir. Unknown flags are ignored (forgiving CLI).
39
+ * Parse `rastack dev` args: `--port`, `--warehouse`, `--out`, `--app`,
40
+ * `--no-open`, and a single positional resources dir. Unknown flags are ignored
41
+ * (forgiving CLI).
31
42
  */
32
43
  export declare function parseDevArgs(argv: string[]): DevArgs;
44
+ /** The file that marks a directory as a servable app root. */
45
+ export declare const APP_ENTRY = "index.html";
46
+ /**
47
+ * Ordered directories to probe for the developer's app (`index.html`). An
48
+ * explicit `--app <dir>` wins outright; otherwise `dev` looks in the
49
+ * conventional static roots and finally the project root. The IO wrapper picks
50
+ * the first candidate that actually holds an `index.html`; if none does, it
51
+ * serves the welcome page instead.
52
+ */
53
+ export declare function appRootCandidates(appDir: string, cwd?: string): string[];
33
54
  /** Args for `rastack admin` — like `DevArgs`, but bound to a real server port. */
34
55
  export interface AdminArgs {
35
56
  resourcesDir: string;
@@ -62,9 +83,19 @@ export declare function wasmBundleCandidates(dirnameDir: string, cwd?: string):
62
83
  /** The name of the file that marks a directory as a usable wasm bundle. */
63
84
  export declare const WASM_ENTRY = "rastack_wasm.js";
64
85
  /**
65
- * The HTML shell served at `/`. It loads the bundled React admin
66
- * (`/dev/admin.js`), which fetches the schema/openapi, boots the wasm engine,
67
- * seeds it from `/data/warehouse/`, and renders the admin. Deliberately tiny —
68
- * all logic lives in the bundle — mirroring the `rastack design` studio.
86
+ * The HTML shell served at `/` by **`rastack admin`**. It loads the bundled
87
+ * React admin (`/dev/admin.js`), which fetches the schema/openapi, boots the
88
+ * wasm engine, seeds it from `/data/warehouse/`, and renders the admin console.
89
+ * Deliberately tiny — all logic lives in the bundle — mirroring the
90
+ * `rastack design` studio. `rastack dev` does **not** use this: it serves the
91
+ * developer's own app (or the welcome page below).
69
92
  */
70
93
  export declare function renderShell(title?: string): string;
94
+ /**
95
+ * The Django-style welcome page `rastack dev` serves at `/` when the project
96
+ * has **no app** to serve (no `index.html` in any `appRootCandidates` dir).
97
+ * It confirms the dev server is up, points at the live backend endpoints the
98
+ * WASM engine exposes, and tells you how to add an app or open the admin — the
99
+ * "It worked!" moment of `django-admin runserver`, on brand for the stack.
100
+ */
101
+ export declare function renderWelcome(title?: string): string;
@@ -2,16 +2,20 @@
2
2
  /**
3
3
  * Pure core of `rastack dev` — the local, always-WASM development server.
4
4
  *
5
- * `rastack dev` boots the app + admin **in the browser** over the WebAssembly
6
- * engine (the same app-generic `rastack-api-core` the Lambda runs, fed the app's
5
+ * `rastack dev` runs **your app** in the browser over the WebAssembly engine
6
+ * (the same app-generic `rastack-api-core` the Lambda runs, fed the app's
7
7
  * compiled manifest). No native server, no cargo: a dependency-free static
8
- * server hands the browser the prebuilt wasm engine, the compiled schema, and
9
- * the committed Iceberg warehouse, and a bundled React admin drives it.
8
+ * server hands the browser the prebuilt wasm engine, the compiled schema, the
9
+ * committed Iceberg warehouse, and the developer's own app. It does **not**
10
+ * serve the admin console — that is a separate command, `rastack admin`.
11
+ *
12
+ * When the project has no app to serve, `dev` shows a Django-style welcome
13
+ * page (`renderWelcome`) so a fresh scaffold still boots to something friendly.
10
14
  *
11
15
  * Everything decidable without IO lives here (arg parsing, MIME types, locating
12
- * the wasm bundle, the HTML shell) so it is unit-tested without a socket or a
13
- * filesystem; `rastack-dev.ts` is the thin IO wrapper that compiles, resolves
14
- * the engine, and serves.
16
+ * the wasm bundle, resolving the app root, the HTML pages) so it is unit-tested
17
+ * without a socket or a filesystem; `rastack-dev.ts` is the thin IO wrapper that
18
+ * compiles, resolves the engine and the app, and serves.
15
19
  */
16
20
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
21
  if (k2 === undefined) k2 = k;
@@ -47,27 +51,31 @@ var __importStar = (this && this.__importStar) || (function () {
47
51
  };
48
52
  })();
49
53
  Object.defineProperty(exports, "__esModule", { value: true });
50
- exports.WASM_ENTRY = exports.ADMIN_DEFAULTS = exports.DEV_DEFAULTS = void 0;
54
+ exports.WASM_ENTRY = exports.ADMIN_DEFAULTS = exports.APP_ENTRY = exports.DEV_DEFAULTS = void 0;
51
55
  exports.parseDevArgs = parseDevArgs;
56
+ exports.appRootCandidates = appRootCandidates;
52
57
  exports.parseAdminArgs = parseAdminArgs;
53
58
  exports.contentType = contentType;
54
59
  exports.wasmBundleCandidates = wasmBundleCandidates;
55
60
  exports.renderShell = renderShell;
61
+ exports.renderWelcome = renderWelcome;
56
62
  const path = __importStar(require("path"));
57
63
  exports.DEV_DEFAULTS = {
58
64
  resourcesDir: "resources",
59
65
  outDir: ".rastack",
60
66
  warehouseDir: "data/warehouse",
67
+ appDir: "",
61
68
  port: 4321,
62
69
  open: true,
63
70
  };
64
71
  /**
65
- * Parse `rastack dev` args: `--port`, `--warehouse`, `--out`, `--no-open`, and a
66
- * single positional resources dir. Unknown flags are ignored (forgiving CLI).
72
+ * Parse `rastack dev` args: `--port`, `--warehouse`, `--out`, `--app`,
73
+ * `--no-open`, and a single positional resources dir. Unknown flags are ignored
74
+ * (forgiving CLI).
67
75
  */
68
76
  function parseDevArgs(argv) {
69
77
  const positional = [];
70
- let { resourcesDir, outDir, warehouseDir, port, open } = exports.DEV_DEFAULTS;
78
+ let { resourcesDir, outDir, warehouseDir, appDir, port, open } = exports.DEV_DEFAULTS;
71
79
  for (let i = 0; i < argv.length; i++) {
72
80
  const a = argv[i];
73
81
  if (a === "--port")
@@ -76,6 +84,8 @@ function parseDevArgs(argv) {
76
84
  warehouseDir = argv[++i] ?? warehouseDir;
77
85
  else if (a === "--out")
78
86
  outDir = argv[++i] ?? outDir;
87
+ else if (a === "--app")
88
+ appDir = argv[++i] ?? appDir;
79
89
  else if (a === "--no-open")
80
90
  open = false;
81
91
  else if (!a.startsWith("-"))
@@ -85,10 +95,25 @@ function parseDevArgs(argv) {
85
95
  resourcesDir: positional[0] || resourcesDir,
86
96
  outDir,
87
97
  warehouseDir,
98
+ appDir,
88
99
  port,
89
100
  open,
90
101
  };
91
102
  }
103
+ /** The file that marks a directory as a servable app root. */
104
+ exports.APP_ENTRY = "index.html";
105
+ /**
106
+ * Ordered directories to probe for the developer's app (`index.html`). An
107
+ * explicit `--app <dir>` wins outright; otherwise `dev` looks in the
108
+ * conventional static roots and finally the project root. The IO wrapper picks
109
+ * the first candidate that actually holds an `index.html`; if none does, it
110
+ * serves the welcome page instead.
111
+ */
112
+ function appRootCandidates(appDir, cwd = process.cwd()) {
113
+ if (appDir)
114
+ return [path.resolve(cwd, appDir)];
115
+ return ["public", "www", "app", "."].map((d) => path.resolve(cwd, d));
116
+ }
92
117
  exports.ADMIN_DEFAULTS = {
93
118
  resourcesDir: "resources",
94
119
  outDir: ".rastack",
@@ -162,12 +187,14 @@ function wasmBundleCandidates(dirnameDir, cwd = process.cwd()) {
162
187
  /** The name of the file that marks a directory as a usable wasm bundle. */
163
188
  exports.WASM_ENTRY = "rastack_wasm.js";
164
189
  /**
165
- * The HTML shell served at `/`. It loads the bundled React admin
166
- * (`/dev/admin.js`), which fetches the schema/openapi, boots the wasm engine,
167
- * seeds it from `/data/warehouse/`, and renders the admin. Deliberately tiny —
168
- * all logic lives in the bundle — mirroring the `rastack design` studio.
190
+ * The HTML shell served at `/` by **`rastack admin`**. It loads the bundled
191
+ * React admin (`/dev/admin.js`), which fetches the schema/openapi, boots the
192
+ * wasm engine, seeds it from `/data/warehouse/`, and renders the admin console.
193
+ * Deliberately tiny — all logic lives in the bundle — mirroring the
194
+ * `rastack design` studio. `rastack dev` does **not** use this: it serves the
195
+ * developer's own app (or the welcome page below).
169
196
  */
170
- function renderShell(title = "React API Stack — dev") {
197
+ function renderShell(title = "React API Stack — admin") {
171
198
  return `<!doctype html>
172
199
  <html lang="en">
173
200
  <head>
@@ -187,3 +214,77 @@ function renderShell(title = "React API Stack — dev") {
187
214
  </html>
188
215
  `;
189
216
  }
217
+ /**
218
+ * The Django-style welcome page `rastack dev` serves at `/` when the project
219
+ * has **no app** to serve (no `index.html` in any `appRootCandidates` dir).
220
+ * It confirms the dev server is up, points at the live backend endpoints the
221
+ * WASM engine exposes, and tells you how to add an app or open the admin — the
222
+ * "It worked!" moment of `django-admin runserver`, on brand for the stack.
223
+ */
224
+ function renderWelcome(title = "React API Stack — dev") {
225
+ return `<!doctype html>
226
+ <html lang="en">
227
+ <head>
228
+ <meta charset="utf-8" />
229
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
230
+ <title>${title}</title>
231
+ <style>
232
+ :root { color-scheme: light dark; }
233
+ * { box-sizing: border-box; }
234
+ html, body { margin: 0; min-height: 100%; }
235
+ body {
236
+ font: 15px/1.6 system-ui, -apple-system, "Segoe UI", sans-serif;
237
+ color: #1f2328; background: #f6f8fa;
238
+ display: flex; align-items: center; justify-content: center; padding: 2rem;
239
+ }
240
+ .card {
241
+ max-width: 640px; width: 100%; background: #fff; border: 1px solid #d0d7de;
242
+ border-radius: 14px; padding: 2.5rem; box-shadow: 0 1px 3px rgba(0,0,0,.06);
243
+ }
244
+ .rocket { font-size: 2.5rem; line-height: 1; }
245
+ h1 { font-size: 1.5rem; margin: .75rem 0 .25rem; }
246
+ p.lead { color: #57606a; margin: 0 0 1.5rem; }
247
+ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
248
+ background: #eff1f3; padding: .1em .4em; border-radius: 5px; font-size: .9em; }
249
+ ul { padding-left: 1.1rem; margin: 0; }
250
+ li { margin: .4rem 0; }
251
+ a { color: #0969da; text-decoration: none; }
252
+ a:hover { text-decoration: underline; }
253
+ .foot { margin-top: 1.75rem; padding-top: 1.25rem; border-top: 1px solid #eaeef2;
254
+ color: #6e7781; font-size: .85rem; }
255
+ @media (prefers-color-scheme: dark) {
256
+ body { color: #e6edf3; background: #0d1117; }
257
+ .card { background: #161b22; border-color: #30363d; box-shadow: none; }
258
+ p.lead { color: #8b949e; }
259
+ code { background: #21262d; }
260
+ .foot { border-color: #21262d; color: #8b949e; }
261
+ }
262
+ </style>
263
+ </head>
264
+ <body>
265
+ <div class="card">
266
+ <div class="rocket">🚀</div>
267
+ <h1>The dev server is running.</h1>
268
+ <p class="lead">
269
+ Congratulations — <strong>rastack dev</strong> is up and your API is running
270
+ in the browser over WebAssembly. You're seeing this page because there's no
271
+ app to serve yet.
272
+ </p>
273
+ <ul>
274
+ <li>Add an <code>index.html</code> (in <code>public/</code>, <code>www/</code>,
275
+ <code>app/</code>, or the project root) and reload — <code>dev</code> will serve it.
276
+ Point it at a different folder with <code>rastack dev --app &lt;dir&gt;</code>.</li>
277
+ <li>Wire your app to the local engine with
278
+ <code>&lt;RAStackProvider mode="local"&gt;</code>.</li>
279
+ <li>Live backend endpoints:
280
+ <a href="/schema.rastack.json">/schema.rastack.json</a>,
281
+ <a href="/openapi.json">/openapi.json</a>,
282
+ <code>/data/warehouse/…</code>, <code>/wasm/…</code>.</li>
283
+ <li>Want the database console instead? Run <code>rastack admin</code>.</li>
284
+ </ul>
285
+ <div class="foot">React API Stack — a full-stack framework on object storage.</div>
286
+ </div>
287
+ </body>
288
+ </html>
289
+ `;
290
+ }
@@ -1,17 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * `rastack dev` — local development, always over the WASM engine.
3
+ * `rastack dev` — local development of **your app**, always over the WASM engine.
4
4
  *
5
- * rastack dev [resourcesDir] [--port <n>] [--warehouse <dir>] [--out <dir>] [--no-open]
5
+ * rastack dev [resourcesDir] [--port <n>] [--warehouse <dir>] [--out <dir>] [--app <dir>] [--no-open]
6
6
  *
7
7
  * Compiles the resources, then boots a dependency-free static server (à la
8
- * `rastack design`) that hands the browser everything it needs to run the app +
9
- * admin locally over WebAssembly — no native server, no cargo:
10
- * • the bundled React admin (`/dev/admin.js`),
8
+ * `rastack design`) that hands the browser everything it needs to run the
9
+ * developer's own app locally over WebAssembly — no native server, no cargo:
10
+ * • the developer's app (`index.html` from the resolved app root), or a
11
+ * Django-style welcome page when the project has no app yet,
11
12
  * • the prebuilt WASM engine (`/wasm/…`) shipped in the package,
12
13
  * • the compiled `schema.rastack.json` / `openapi.json`,
13
14
  * • the committed Iceberg warehouse (`/data/warehouse/…`) to seed from.
14
15
  *
16
+ * It does **not** serve the admin console — that is a separate command,
17
+ * `rastack admin`.
18
+ *
15
19
  * The engine is resolved from the package's prebuilt bundle; if none is present
16
20
  * but a Rust + wasm toolchain is, it is built from source as a fallback.
17
21
  */
@@ -1,18 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  /**
4
- * `rastack dev` — local development, always over the WASM engine.
4
+ * `rastack dev` — local development of **your app**, always over the WASM engine.
5
5
  *
6
- * rastack dev [resourcesDir] [--port <n>] [--warehouse <dir>] [--out <dir>] [--no-open]
6
+ * rastack dev [resourcesDir] [--port <n>] [--warehouse <dir>] [--out <dir>] [--app <dir>] [--no-open]
7
7
  *
8
8
  * Compiles the resources, then boots a dependency-free static server (à la
9
- * `rastack design`) that hands the browser everything it needs to run the app +
10
- * admin locally over WebAssembly — no native server, no cargo:
11
- * • the bundled React admin (`/dev/admin.js`),
9
+ * `rastack design`) that hands the browser everything it needs to run the
10
+ * developer's own app locally over WebAssembly — no native server, no cargo:
11
+ * • the developer's app (`index.html` from the resolved app root), or a
12
+ * Django-style welcome page when the project has no app yet,
12
13
  * • the prebuilt WASM engine (`/wasm/…`) shipped in the package,
13
14
  * • the compiled `schema.rastack.json` / `openapi.json`,
14
15
  * • the committed Iceberg warehouse (`/data/warehouse/…`) to seed from.
15
16
  *
17
+ * It does **not** serve the admin console — that is a separate command,
18
+ * `rastack admin`.
19
+ *
16
20
  * The engine is resolved from the package's prebuilt bundle; if none is present
17
21
  * but a Rust + wasm toolchain is, it is built from source as a fallback.
18
22
  */
@@ -73,6 +77,14 @@ function cargoAvailable() {
73
77
  return false;
74
78
  }
75
79
  }
80
+ /** First app-root candidate that holds an `index.html`, or null (→ welcome). */
81
+ function resolveAppRoot(appDir) {
82
+ for (const dir of (0, harness_1.appRootCandidates)(appDir)) {
83
+ if (fs.existsSync(path.join(dir, harness_1.APP_ENTRY)))
84
+ return dir;
85
+ }
86
+ return null;
87
+ }
76
88
  /** Locate the prebuilt wasm bundle dir, building from source as a fallback. */
77
89
  function resolveWasmDir() {
78
90
  for (const dir of (0, harness_1.wasmBundleCandidates)(HERE)) {
@@ -141,7 +153,7 @@ function openBrowser(url) {
141
153
  }
142
154
  function main(argv) {
143
155
  const args = (0, harness_1.parseDevArgs)(argv);
144
- console.log(`\n rastack dev — the app + admin, in your browser over WASM\n`);
156
+ console.log(`\n rastack dev — your app, in your browser over WASM\n`);
145
157
  console.log(`▸ Compiling ${args.resourcesDir} → ${args.outDir}`);
146
158
  if (!compile(args.resourcesDir, args.outDir)) {
147
159
  console.error(" ✗ compile failed — fix the resource graph and re-run.");
@@ -156,38 +168,53 @@ function main(argv) {
156
168
  " cargo install wasm-bindgen-cli\n");
157
169
  process.exit(1);
158
170
  }
159
- const adminBundle = path.join(HERE, "admin.js");
160
- if (!fs.existsSync(adminBundle)) {
161
- console.error(" ✗ admin bundle (dist/admin.js) not found — reinstall rastack.");
162
- process.exit(1);
163
- }
171
+ // Serve the developer's own app when there is one; otherwise the welcome page.
172
+ const appRoot = resolveAppRoot(args.appDir);
164
173
  const server = http.createServer((req, res) => {
165
174
  const url = (req.url || "/").split("?")[0];
166
175
  if (req.method !== "GET") {
167
176
  res.writeHead(405).end("Method not allowed");
168
177
  return;
169
178
  }
170
- if (url === "/" || url === "/index.html") {
171
- res
172
- .writeHead(200, { "Content-Type": "text/html; charset=utf-8" })
173
- .end((0, harness_1.renderShell)());
174
- return;
175
- }
176
- if (url === "/dev/admin.js")
177
- return serveFile(res, adminBundle);
179
+ // Reserved backend routes always win over the app's static files.
178
180
  if (url.startsWith("/wasm/"))
179
181
  return serveUnder(res, wasmDir, url.slice("/wasm/".length));
180
182
  if (url === "/schema.rastack.json" || url === "/openapi.json")
181
183
  return serveUnder(res, args.outDir, path.basename(url));
182
184
  if (url.startsWith("/data/warehouse/"))
183
185
  return serveUnder(res, args.warehouseDir, url.slice("/data/warehouse/".length));
184
- res.writeHead(404).end("Not found");
186
+ // No app → the Django-style welcome page (root only; else 404).
187
+ if (!appRoot) {
188
+ if (url === "/" || url === "/index.html") {
189
+ res
190
+ .writeHead(200, { "Content-Type": "text/html; charset=utf-8" })
191
+ .end((0, harness_1.renderWelcome)());
192
+ return;
193
+ }
194
+ res.writeHead(404).end("Not found");
195
+ return;
196
+ }
197
+ // Serve the app: its index.html at `/`, an existing file as-is, and any
198
+ // other route back to index.html (SPA client-side routing).
199
+ if (url === "/" || url === "/index.html")
200
+ return serveFile(res, path.join(appRoot, harness_1.APP_ENTRY));
201
+ const rel = decodeURIComponent(url).replace(/^\/+/, "");
202
+ const target = path.resolve(appRoot, rel);
203
+ const safeRoot = path.resolve(appRoot);
204
+ const inRoot = target === safeRoot || target.startsWith(safeRoot + path.sep);
205
+ if (inRoot && fs.existsSync(target) && fs.statSync(target).isFile())
206
+ return serveFile(res, target);
207
+ return serveFile(res, path.join(appRoot, harness_1.APP_ENTRY));
185
208
  });
186
209
  server.listen(args.port, () => {
187
210
  const url = `http://localhost:${args.port}`;
188
211
  console.log(` ✓ WASM engine: ${path.relative(process.cwd(), wasmDir)}`);
189
- console.log(`\n ▸ ${url} (admin at ${url}/#/)\n`);
190
- console.log(" Press Ctrl+C to stop.\n");
212
+ if (appRoot)
213
+ console.log(` ✓ app: ${path.relative(process.cwd(), appRoot) || "."}`);
214
+ else
215
+ console.log(` ○ no app found — serving the welcome page`);
216
+ console.log(`\n ▸ ${url}\n`);
217
+ console.log(" Need the database console? Run `rastack admin`. Ctrl+C to stop.\n");
191
218
  if (args.open)
192
219
  openBrowser(url);
193
220
  });
@@ -82,10 +82,17 @@ function readVersion(file) {
82
82
  * sanitized (`sanitizeVersion`). POSIX keeps the shell-free `execFile`.
83
83
  */
84
84
  function runNpm(args, opts) {
85
- // nosemgrep: javascript.lang.security.detect-child-process.detect-child-process
86
- return NPM_SHELL
87
- ? (0, child_process_1.execSync)((0, update_1.npmShellCommand)(NPM, args), opts)
88
- : (0, child_process_1.execFileSync)(NPM, args, opts);
85
+ if (NPM_SHELL) {
86
+ // Windows: launch the `npm.cmd` shim through a shell (a bare `.cmd` spawn is
87
+ // rejected with EINVAL since the Node CVE-2024-27980 fix). The only
88
+ // non-literal token — the version — is sanitized in `parseUpdateFlags`, and
89
+ // every other arg is a fixed literal, so nothing injectable reaches it. The
90
+ // nosemgrep must sit on the line directly above the `execSync` call for the
91
+ // engine to honour it.
92
+ // nosemgrep: javascript.lang.security.detect-child-process.detect-child-process
93
+ return (0, child_process_1.execSync)((0, update_1.npmShellCommand)(NPM, args), opts);
94
+ }
95
+ return (0, child_process_1.execFileSync)(NPM, args, opts);
89
96
  }
90
97
  /** Capture `npm <args>` stdout, or null when npm is absent / the call fails. */
91
98
  function npmCapture(args) {
package/dist/rastack.d.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  * rastack generate [--schema-only] Generate typed hooks from OpenAPI
11
11
  * rastack tokens [input] [outDir] Compile design tokens → CSS vars + typed theme
12
12
  * rastack design [input] [--port n] Live design-system studio (showcase + edit)
13
- * rastack dev [--port n] [--warehouse d] Local dev: run the app + admin in-browser over WASM
13
+ * rastack dev [--port n] [--warehouse d] Local dev: run your app in-browser over WASM
14
14
  * rastack admin [--warehouse dir] [--port n] Full admin console — React UI (rastack/components) over the native server
15
15
  * rastack import <file> --resource app.model Load CSV/XLSX/PDF data and validate it (state machine)
16
16
  * rastack scan [files...] [--fail-on-pii] Scan CSVs for PII and schema info
package/dist/rastack.js CHANGED
@@ -11,7 +11,7 @@
11
11
  * rastack generate [--schema-only] Generate typed hooks from OpenAPI
12
12
  * rastack tokens [input] [outDir] Compile design tokens → CSS vars + typed theme
13
13
  * rastack design [input] [--port n] Live design-system studio (showcase + edit)
14
- * rastack dev [--port n] [--warehouse d] Local dev: run the app + admin in-browser over WASM
14
+ * rastack dev [--port n] [--warehouse d] Local dev: run your app in-browser over WASM
15
15
  * rastack admin [--warehouse dir] [--port n] Full admin console — React UI (rastack/components) over the native server
16
16
  * rastack import <file> --resource app.model Load CSV/XLSX/PDF data and validate it (state machine)
17
17
  * rastack scan [files...] [--fail-on-pii] Scan CSVs for PII and schema info
@@ -71,8 +71,9 @@ switch (command) {
71
71
  run("rastack-compile.js", [command, ...rest]);
72
72
  break;
73
73
  case "dev":
74
- // Local development: serve the app + admin in the browser over the WASM
75
- // engine (no native server, no cargo). Replaces `serve` + `wasm`.
74
+ // Local development: serve your app in the browser over the WASM engine
75
+ // (no native server, no cargo). The admin console is a separate command,
76
+ // `rastack admin`. Replaces `serve` + `wasm`.
76
77
  run("rastack-dev.js", rest);
77
78
  break;
78
79
  case "admin":
@@ -137,7 +138,7 @@ switch (command) {
137
138
  ` rastack generate [--schema-only]\n` +
138
139
  ` rastack tokens [input] [outDir] [--prefix p] Compile design tokens → CSS vars + typed theme\n` +
139
140
  ` rastack design [input] [--port n] Live design-system studio (showcase + edit)\n` +
140
- ` rastack dev [--port n] [--warehouse dir] [--no-open] Run the app + admin in-browser over WASM (local dev)\n` +
141
+ ` rastack dev [--port n] [--warehouse dir] [--app dir] [--no-open] Run your app in-browser over WASM (local dev)\n` +
141
142
  ` rastack admin [--warehouse dir] [--port n] [--no-open] Full admin console (React UI over the native server; needs a built rastack-server)\n` +
142
143
  ` rastack import <file.csv|.xlsx|.pdf> --resource app.model [--related app.model=<file>] [--out cleaned.json]\n` +
143
144
  ` rastack scan [files...] [--fail-on-pii]\n` +
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rastack",
3
- "version": "0.0.54",
3
+ "version": "0.0.56",
4
4
  "description": "",
5
5
  "main": "runtime.ts",
6
6
  "types": "runtime.ts",
@@ -21,7 +21,7 @@
21
21
  "author": "",
22
22
  "license": "ISC",
23
23
  "dependencies": {
24
- "@apidevtools/json-schema-ref-parser": "^15.4.0",
24
+ "@apidevtools/json-schema-ref-parser": "^15.5.0",
25
25
  "@tanstack/react-query": "^5.101.2",
26
26
  "@ts-stack/openapi-spec": "^3.1.5",
27
27
  "@types/json-schema": "^7.0.15",
@@ -37,9 +37,9 @@
37
37
  "lodash": "^4.18.0",
38
38
  "luxon": "^3.7.2",
39
39
  "minimatch": "^10.2.5",
40
- "prettier": "^3.9.4",
40
+ "prettier": "^3.9.5",
41
41
  "react-query": "^3.39.3",
42
- "typescript": "^6.0.3",
42
+ "typescript": "~5.9.3",
43
43
  "usehooks-ts": "^3.1.1"
44
44
  },
45
45
  "peerDependencies": {
@@ -49,10 +49,10 @@
49
49
  "@types/jest": "^30.0.0",
50
50
  "@types/js-yaml": "^4.0.9",
51
51
  "@types/mocha": "^10.0.6",
52
- "@types/node": "^26.1.0",
52
+ "@types/node": "^26.1.1",
53
53
  "@types/react-dom": "^19.2.0",
54
- "esbuild": "^0.25.0",
55
- "eslint": "^10.6.0",
54
+ "esbuild": "^0.28.1",
55
+ "eslint": "^10.7.0",
56
56
  "jest": "^30.4.2",
57
57
  "react": "^19.2.0",
58
58
  "react-dom": "^19.2.0",