rastack 0.0.55 → 0.0.57
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/compile/index.d.ts +1 -0
- package/dist/compile/index.js +8 -3
- package/dist/compile/run.d.ts +13 -0
- package/dist/compile/run.js +63 -0
- package/dist/deploy/ci.d.ts +8 -1
- package/dist/deploy/ci.js +15 -9
- package/dist/dev/harness.d.ts +44 -13
- package/dist/dev/harness.js +117 -16
- package/dist/rastack-admin.js +2 -9
- package/dist/rastack-ci.js +15 -3
- package/dist/rastack-compile.d.ts +6 -3
- package/dist/rastack-compile.js +10 -16
- package/dist/rastack-dev.d.ts +9 -5
- package/dist/rastack-dev.js +52 -32
- package/dist/rastack-update.js +11 -4
- package/dist/rastack.d.ts +4 -2
- package/dist/rastack.js +17 -6
- package/dist/wasm/rastack_wasm_bg.wasm +0 -0
- package/package.json +7 -7
- package/src/compile/index.ts +13 -4
- package/src/compile/run.ts +26 -0
- package/src/deploy/ci.ts +24 -10
- package/src/dev/harness.ts +121 -15
- package/src/rastack-admin.ts +6 -15
- package/src/rastack-ci.ts +16 -3
- package/src/rastack-compile.ts +10 -18
- package/src/rastack-dev.ts +59 -40
- package/src/rastack-update.ts +11 -4
- package/src/rastack.ts +19 -6
- package/test/deploy.spec.ts +5 -2
- package/test/dev.spec.ts +42 -1
- package/wasm/rastack_wasm_bg.wasm +0 -0
package/dist/compile/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { analyze, analyzeDsl } from "./analyze";
|
|
|
4
4
|
export { analyzeEntities, detectCycles } from "./entities";
|
|
5
5
|
export type { EntityAnalysis, EntityDiagnostic, EntityTypeExport, } from "./entities";
|
|
6
6
|
export { buildManifest } from "./manifest";
|
|
7
|
+
export { runCompile } from "./run";
|
|
7
8
|
export { buildOpenApi, writeSchema } from "./openapi";
|
|
8
9
|
export * from "./model";
|
|
9
10
|
export interface CompileResult {
|
package/dist/compile/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
36
36
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.writeSchema = exports.buildOpenApi = exports.buildManifest = exports.detectCycles = exports.analyzeEntities = exports.analyzeDsl = exports.analyze = void 0;
|
|
39
|
+
exports.writeSchema = exports.buildOpenApi = exports.runCompile = exports.buildManifest = exports.detectCycles = exports.analyzeEntities = exports.analyzeDsl = exports.analyze = void 0;
|
|
40
40
|
exports.resolveResourceFiles = resolveResourceFiles;
|
|
41
41
|
exports.analyzeProject = analyzeProject;
|
|
42
42
|
exports.detectTransitionProblems = detectTransitionProblems;
|
|
@@ -61,6 +61,8 @@ Object.defineProperty(exports, "analyzeEntities", { enumerable: true, get: funct
|
|
|
61
61
|
Object.defineProperty(exports, "detectCycles", { enumerable: true, get: function () { return entities_2.detectCycles; } });
|
|
62
62
|
var manifest_2 = require("./manifest");
|
|
63
63
|
Object.defineProperty(exports, "buildManifest", { enumerable: true, get: function () { return manifest_2.buildManifest; } });
|
|
64
|
+
var run_1 = require("./run");
|
|
65
|
+
Object.defineProperty(exports, "runCompile", { enumerable: true, get: function () { return run_1.runCompile; } });
|
|
64
66
|
var openapi_2 = require("./openapi");
|
|
65
67
|
Object.defineProperty(exports, "buildOpenApi", { enumerable: true, get: function () { return openapi_2.buildOpenApi; } });
|
|
66
68
|
Object.defineProperty(exports, "writeSchema", { enumerable: true, get: function () { return openapi_2.writeSchema; } });
|
|
@@ -96,7 +98,8 @@ function resolveResourceFiles(input) {
|
|
|
96
98
|
if (!IGNORE_DIRS.has(entry.name))
|
|
97
99
|
walk(path.join(dir, entry.name));
|
|
98
100
|
}
|
|
99
|
-
else if (/\.tsx?$/.test(entry.name) &&
|
|
101
|
+
else if (/\.tsx?$/.test(entry.name) &&
|
|
102
|
+
!entry.name.endsWith(".d.ts")) {
|
|
100
103
|
files.push(path.resolve(dir, entry.name));
|
|
101
104
|
}
|
|
102
105
|
}
|
|
@@ -124,7 +127,9 @@ function analyzeProject(input) {
|
|
|
124
127
|
...fromDsl.resources,
|
|
125
128
|
...fromInterfaces.resources.filter((r) => !defined.has(`${r.app}.${r.model}`)),
|
|
126
129
|
];
|
|
127
|
-
resources.sort((a, b) => a.app === b.app
|
|
130
|
+
resources.sort((a, b) => a.app === b.app
|
|
131
|
+
? a.model.localeCompare(b.model)
|
|
132
|
+
: a.app.localeCompare(b.app));
|
|
128
133
|
// Registry entries follow the same merge rule as the resources: the DSL
|
|
129
134
|
// definition wins an `app.model` collision.
|
|
130
135
|
const types = [
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run the compiler **in-process**, writing `schema.rastack.json` +
|
|
3
|
+
* `openapi.json` (and `rastack-env.d.ts`) into `outDir`. Prints any warnings
|
|
4
|
+
* and, on failure, the error; returns `true` on success.
|
|
5
|
+
*
|
|
6
|
+
* This is the single entry point the two real modalities of use share instead
|
|
7
|
+
* of shelling out to a standalone `compile` command:
|
|
8
|
+
* • `rastack dev` / `rastack admin` — local development (compile, then serve
|
|
9
|
+
* the app + admin in the browser over WASM), and
|
|
10
|
+
* • `rastack ci` — the deploy pipeline (compile the manifest the Rust backend
|
|
11
|
+
* reads + the OpenAPI contract, then build/ship).
|
|
12
|
+
*/
|
|
13
|
+
export declare function runCompile(resourcesDir: string, outDir: string): boolean;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runCompile = runCompile;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const index_1 = require("./index");
|
|
40
|
+
/**
|
|
41
|
+
* Run the compiler **in-process**, writing `schema.rastack.json` +
|
|
42
|
+
* `openapi.json` (and `rastack-env.d.ts`) into `outDir`. Prints any warnings
|
|
43
|
+
* and, on failure, the error; returns `true` on success.
|
|
44
|
+
*
|
|
45
|
+
* This is the single entry point the two real modalities of use share instead
|
|
46
|
+
* of shelling out to a standalone `compile` command:
|
|
47
|
+
* • `rastack dev` / `rastack admin` — local development (compile, then serve
|
|
48
|
+
* the app + admin in the browser over WASM), and
|
|
49
|
+
* • `rastack ci` — the deploy pipeline (compile the manifest the Rust backend
|
|
50
|
+
* reads + the OpenAPI contract, then build/ship).
|
|
51
|
+
*/
|
|
52
|
+
function runCompile(resourcesDir, outDir) {
|
|
53
|
+
try {
|
|
54
|
+
const result = (0, index_1.compile)(resourcesDir, outDir);
|
|
55
|
+
for (const d of result.diagnostics)
|
|
56
|
+
console.warn(` ⚠ ${d.message}`);
|
|
57
|
+
return fs.existsSync(path.join(outDir, "schema.rastack.json"));
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.error(` ✗ ${err.message}`);
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
package/dist/deploy/ci.d.ts
CHANGED
|
@@ -20,10 +20,17 @@ export type CiPhase = "check" | "build" | "deploy";
|
|
|
20
20
|
export interface CiStep {
|
|
21
21
|
/** Human label, echoed before the step runs. */
|
|
22
22
|
name: string;
|
|
23
|
-
/** The shell command to execute. */
|
|
23
|
+
/** The shell command to execute (or, for an in-process step, a description). */
|
|
24
24
|
run: string;
|
|
25
25
|
/** Working directory relative to the repo root (default: repo root). */
|
|
26
26
|
cwd?: string;
|
|
27
|
+
/**
|
|
28
|
+
* When set, the step is executed **in-process by the CLI** rather than through
|
|
29
|
+
* a shell — `run` is then a human-readable description, not a command. Today
|
|
30
|
+
* the only in-process action is `"compile"`, which the CLI runs via the shared
|
|
31
|
+
* compiler (`runCompile`) instead of shelling out to a standalone command.
|
|
32
|
+
*/
|
|
33
|
+
action?: "compile";
|
|
27
34
|
}
|
|
28
35
|
export interface CiPlanOptions {
|
|
29
36
|
/** How to invoke the rastack CLI for nested steps (default: `rastack`). */
|
package/dist/deploy/ci.js
CHANGED
|
@@ -21,6 +21,19 @@ exports.checkSteps = checkSteps;
|
|
|
21
21
|
exports.buildSteps = buildSteps;
|
|
22
22
|
exports.deploySteps = deploySteps;
|
|
23
23
|
exports.ciPlan = ciPlan;
|
|
24
|
+
/**
|
|
25
|
+
* The in-process compile step shared by `check` and `build`: it produces
|
|
26
|
+
* `schema.rastack.json` + `openapi.json` in `cfg.outDir` without a subprocess,
|
|
27
|
+
* so compilation lives inside the two modalities of use (`dev` and `ci`) rather
|
|
28
|
+
* than in a separately-invoked `compile` command.
|
|
29
|
+
*/
|
|
30
|
+
function compileStep(cfg) {
|
|
31
|
+
return {
|
|
32
|
+
name: "Compile manifest + OpenAPI",
|
|
33
|
+
run: `compile ${cfg.resourcesDir} ${cfg.outDir} (in-process)`,
|
|
34
|
+
action: "compile",
|
|
35
|
+
};
|
|
36
|
+
}
|
|
24
37
|
/**
|
|
25
38
|
* A stack Output value: the literal from `cfg.outputs` if wired, else a shell
|
|
26
39
|
* command substitution that resolves it live from CloudFormation. Keeping the
|
|
@@ -46,10 +59,7 @@ function checkSteps(cfg, bin) {
|
|
|
46
59
|
name: "Validate resource graph",
|
|
47
60
|
run: `${bin} check ${cfg.resourcesDir}`,
|
|
48
61
|
},
|
|
49
|
-
|
|
50
|
-
name: "Compile manifest + OpenAPI",
|
|
51
|
-
run: `${bin} compile ${cfg.resourcesDir} ${cfg.outDir}`,
|
|
52
|
-
},
|
|
62
|
+
compileStep(cfg),
|
|
53
63
|
];
|
|
54
64
|
}
|
|
55
65
|
/**
|
|
@@ -58,15 +68,11 @@ function checkSteps(cfg, bin) {
|
|
|
58
68
|
* binary together with the files it reads at `/var/task`.
|
|
59
69
|
*/
|
|
60
70
|
function buildSteps(cfg, opts = {}) {
|
|
61
|
-
const bin = opts.bin ?? "rastack";
|
|
62
71
|
const stage = stageDir(cfg);
|
|
63
72
|
const archFlag = cfg.lambda.arch === "arm64" ? "--arm64" : "--x86-64";
|
|
64
73
|
const jwks = stackOutput(cfg, "JwksUrl", opts.jwksUrl ?? cfg.outputs?.jwksUrl);
|
|
65
74
|
return [
|
|
66
|
-
|
|
67
|
-
name: "Compile manifest + OpenAPI",
|
|
68
|
-
run: `${bin} compile ${cfg.resourcesDir} ${cfg.outDir}`,
|
|
69
|
-
},
|
|
75
|
+
compileStep(cfg),
|
|
70
76
|
{
|
|
71
77
|
name: "Cross-build the Lambda binary",
|
|
72
78
|
run: `cargo lambda build --release ${archFlag} --bin ${cfg.lambda.bin} --features ${cfg.lambda.features}`,
|
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-admin.js
CHANGED
|
@@ -57,16 +57,9 @@ const child_process_1 = require("child_process");
|
|
|
57
57
|
const fs = __importStar(require("fs"));
|
|
58
58
|
const http = __importStar(require("http"));
|
|
59
59
|
const path = __importStar(require("path"));
|
|
60
|
+
const compile_1 = require("./compile");
|
|
60
61
|
const harness_1 = require("./dev/harness");
|
|
61
62
|
const HERE = __dirname; // dist/ when installed — the bundle lives beside us.
|
|
62
|
-
/** Compile the resources to schema.rastack.json + openapi.json in outDir. */
|
|
63
|
-
function compile(resourcesDir, outDir) {
|
|
64
|
-
const compiler = path.join(HERE, "rastack-compile.js");
|
|
65
|
-
const result = (0, child_process_1.spawnSync)(process.execPath, [compiler, "compile", resourcesDir, outDir], { stdio: "inherit" });
|
|
66
|
-
if (result.status !== 0)
|
|
67
|
-
return false;
|
|
68
|
-
return fs.existsSync(path.join(outDir, "schema.rastack.json"));
|
|
69
|
-
}
|
|
70
63
|
/** Locate the prebuilt wasm bundle dir shipped in the package (no cargo fallback). */
|
|
71
64
|
function resolveWasmDir() {
|
|
72
65
|
for (const dir of (0, harness_1.wasmBundleCandidates)(HERE)) {
|
|
@@ -121,7 +114,7 @@ function main(argv) {
|
|
|
121
114
|
const args = (0, harness_1.parseAdminArgs)(argv);
|
|
122
115
|
console.log(`\n rastack admin — the database console, built with React API Stack\n`);
|
|
123
116
|
console.log(`▸ Compiling ${args.resourcesDir} → ${args.outDir}`);
|
|
124
|
-
if (!
|
|
117
|
+
if (!(0, compile_1.runCompile)(args.resourcesDir, args.outDir)) {
|
|
125
118
|
console.error(" ✗ compile failed — fix the resource graph and re-run.");
|
|
126
119
|
process.exit(1);
|
|
127
120
|
}
|
package/dist/rastack-ci.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
20
|
const child_process_1 = require("child_process");
|
|
21
|
+
const compile_1 = require("./compile");
|
|
21
22
|
const ci_1 = require("./deploy/ci");
|
|
22
23
|
const io_1 = require("./deploy/io");
|
|
23
24
|
const PHASES = ["check", "build", "deploy"];
|
|
@@ -74,12 +75,23 @@ function printPlan(phase, steps) {
|
|
|
74
75
|
steps.forEach((s, i) => {
|
|
75
76
|
const at = s.cwd ? ` (in ${s.cwd}/)` : "";
|
|
76
77
|
console.log(` ${i + 1}. ${s.name}${at}`);
|
|
77
|
-
|
|
78
|
+
// In-process steps have no shell command; `run` is a description.
|
|
79
|
+
console.log(` ${s.action ? "» " : "$ "}${s.run}\n`);
|
|
78
80
|
});
|
|
79
81
|
}
|
|
80
|
-
function runSteps(phase, steps) {
|
|
82
|
+
function runSteps(phase, steps, cfg) {
|
|
81
83
|
for (const step of steps) {
|
|
82
84
|
console.log(`\n▸ ${step.name}${step.cwd ? ` (in ${step.cwd}/)` : ""}`);
|
|
85
|
+
if (step.action === "compile") {
|
|
86
|
+
// Compilation runs in-process — it lives inside `ci` (and `dev`), not in a
|
|
87
|
+
// separately-invoked `compile` command.
|
|
88
|
+
console.log(` » ${step.run}`);
|
|
89
|
+
if (!(0, compile_1.runCompile)(cfg.resourcesDir, cfg.outDir)) {
|
|
90
|
+
console.error(`\n ✗ step failed: ${step.name}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
83
95
|
console.log(` $ ${step.run}`);
|
|
84
96
|
try {
|
|
85
97
|
// Runs a CI pipeline step derived from the developer's own deploy config
|
|
@@ -111,7 +123,7 @@ function main(argv) {
|
|
|
111
123
|
if (plan)
|
|
112
124
|
printPlan(phase, steps);
|
|
113
125
|
else
|
|
114
|
-
runSteps(phase, steps);
|
|
126
|
+
runSteps(phase, steps, cfg);
|
|
115
127
|
}
|
|
116
128
|
if (require.main === module) {
|
|
117
129
|
main(process.argv.slice(2));
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* `rastack
|
|
4
|
-
*
|
|
3
|
+
* `rastack check | list | urls` — introspection over the TypeScript-first
|
|
4
|
+
* resource graph.
|
|
5
5
|
*
|
|
6
|
-
* rastack compile [resourcesDir] [outDir] defs → schema.rastack.json + openapi.json
|
|
7
6
|
* rastack check [resourcesDir] validate the resource graph (exit != 0 on error)
|
|
8
7
|
* rastack list [resourcesDir] print every resource + its fields/relations
|
|
9
8
|
* rastack urls [resourcesDir] print the generated /api/{app}/v1/{model}/ routes
|
|
9
|
+
*
|
|
10
|
+
* Compilation itself (defs → schema.rastack.json + openapi.json) is no longer a
|
|
11
|
+
* command here: it runs in-process inside the two modalities of use — `rastack
|
|
12
|
+
* dev`/`admin` (local) and `rastack ci` (deploy) — via the shared `runCompile`.
|
|
10
13
|
*/
|
|
11
14
|
export {};
|
package/dist/rastack-compile.js
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
* `rastack
|
|
5
|
-
*
|
|
4
|
+
* `rastack check | list | urls` — introspection over the TypeScript-first
|
|
5
|
+
* resource graph.
|
|
6
6
|
*
|
|
7
|
-
* rastack compile [resourcesDir] [outDir] defs → schema.rastack.json + openapi.json
|
|
8
7
|
* rastack check [resourcesDir] validate the resource graph (exit != 0 on error)
|
|
9
8
|
* rastack list [resourcesDir] print every resource + its fields/relations
|
|
10
9
|
* rastack urls [resourcesDir] print the generated /api/{app}/v1/{model}/ routes
|
|
10
|
+
*
|
|
11
|
+
* Compilation itself (defs → schema.rastack.json + openapi.json) is no longer a
|
|
12
|
+
* command here: it runs in-process inside the two modalities of use — `rastack
|
|
13
|
+
* dev`/`admin` (local) and `rastack ci` (deploy) — via the shared `runCompile`.
|
|
11
14
|
*/
|
|
12
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
16
|
const compile_1 = require("./compile");
|
|
14
17
|
const DEFAULT_RESOURCES = "resources";
|
|
15
|
-
const DEFAULT_OUT = ".rastack";
|
|
16
18
|
function main(argv) {
|
|
17
19
|
const [sub, ...rest] = argv;
|
|
18
20
|
switch (sub) {
|
|
19
|
-
case "compile": {
|
|
20
|
-
const resourcesDir = rest[0] || DEFAULT_RESOURCES;
|
|
21
|
-
const outDir = rest[1] || DEFAULT_OUT;
|
|
22
|
-
const result = (0, compile_1.compile)(resourcesDir, outDir);
|
|
23
|
-
for (const d of result.diagnostics)
|
|
24
|
-
console.warn(` ⚠ ${d.message}`);
|
|
25
|
-
console.log(`✓ compiled ${result.manifest.resources.length} resource(s) → ${result.files.join(", ")}`);
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
21
|
case "check": {
|
|
29
22
|
const { resources, diagnostics } = (0, compile_1.analyzeProject)(rest[0] || DEFAULT_RESOURCES);
|
|
30
23
|
const errors = [
|
|
@@ -54,7 +47,9 @@ function main(argv) {
|
|
|
54
47
|
for (const r of resources) {
|
|
55
48
|
console.log(`${r.app}.${r.model}`);
|
|
56
49
|
for (const f of r.fields) {
|
|
57
|
-
const rel = f.relation
|
|
50
|
+
const rel = f.relation
|
|
51
|
+
? ` → ${f.relation.app}.${f.relation.model}`
|
|
52
|
+
: "";
|
|
58
53
|
console.log(` ${f.name}: ${f.type}${rel}`);
|
|
59
54
|
}
|
|
60
55
|
if (r.sync) {
|
|
@@ -78,9 +73,8 @@ function main(argv) {
|
|
|
78
73
|
break;
|
|
79
74
|
}
|
|
80
75
|
default:
|
|
81
|
-
console.error(`Unknown
|
|
76
|
+
console.error(`Unknown subcommand: "${sub}"\n\n` +
|
|
82
77
|
`Usage:\n` +
|
|
83
|
-
` rastack compile [resourcesDir] [outDir]\n` +
|
|
84
78
|
` rastack check [resourcesDir]\n` +
|
|
85
79
|
` rastack list [resourcesDir]\n` +
|
|
86
80
|
` rastack urls [resourcesDir]\n`);
|
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
|
*/
|