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.
- package/CHANGELOG.md +9 -0
- package/admin/AdminApp.tsx +307 -50
- package/admin/ui/DetailsModal.tsx +125 -0
- package/admin/ui/Sidebar.tsx +28 -10
- package/admin/ui/icons.tsx +41 -0
- package/admin/ui/motion.tsx +292 -0
- package/admin/ui/styles.ts +277 -0
- package/admin/useAdmin.ts +91 -0
- package/dist/admin.js +295 -18
- package/dist/dev/harness.d.ts +44 -13
- package/dist/dev/harness.js +117 -16
- package/dist/rastack-dev.d.ts +9 -5
- package/dist/rastack-dev.js +49 -22
- package/dist/rastack-update.js +11 -4
- package/dist/rastack.d.ts +1 -1
- package/dist/rastack.js +5 -4
- package/dist/wasm/rastack_wasm_bg.wasm +0 -0
- package/package.json +7 -7
- package/src/dev/harness.ts +121 -15
- package/src/rastack-dev.ts +56 -24
- package/src/rastack-update.ts +11 -4
- package/src/rastack.ts +5 -4
- package/test/dev.spec.ts +42 -1
- package/wasm/rastack_wasm_bg.wasm +0 -0
package/dist/dev/harness.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure core of `rastack dev` — the local, always-WASM development server.
|
|
3
3
|
*
|
|
4
|
-
* `rastack dev`
|
|
5
|
-
*
|
|
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,
|
|
8
|
-
*
|
|
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
|
|
12
|
-
* filesystem; `rastack-dev.ts` is the thin IO wrapper that
|
|
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`, `--
|
|
30
|
-
* single positional resources dir. Unknown flags are ignored
|
|
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
|
|
66
|
-
* (`/dev/admin.js`), which fetches the schema/openapi, boots the
|
|
67
|
-
* seeds it from `/data/warehouse/`, and renders the admin.
|
|
68
|
-
* all logic lives in the bundle — mirroring the
|
|
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;
|
package/dist/dev/harness.js
CHANGED
|
@@ -2,16 +2,20 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Pure core of `rastack dev` — the local, always-WASM development server.
|
|
4
4
|
*
|
|
5
|
-
* `rastack dev`
|
|
6
|
-
*
|
|
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,
|
|
9
|
-
*
|
|
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
|
|
13
|
-
* filesystem; `rastack-dev.ts` is the thin IO wrapper that
|
|
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`, `--
|
|
66
|
-
* single positional resources dir. Unknown flags are ignored
|
|
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
|
|
166
|
-
* (`/dev/admin.js`), which fetches the schema/openapi, boots the
|
|
167
|
-
* seeds it from `/data/warehouse/`, and renders the admin.
|
|
168
|
-
* all logic lives in the bundle — mirroring the
|
|
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 —
|
|
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 <dir></code>.</li>
|
|
277
|
+
<li>Wire your app to the local engine with
|
|
278
|
+
<code><RAStackProvider mode="local"></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
|
+
}
|
package/dist/rastack-dev.d.ts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* `rastack dev` — local development
|
|
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
|
|
9
|
-
*
|
|
10
|
-
* • the
|
|
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
|
*/
|
package/dist/rastack-dev.js
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
* `rastack dev` — local development
|
|
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
|
|
10
|
-
*
|
|
11
|
-
* • the
|
|
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 —
|
|
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
|
-
|
|
160
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
190
|
-
|
|
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
|
});
|
package/dist/rastack-update.js
CHANGED
|
@@ -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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
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
|
|
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
|
|
75
|
-
//
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
40
|
+
"prettier": "^3.9.5",
|
|
41
41
|
"react-query": "^3.39.3",
|
|
42
|
-
"typescript": "
|
|
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.
|
|
52
|
+
"@types/node": "^26.1.1",
|
|
53
53
|
"@types/react-dom": "^19.2.0",
|
|
54
|
-
"esbuild": "^0.
|
|
55
|
-
"eslint": "^10.
|
|
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",
|