rastack 0.0.63 → 0.0.69
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 +32 -0
- package/README.md +19 -24
- package/admin/AdminApp.tsx +56 -3
- package/admin/httpEngine.ts +5 -6
- package/admin/index.tsx +11 -85
- package/admin/ui/icons.tsx +9 -0
- package/admin/ui/styles.ts +3 -0
- package/admin/useAdmin.ts +41 -4
- package/dist/admin.js +17 -22
- package/dist/compile/analyze.js +11 -1
- package/dist/compile/model.d.ts +1 -1
- package/dist/compile/run.d.ts +2 -2
- package/dist/compile/run.js +2 -2
- package/dist/define/index.d.ts +10 -4
- package/dist/define/index.js +2 -2
- package/dist/define/manifest.js +7 -1
- package/dist/deploy/io.d.ts +50 -0
- package/dist/deploy/io.js +124 -0
- package/dist/deploy/workflows.js +1 -1
- package/dist/dev/harness.d.ts +19 -27
- package/dist/dev/harness.js +31 -40
- package/dist/dev/native-server.d.ts +29 -0
- package/dist/dev/native-server.js +174 -0
- package/dist/external/envelope.d.ts +1 -1
- package/dist/external/envelope.js +1 -1
- package/dist/external/service.d.ts +2 -2
- package/dist/external/service.js +2 -2
- package/dist/external/types.d.ts +1 -1
- package/dist/external/types.js +1 -1
- package/dist/rastack-admin.d.ts +6 -14
- package/dist/rastack-admin.js +60 -88
- package/dist/rastack-bootstrap.js +18 -47
- package/dist/rastack-design.d.ts +1 -2
- package/dist/rastack-design.js +1 -2
- package/dist/rastack-dev.d.ts +7 -10
- package/dist/rastack-dev.js +68 -80
- package/dist/rastack-init.d.ts +6 -3
- package/dist/rastack-init.js +43 -30
- package/dist/rastack.d.ts +1 -1
- package/dist/rastack.js +5 -6
- package/dist/validate/transitions.d.ts +1 -1
- package/dist/validate/transitions.js +1 -1
- package/hooks/query/api.ts +4 -6
- package/package.json +2 -2
- package/provider/index.ts +0 -1
- package/provider/provider.tsx +31 -134
- package/provider/types.ts +30 -69
- package/src/compile/analyze.ts +11 -1
- package/src/compile/model.ts +1 -1
- package/src/compile/run.ts +2 -2
- package/src/define/index.ts +7 -4
- package/src/define/manifest.ts +7 -1
- package/src/deploy/io.ts +162 -1
- package/src/deploy/workflows.ts +1 -1
- package/src/dev/harness.ts +30 -43
- package/src/dev/native-server.ts +164 -0
- package/src/external/envelope.ts +1 -1
- package/src/external/service.ts +2 -2
- package/src/external/types.ts +1 -1
- package/src/rastack-admin.ts +66 -107
- package/src/rastack-bootstrap.ts +24 -69
- package/src/rastack-design.ts +1 -2
- package/src/rastack-dev.ts +79 -91
- package/src/rastack-init.ts +50 -41
- package/src/rastack.ts +5 -6
- package/src/validate/transitions.ts +1 -1
- package/dist/rastack-wasm-build.d.ts +0 -19
- package/dist/rastack-wasm-build.js +0 -94
- package/dist/wasm/package.json +0 -4
- package/dist/wasm/rastack_wasm.d.ts +0 -100
- package/dist/wasm/rastack_wasm.js +0 -745
- package/dist/wasm/rastack_wasm_bg.wasm +0 -0
- package/dist/wasm/rastack_wasm_bg.wasm.d.ts +0 -28
- package/provider/wasm.ts +0 -126
- package/scripts/copy-wasm.js +0 -35
- package/src/rastack-wasm-build.ts +0 -113
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Start the native `rastack-server` binary — the same `rastack-api-core`
|
|
4
|
+
* process Lambda runs. The browser never executes this binary. `rastack dev`
|
|
5
|
+
* proxies `/api` to it; `rastack admin` lets the binary serve `/admin` itself.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.resolveServerBinary = resolveServerBinary;
|
|
42
|
+
exports.ensureServerBinary = ensureServerBinary;
|
|
43
|
+
exports.startNativeServer = startNativeServer;
|
|
44
|
+
exports.waitForTcp = waitForTcp;
|
|
45
|
+
const child_process_1 = require("child_process");
|
|
46
|
+
const fs = __importStar(require("fs"));
|
|
47
|
+
const net = __importStar(require("net"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const harness_1 = require("./harness");
|
|
50
|
+
const MISSING = `
|
|
51
|
+
✗ No native rastack-server binary.
|
|
52
|
+
The API does not run in the browser. rastack dev and rastack admin start
|
|
53
|
+
the native Rust server (rastack-api-core) and the page talks to it over HTTP.
|
|
54
|
+
Build it from this repo:
|
|
55
|
+
|
|
56
|
+
cargo build -p rastack-server --manifest-path engine/Cargo.toml
|
|
57
|
+
|
|
58
|
+
Or set RASTACK_SERVER to the binary. There is no in-browser engine.
|
|
59
|
+
`;
|
|
60
|
+
/**
|
|
61
|
+
* `rastack-server` on PATH. Walks the directories ourselves so the lookup
|
|
62
|
+
* never goes through a shell (`command -v` with `shell: true`).
|
|
63
|
+
*/
|
|
64
|
+
function serverOnPath() {
|
|
65
|
+
const entries = (process.env.PATH ?? "").split(path.delimiter);
|
|
66
|
+
for (const dir of entries) {
|
|
67
|
+
if (!dir)
|
|
68
|
+
continue;
|
|
69
|
+
const candidate = path.join(dir, "rastack-server");
|
|
70
|
+
try {
|
|
71
|
+
if (fs.existsSync(candidate))
|
|
72
|
+
return candidate;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// An unreadable PATH entry is not a candidate.
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/** `RASTACK_SERVER`, a workspace target dir, or `rastack-server` on PATH. */
|
|
81
|
+
function resolveServerBinary(cwd) {
|
|
82
|
+
const fromEnv = process.env.RASTACK_SERVER;
|
|
83
|
+
if (fromEnv && fs.existsSync(fromEnv))
|
|
84
|
+
return fromEnv;
|
|
85
|
+
for (const candidate of (0, harness_1.serverBinaryCandidates)(cwd)) {
|
|
86
|
+
if (fs.existsSync(candidate))
|
|
87
|
+
return candidate;
|
|
88
|
+
}
|
|
89
|
+
return serverOnPath();
|
|
90
|
+
}
|
|
91
|
+
function cargoAvailable() {
|
|
92
|
+
try {
|
|
93
|
+
return (0, child_process_1.spawnSync)("cargo", ["--version"], { stdio: "ignore" }).status === 0;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Locate the native binary, building it with cargo when this repo's workspace
|
|
101
|
+
* is present and the binary is not. Throws when nothing native can be started.
|
|
102
|
+
*/
|
|
103
|
+
function ensureServerBinary(cwd) {
|
|
104
|
+
const ready = resolveServerBinary(cwd);
|
|
105
|
+
if (ready)
|
|
106
|
+
return ready;
|
|
107
|
+
const manifest = path.join(cwd, "engine", "Cargo.toml");
|
|
108
|
+
if (fs.existsSync(manifest) && cargoAvailable()) {
|
|
109
|
+
console.log("\n▸ Building native rastack-server (cargo build -p rastack-server)…\n");
|
|
110
|
+
const built = (0, child_process_1.spawnSync)("cargo", ["build", "-p", "rastack-server", "--manifest-path", manifest], { stdio: "inherit" });
|
|
111
|
+
if (built.status === 0) {
|
|
112
|
+
const after = resolveServerBinary(cwd);
|
|
113
|
+
if (after)
|
|
114
|
+
return after;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
throw new Error(MISSING.trim());
|
|
118
|
+
}
|
|
119
|
+
/** Spawn `rastack-server serve|admin`. Stdio is inherited. */
|
|
120
|
+
function startNativeServer(opts) {
|
|
121
|
+
const env = { ...process.env };
|
|
122
|
+
if (opts.adminAssets)
|
|
123
|
+
env.RASTACK_ADMIN_ASSETS = opts.adminAssets;
|
|
124
|
+
// `bin` is resolveServerBinary's result: RASTACK_SERVER (a file that exists),
|
|
125
|
+
// a workspace target path, or a PATH entry named rastack-server. It is not
|
|
126
|
+
// request input. The command cannot be a string literal because the path
|
|
127
|
+
// depends on which of those three resolved. The nosemgrep comment has to sit
|
|
128
|
+
// on the line directly above the tainted argument — that is the line Semgrep
|
|
129
|
+
// reports, not the `spawn(` line.
|
|
130
|
+
const bin = opts.bin;
|
|
131
|
+
return (0, child_process_1.spawn)(
|
|
132
|
+
// nosemgrep: javascript.lang.security.detect-child-process.detect-child-process
|
|
133
|
+
bin, [
|
|
134
|
+
opts.command,
|
|
135
|
+
"--manifest",
|
|
136
|
+
opts.manifest,
|
|
137
|
+
"--warehouse",
|
|
138
|
+
opts.warehouse,
|
|
139
|
+
"--addr",
|
|
140
|
+
opts.addr,
|
|
141
|
+
"--insecure-dev-auth",
|
|
142
|
+
], { stdio: "inherit", env });
|
|
143
|
+
}
|
|
144
|
+
/** Resolve once the process accepts TCP, or reject if it exits or times out. */
|
|
145
|
+
function waitForTcp(port, child, timeoutMs = 30000) {
|
|
146
|
+
return new Promise((resolve, reject) => {
|
|
147
|
+
const deadline = Date.now() + timeoutMs;
|
|
148
|
+
let settled = false;
|
|
149
|
+
const finish = (err) => {
|
|
150
|
+
if (settled)
|
|
151
|
+
return;
|
|
152
|
+
settled = true;
|
|
153
|
+
if (err)
|
|
154
|
+
reject(err);
|
|
155
|
+
else
|
|
156
|
+
resolve();
|
|
157
|
+
};
|
|
158
|
+
child.once("exit", (code) => finish(new Error(`rastack-server exited (${code ?? "?"}) before it accepted connections`)));
|
|
159
|
+
const tick = () => {
|
|
160
|
+
if (settled)
|
|
161
|
+
return;
|
|
162
|
+
if (Date.now() > deadline) {
|
|
163
|
+
finish(new Error(`rastack-server did not listen on 127.0.0.1:${port}`));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const socket = net.connect(port, "127.0.0.1", () => {
|
|
167
|
+
socket.end();
|
|
168
|
+
finish();
|
|
169
|
+
});
|
|
170
|
+
socket.on("error", () => setTimeout(tick, 100));
|
|
171
|
+
};
|
|
172
|
+
tick();
|
|
173
|
+
});
|
|
174
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Normalise an upstream response into rastack's REST contract — the DRF-shaped
|
|
3
3
|
* list envelope and bare detail object the typed hooks and `<DataTable>` expect,
|
|
4
|
-
* identical to what the Rust API
|
|
4
|
+
* identical to what the native Rust API emits.
|
|
5
5
|
*
|
|
6
6
|
* External APIs rarely page the way rastack does (GitHub uses `per_page` + Link
|
|
7
7
|
* headers; a GraphQL list just returns an array), so the envelope is synthesised
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Normalise an upstream response into rastack's REST contract — the DRF-shaped
|
|
4
4
|
* list envelope and bare detail object the typed hooks and `<DataTable>` expect,
|
|
5
|
-
* identical to what the Rust API
|
|
5
|
+
* identical to what the native Rust API emits.
|
|
6
6
|
*
|
|
7
7
|
* External APIs rarely page the way rastack does (GitHub uses `per_page` + Link
|
|
8
8
|
* headers; a GraphQL list just returns an array), so the envelope is synthesised
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The mini local proxy service — the "lambda you run while iterating".
|
|
3
3
|
*
|
|
4
|
-
* `rastack dev`
|
|
5
|
-
*
|
|
4
|
+
* `rastack dev` proxies the stack's own resources to the native
|
|
5
|
+
* `rastack-server`. This adds the other half for **external** resources: a request
|
|
6
6
|
* handler it mounts under `/api/`, so `useData("github.repo")` works locally,
|
|
7
7
|
* cached, before any real Lambda is deployed. It is a thin adapter over the pure
|
|
8
8
|
* {@link handleExternalRequest} core — parse the path, resolve dev auth from env
|
package/dist/external/service.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* The mini local proxy service — the "lambda you run while iterating".
|
|
4
4
|
*
|
|
5
|
-
* `rastack dev`
|
|
6
|
-
*
|
|
5
|
+
* `rastack dev` proxies the stack's own resources to the native
|
|
6
|
+
* `rastack-server`. This adds the other half for **external** resources: a request
|
|
7
7
|
* handler it mounts under `/api/`, so `useData("github.repo")` works locally,
|
|
8
8
|
* cached, before any real Lambda is deployed. It is a thin adapter over the pure
|
|
9
9
|
* {@link handleExternalRequest} core — parse the path, resolve dev auth from env
|
package/dist/external/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* External-API bindings — how a rastack `app.model` is served from an upstream
|
|
3
3
|
* REST or GraphQL API.
|
|
4
4
|
*
|
|
5
|
-
* The stack's own resources are served by the Rust API
|
|
5
|
+
* The stack's own resources are served by the native Rust API over the
|
|
6
6
|
* `/api/{app}/v1/{model}/` contract. An **external** resource (a GitHub repo, an
|
|
7
7
|
* Expo project, an AWS stack) is served by the proxy instead: it speaks the same
|
|
8
8
|
* contract to the client, and translates each request into an upstream call,
|
package/dist/external/types.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* External-API bindings — how a rastack `app.model` is served from an upstream
|
|
4
4
|
* REST or GraphQL API.
|
|
5
5
|
*
|
|
6
|
-
* The stack's own resources are served by the Rust API
|
|
6
|
+
* The stack's own resources are served by the native Rust API over the
|
|
7
7
|
* `/api/{app}/v1/{model}/` contract. An **external** resource (a GitHub repo, an
|
|
8
8
|
* Expo project, an AWS stack) is served by the proxy instead: it speaks the same
|
|
9
9
|
* contract to the client, and translates each request into an upstream call,
|
package/dist/rastack-admin.d.ts
CHANGED
|
@@ -1,21 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* `rastack admin` — the
|
|
4
|
-
*
|
|
3
|
+
* `rastack admin` — the Django-admin-style console, served by the native
|
|
4
|
+
* `rastack-server` process.
|
|
5
5
|
*
|
|
6
6
|
* rastack admin [resourcesDir] [--warehouse <dir>] [--port <n>] [--out <dir>] [--no-open]
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* • the bundled React admin (`/dev/admin.js`), which defaults to `mode:"local"`,
|
|
13
|
-
* • the prebuilt WASM engine (`/wasm/…`) shipped in the package,
|
|
14
|
-
* • the compiled `schema.rastack.json` / `openapi.json`,
|
|
15
|
-
* • the committed Iceberg warehouse (`/data/warehouse/…`) to seed from.
|
|
16
|
-
*
|
|
17
|
-
* The engine is the single prebuilt `.wasm` bundle shipped in the npm package;
|
|
18
|
-
* if it is missing the command errors and points at `rastack update` — it never
|
|
19
|
-
* falls back to a from-source cargo build.
|
|
8
|
+
* Compiles the resources, then starts `rastack-server admin`. That process is
|
|
9
|
+
* the API (`rastack-api-core`) and it serves the React bundle at `/admin/`.
|
|
10
|
+
* The browser renders the console and calls `/api` on that same origin.
|
|
11
|
+
* The engine does not run in the browser.
|
|
20
12
|
*/
|
|
21
13
|
export {};
|
package/dist/rastack-admin.js
CHANGED
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
* `rastack admin` — the
|
|
5
|
-
*
|
|
4
|
+
* `rastack admin` — the Django-admin-style console, served by the native
|
|
5
|
+
* `rastack-server` process.
|
|
6
6
|
*
|
|
7
7
|
* rastack admin [resourcesDir] [--warehouse <dir>] [--port <n>] [--out <dir>] [--no-open]
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* • the bundled React admin (`/dev/admin.js`), which defaults to `mode:"local"`,
|
|
14
|
-
* • the prebuilt WASM engine (`/wasm/…`) shipped in the package,
|
|
15
|
-
* • the compiled `schema.rastack.json` / `openapi.json`,
|
|
16
|
-
* • the committed Iceberg warehouse (`/data/warehouse/…`) to seed from.
|
|
17
|
-
*
|
|
18
|
-
* The engine is the single prebuilt `.wasm` bundle shipped in the npm package;
|
|
19
|
-
* if it is missing the command errors and points at `rastack update` — it never
|
|
20
|
-
* falls back to a from-source cargo build.
|
|
9
|
+
* Compiles the resources, then starts `rastack-server admin`. That process is
|
|
10
|
+
* the API (`rastack-api-core`) and it serves the React bundle at `/admin/`.
|
|
11
|
+
* The browser renders the console and calls `/api` on that same origin.
|
|
12
|
+
* The engine does not run in the browser.
|
|
21
13
|
*/
|
|
22
14
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
23
15
|
if (k2 === undefined) k2 = k;
|
|
@@ -55,47 +47,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
55
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
48
|
const child_process_1 = require("child_process");
|
|
57
49
|
const fs = __importStar(require("fs"));
|
|
58
|
-
const http = __importStar(require("http"));
|
|
59
50
|
const path = __importStar(require("path"));
|
|
60
51
|
const compile_1 = require("./compile");
|
|
61
52
|
const harness_1 = require("./dev/harness");
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
function resolveWasmDir() {
|
|
65
|
-
for (const dir of (0, harness_1.wasmBundleCandidates)(HERE)) {
|
|
66
|
-
if (fs.existsSync(path.join(dir, harness_1.WASM_ENTRY)))
|
|
67
|
-
return dir;
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
/** Serve one file if it exists and stays within `root`; else 404/403. */
|
|
72
|
-
function serveUnder(res, root, relPath) {
|
|
73
|
-
const safeRoot = path.resolve(root);
|
|
74
|
-
const rel = decodeURIComponent(relPath).replace(/^\/+/, "");
|
|
75
|
-
const target = path.resolve(safeRoot, rel);
|
|
76
|
-
// Path-traversal guard: the resolved target must stay inside the root.
|
|
77
|
-
if (target !== safeRoot && !target.startsWith(safeRoot + path.sep)) {
|
|
78
|
-
res.writeHead(403).end("Forbidden");
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
fs.readFile(target, (err, data) => {
|
|
82
|
-
if (err) {
|
|
83
|
-
res.writeHead(404).end("Not found");
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
res.writeHead(200, { "Content-Type": (0, harness_1.contentType)(target) }).end(data);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
/** Serve an exact file (no traversal concern — a fixed internal artifact). */
|
|
90
|
-
function serveFile(res, file) {
|
|
91
|
-
fs.readFile(file, (err, data) => {
|
|
92
|
-
if (err) {
|
|
93
|
-
res.writeHead(404).end("Not found");
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
res.writeHead(200, { "Content-Type": (0, harness_1.contentType)(file) }).end(data);
|
|
97
|
-
});
|
|
98
|
-
}
|
|
53
|
+
const native_server_1 = require("./dev/native-server");
|
|
54
|
+
const HERE = __dirname; // dist/ when installed — admin.js lives beside us.
|
|
99
55
|
/** Best-effort open the default browser at `url`. */
|
|
100
56
|
function openBrowser(url) {
|
|
101
57
|
const cmd = process.platform === "darwin"
|
|
@@ -110,57 +66,73 @@ function openBrowser(url) {
|
|
|
110
66
|
/* non-fatal — the URL is printed anyway */
|
|
111
67
|
}
|
|
112
68
|
}
|
|
113
|
-
function main(argv) {
|
|
69
|
+
async function main(argv) {
|
|
114
70
|
const args = (0, harness_1.parseAdminArgs)(argv);
|
|
115
|
-
|
|
71
|
+
const cwd = process.cwd();
|
|
72
|
+
console.log(`\n rastack admin — the database console, on the native Rust server\n`);
|
|
116
73
|
console.log(`▸ Compiling ${args.resourcesDir} → ${args.outDir}`);
|
|
117
74
|
if (!(0, compile_1.runCompile)(args.resourcesDir, args.outDir)) {
|
|
118
75
|
console.error(" ✗ compile failed — fix the resource graph and re-run.");
|
|
119
76
|
process.exit(1);
|
|
120
77
|
}
|
|
121
|
-
const wasmDir = resolveWasmDir();
|
|
122
|
-
if (!wasmDir) {
|
|
123
|
-
console.error("\n ✗ No prebuilt WASM engine found in this rastack install.\n" +
|
|
124
|
-
" Update rastack to pull the prebuilt bundle:\n" +
|
|
125
|
-
" rastack update\n");
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
78
|
const adminBundle = path.join(HERE, "admin.js");
|
|
129
79
|
if (!fs.existsSync(adminBundle)) {
|
|
130
80
|
console.error(" ✗ admin bundle (dist/admin.js) not found — reinstall rastack.");
|
|
131
81
|
process.exit(1);
|
|
132
82
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
83
|
+
let bin;
|
|
84
|
+
try {
|
|
85
|
+
bin = (0, native_server_1.ensureServerBinary)(cwd);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
console.error(`\n${err.message}\n`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
const manifest = path.resolve(cwd, args.outDir, "schema.rastack.json");
|
|
92
|
+
const warehouse = path.resolve(cwd, args.warehouseDir);
|
|
93
|
+
const child = (0, native_server_1.startNativeServer)({
|
|
94
|
+
bin,
|
|
95
|
+
command: "admin",
|
|
96
|
+
manifest,
|
|
97
|
+
warehouse,
|
|
98
|
+
addr: `127.0.0.1:${args.port}`,
|
|
99
|
+
adminAssets: HERE,
|
|
100
|
+
});
|
|
101
|
+
const stop = () => {
|
|
102
|
+
try {
|
|
103
|
+
child.kill("SIGTERM");
|
|
138
104
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
.writeHead(200, { "Content-Type": "text/html; charset=utf-8" })
|
|
142
|
-
.end((0, harness_1.renderShell)("React API Stack — admin"));
|
|
143
|
-
return;
|
|
105
|
+
catch {
|
|
106
|
+
/* already gone */
|
|
144
107
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (url === "/schema.rastack.json" || url === "/openapi.json")
|
|
150
|
-
return serveUnder(res, args.outDir, path.basename(url));
|
|
151
|
-
if (url.startsWith("/data/warehouse/"))
|
|
152
|
-
return serveUnder(res, args.warehouseDir, url.slice("/data/warehouse/".length));
|
|
153
|
-
res.writeHead(404).end("Not found");
|
|
108
|
+
};
|
|
109
|
+
process.on("SIGINT", () => {
|
|
110
|
+
stop();
|
|
111
|
+
process.exit(0);
|
|
154
112
|
});
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
console.log(`\n ▸ ${url}\n`);
|
|
159
|
-
console.log(" Press Ctrl+C to stop.\n");
|
|
160
|
-
if (args.open)
|
|
161
|
-
openBrowser(url);
|
|
113
|
+
process.on("SIGTERM", () => {
|
|
114
|
+
stop();
|
|
115
|
+
process.exit(0);
|
|
162
116
|
});
|
|
117
|
+
try {
|
|
118
|
+
await (0, native_server_1.waitForTcp)(args.port, child);
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
console.error(`\n${err.message}\n`);
|
|
122
|
+
stop();
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
const url = `http://127.0.0.1:${args.port}/admin/`;
|
|
126
|
+
console.log(` ✓ native engine: ${bin}`);
|
|
127
|
+
console.log(`\n ▸ ${url}\n`);
|
|
128
|
+
console.log(" Press Ctrl+C to stop.\n");
|
|
129
|
+
if (args.open)
|
|
130
|
+
openBrowser(url);
|
|
131
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
163
132
|
}
|
|
164
133
|
if (require.main === module) {
|
|
165
|
-
main(process.argv.slice(2))
|
|
134
|
+
main(process.argv.slice(2)).catch((err) => {
|
|
135
|
+
console.error(err);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|
|
166
138
|
}
|
|
@@ -124,60 +124,31 @@ function printPlan(cfg, reuseOidc) {
|
|
|
124
124
|
" ArtifactsBucket to create app backends. Nothing here is app-specific.\n");
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
127
|
+
* Stand the tier-0 bootstrap stack up and upload the Lambda placeholder. The
|
|
128
|
+
* deploy (with the GitHub-OIDC-reuse retry) and template resolution are shared
|
|
129
|
+
* with `rastack init` via `ensureBootstrapStack`, so both stand the stack up
|
|
130
|
+
* identically.
|
|
130
131
|
*/
|
|
131
|
-
function
|
|
132
|
-
const template = (0, io_1.resolveDeployAsset)("bootstrap.yaml");
|
|
133
|
-
if (!template) {
|
|
134
|
-
console.error(" ✗ bootstrap.yaml template not found in the rastack package. Reinstall\n" +
|
|
135
|
-
" rastack (`npm i -g rastack`) or run from the framework repo.");
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
try {
|
|
139
|
-
(0, io_1.awsRun)((0, config_1.bootstrapStackArgs)(cfg, reuseOidc, template));
|
|
140
|
-
}
|
|
141
|
-
catch (err) {
|
|
142
|
-
if (reuseOidc) {
|
|
143
|
-
console.error(`\n ✗ bootstrap stack deploy failed.\n ${err.message}`);
|
|
144
|
-
process.exit(1);
|
|
145
|
-
}
|
|
146
|
-
// The most common cause is an account that already has a GitHub OIDC
|
|
147
|
-
// provider. Retry telling the template to reuse it instead of creating a
|
|
148
|
-
// second (which CloudFormation rejects).
|
|
149
|
-
console.log(" • retrying bootstrap, reusing the account's existing GitHub OIDC provider");
|
|
150
|
-
try {
|
|
151
|
-
(0, io_1.awsRun)((0, config_1.bootstrapStackArgs)(cfg, true, template));
|
|
152
|
-
}
|
|
153
|
-
catch (retryErr) {
|
|
154
|
-
console.error(`\n ✗ bootstrap stack deploy failed.\n ${retryErr.message}`);
|
|
155
|
-
process.exit(1);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
/** Stand the tier-0 bootstrap stack up and upload the Lambda placeholder. */
|
|
160
|
-
function standUp(cfg, reuseOidc) {
|
|
132
|
+
async function standUp(cfg, reuseOidc) {
|
|
161
133
|
if (!(0, io_1.awsAvailable)()) {
|
|
162
134
|
console.error(" ✗ the AWS CLI is not on PATH. Install it and configure credentials,\n" +
|
|
163
135
|
" or re-run with --print to see the command.");
|
|
164
136
|
process.exit(1);
|
|
165
137
|
}
|
|
166
|
-
|
|
167
|
-
const
|
|
168
|
-
if (
|
|
169
|
-
console.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
console.log(`\n▸ Creating bootstrap stack ${stack} (@ ${cfg.region})`);
|
|
173
|
-
}
|
|
174
|
-
deployBootstrap(cfg, reuseOidc);
|
|
175
|
-
const artifactsBucket = (0, io_1.stackOutput)(stack, config_1.BOOTSTRAP_ARTIFACTS_OUTPUT, cfg.region);
|
|
176
|
-
const templatesBucket = (0, io_1.stackOutput)(stack, config_1.BOOTSTRAP_TEMPLATES_OUTPUT, cfg.region);
|
|
177
|
-
if (!artifactsBucket) {
|
|
178
|
-
console.error(" ✗ bootstrap stack deployed but its ArtifactsBucket output could not be read.");
|
|
138
|
+
// Verify the AWS CLI is logged in before attempting a stack deploy.
|
|
139
|
+
const account = (0, io_1.awsIdentity)(cfg.region);
|
|
140
|
+
if (!account) {
|
|
141
|
+
console.error(" ✗ the AWS CLI has no usable credentials — it is not logged in.\n" +
|
|
142
|
+
" Run `aws configure` (or `aws sso login`), then re-run `rastack bootstrap`.\n" +
|
|
143
|
+
" Or re-run with --print to see the command.");
|
|
179
144
|
process.exit(1);
|
|
180
145
|
}
|
|
146
|
+
console.log(` ✓ AWS account ${account} (${cfg.region})`);
|
|
147
|
+
const stack = (0, config_1.bootstrapStackName)(cfg);
|
|
148
|
+
const { artifactsBucket, templatesBucket } = await (0, io_1.ensureBootstrapStack)(cfg, reuseOidc).catch((err) => {
|
|
149
|
+
console.error(`\n ✗ ${err.message}`);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
});
|
|
181
152
|
console.log(` ✓ artifacts bucket: ${artifactsBucket}`);
|
|
182
153
|
if (templatesBucket)
|
|
183
154
|
console.log(` ✓ templates bucket: ${templatesBucket}`);
|
|
@@ -220,7 +191,7 @@ async function main(argv) {
|
|
|
220
191
|
return;
|
|
221
192
|
}
|
|
222
193
|
}
|
|
223
|
-
standUp(cfg, flags.reuseOidc);
|
|
194
|
+
await standUp(cfg, flags.reuseOidc);
|
|
224
195
|
}
|
|
225
196
|
if (require.main === module) {
|
|
226
197
|
main(process.argv.slice(2)).catch((err) => {
|
package/dist/rastack-design.d.ts
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
* source and hitting **Save** writes it back and recompiles `tokens.css` /
|
|
12
12
|
* `tokens.ts`, so the rest of the app picks the change up on reload.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* WASM), the studio needs no build step and no external dependencies.
|
|
14
|
+
* The studio needs no build step and no external dependencies.
|
|
16
15
|
*/
|
|
17
16
|
export {};
|
package/dist/rastack-design.js
CHANGED
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
* source and hitting **Save** writes it back and recompiles `tokens.css` /
|
|
13
13
|
* `tokens.ts`, so the rest of the app picks the change up on reload.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
* WASM), the studio needs no build step and no external dependencies.
|
|
15
|
+
* The studio needs no build step and no external dependencies.
|
|
17
16
|
*/
|
|
18
17
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
18
|
if (k2 === undefined) k2 = k;
|
package/dist/rastack-dev.d.ts
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* `rastack dev` — local development of **your app
|
|
3
|
+
* `rastack dev` — local development of **your app** against the native engine.
|
|
4
4
|
*
|
|
5
5
|
* rastack dev [resourcesDir] [--port <n>] [--warehouse <dir>] [--out <dir>] [--app <dir>] [--no-open]
|
|
6
6
|
*
|
|
7
|
-
* Compiles the resources,
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Compiles the resources, starts a native `rastack-server` (`rastack-api-core`
|
|
8
|
+
* over the on-disk Iceberg warehouse), and serves the developer's app. The
|
|
9
|
+
* browser is the UI. `/api` on this origin is proxied to that process.
|
|
10
10
|
* • the developer's app (`index.html` from the resolved app root), or a
|
|
11
11
|
* Django-style welcome page when the project has no app yet,
|
|
12
|
-
* • the prebuilt WASM engine (`/wasm/…`) shipped in the package,
|
|
13
12
|
* • the compiled `schema.rastack.json` / `openapi.json`,
|
|
14
|
-
* •
|
|
13
|
+
* • `/api/…` forwarded to the native server.
|
|
15
14
|
*
|
|
16
15
|
* It does **not** serve the admin console — that is a separate command,
|
|
17
|
-
* `rastack admin`.
|
|
18
|
-
*
|
|
19
|
-
* The engine is resolved from the package's prebuilt bundle; if none is present
|
|
20
|
-
* but a Rust + wasm toolchain is, it is built from source as a fallback.
|
|
16
|
+
* `rastack admin`. The browser does not execute the engine. There is no
|
|
17
|
+
* in-browser fallback.
|
|
21
18
|
*/
|
|
22
19
|
export {};
|