rastack 0.0.56 → 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 +2 -0
- 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/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.js +3 -10
- package/dist/rastack.d.ts +3 -1
- package/dist/rastack.js +12 -2
- package/dist/wasm/rastack_wasm_bg.wasm +0 -0
- package/package.json +1 -1
- package/src/compile/index.ts +13 -4
- package/src/compile/run.ts +26 -0
- package/src/deploy/ci.ts +24 -10
- 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 +3 -16
- package/src/rastack.ts +14 -2
- package/test/deploy.spec.ts +5 -2
- package/wasm/rastack_wasm_bg.wasm +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.0.57](https://github.com/theserverkid/reactapistack/compare/v0.0.56...v0.0.57) (2026-07-18)
|
|
6
|
+
|
|
5
7
|
### [0.0.56](https://github.com/theserverkid/reactapistack/compare/v0.0.55...v0.0.56) (2026-07-18)
|
|
6
8
|
|
|
7
9
|
|
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/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.js
CHANGED
|
@@ -58,20 +58,13 @@ const child_process_1 = require("child_process");
|
|
|
58
58
|
const fs = __importStar(require("fs"));
|
|
59
59
|
const http = __importStar(require("http"));
|
|
60
60
|
const path = __importStar(require("path"));
|
|
61
|
+
const compile_1 = require("./compile");
|
|
61
62
|
const harness_1 = require("./dev/harness");
|
|
62
63
|
const HERE = __dirname; // dist/ when installed
|
|
63
|
-
/** Compile the resources to schema.rastack.json + openapi.json in outDir. */
|
|
64
|
-
function compile(resourcesDir, outDir) {
|
|
65
|
-
const compiler = path.join(HERE, "rastack-compile.js");
|
|
66
|
-
const result = (0, child_process_1.spawnSync)(process.execPath, [compiler, "compile", resourcesDir, outDir], { stdio: "inherit" });
|
|
67
|
-
if (result.status !== 0)
|
|
68
|
-
return false;
|
|
69
|
-
return fs.existsSync(path.join(outDir, "schema.rastack.json"));
|
|
70
|
-
}
|
|
71
64
|
/** True when `cargo` is on PATH (the from-source wasm fallback needs it). */
|
|
72
65
|
function cargoAvailable() {
|
|
73
66
|
try {
|
|
74
|
-
return (
|
|
67
|
+
return (0, child_process_1.spawnSync)("cargo", ["--version"], { stdio: "ignore" }).status === 0;
|
|
75
68
|
}
|
|
76
69
|
catch {
|
|
77
70
|
return false;
|
|
@@ -155,7 +148,7 @@ function main(argv) {
|
|
|
155
148
|
const args = (0, harness_1.parseDevArgs)(argv);
|
|
156
149
|
console.log(`\n rastack dev — your app, in your browser over WASM\n`);
|
|
157
150
|
console.log(`▸ Compiling ${args.resourcesDir} → ${args.outDir}`);
|
|
158
|
-
if (!
|
|
151
|
+
if (!(0, compile_1.runCompile)(args.resourcesDir, args.outDir)) {
|
|
159
152
|
console.error(" ✗ compile failed — fix the resource graph and re-run.");
|
|
160
153
|
process.exit(1);
|
|
161
154
|
}
|
package/dist/rastack.d.ts
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* rastack — unified CLI for React API Stack
|
|
4
4
|
*
|
|
5
|
+
* Compilation is not a command of its own: it runs in-process inside the two
|
|
6
|
+
* modalities of use — `rastack dev`/`admin` (local) and `rastack ci` (deploy).
|
|
7
|
+
*
|
|
5
8
|
* Commands:
|
|
6
|
-
* rastack compile [resourcesDir] [outDir] TypeScript resources → schema.rastack.json + openapi.json
|
|
7
9
|
* rastack check [resourcesDir] Validate the resource graph
|
|
8
10
|
* rastack list [resourcesDir] Print resources, fields and relations
|
|
9
11
|
* rastack urls [resourcesDir] Print the generated /api/{app}/v1/{model}/ routes
|
package/dist/rastack.js
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* rastack — unified CLI for React API Stack
|
|
5
5
|
*
|
|
6
|
+
* Compilation is not a command of its own: it runs in-process inside the two
|
|
7
|
+
* modalities of use — `rastack dev`/`admin` (local) and `rastack ci` (deploy).
|
|
8
|
+
*
|
|
6
9
|
* Commands:
|
|
7
|
-
* rastack compile [resourcesDir] [outDir] TypeScript resources → schema.rastack.json + openapi.json
|
|
8
10
|
* rastack check [resourcesDir] Validate the resource graph
|
|
9
11
|
* rastack list [resourcesDir] Print resources, fields and relations
|
|
10
12
|
* rastack urls [resourcesDir] Print the generated /api/{app}/v1/{model}/ routes
|
|
@@ -64,6 +66,15 @@ switch (command) {
|
|
|
64
66
|
printVersion();
|
|
65
67
|
break;
|
|
66
68
|
case "compile":
|
|
69
|
+
// Compilation is no longer a standalone command — it runs in-process as
|
|
70
|
+
// part of the two modalities of use. Point the way rather than 404.
|
|
71
|
+
console.error("`rastack compile` has been removed — compilation now runs automatically\n" +
|
|
72
|
+
"inside the two modalities of use:\n" +
|
|
73
|
+
" • rastack dev local development (compiles, then serves over WASM)\n" +
|
|
74
|
+
" • rastack ci the deploy pipeline (compiles the manifest + OpenAPI)\n\n" +
|
|
75
|
+
"Introspect the resource graph with: rastack check | list | urls\n");
|
|
76
|
+
process.exit(1);
|
|
77
|
+
break;
|
|
67
78
|
case "check":
|
|
68
79
|
case "list":
|
|
69
80
|
case "urls":
|
|
@@ -133,7 +144,6 @@ switch (command) {
|
|
|
133
144
|
default:
|
|
134
145
|
console.error(`Unknown command: "${command}"\n\n` +
|
|
135
146
|
`Usage:\n` +
|
|
136
|
-
` rastack compile [resourcesDir] [outDir]\n` +
|
|
137
147
|
` rastack check | list | urls [resourcesDir]\n` +
|
|
138
148
|
` rastack generate [--schema-only]\n` +
|
|
139
149
|
` rastack tokens [input] [outDir] [--prefix p] Compile design tokens → CSS vars + typed theme\n` +
|
|
Binary file
|
package/package.json
CHANGED
package/src/compile/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ export type {
|
|
|
21
21
|
EntityTypeExport,
|
|
22
22
|
} from "./entities";
|
|
23
23
|
export { buildManifest } from "./manifest";
|
|
24
|
+
export { runCompile } from "./run";
|
|
24
25
|
export { buildOpenApi, writeSchema } from "./openapi";
|
|
25
26
|
export * from "./model";
|
|
26
27
|
|
|
@@ -60,7 +61,10 @@ export function resolveResourceFiles(input: string): string[] {
|
|
|
60
61
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
61
62
|
if (entry.isDirectory()) {
|
|
62
63
|
if (!IGNORE_DIRS.has(entry.name)) walk(path.join(dir, entry.name));
|
|
63
|
-
} else if (
|
|
64
|
+
} else if (
|
|
65
|
+
/\.tsx?$/.test(entry.name) &&
|
|
66
|
+
!entry.name.endsWith(".d.ts")
|
|
67
|
+
) {
|
|
64
68
|
files.push(path.resolve(dir, entry.name));
|
|
65
69
|
}
|
|
66
70
|
}
|
|
@@ -96,10 +100,14 @@ export function analyzeProject(input: string): ProjectAnalysis {
|
|
|
96
100
|
const defined = new Set(fromDsl.resources.map((r) => `${r.app}.${r.model}`));
|
|
97
101
|
const resources = [
|
|
98
102
|
...fromDsl.resources,
|
|
99
|
-
...fromInterfaces.resources.filter(
|
|
103
|
+
...fromInterfaces.resources.filter(
|
|
104
|
+
(r) => !defined.has(`${r.app}.${r.model}`),
|
|
105
|
+
),
|
|
100
106
|
];
|
|
101
107
|
resources.sort((a, b) =>
|
|
102
|
-
a.app === b.app
|
|
108
|
+
a.app === b.app
|
|
109
|
+
? a.model.localeCompare(b.model)
|
|
110
|
+
: a.app.localeCompare(b.app),
|
|
103
111
|
);
|
|
104
112
|
|
|
105
113
|
// Registry entries follow the same merge rule as the resources: the DSL
|
|
@@ -237,7 +245,8 @@ export function collisions(resources: ResourceModel[]): string[] {
|
|
|
237
245
|
}
|
|
238
246
|
}
|
|
239
247
|
for (const [key, count] of seen) {
|
|
240
|
-
if (count > 1)
|
|
248
|
+
if (count > 1)
|
|
249
|
+
errors.push(`Duplicate resource ${key} defined ${count} times.`);
|
|
241
250
|
}
|
|
242
251
|
return errors;
|
|
243
252
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { compile } from "./index";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Run the compiler **in-process**, writing `schema.rastack.json` +
|
|
7
|
+
* `openapi.json` (and `rastack-env.d.ts`) into `outDir`. Prints any warnings
|
|
8
|
+
* and, on failure, the error; returns `true` on success.
|
|
9
|
+
*
|
|
10
|
+
* This is the single entry point the two real modalities of use share instead
|
|
11
|
+
* of shelling out to a standalone `compile` command:
|
|
12
|
+
* • `rastack dev` / `rastack admin` — local development (compile, then serve
|
|
13
|
+
* the app + admin in the browser over WASM), and
|
|
14
|
+
* • `rastack ci` — the deploy pipeline (compile the manifest the Rust backend
|
|
15
|
+
* reads + the OpenAPI contract, then build/ship).
|
|
16
|
+
*/
|
|
17
|
+
export function runCompile(resourcesDir: string, outDir: string): boolean {
|
|
18
|
+
try {
|
|
19
|
+
const result = compile(resourcesDir, outDir);
|
|
20
|
+
for (const d of result.diagnostics) console.warn(` ⚠ ${d.message}`);
|
|
21
|
+
return fs.existsSync(path.join(outDir, "schema.rastack.json"));
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.error(` ✗ ${(err as Error).message}`);
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/deploy/ci.ts
CHANGED
|
@@ -23,10 +23,31 @@ export type CiPhase = "check" | "build" | "deploy";
|
|
|
23
23
|
export interface CiStep {
|
|
24
24
|
/** Human label, echoed before the step runs. */
|
|
25
25
|
name: string;
|
|
26
|
-
/** The shell command to execute. */
|
|
26
|
+
/** The shell command to execute (or, for an in-process step, a description). */
|
|
27
27
|
run: string;
|
|
28
28
|
/** Working directory relative to the repo root (default: repo root). */
|
|
29
29
|
cwd?: string;
|
|
30
|
+
/**
|
|
31
|
+
* When set, the step is executed **in-process by the CLI** rather than through
|
|
32
|
+
* a shell — `run` is then a human-readable description, not a command. Today
|
|
33
|
+
* the only in-process action is `"compile"`, which the CLI runs via the shared
|
|
34
|
+
* compiler (`runCompile`) instead of shelling out to a standalone command.
|
|
35
|
+
*/
|
|
36
|
+
action?: "compile";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The in-process compile step shared by `check` and `build`: it produces
|
|
41
|
+
* `schema.rastack.json` + `openapi.json` in `cfg.outDir` without a subprocess,
|
|
42
|
+
* so compilation lives inside the two modalities of use (`dev` and `ci`) rather
|
|
43
|
+
* than in a separately-invoked `compile` command.
|
|
44
|
+
*/
|
|
45
|
+
function compileStep(cfg: DeployConfig): CiStep {
|
|
46
|
+
return {
|
|
47
|
+
name: "Compile manifest + OpenAPI",
|
|
48
|
+
run: `compile ${cfg.resourcesDir} ${cfg.outDir} (in-process)`,
|
|
49
|
+
action: "compile",
|
|
50
|
+
};
|
|
30
51
|
}
|
|
31
52
|
|
|
32
53
|
export interface CiPlanOptions {
|
|
@@ -72,10 +93,7 @@ export function checkSteps(cfg: DeployConfig, bin: string): CiStep[] {
|
|
|
72
93
|
name: "Validate resource graph",
|
|
73
94
|
run: `${bin} check ${cfg.resourcesDir}`,
|
|
74
95
|
},
|
|
75
|
-
|
|
76
|
-
name: "Compile manifest + OpenAPI",
|
|
77
|
-
run: `${bin} compile ${cfg.resourcesDir} ${cfg.outDir}`,
|
|
78
|
-
},
|
|
96
|
+
compileStep(cfg),
|
|
79
97
|
];
|
|
80
98
|
}
|
|
81
99
|
|
|
@@ -88,7 +106,6 @@ export function buildSteps(
|
|
|
88
106
|
cfg: DeployConfig,
|
|
89
107
|
opts: CiPlanOptions = {},
|
|
90
108
|
): CiStep[] {
|
|
91
|
-
const bin = opts.bin ?? "rastack";
|
|
92
109
|
const stage = stageDir(cfg);
|
|
93
110
|
const archFlag = cfg.lambda.arch === "arm64" ? "--arm64" : "--x86-64";
|
|
94
111
|
const jwks = stackOutput(
|
|
@@ -97,10 +114,7 @@ export function buildSteps(
|
|
|
97
114
|
opts.jwksUrl ?? cfg.outputs?.jwksUrl,
|
|
98
115
|
);
|
|
99
116
|
return [
|
|
100
|
-
|
|
101
|
-
name: "Compile manifest + OpenAPI",
|
|
102
|
-
run: `${bin} compile ${cfg.resourcesDir} ${cfg.outDir}`,
|
|
103
|
-
},
|
|
117
|
+
compileStep(cfg),
|
|
104
118
|
{
|
|
105
119
|
name: "Cross-build the Lambda binary",
|
|
106
120
|
run: `cargo lambda build --release ${archFlag} --bin ${cfg.lambda.bin} --features ${cfg.lambda.features}`,
|
package/src/rastack-admin.ts
CHANGED
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
* falls back to a from-source cargo build.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import { execFileSync
|
|
23
|
+
import { execFileSync } from "child_process";
|
|
24
24
|
import * as fs from "fs";
|
|
25
25
|
import * as http from "http";
|
|
26
26
|
import * as path from "path";
|
|
27
|
+
import { runCompile } from "./compile";
|
|
27
28
|
import {
|
|
28
29
|
WASM_ENTRY,
|
|
29
30
|
contentType,
|
|
@@ -34,18 +35,6 @@ import {
|
|
|
34
35
|
|
|
35
36
|
const HERE = __dirname; // dist/ when installed — the bundle lives beside us.
|
|
36
37
|
|
|
37
|
-
/** Compile the resources to schema.rastack.json + openapi.json in outDir. */
|
|
38
|
-
function compile(resourcesDir: string, outDir: string): boolean {
|
|
39
|
-
const compiler = path.join(HERE, "rastack-compile.js");
|
|
40
|
-
const result = spawnSync(
|
|
41
|
-
process.execPath,
|
|
42
|
-
[compiler, "compile", resourcesDir, outDir],
|
|
43
|
-
{ stdio: "inherit" },
|
|
44
|
-
);
|
|
45
|
-
if (result.status !== 0) return false;
|
|
46
|
-
return fs.existsSync(path.join(outDir, "schema.rastack.json"));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
38
|
/** Locate the prebuilt wasm bundle dir shipped in the package (no cargo fallback). */
|
|
50
39
|
function resolveWasmDir(): string | null {
|
|
51
40
|
for (const dir of wasmBundleCandidates(HERE)) {
|
|
@@ -106,9 +95,11 @@ function openBrowser(url: string): void {
|
|
|
106
95
|
function main(argv: string[]): void {
|
|
107
96
|
const args = parseAdminArgs(argv);
|
|
108
97
|
|
|
109
|
-
console.log(
|
|
98
|
+
console.log(
|
|
99
|
+
`\n rastack admin — the database console, built with React API Stack\n`,
|
|
100
|
+
);
|
|
110
101
|
console.log(`▸ Compiling ${args.resourcesDir} → ${args.outDir}`);
|
|
111
|
-
if (!
|
|
102
|
+
if (!runCompile(args.resourcesDir, args.outDir)) {
|
|
112
103
|
console.error(" ✗ compile failed — fix the resource graph and re-run.");
|
|
113
104
|
process.exit(1);
|
|
114
105
|
}
|
package/src/rastack-ci.ts
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { execSync } from "child_process";
|
|
21
|
+
import { runCompile } from "./compile";
|
|
22
|
+
import { DeployConfig } from "./deploy/config";
|
|
21
23
|
import { CiPhase, CiPlanOptions, CiStep, ciPlan } from "./deploy/ci";
|
|
22
24
|
import { loadConfig } from "./deploy/io";
|
|
23
25
|
|
|
@@ -85,13 +87,24 @@ function printPlan(phase: CiPhase, steps: CiStep[]): void {
|
|
|
85
87
|
steps.forEach((s, i) => {
|
|
86
88
|
const at = s.cwd ? ` (in ${s.cwd}/)` : "";
|
|
87
89
|
console.log(` ${i + 1}. ${s.name}${at}`);
|
|
88
|
-
|
|
90
|
+
// In-process steps have no shell command; `run` is a description.
|
|
91
|
+
console.log(` ${s.action ? "» " : "$ "}${s.run}\n`);
|
|
89
92
|
});
|
|
90
93
|
}
|
|
91
94
|
|
|
92
|
-
function runSteps(phase: CiPhase, steps: CiStep[]): void {
|
|
95
|
+
function runSteps(phase: CiPhase, steps: CiStep[], cfg: DeployConfig): void {
|
|
93
96
|
for (const step of steps) {
|
|
94
97
|
console.log(`\n▸ ${step.name}${step.cwd ? ` (in ${step.cwd}/)` : ""}`);
|
|
98
|
+
if (step.action === "compile") {
|
|
99
|
+
// Compilation runs in-process — it lives inside `ci` (and `dev`), not in a
|
|
100
|
+
// separately-invoked `compile` command.
|
|
101
|
+
console.log(` » ${step.run}`);
|
|
102
|
+
if (!runCompile(cfg.resourcesDir, cfg.outDir)) {
|
|
103
|
+
console.error(`\n ✗ step failed: ${step.name}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
95
108
|
console.log(` $ ${step.run}`);
|
|
96
109
|
try {
|
|
97
110
|
// Runs a CI pipeline step derived from the developer's own deploy config
|
|
@@ -123,7 +136,7 @@ function main(argv: string[]): void {
|
|
|
123
136
|
}
|
|
124
137
|
const steps = ciPlan(phase, cfg, opts);
|
|
125
138
|
if (plan) printPlan(phase, steps);
|
|
126
|
-
else runSteps(phase, steps);
|
|
139
|
+
else runSteps(phase, steps, cfg);
|
|
127
140
|
}
|
|
128
141
|
|
|
129
142
|
if (require.main === module) {
|
package/src/rastack-compile.ts
CHANGED
|
@@ -1,40 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
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
|
|
|
13
16
|
import {
|
|
14
17
|
analyzeProject,
|
|
15
18
|
analyzeResources,
|
|
16
19
|
collisions,
|
|
17
|
-
compile,
|
|
18
20
|
urlsFor,
|
|
19
21
|
} from "./compile";
|
|
20
22
|
|
|
21
23
|
const DEFAULT_RESOURCES = "resources";
|
|
22
|
-
const DEFAULT_OUT = ".rastack";
|
|
23
24
|
|
|
24
25
|
function main(argv: string[]): void {
|
|
25
26
|
const [sub, ...rest] = argv;
|
|
26
27
|
|
|
27
28
|
switch (sub) {
|
|
28
|
-
case "compile": {
|
|
29
|
-
const resourcesDir = rest[0] || DEFAULT_RESOURCES;
|
|
30
|
-
const outDir = rest[1] || DEFAULT_OUT;
|
|
31
|
-
const result = compile(resourcesDir, outDir);
|
|
32
|
-
for (const d of result.diagnostics) console.warn(` ⚠ ${d.message}`);
|
|
33
|
-
console.log(
|
|
34
|
-
`✓ compiled ${result.manifest.resources.length} resource(s) → ${result.files.join(", ")}`,
|
|
35
|
-
);
|
|
36
|
-
break;
|
|
37
|
-
}
|
|
38
29
|
case "check": {
|
|
39
30
|
const { resources, diagnostics } = analyzeProject(
|
|
40
31
|
rest[0] || DEFAULT_RESOURCES,
|
|
@@ -65,7 +56,9 @@ function main(argv: string[]): void {
|
|
|
65
56
|
for (const r of resources) {
|
|
66
57
|
console.log(`${r.app}.${r.model}`);
|
|
67
58
|
for (const f of r.fields) {
|
|
68
|
-
const rel = f.relation
|
|
59
|
+
const rel = f.relation
|
|
60
|
+
? ` → ${f.relation.app}.${f.relation.model}`
|
|
61
|
+
: "";
|
|
69
62
|
console.log(` ${f.name}: ${f.type}${rel}`);
|
|
70
63
|
}
|
|
71
64
|
if (r.sync) {
|
|
@@ -89,9 +82,8 @@ function main(argv: string[]): void {
|
|
|
89
82
|
}
|
|
90
83
|
default:
|
|
91
84
|
console.error(
|
|
92
|
-
`Unknown
|
|
85
|
+
`Unknown subcommand: "${sub}"\n\n` +
|
|
93
86
|
`Usage:\n` +
|
|
94
|
-
` rastack compile [resourcesDir] [outDir]\n` +
|
|
95
87
|
` rastack check [resourcesDir]\n` +
|
|
96
88
|
` rastack list [resourcesDir]\n` +
|
|
97
89
|
` rastack urls [resourcesDir]\n`,
|
package/src/rastack-dev.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { execFileSync, spawnSync } from "child_process";
|
|
|
25
25
|
import * as fs from "fs";
|
|
26
26
|
import * as http from "http";
|
|
27
27
|
import * as path from "path";
|
|
28
|
+
import { runCompile } from "./compile";
|
|
28
29
|
import {
|
|
29
30
|
APP_ENTRY,
|
|
30
31
|
WASM_ENTRY,
|
|
@@ -37,24 +38,10 @@ import {
|
|
|
37
38
|
|
|
38
39
|
const HERE = __dirname; // dist/ when installed
|
|
39
40
|
|
|
40
|
-
/** Compile the resources to schema.rastack.json + openapi.json in outDir. */
|
|
41
|
-
function compile(resourcesDir: string, outDir: string): boolean {
|
|
42
|
-
const compiler = path.join(HERE, "rastack-compile.js");
|
|
43
|
-
const result = spawnSync(
|
|
44
|
-
process.execPath,
|
|
45
|
-
[compiler, "compile", resourcesDir, outDir],
|
|
46
|
-
{ stdio: "inherit" },
|
|
47
|
-
);
|
|
48
|
-
if (result.status !== 0) return false;
|
|
49
|
-
return fs.existsSync(path.join(outDir, "schema.rastack.json"));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
41
|
/** True when `cargo` is on PATH (the from-source wasm fallback needs it). */
|
|
53
42
|
function cargoAvailable(): boolean {
|
|
54
43
|
try {
|
|
55
|
-
return (
|
|
56
|
-
spawnSync("cargo", ["--version"], { stdio: "ignore" }).status === 0
|
|
57
|
-
);
|
|
44
|
+
return spawnSync("cargo", ["--version"], { stdio: "ignore" }).status === 0;
|
|
58
45
|
} catch {
|
|
59
46
|
return false;
|
|
60
47
|
}
|
|
@@ -146,7 +133,7 @@ function main(argv: string[]): void {
|
|
|
146
133
|
|
|
147
134
|
console.log(`\n rastack dev — your app, in your browser over WASM\n`);
|
|
148
135
|
console.log(`▸ Compiling ${args.resourcesDir} → ${args.outDir}`);
|
|
149
|
-
if (!
|
|
136
|
+
if (!runCompile(args.resourcesDir, args.outDir)) {
|
|
150
137
|
console.error(" ✗ compile failed — fix the resource graph and re-run.");
|
|
151
138
|
process.exit(1);
|
|
152
139
|
}
|
package/src/rastack.ts
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* rastack — unified CLI for React API Stack
|
|
5
5
|
*
|
|
6
|
+
* Compilation is not a command of its own: it runs in-process inside the two
|
|
7
|
+
* modalities of use — `rastack dev`/`admin` (local) and `rastack ci` (deploy).
|
|
8
|
+
*
|
|
6
9
|
* Commands:
|
|
7
|
-
* rastack compile [resourcesDir] [outDir] TypeScript resources → schema.rastack.json + openapi.json
|
|
8
10
|
* rastack check [resourcesDir] Validate the resource graph
|
|
9
11
|
* rastack list [resourcesDir] Print resources, fields and relations
|
|
10
12
|
* rastack urls [resourcesDir] Print the generated /api/{app}/v1/{model}/ routes
|
|
@@ -65,6 +67,17 @@ switch (command) {
|
|
|
65
67
|
printVersion();
|
|
66
68
|
break;
|
|
67
69
|
case "compile":
|
|
70
|
+
// Compilation is no longer a standalone command — it runs in-process as
|
|
71
|
+
// part of the two modalities of use. Point the way rather than 404.
|
|
72
|
+
console.error(
|
|
73
|
+
"`rastack compile` has been removed — compilation now runs automatically\n" +
|
|
74
|
+
"inside the two modalities of use:\n" +
|
|
75
|
+
" • rastack dev local development (compiles, then serves over WASM)\n" +
|
|
76
|
+
" • rastack ci the deploy pipeline (compiles the manifest + OpenAPI)\n\n" +
|
|
77
|
+
"Introspect the resource graph with: rastack check | list | urls\n",
|
|
78
|
+
);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
break;
|
|
68
81
|
case "check":
|
|
69
82
|
case "list":
|
|
70
83
|
case "urls":
|
|
@@ -135,7 +148,6 @@ switch (command) {
|
|
|
135
148
|
console.error(
|
|
136
149
|
`Unknown command: "${command}"\n\n` +
|
|
137
150
|
`Usage:\n` +
|
|
138
|
-
` rastack compile [resourcesDir] [outDir]\n` +
|
|
139
151
|
` rastack check | list | urls [resourcesDir]\n` +
|
|
140
152
|
` rastack generate [--schema-only]\n` +
|
|
141
153
|
` rastack tokens [input] [outDir] [--prefix p] Compile design tokens → CSS vars + typed theme\n` +
|
package/test/deploy.spec.ts
CHANGED
|
@@ -419,12 +419,15 @@ describe("repo variables + lambda env", () => {
|
|
|
419
419
|
});
|
|
420
420
|
|
|
421
421
|
describe("ci plan — check", () => {
|
|
422
|
-
it("validates then compiles, honouring the resources dir + bin", () => {
|
|
422
|
+
it("validates then compiles in-process, honouring the resources dir + bin", () => {
|
|
423
423
|
const steps = checkSteps(base({ resourcesDir: "res" }), "npx rastack");
|
|
424
424
|
expect(steps.map((s) => s.run)).toEqual([
|
|
425
425
|
"npx rastack check res",
|
|
426
|
-
"
|
|
426
|
+
"compile res .rastack (in-process)",
|
|
427
427
|
]);
|
|
428
|
+
// The compile step runs in-process (no shell command), so the CLI can drop
|
|
429
|
+
// the standalone `compile` command entirely.
|
|
430
|
+
expect(steps[1].action).toBe("compile");
|
|
428
431
|
expect(ciPlan("check", base(), { bin: "rastack" })).toEqual(
|
|
429
432
|
checkSteps(base(), "rastack"),
|
|
430
433
|
);
|
|
Binary file
|