@unispechq/unispec-platform 0.1.5 → 0.2.1
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/README.md +144 -31
- package/dist/cli.js +25 -4
- package/dist/cli.js.map +1 -1
- package/dist/commands/index.d.ts +1 -2
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -2
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/portal.d.ts +3 -0
- package/dist/commands/portal.d.ts.map +1 -0
- package/dist/commands/portal.js +90 -0
- package/dist/commands/portal.js.map +1 -0
- package/package.json +1 -1
- package/dist/commands/dev.d.ts +0 -3
- package/dist/commands/dev.d.ts.map +0 -1
- package/dist/commands/dev.js +0 -207
- package/dist/commands/dev.js.map +0 -1
- package/dist/commands/start.d.ts +0 -3
- package/dist/commands/start.d.ts.map +0 -1
- package/dist/commands/start.js +0 -121
- package/dist/commands/start.js.map +0 -1
- package/dist/dev/aggregate.d.ts +0 -15
- package/dist/dev/aggregate.d.ts.map +0 -1
- package/dist/dev/aggregate.js +0 -56
- package/dist/dev/aggregate.js.map +0 -1
- package/dist/dev/index.d.ts +0 -3
- package/dist/dev/index.d.ts.map +0 -1
- package/dist/dev/index.js +0 -3
- package/dist/dev/index.js.map +0 -1
- package/dist/dev/server.d.ts +0 -14
- package/dist/dev/server.d.ts.map +0 -1
- package/dist/dev/server.js +0 -175
- package/dist/dev/server.js.map +0 -1
- package/dist/dev/ui.d.ts +0 -3
- package/dist/dev/ui.d.ts.map +0 -1
- package/dist/dev/ui.js +0 -93
- package/dist/dev/ui.js.map +0 -1
package/README.md
CHANGED
|
@@ -89,48 +89,39 @@ Options:
|
|
|
89
89
|
- `--format <format>` — `json|yaml` (for JSON-like targets)
|
|
90
90
|
- `--output <file>` — write output to file (use `-` for stdout)
|
|
91
91
|
|
|
92
|
-
### `unispec dev
|
|
93
|
-
|
|
92
|
+
### `unispec portal <dev|start>`
|
|
93
|
+
Launch UniSpec Portal (Next.js orchestrator).
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
In the current architecture, `unispec-platform` provides CLI utilities (validate/normalize/diff/convert) and a launcher for `@unispechq/unispec-portal`.
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
- `GET /unispec.json` — aggregated snapshot
|
|
99
|
-
- `GET /health` — healthcheck
|
|
97
|
+
Examples:
|
|
100
98
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
- `--port <port>` — bind port (default: `4141`)
|
|
106
|
-
- `--watch` — watch config/spec files and refresh aggregated snapshot
|
|
107
|
-
- `--ui` / `--no-ui` — enable/disable embedded UI at `/` (default: enabled)
|
|
108
|
-
- `--ui-dev <url>` — proxy UI requests to an external dev server (e.g. Next.js) for HMR
|
|
99
|
+
```bash
|
|
100
|
+
unispec portal dev --config ./unispec.config.json
|
|
101
|
+
unispec portal start --config ./unispec.config.json
|
|
102
|
+
```
|
|
109
103
|
|
|
110
|
-
|
|
104
|
+
Options:
|
|
111
105
|
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
106
|
+
- `--config <path>` — path to config file
|
|
107
|
+
- `--host <host>` — bind host (forwarded to portal)
|
|
108
|
+
- `--port <port>` — bind port (forwarded to portal)
|
|
109
|
+
- `--storage <type>` — `json|sqlite` (forwarded to portal)
|
|
110
|
+
- `--data-dir <path>` — data directory (forwarded to portal)
|
|
111
|
+
- `--open` — open browser (forwarded to portal)
|
|
112
|
+
- `--verbose` — verbose output (forwarded to portal)
|
|
113
|
+
- `--json-errors` — output errors as JSON (forwarded to portal)
|
|
114
|
+
- `--portal-package <name>` — portal package name (default: `@unispechq/unispec-portal`)
|
|
116
115
|
|
|
117
116
|
---
|
|
118
117
|
|
|
119
|
-
##
|
|
118
|
+
## Notes
|
|
120
119
|
|
|
121
|
-
|
|
120
|
+
All orchestration responsibilities (HTTP API, watch mode, workspace storage, and test runner) live in the Portal package.
|
|
122
121
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
- Host: `127.0.0.1`
|
|
126
|
-
- Port: `4141`
|
|
127
|
-
|
|
128
|
-
Endpoints:
|
|
129
|
-
|
|
130
|
-
- `GET /health` -> `OK`
|
|
131
|
-
- `GET /unispec.json` -> aggregated JSON
|
|
122
|
+
---
|
|
132
123
|
|
|
133
|
-
Aggregation format (A)
|
|
124
|
+
## Aggregation format (A)
|
|
134
125
|
|
|
135
126
|
```json
|
|
136
127
|
{
|
|
@@ -169,6 +160,128 @@ Then open:
|
|
|
169
160
|
- `http://127.0.0.1:4141/unispec.json`
|
|
170
161
|
- `http://127.0.0.1:4141/`
|
|
171
162
|
|
|
163
|
+
### `unispec start`
|
|
164
|
+
Production-like server mode.
|
|
165
|
+
|
|
166
|
+
`unispec start` runs the same HTTP surface as `unispec dev`, but is intended for long-running use.
|
|
167
|
+
|
|
168
|
+
Options:
|
|
169
|
+
|
|
170
|
+
- `--config <path>` — path to config file
|
|
171
|
+
- `--host <host>` — bind host (default: `127.0.0.1`)
|
|
172
|
+
- `--port <port>` — bind port (default: `4141`)
|
|
173
|
+
- `--ui` / `--no-ui` — enable/disable embedded UI
|
|
174
|
+
- `--ui-url <url>` — proxy UI requests to an external UI server
|
|
175
|
+
- `--portal` — spawn portal server (SSR) from an installed dependency and proxy UI to it
|
|
176
|
+
- `--portal-port <port>` — port for portal server (default: `3000`)
|
|
177
|
+
- `--portal-package <name>` — portal package name (default: `@unispechq/unispec-portal`)
|
|
178
|
+
|
|
179
|
+
### Portal package contract
|
|
180
|
+
|
|
181
|
+
When using `--portal`, the portal package is expected to provide a single runnable `bin` entry which supports:
|
|
182
|
+
|
|
183
|
+
- `--port <port>`
|
|
184
|
+
- `--mode dev|start`
|
|
185
|
+
|
|
186
|
+
Example:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
unispec-portal --mode dev --port 3000
|
|
190
|
+
unispec-portal --mode start --port 3000
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Workspace layer
|
|
196
|
+
|
|
197
|
+
Workspace data is stored in `.unispec/workspace.json` next to your config file. This file is not part of UniSpec.
|
|
198
|
+
|
|
199
|
+
### Workspace endpoints
|
|
200
|
+
|
|
201
|
+
- `GET /workspace.json` — info for clients (mode, configPath, storage paths, and API URLs)
|
|
202
|
+
- `GET /workspace/state` — workspace state JSON
|
|
203
|
+
- `PUT /workspace/state` — replace workspace state JSON (atomic write)
|
|
204
|
+
|
|
205
|
+
### Endpoint IDs
|
|
206
|
+
|
|
207
|
+
Workspace entities reference endpoints using:
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
{serviceName}:{METHOD}:{path}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Example:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
users:GET:/users
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Workspace tests
|
|
222
|
+
|
|
223
|
+
Tests are stored in workspace state as YAML or JSON strings and can be run through:
|
|
224
|
+
|
|
225
|
+
- `POST /tests/run` with `{ "suiteId": "..." }` or `{ "testIds": ["..."] }`
|
|
226
|
+
|
|
227
|
+
### YAML/JSON test format (single request)
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
request:
|
|
231
|
+
method: GET
|
|
232
|
+
url: "http://127.0.0.1:4141/health"
|
|
233
|
+
expect:
|
|
234
|
+
status: 200
|
|
235
|
+
bodyContains: "OK"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Multi-step tests (flow)
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
steps:
|
|
242
|
+
- name: health
|
|
243
|
+
request:
|
|
244
|
+
method: GET
|
|
245
|
+
url: "http://127.0.0.1:4141/health"
|
|
246
|
+
expect:
|
|
247
|
+
status: 200
|
|
248
|
+
bodyContains: "OK"
|
|
249
|
+
extract:
|
|
250
|
+
st:
|
|
251
|
+
from: status
|
|
252
|
+
|
|
253
|
+
- name: unispec
|
|
254
|
+
request:
|
|
255
|
+
method: GET
|
|
256
|
+
url: "http://127.0.0.1:4141/unispec.json"
|
|
257
|
+
expect:
|
|
258
|
+
status: 200
|
|
259
|
+
jsonContains:
|
|
260
|
+
version: 1
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Variables and interpolation
|
|
264
|
+
|
|
265
|
+
You can extract variables and use them with `{{var}}` in URL/headers/body:
|
|
266
|
+
|
|
267
|
+
```yaml
|
|
268
|
+
steps:
|
|
269
|
+
- request:
|
|
270
|
+
method: GET
|
|
271
|
+
url: "https://example.com/api/session"
|
|
272
|
+
extract:
|
|
273
|
+
token:
|
|
274
|
+
from: json
|
|
275
|
+
path: "$.token"
|
|
276
|
+
- request:
|
|
277
|
+
method: GET
|
|
278
|
+
url: "https://example.com/api/me"
|
|
279
|
+
headers:
|
|
280
|
+
authorization: "Bearer {{token}}"
|
|
281
|
+
expect:
|
|
282
|
+
status: 200
|
|
283
|
+
```
|
|
284
|
+
|
|
172
285
|
---
|
|
173
286
|
|
|
174
287
|
## Development
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
|
-
import { registerConvertCommand,
|
|
3
|
+
import { registerConvertCommand, registerDiffCommand, registerNormalizeCommand, registerPortalCommand, registerValidateCommand, } from "./commands/index.js";
|
|
4
4
|
function errorToJson(err, includeStack) {
|
|
5
5
|
const message = err instanceof Error ? err.message : String(err);
|
|
6
6
|
const code = err instanceof Error && "code" in err ? String(err.code) : undefined;
|
|
7
7
|
const stack = includeStack && err instanceof Error ? err.stack : undefined;
|
|
8
8
|
return { error: { message, ...(code ? { code } : {}), ...(stack ? { stack } : {}) } };
|
|
9
9
|
}
|
|
10
|
+
function normalizeGlobalOptionsArgv(argv) {
|
|
11
|
+
if (argv.length <= 2)
|
|
12
|
+
return argv;
|
|
13
|
+
const head = argv.slice(0, 2);
|
|
14
|
+
const rest = argv.slice(2);
|
|
15
|
+
const globalNoValue = new Set(["--verbose", "--json-errors", "--quiet", "-q"]);
|
|
16
|
+
const extracted = [];
|
|
17
|
+
const remaining = [];
|
|
18
|
+
for (let i = 0; i < rest.length; i++) {
|
|
19
|
+
const a = rest[i];
|
|
20
|
+
if (a === "--") {
|
|
21
|
+
remaining.push(...rest.slice(i));
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
if (globalNoValue.has(a)) {
|
|
25
|
+
extracted.push(a);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
remaining.push(a);
|
|
29
|
+
}
|
|
30
|
+
return [...head, ...extracted, ...remaining];
|
|
31
|
+
}
|
|
10
32
|
const program = new Command();
|
|
11
33
|
program
|
|
12
34
|
.name("unispec")
|
|
@@ -19,9 +41,8 @@ registerValidateCommand(program);
|
|
|
19
41
|
registerNormalizeCommand(program);
|
|
20
42
|
registerDiffCommand(program);
|
|
21
43
|
registerConvertCommand(program);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
program.parseAsync(process.argv).catch((err) => {
|
|
44
|
+
registerPortalCommand(program);
|
|
45
|
+
program.parseAsync(normalizeGlobalOptionsArgv(process.argv)).catch((err) => {
|
|
25
46
|
const opts = program.opts();
|
|
26
47
|
const verbose = opts.verbose ?? false;
|
|
27
48
|
const jsonErrors = opts["jsonErrors"] ?? opts["json-errors"] ?? false;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,sBAAsB,EACtB,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
|
package/dist/commands/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../src/commands/portal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoCzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoE5D"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
async function resolvePortalBin(portalPackage) {
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const pkgJsonPath = require.resolve(`${portalPackage}/package.json`);
|
|
8
|
+
const pkgDir = dirname(pkgJsonPath);
|
|
9
|
+
const pkgRaw = await readFile(pkgJsonPath, "utf8");
|
|
10
|
+
const pkg = JSON.parse(pkgRaw);
|
|
11
|
+
if (!pkg.bin) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
if (typeof pkg.bin === "string") {
|
|
15
|
+
return { binPath: join(pkgDir, pkg.bin), binName: portalPackage };
|
|
16
|
+
}
|
|
17
|
+
const entries = Object.entries(pkg.bin);
|
|
18
|
+
if (entries.length === 0) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const preferred = entries.find(([name]) => name === "unispec-portal") ?? entries[0];
|
|
22
|
+
return { binPath: join(pkgDir, preferred[1]), binName: preferred[0] };
|
|
23
|
+
}
|
|
24
|
+
function pickArg(options, camel, kebab) {
|
|
25
|
+
const v = options[camel] ?? options[kebab];
|
|
26
|
+
if (v === undefined || v === null)
|
|
27
|
+
return undefined;
|
|
28
|
+
return String(v);
|
|
29
|
+
}
|
|
30
|
+
export function registerPortalCommand(program) {
|
|
31
|
+
const cmd = program
|
|
32
|
+
.command("portal")
|
|
33
|
+
.description("Launch UniSpec Portal (Next.js orchestrator)")
|
|
34
|
+
.option("--portal-package <name>", "Portal package name", "@unispechq/unispec-portal");
|
|
35
|
+
const addSharedOptions = (c) => c
|
|
36
|
+
.requiredOption("--config <path>", "Path to unispec config file")
|
|
37
|
+
.option("--host <host>", "Bind host")
|
|
38
|
+
.option("--port <port>", "Bind port")
|
|
39
|
+
.option("--storage <type>", "Storage backend (json|sqlite)")
|
|
40
|
+
.option("--data-dir <path>", "Data directory (default: <configDir>/.unispec)")
|
|
41
|
+
.option("--open", "Open browser")
|
|
42
|
+
.option("--verbose", "Verbose portal output")
|
|
43
|
+
.option("--json-errors", "Output portal errors as JSON");
|
|
44
|
+
for (const mode of ["dev", "start"]) {
|
|
45
|
+
addSharedOptions(cmd
|
|
46
|
+
.command(mode)
|
|
47
|
+
.description(`Run portal in ${mode} mode`)
|
|
48
|
+
.action(async function (options) {
|
|
49
|
+
const parentOpts = this.parent?.opts?.();
|
|
50
|
+
const portalPackage = String(parentOpts?.portalPackage ?? "@unispechq/unispec-portal");
|
|
51
|
+
let resolved = null;
|
|
52
|
+
try {
|
|
53
|
+
resolved = await resolvePortalBin(portalPackage);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
57
|
+
throw new Error(`Failed to resolve portal package '${portalPackage}': ${message}`);
|
|
58
|
+
}
|
|
59
|
+
if (!resolved) {
|
|
60
|
+
throw new Error(`Portal package '${portalPackage}' does not expose a runnable bin. Expected a package.json "bin" entry.`);
|
|
61
|
+
}
|
|
62
|
+
const args = [resolved.binPath, mode, "--config", String(options.config)];
|
|
63
|
+
const host = pickArg(options, "host", "host");
|
|
64
|
+
if (host)
|
|
65
|
+
args.push("--host", host);
|
|
66
|
+
const port = pickArg(options, "port", "port");
|
|
67
|
+
if (port)
|
|
68
|
+
args.push("--port", port);
|
|
69
|
+
const storage = pickArg(options, "storage", "storage");
|
|
70
|
+
if (storage)
|
|
71
|
+
args.push("--storage", storage);
|
|
72
|
+
const dataDir = pickArg(options, "dataDir", "data-dir");
|
|
73
|
+
if (dataDir)
|
|
74
|
+
args.push("--data-dir", dataDir);
|
|
75
|
+
if (options.open)
|
|
76
|
+
args.push("--open");
|
|
77
|
+
if (options.verbose)
|
|
78
|
+
args.push("--verbose");
|
|
79
|
+
if (options["jsonErrors"] ?? options["json-errors"])
|
|
80
|
+
args.push("--json-errors");
|
|
81
|
+
const child = spawn(process.execPath, args, {
|
|
82
|
+
stdio: "inherit",
|
|
83
|
+
env: { ...process.env },
|
|
84
|
+
});
|
|
85
|
+
const code = await new Promise((resolve) => child.once("exit", (c) => resolve(c ?? 0)));
|
|
86
|
+
process.exitCode = code;
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=portal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../src/commands/portal.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/dist/commands/dev.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiFzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4KzD"}
|
package/dist/commands/dev.js
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { watch } from "node:fs";
|
|
3
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
-
import { createRequire } from "node:module";
|
|
5
|
-
import { readFile } from "node:fs/promises";
|
|
6
|
-
import { loadConfig } from "../config/loadConfig.js";
|
|
7
|
-
import { findConfigPath } from "../config/loadConfig.js";
|
|
8
|
-
import { aggregateFromConfig } from "../dev/aggregate.js";
|
|
9
|
-
import { startDevServer } from "../dev/server.js";
|
|
10
|
-
function resolveConfigSpecPaths(config, baseDir) {
|
|
11
|
-
if (!baseDir)
|
|
12
|
-
return config;
|
|
13
|
-
const services = Array.isArray(config.services) ? config.services : [];
|
|
14
|
-
return {
|
|
15
|
-
...config,
|
|
16
|
-
services: services.map((s) => {
|
|
17
|
-
const spec = String(s?.spec ?? "");
|
|
18
|
-
const resolvedSpec = spec && !isAbsolute(spec) ? resolve(baseDir, spec) : spec;
|
|
19
|
-
return {
|
|
20
|
-
...s,
|
|
21
|
-
spec: resolvedSpec,
|
|
22
|
-
};
|
|
23
|
-
}),
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
async function resolvePortalBin(portalPackage) {
|
|
27
|
-
const require = createRequire(import.meta.url);
|
|
28
|
-
const pkgJsonPath = require.resolve(`${portalPackage}/package.json`);
|
|
29
|
-
const pkgDir = dirname(pkgJsonPath);
|
|
30
|
-
const pkgRaw = await readFile(pkgJsonPath, "utf8");
|
|
31
|
-
const pkg = JSON.parse(pkgRaw);
|
|
32
|
-
if (!pkg.bin) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
if (typeof pkg.bin === "string") {
|
|
36
|
-
return { binPath: join(pkgDir, pkg.bin), binName: portalPackage };
|
|
37
|
-
}
|
|
38
|
-
const entries = Object.entries(pkg.bin);
|
|
39
|
-
if (entries.length === 0) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
const preferred = entries.find(([name]) => name.includes("dev")) ?? entries[0];
|
|
43
|
-
return { binPath: join(pkgDir, preferred[1]), binName: preferred[0] };
|
|
44
|
-
}
|
|
45
|
-
async function spawnPortalDevServer(options) {
|
|
46
|
-
const resolved = await resolvePortalBin(options.portalPackage);
|
|
47
|
-
if (!resolved) {
|
|
48
|
-
throw new Error(`Portal package '${options.portalPackage}' does not expose a runnable bin. Expected a package.json "bin" entry.`);
|
|
49
|
-
}
|
|
50
|
-
const args = [resolved.binPath, "--port", String(options.port)];
|
|
51
|
-
const child = spawn(process.execPath, args, {
|
|
52
|
-
stdio: options.verbose ? "inherit" : "ignore",
|
|
53
|
-
env: { ...process.env, PORT: String(options.port) },
|
|
54
|
-
});
|
|
55
|
-
child.once("exit", (code) => {
|
|
56
|
-
if (options.verbose) {
|
|
57
|
-
process.stderr.write(`Portal dev server exited with code ${code ?? "null"}\n`);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
return child;
|
|
61
|
-
}
|
|
62
|
-
export function registerDevCommand(program) {
|
|
63
|
-
program
|
|
64
|
-
.command("dev")
|
|
65
|
-
.description("Local orchestrator mode: aggregate specs and serve a local API")
|
|
66
|
-
.option("--config <path>", "Path to unispec config file")
|
|
67
|
-
.option("--host <host>", "Host to bind", "127.0.0.1")
|
|
68
|
-
.option("--port <port>", "Port to bind", "4141")
|
|
69
|
-
.option("--watch", "Watch config/spec files and refresh aggregated snapshot")
|
|
70
|
-
.option("--ui", "Serve embedded UI at /", true)
|
|
71
|
-
.option("--no-ui", "Disable embedded UI")
|
|
72
|
-
.option("--ui-dev <url>", "Proxy UI requests to an external dev server (e.g. Next.js)")
|
|
73
|
-
.option("--portal", "Spawn portal server and proxy UI to it")
|
|
74
|
-
.option("--portal-port <port>", "Port for portal server", "3000")
|
|
75
|
-
.option("--portal-dev", "Spawn portal dev server from an installed dependency and proxy UI to it")
|
|
76
|
-
.option("--portal-dev-port <port>", "Port for portal dev server")
|
|
77
|
-
.option("--portal-package <name>", "Portal package name", "@unispechq/unispec-portal")
|
|
78
|
-
.action(async function (options) {
|
|
79
|
-
const parentOpts = this.parent?.opts?.();
|
|
80
|
-
const verbose = parentOpts?.verbose ?? false;
|
|
81
|
-
const host = String(options.host ?? "127.0.0.1");
|
|
82
|
-
const port = Number(options.port ?? 4141);
|
|
83
|
-
let snapshot;
|
|
84
|
-
let snapshotError;
|
|
85
|
-
const configPath = await findConfigPath({ explicitPath: options.config });
|
|
86
|
-
const configDir = configPath ? dirname(configPath) : undefined;
|
|
87
|
-
const loadAndAggregate = async () => {
|
|
88
|
-
const config = await loadConfig({ explicitPath: options.config });
|
|
89
|
-
const cfg = resolveConfigSpecPaths(config ?? { version: 1, services: [] }, configDir);
|
|
90
|
-
return aggregateFromConfig(cfg);
|
|
91
|
-
};
|
|
92
|
-
const refreshSnapshot = async () => {
|
|
93
|
-
try {
|
|
94
|
-
snapshot = await loadAndAggregate();
|
|
95
|
-
snapshotError = undefined;
|
|
96
|
-
if (verbose) {
|
|
97
|
-
process.stderr.write("Refreshed aggregated snapshot\n");
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
catch (err) {
|
|
101
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
102
|
-
snapshotError = { message };
|
|
103
|
-
if (verbose) {
|
|
104
|
-
process.stderr.write(`Failed to refresh snapshot: ${message}\n`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
await refreshSnapshot();
|
|
109
|
-
const getConfig = async () => {
|
|
110
|
-
const config = await loadConfig({ explicitPath: options.config });
|
|
111
|
-
return resolveConfigSpecPaths(config ?? { version: 1, services: [] }, configDir);
|
|
112
|
-
};
|
|
113
|
-
const getAggregated = async () => {
|
|
114
|
-
if (snapshot) {
|
|
115
|
-
return snapshot;
|
|
116
|
-
}
|
|
117
|
-
if (snapshotError) {
|
|
118
|
-
return {
|
|
119
|
-
version: 1,
|
|
120
|
-
generatedAt: new Date().toISOString(),
|
|
121
|
-
services: [
|
|
122
|
-
{
|
|
123
|
-
name: "orchestrator",
|
|
124
|
-
specPath: "config",
|
|
125
|
-
valid: false,
|
|
126
|
-
errors: [snapshotError],
|
|
127
|
-
},
|
|
128
|
-
],
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
return loadAndAggregate();
|
|
132
|
-
};
|
|
133
|
-
let portalChild;
|
|
134
|
-
let uiDevUrl = options.uiDev;
|
|
135
|
-
const portalEnabled = options.portalDev || options.portal;
|
|
136
|
-
const portalPortRaw = options.portalDevPort ?? options.portalPort;
|
|
137
|
-
if (portalEnabled) {
|
|
138
|
-
if (uiDevUrl) {
|
|
139
|
-
throw new Error("--portal cannot be used together with --ui-dev");
|
|
140
|
-
}
|
|
141
|
-
const portalPort = Number(portalPortRaw ?? 3000);
|
|
142
|
-
const portalPackage = String(options.portalPackage ?? "@unispechq/unispec-portal");
|
|
143
|
-
uiDevUrl = `http://127.0.0.1:${portalPort}`;
|
|
144
|
-
try {
|
|
145
|
-
portalChild = await spawnPortalDevServer({ portalPackage, port: portalPort, verbose });
|
|
146
|
-
const stop = () => {
|
|
147
|
-
try {
|
|
148
|
-
portalChild?.kill("SIGINT");
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
// ignore
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
process.once("SIGINT", stop);
|
|
155
|
-
process.once("SIGTERM", stop);
|
|
156
|
-
process.once("exit", stop);
|
|
157
|
-
if (verbose) {
|
|
158
|
-
process.stderr.write(`Spawned portal server (${portalPackage}) at ${uiDevUrl}\n`);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
catch (err) {
|
|
162
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
163
|
-
throw new Error(`Failed to start portal dev server: ${message}`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
if (options.watch) {
|
|
167
|
-
const cfg = await getConfig();
|
|
168
|
-
const serviceSpecs = Array.isArray(cfg.services) ? cfg.services.map((s) => String(s.spec ?? "")) : [];
|
|
169
|
-
const watchTargets = [
|
|
170
|
-
...(configPath ? [configPath] : []),
|
|
171
|
-
...serviceSpecs.filter(Boolean).map((p) => (isAbsolute(p) ? p : resolve(process.cwd(), p))),
|
|
172
|
-
];
|
|
173
|
-
let timer;
|
|
174
|
-
const scheduleRefresh = () => {
|
|
175
|
-
if (timer)
|
|
176
|
-
clearTimeout(timer);
|
|
177
|
-
timer = setTimeout(() => {
|
|
178
|
-
void refreshSnapshot();
|
|
179
|
-
}, 200);
|
|
180
|
-
};
|
|
181
|
-
for (const target of watchTargets) {
|
|
182
|
-
try {
|
|
183
|
-
watch(target, { persistent: true }, () => scheduleRefresh());
|
|
184
|
-
if (verbose) {
|
|
185
|
-
process.stderr.write(`Watching ${target}\n`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
catch (err) {
|
|
189
|
-
if (verbose) {
|
|
190
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
191
|
-
process.stderr.write(`Failed to watch ${target}: ${message}\n`);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
await startDevServer({
|
|
197
|
-
host,
|
|
198
|
-
port,
|
|
199
|
-
getConfig,
|
|
200
|
-
getAggregated,
|
|
201
|
-
verbose,
|
|
202
|
-
ui: options.ui,
|
|
203
|
-
uiDevUrl,
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
//# sourceMappingURL=dev.js.map
|
package/dist/commands/dev.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/start.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0EzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoF3D"}
|
package/dist/commands/start.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import { readFile } from "node:fs/promises";
|
|
4
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
5
|
-
import { loadConfig, findConfigPath } from "../config/loadConfig.js";
|
|
6
|
-
import { startDevServer } from "../dev/server.js";
|
|
7
|
-
function resolveConfigSpecPaths(config, baseDir) {
|
|
8
|
-
if (!baseDir)
|
|
9
|
-
return config;
|
|
10
|
-
const services = Array.isArray(config.services) ? config.services : [];
|
|
11
|
-
return {
|
|
12
|
-
...config,
|
|
13
|
-
services: services.map((s) => {
|
|
14
|
-
const spec = String(s?.spec ?? "");
|
|
15
|
-
const resolvedSpec = spec && !isAbsolute(spec) ? resolve(baseDir, spec) : spec;
|
|
16
|
-
return {
|
|
17
|
-
...s,
|
|
18
|
-
spec: resolvedSpec,
|
|
19
|
-
};
|
|
20
|
-
}),
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
async function resolvePortalBin(portalPackage, kind) {
|
|
24
|
-
const require = createRequire(import.meta.url);
|
|
25
|
-
const pkgJsonPath = require.resolve(`${portalPackage}/package.json`);
|
|
26
|
-
const pkgDir = dirname(pkgJsonPath);
|
|
27
|
-
const pkgRaw = await readFile(pkgJsonPath, "utf8");
|
|
28
|
-
const pkg = JSON.parse(pkgRaw);
|
|
29
|
-
if (!pkg.bin)
|
|
30
|
-
return null;
|
|
31
|
-
if (typeof pkg.bin === "string") {
|
|
32
|
-
return join(pkgDir, pkg.bin);
|
|
33
|
-
}
|
|
34
|
-
const entries = Object.entries(pkg.bin);
|
|
35
|
-
if (entries.length === 0)
|
|
36
|
-
return null;
|
|
37
|
-
const preferred = entries.find(([name]) => name.includes(kind)) ?? entries[0];
|
|
38
|
-
return join(pkgDir, preferred[1]);
|
|
39
|
-
}
|
|
40
|
-
async function spawnPortalServer(options) {
|
|
41
|
-
const binPath = await resolvePortalBin(options.portalPackage, options.mode);
|
|
42
|
-
if (!binPath) {
|
|
43
|
-
throw new Error(`Portal package '${options.portalPackage}' does not expose a runnable bin. Expected a package.json "bin" entry.`);
|
|
44
|
-
}
|
|
45
|
-
const args = [binPath, "--port", String(options.port), "--mode", options.mode];
|
|
46
|
-
const child = spawn(process.execPath, args, {
|
|
47
|
-
stdio: options.verbose ? "inherit" : "ignore",
|
|
48
|
-
env: { ...process.env, PORT: String(options.port) },
|
|
49
|
-
});
|
|
50
|
-
child.once("exit", (code) => {
|
|
51
|
-
if (options.verbose) {
|
|
52
|
-
process.stderr.write(`Portal server exited with code ${code ?? "null"}\n`);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
return child;
|
|
56
|
-
}
|
|
57
|
-
export function registerStartCommand(program) {
|
|
58
|
-
program
|
|
59
|
-
.command("start")
|
|
60
|
-
.description("Start a local server (UI + /unispec.json)")
|
|
61
|
-
.option("--config <path>", "Path to unispec config file")
|
|
62
|
-
.option("--host <host>", "Host to bind", "127.0.0.1")
|
|
63
|
-
.option("--port <port>", "Port to bind", "4141")
|
|
64
|
-
.option("--ui", "Serve embedded UI at /", true)
|
|
65
|
-
.option("--no-ui", "Disable embedded UI")
|
|
66
|
-
.option("--ui-url <url>", "Proxy UI requests to an external UI server")
|
|
67
|
-
.option("--portal", "Spawn portal server (SSR) from an installed dependency and proxy UI to it")
|
|
68
|
-
.option("--portal-port <port>", "Port for portal server", "3000")
|
|
69
|
-
.option("--portal-package <name>", "Portal package name", "@unispechq/unispec-portal")
|
|
70
|
-
.action(async function (options) {
|
|
71
|
-
const parentOpts = this.parent?.opts?.();
|
|
72
|
-
const verbose = parentOpts?.verbose ?? false;
|
|
73
|
-
const host = String(options.host ?? "127.0.0.1");
|
|
74
|
-
const port = Number(options.port ?? 4141);
|
|
75
|
-
const configPath = await findConfigPath({ explicitPath: options.config });
|
|
76
|
-
const configDir = configPath ? dirname(configPath) : undefined;
|
|
77
|
-
const getConfig = async () => {
|
|
78
|
-
const config = await loadConfig({ explicitPath: options.config });
|
|
79
|
-
return resolveConfigSpecPaths(config ?? { version: 1, services: [] }, configDir);
|
|
80
|
-
};
|
|
81
|
-
let portalChild;
|
|
82
|
-
let uiDevUrl = options.uiUrl;
|
|
83
|
-
if (options.portal) {
|
|
84
|
-
if (uiDevUrl) {
|
|
85
|
-
throw new Error("--portal cannot be used together with --ui-url");
|
|
86
|
-
}
|
|
87
|
-
const portalPort = Number(options.portalPort ?? 3000);
|
|
88
|
-
const portalPackage = String(options.portalPackage ?? "@unispechq/unispec-portal");
|
|
89
|
-
uiDevUrl = `http://127.0.0.1:${portalPort}`;
|
|
90
|
-
portalChild = await spawnPortalServer({
|
|
91
|
-
portalPackage,
|
|
92
|
-
port: portalPort,
|
|
93
|
-
mode: "start",
|
|
94
|
-
verbose,
|
|
95
|
-
});
|
|
96
|
-
const stop = () => {
|
|
97
|
-
try {
|
|
98
|
-
portalChild?.kill("SIGINT");
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
// ignore
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
process.once("SIGINT", stop);
|
|
105
|
-
process.once("SIGTERM", stop);
|
|
106
|
-
process.once("exit", stop);
|
|
107
|
-
if (verbose) {
|
|
108
|
-
process.stderr.write(`Spawned portal server (${portalPackage}) at ${uiDevUrl}\n`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
await startDevServer({
|
|
112
|
-
host,
|
|
113
|
-
port,
|
|
114
|
-
getConfig,
|
|
115
|
-
verbose,
|
|
116
|
-
ui: options.ui,
|
|
117
|
-
uiDevUrl: uiDevUrl,
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
//# sourceMappingURL=start.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
package/dist/dev/aggregate.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { UniSpecPlatformConfig } from "../config/loadConfig.js";
|
|
2
|
-
export interface AggregatedService {
|
|
3
|
-
name: string;
|
|
4
|
-
specPath: string;
|
|
5
|
-
valid: boolean;
|
|
6
|
-
errors?: unknown;
|
|
7
|
-
spec?: unknown;
|
|
8
|
-
}
|
|
9
|
-
export interface AggregateResult {
|
|
10
|
-
version: number;
|
|
11
|
-
generatedAt: string;
|
|
12
|
-
services: AggregatedService[];
|
|
13
|
-
}
|
|
14
|
-
export declare function aggregateFromConfig(config: UniSpecPlatformConfig): Promise<AggregateResult>;
|
|
15
|
-
//# sourceMappingURL=aggregate.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../src/dev/aggregate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGrE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CA0DjG"}
|
package/dist/dev/aggregate.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { loadUniSpec, normalizeUniSpec, validateUniSpec } from "@unispechq/unispec-core";
|
|
2
|
-
import { readSpecFile } from "../io/readSpecFile.js";
|
|
3
|
-
export async function aggregateFromConfig(config) {
|
|
4
|
-
const version = typeof config.version === "number" ? config.version : 1;
|
|
5
|
-
const services = Array.isArray(config.services) ? config.services : [];
|
|
6
|
-
const results = [];
|
|
7
|
-
for (const service of services) {
|
|
8
|
-
const name = String(service?.name ?? "");
|
|
9
|
-
const specPath = String(service?.spec ?? "");
|
|
10
|
-
if (!name || !specPath) {
|
|
11
|
-
results.push({
|
|
12
|
-
name: name || "unknown",
|
|
13
|
-
specPath,
|
|
14
|
-
valid: false,
|
|
15
|
-
errors: [{ message: "Invalid config entry: service.name and service.spec are required" }],
|
|
16
|
-
});
|
|
17
|
-
continue;
|
|
18
|
-
}
|
|
19
|
-
try {
|
|
20
|
-
const raw = await readSpecFile(specPath);
|
|
21
|
-
const doc = await loadUniSpec(raw);
|
|
22
|
-
const validation = await validateUniSpec(doc);
|
|
23
|
-
if (!validation.valid) {
|
|
24
|
-
results.push({
|
|
25
|
-
name,
|
|
26
|
-
specPath,
|
|
27
|
-
valid: false,
|
|
28
|
-
errors: validation.errors,
|
|
29
|
-
});
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
const normalized = normalizeUniSpec(doc);
|
|
33
|
-
results.push({
|
|
34
|
-
name,
|
|
35
|
-
specPath,
|
|
36
|
-
valid: true,
|
|
37
|
-
spec: normalized,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
catch (err) {
|
|
41
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
42
|
-
results.push({
|
|
43
|
-
name,
|
|
44
|
-
specPath,
|
|
45
|
-
valid: false,
|
|
46
|
-
errors: [{ message }],
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return {
|
|
51
|
-
version,
|
|
52
|
-
generatedAt: new Date().toISOString(),
|
|
53
|
-
services: results,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
//# sourceMappingURL=aggregate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../src/dev/aggregate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAgBrD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAA6B;IACrE,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAEvE,MAAM,OAAO,GAAwB,EAAE,CAAC;IAExC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QAE7C,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,IAAI,IAAI,SAAS;gBACvB,QAAQ;gBACR,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,kEAAkE,EAAE,CAAC;aAC1F,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;YACnC,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;YAE9C,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI;oBACJ,QAAQ;oBACR,KAAK,EAAE,KAAK;oBACZ,MAAM,EAAE,UAAU,CAAC,MAAM;iBAC1B,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI;gBACJ,QAAQ;gBACR,KAAK,EAAE,IAAI;gBACX,IAAI,EAAE,UAAU;aACjB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI;gBACJ,QAAQ;gBACR,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,QAAQ,EAAE,OAAO;KAClB,CAAC;AACJ,CAAC"}
|
package/dist/dev/index.d.ts
DELETED
package/dist/dev/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
|
package/dist/dev/index.js
DELETED
package/dist/dev/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
|
package/dist/dev/server.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
import type { AggregateResult } from "./aggregate.js";
|
|
3
|
-
import type { UniSpecPlatformConfig } from "../config/loadConfig.js";
|
|
4
|
-
export interface DevServerOptions {
|
|
5
|
-
host: string;
|
|
6
|
-
port: number;
|
|
7
|
-
getConfig: () => Promise<UniSpecPlatformConfig>;
|
|
8
|
-
getAggregated?: () => Promise<AggregateResult>;
|
|
9
|
-
verbose?: boolean;
|
|
10
|
-
ui?: boolean;
|
|
11
|
-
uiDevUrl?: string;
|
|
12
|
-
}
|
|
13
|
-
export declare function startDevServer(options: DevServerOptions): Promise<http.Server>;
|
|
14
|
-
//# sourceMappingURL=server.d.ts.map
|
package/dist/dev/server.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dev/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGrE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAgID,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAoEpF"}
|
package/dist/dev/server.js
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
import net from "node:net";
|
|
3
|
-
import { aggregateFromConfig } from "./aggregate.js";
|
|
4
|
-
import { getEmbeddedIndexHtml, getEmbeddedUiJs } from "./ui.js";
|
|
5
|
-
function writeJson(res, status, body) {
|
|
6
|
-
const json = JSON.stringify(body, null, 2);
|
|
7
|
-
res.statusCode = status;
|
|
8
|
-
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
9
|
-
res.end(`${json}\n`);
|
|
10
|
-
}
|
|
11
|
-
function writeHtml(res, status, html) {
|
|
12
|
-
res.statusCode = status;
|
|
13
|
-
res.setHeader("content-type", "text/html; charset=utf-8");
|
|
14
|
-
res.end(html);
|
|
15
|
-
}
|
|
16
|
-
function writeJs(res, status, js) {
|
|
17
|
-
res.statusCode = status;
|
|
18
|
-
res.setHeader("content-type", "application/javascript; charset=utf-8");
|
|
19
|
-
res.end(js);
|
|
20
|
-
}
|
|
21
|
-
function shouldProxyUi(options) {
|
|
22
|
-
return Boolean(options.uiDevUrl);
|
|
23
|
-
}
|
|
24
|
-
function getForwardedPort(hostHeader) {
|
|
25
|
-
if (!hostHeader)
|
|
26
|
-
return undefined;
|
|
27
|
-
const idx = hostHeader.lastIndexOf(":");
|
|
28
|
-
if (idx === -1)
|
|
29
|
-
return undefined;
|
|
30
|
-
const port = hostHeader.slice(idx + 1);
|
|
31
|
-
return port ? port : undefined;
|
|
32
|
-
}
|
|
33
|
-
function buildProxyHeaders(target, req) {
|
|
34
|
-
const headers = { ...req.headers };
|
|
35
|
-
const originalHost = req.headers.host;
|
|
36
|
-
const forwardedFor = req.socket.remoteAddress;
|
|
37
|
-
const forwardedPort = getForwardedPort(originalHost);
|
|
38
|
-
delete headers.host;
|
|
39
|
-
headers["x-forwarded-host"] = originalHost;
|
|
40
|
-
headers["x-forwarded-proto"] = "http";
|
|
41
|
-
if (forwardedPort) {
|
|
42
|
-
headers["x-forwarded-port"] = forwardedPort;
|
|
43
|
-
}
|
|
44
|
-
if (forwardedFor) {
|
|
45
|
-
headers["x-forwarded-for"] = forwardedFor;
|
|
46
|
-
}
|
|
47
|
-
headers.host = target.host;
|
|
48
|
-
return headers;
|
|
49
|
-
}
|
|
50
|
-
function proxyHttpRequest(target, req, res) {
|
|
51
|
-
const headers = buildProxyHeaders(target, req);
|
|
52
|
-
const proxyReq = http.request({
|
|
53
|
-
protocol: target.protocol,
|
|
54
|
-
hostname: target.hostname,
|
|
55
|
-
port: target.port || (target.protocol === "https:" ? 443 : 80),
|
|
56
|
-
method: req.method,
|
|
57
|
-
path: req.url,
|
|
58
|
-
headers,
|
|
59
|
-
}, (proxyRes) => {
|
|
60
|
-
res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
|
|
61
|
-
proxyRes.pipe(res);
|
|
62
|
-
});
|
|
63
|
-
proxyReq.on("error", (err) => {
|
|
64
|
-
res.statusCode = 502;
|
|
65
|
-
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
66
|
-
res.end(JSON.stringify({ error: { message: `UI proxy error: ${err.message}` } }, null, 2) + "\n");
|
|
67
|
-
});
|
|
68
|
-
req.pipe(proxyReq);
|
|
69
|
-
}
|
|
70
|
-
function proxyWebSocketUpgrade(target, req, socket, head) {
|
|
71
|
-
const port = Number(target.port || (target.protocol === "https:" ? 443 : 80));
|
|
72
|
-
const upstream = net.connect(port, target.hostname, () => {
|
|
73
|
-
const lines = [];
|
|
74
|
-
const path = req.url ?? "/";
|
|
75
|
-
lines.push(`${req.method ?? "GET"} ${path} HTTP/1.1`);
|
|
76
|
-
const originalHost = req.headers.host;
|
|
77
|
-
const forwardedFor = req.socket.remoteAddress;
|
|
78
|
-
const forwardedPort = getForwardedPort(originalHost);
|
|
79
|
-
const targetHost = target.host || `${target.hostname}:${port}`;
|
|
80
|
-
const headers = { ...req.headers };
|
|
81
|
-
headers.host = targetHost;
|
|
82
|
-
headers["x-forwarded-host"] = originalHost;
|
|
83
|
-
headers["x-forwarded-proto"] = "http";
|
|
84
|
-
if (forwardedPort)
|
|
85
|
-
headers["x-forwarded-port"] = forwardedPort;
|
|
86
|
-
if (forwardedFor)
|
|
87
|
-
headers["x-forwarded-for"] = forwardedFor;
|
|
88
|
-
for (const [k, v] of Object.entries(headers)) {
|
|
89
|
-
if (v === undefined)
|
|
90
|
-
continue;
|
|
91
|
-
if (Array.isArray(v)) {
|
|
92
|
-
for (const vv of v)
|
|
93
|
-
lines.push(`${k}: ${vv}`);
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
lines.push(`${k}: ${v}`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
lines.push("\r\n");
|
|
100
|
-
upstream.write(lines.join("\r\n"));
|
|
101
|
-
if (head && head.length) {
|
|
102
|
-
upstream.write(head);
|
|
103
|
-
}
|
|
104
|
-
socket.pipe(upstream);
|
|
105
|
-
upstream.pipe(socket);
|
|
106
|
-
});
|
|
107
|
-
upstream.on("error", () => {
|
|
108
|
-
try {
|
|
109
|
-
socket.end();
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
// ignore
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
export async function startDevServer(options) {
|
|
117
|
-
const uiEnabled = options.ui ?? true;
|
|
118
|
-
const uiDevUrl = options.uiDevUrl ? new URL(options.uiDevUrl) : undefined;
|
|
119
|
-
const server = http.createServer(async (req, res) => {
|
|
120
|
-
const method = req.method ?? "GET";
|
|
121
|
-
const url = req.url ?? "/";
|
|
122
|
-
if (method === "GET" && url === "/health") {
|
|
123
|
-
res.statusCode = 200;
|
|
124
|
-
res.setHeader("content-type", "text/plain; charset=utf-8");
|
|
125
|
-
res.end("OK\n");
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
if (method === "GET" && url === "/unispec.json") {
|
|
129
|
-
try {
|
|
130
|
-
const aggregated = options.getAggregated
|
|
131
|
-
? await options.getAggregated()
|
|
132
|
-
: await aggregateFromConfig(await options.getConfig());
|
|
133
|
-
const hasErrors = aggregated.services.some((s) => !s.valid);
|
|
134
|
-
writeJson(res, hasErrors ? 422 : 200, aggregated);
|
|
135
|
-
}
|
|
136
|
-
catch (err) {
|
|
137
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
138
|
-
writeJson(res, 500, { error: { message } });
|
|
139
|
-
}
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
if (uiEnabled) {
|
|
143
|
-
if (uiDevUrl && shouldProxyUi(options)) {
|
|
144
|
-
proxyHttpRequest(uiDevUrl, req, res);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
if (method === "GET" && (url === "/" || url === "/index.html")) {
|
|
148
|
-
writeHtml(res, 200, getEmbeddedIndexHtml());
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (method === "GET" && url === "/ui.js") {
|
|
152
|
-
writeJs(res, 200, getEmbeddedUiJs());
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
writeJson(res, 404, { error: { message: "Not found" } });
|
|
157
|
-
});
|
|
158
|
-
server.on("upgrade", (req, socket, head) => {
|
|
159
|
-
const uiDev = uiDevUrl;
|
|
160
|
-
if (!uiDev || !uiEnabled) {
|
|
161
|
-
socket.destroy();
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
proxyWebSocketUpgrade(uiDev, req, socket, head);
|
|
165
|
-
});
|
|
166
|
-
await new Promise((resolve, reject) => {
|
|
167
|
-
server.once("error", reject);
|
|
168
|
-
server.listen(options.port, options.host, () => resolve());
|
|
169
|
-
});
|
|
170
|
-
if (options.verbose) {
|
|
171
|
-
process.stderr.write(`Dev server listening on http://${options.host}:${options.port}\n`);
|
|
172
|
-
}
|
|
173
|
-
return server;
|
|
174
|
-
}
|
|
175
|
-
//# sourceMappingURL=server.js.map
|
package/dist/dev/server.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/dev/server.ts"],"names":[],"mappings":"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"}
|
package/dist/dev/ui.d.ts
DELETED
package/dist/dev/ui.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/dev/ui.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,IAAI,MAAM,CAqC7C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAqDxC"}
|
package/dist/dev/ui.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
export function getEmbeddedIndexHtml() {
|
|
2
|
-
return `<!doctype html>
|
|
3
|
-
<html lang="en">
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="utf-8" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
<title>UniSpec Dev</title>
|
|
8
|
-
<style>
|
|
9
|
-
:root { color-scheme: light dark; }
|
|
10
|
-
body { font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; margin: 0; }
|
|
11
|
-
header { padding: 16px 20px; border-bottom: 1px solid rgba(127,127,127,0.25); }
|
|
12
|
-
main { padding: 16px 20px; }
|
|
13
|
-
.muted { opacity: 0.75; font-size: 12px; }
|
|
14
|
-
.card { border: 1px solid rgba(127,127,127,0.25); border-radius: 10px; padding: 12px; margin: 12px 0; }
|
|
15
|
-
.ok { color: #1f8a4c; }
|
|
16
|
-
.bad { color: #b42318; }
|
|
17
|
-
pre { overflow: auto; max-height: calc(100vh - 380px); }
|
|
18
|
-
button { cursor: pointer; padding: 8px 12px; border-radius: 8px; border: 1px solid rgba(127,127,127,0.35); background: transparent; }
|
|
19
|
-
</style>
|
|
20
|
-
</head>
|
|
21
|
-
<body>
|
|
22
|
-
<header>
|
|
23
|
-
<div><strong>UniSpec Dev</strong></div>
|
|
24
|
-
<div class="muted">Data source: <code>/unispec.json</code></div>
|
|
25
|
-
</header>
|
|
26
|
-
<main>
|
|
27
|
-
<button id="refresh">Refresh</button>
|
|
28
|
-
<div id="status" class="muted" style="margin-top: 8px;"></div>
|
|
29
|
-
<div id="root"></div>
|
|
30
|
-
<details style="margin-top: 16px;">
|
|
31
|
-
<summary>Raw <code>/unispec.json</code></summary>
|
|
32
|
-
<pre id="raw"></pre>
|
|
33
|
-
</details>
|
|
34
|
-
</main>
|
|
35
|
-
<script type="module" src="/ui.js"></script>
|
|
36
|
-
</body>
|
|
37
|
-
</html>`;
|
|
38
|
-
}
|
|
39
|
-
export function getEmbeddedUiJs() {
|
|
40
|
-
return `async function load() {
|
|
41
|
-
const status = document.getElementById('status');
|
|
42
|
-
const root = document.getElementById('root');
|
|
43
|
-
const raw = document.getElementById('raw');
|
|
44
|
-
|
|
45
|
-
status.textContent = 'Loading /unispec.json ...';
|
|
46
|
-
root.innerHTML = '';
|
|
47
|
-
raw.textContent = '';
|
|
48
|
-
|
|
49
|
-
const res = await fetch('/unispec.json', { cache: 'no-store' });
|
|
50
|
-
const text = await res.text();
|
|
51
|
-
let json;
|
|
52
|
-
try { json = JSON.parse(text); } catch { json = undefined; }
|
|
53
|
-
|
|
54
|
-
status.textContent = 'HTTP ' + res.status + ' • ' + new Date().toLocaleTimeString();
|
|
55
|
-
raw.textContent = text;
|
|
56
|
-
|
|
57
|
-
if (!json || !Array.isArray(json.services)) {
|
|
58
|
-
const div = document.createElement('div');
|
|
59
|
-
div.className = 'card';
|
|
60
|
-
div.innerHTML = '<div class="bad"><strong>Invalid response</strong></div>';
|
|
61
|
-
root.appendChild(div);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
for (const svc of json.services) {
|
|
66
|
-
const div = document.createElement('div');
|
|
67
|
-
div.className = 'card';
|
|
68
|
-
const ok = svc && svc.valid === true;
|
|
69
|
-
const title = (svc && svc.name) ? String(svc.name) : '(unnamed)';
|
|
70
|
-
const path = (svc && svc.specPath) ? String(svc.specPath) : '';
|
|
71
|
-
div.innerHTML =
|
|
72
|
-
'<div><strong>' + title + '</strong> ' +
|
|
73
|
-
'<span class="' + (ok ? 'ok' : 'bad') + '">' + (ok ? 'valid' : 'invalid') + '</span></div>' +
|
|
74
|
-
(path ? '<div class="muted">' + path + '</div>' : '');
|
|
75
|
-
|
|
76
|
-
if (!ok && svc && Array.isArray(svc.errors) && svc.errors.length) {
|
|
77
|
-
const pre = document.createElement('pre');
|
|
78
|
-
pre.textContent = JSON.stringify(svc.errors, null, 2);
|
|
79
|
-
div.appendChild(pre);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
root.appendChild(div);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
document.getElementById('refresh')?.addEventListener('click', () => {
|
|
87
|
-
void load();
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
void load();
|
|
91
|
-
`;
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=ui.js.map
|
package/dist/dev/ui.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/dev/ui.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAmCD,CAAC;AACT,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDR,CAAC;AACF,CAAC"}
|