@wairon/cli 5.0.2-dev.10 → 5.0.2-dev.12
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/dist/cli/index.js +175 -42
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +51 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var init_defaults = __esm({
|
|
|
65
65
|
copilot: ".github/prompts",
|
|
66
66
|
codex: ".codex/agents"
|
|
67
67
|
};
|
|
68
|
-
WAIRON_VERSION = "5.0.2-dev.
|
|
68
|
+
WAIRON_VERSION = "5.0.2-dev.12";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
ARCHITECT_AGENT_ID = "agent-architect";
|
|
71
71
|
ARCHITECT_TEMPLATE_ID = "architect";
|
|
@@ -6859,6 +6859,16 @@ var init_type_references = __esm({
|
|
|
6859
6859
|
}
|
|
6860
6860
|
});
|
|
6861
6861
|
|
|
6862
|
+
// src/utils/filenames.ts
|
|
6863
|
+
function safeFilenamePart(value) {
|
|
6864
|
+
return value.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
6865
|
+
}
|
|
6866
|
+
var init_filenames = __esm({
|
|
6867
|
+
"src/utils/filenames.ts"() {
|
|
6868
|
+
"use strict";
|
|
6869
|
+
}
|
|
6870
|
+
});
|
|
6871
|
+
|
|
6862
6872
|
// src/core/statehash.ts
|
|
6863
6873
|
function computeStateId() {
|
|
6864
6874
|
const tree = {
|
|
@@ -7379,29 +7389,53 @@ function saveSnapshot(snapshot, rootDir = getProjectRoot()) {
|
|
|
7379
7389
|
function loadSurfaceSnapshots() {
|
|
7380
7390
|
return listSnapshots();
|
|
7381
7391
|
}
|
|
7382
|
-
function
|
|
7383
|
-
const
|
|
7384
|
-
|
|
7392
|
+
function selectPortalSpec(renderedSet, portalId) {
|
|
7393
|
+
const hit = renderedSet.find((spec) => spec.portalId === portalId);
|
|
7394
|
+
if (!hit) {
|
|
7395
|
+
const known = renderedSet.map((s) => s.portalId).join(", ");
|
|
7396
|
+
throw new Error(`Unknown portal "${portalId}" \u2014 this surface renders: ${known || "(no portals)"}.`);
|
|
7397
|
+
}
|
|
7398
|
+
return [hit];
|
|
7385
7399
|
}
|
|
7386
|
-
function
|
|
7400
|
+
function perPortalPath(resolvedOut, portalId) {
|
|
7401
|
+
const ext = path10.extname(resolvedOut);
|
|
7402
|
+
const stem2 = ext ? resolvedOut.slice(0, -ext.length) : resolvedOut;
|
|
7403
|
+
return `${stem2}.${safeFilenamePart(portalId)}${ext}`;
|
|
7404
|
+
}
|
|
7405
|
+
function writeSurfaceFile(outPath, snapshot, renderedSet) {
|
|
7387
7406
|
const resolved = path10.resolve(outPath);
|
|
7388
7407
|
fs9.mkdirSync(path10.dirname(resolved), { recursive: true });
|
|
7389
|
-
if (
|
|
7390
|
-
|
|
7391
|
-
|
|
7408
|
+
if (!renderedSet || renderedSet.length === 0) {
|
|
7409
|
+
writeYamlFile(resolved, snapshot);
|
|
7410
|
+
return [resolved];
|
|
7411
|
+
}
|
|
7412
|
+
if (renderedSet.length === 1) {
|
|
7413
|
+
fs9.writeFileSync(resolved, renderedSet[0].document);
|
|
7414
|
+
return [resolved];
|
|
7415
|
+
}
|
|
7416
|
+
return renderedSet.map((spec) => {
|
|
7417
|
+
const target = perPortalPath(resolved, spec.portalId);
|
|
7418
|
+
fs9.writeFileSync(target, spec.document);
|
|
7419
|
+
return target;
|
|
7420
|
+
});
|
|
7392
7421
|
}
|
|
7393
|
-
function
|
|
7394
|
-
const
|
|
7395
|
-
const openapi = format === "openapi" ? renderOpenApiForms(snapshot) : void 0;
|
|
7396
|
-
const body = openapi?.rendered ?? openapi?.renderedSet[0]?.document;
|
|
7397
|
-
const writtenTo = outPath ? writeSurfaceFile(outPath, body, snapshot) : void 0;
|
|
7422
|
+
function exportResult(snapshot, renderedSet, writtenPaths) {
|
|
7423
|
+
const rendered = renderedSet?.length === 1 ? renderedSet[0].document : void 0;
|
|
7398
7424
|
return {
|
|
7399
7425
|
snapshot,
|
|
7400
|
-
...
|
|
7401
|
-
...
|
|
7402
|
-
...
|
|
7426
|
+
...rendered !== void 0 ? { rendered } : {},
|
|
7427
|
+
...renderedSet ? { renderedSet } : {},
|
|
7428
|
+
...writtenPaths.length === 1 ? { writtenTo: writtenPaths[0] } : {},
|
|
7429
|
+
...writtenPaths.length ? { writtenPaths } : {}
|
|
7403
7430
|
};
|
|
7404
7431
|
}
|
|
7432
|
+
function exportSurface(maxAudience, format, outPath, portalId) {
|
|
7433
|
+
const snapshot = projectOwnSurface(maxAudience);
|
|
7434
|
+
let renderedSet = format === "openapi" ? toOpenApiSet(snapshot) : void 0;
|
|
7435
|
+
if (renderedSet && portalId) renderedSet = selectPortalSpec(renderedSet, portalId);
|
|
7436
|
+
const writtenPaths = outPath ? writeSurfaceFile(outPath, snapshot, renderedSet) : [];
|
|
7437
|
+
return exportResult(snapshot, renderedSet, writtenPaths);
|
|
7438
|
+
}
|
|
7405
7439
|
function importSurface(sourcePath, origin) {
|
|
7406
7440
|
const resolved = path10.resolve(sourcePath);
|
|
7407
7441
|
if (!fs9.existsSync(resolved)) {
|
|
@@ -7466,6 +7500,7 @@ var init_surfaces = __esm({
|
|
|
7466
7500
|
path10 = __toESM(require("path"));
|
|
7467
7501
|
init_fs();
|
|
7468
7502
|
init_yaml();
|
|
7503
|
+
init_filenames();
|
|
7469
7504
|
init_models();
|
|
7470
7505
|
init_specs2();
|
|
7471
7506
|
init_statehash();
|
|
@@ -29176,6 +29211,17 @@ function audienceDistance(resolution, targetProjectId) {
|
|
|
29176
29211
|
|
|
29177
29212
|
// src/server/landscape.ts
|
|
29178
29213
|
var yamlLib = __toESM(require("js-yaml"));
|
|
29214
|
+
init_filenames();
|
|
29215
|
+
|
|
29216
|
+
// src/server/openapiindex.ts
|
|
29217
|
+
function buildOpenApiSpecIndex(specs) {
|
|
29218
|
+
return { openapiIndex: true, specs: specs.map((s) => ({ portalId: s.portalId, name: s.name })) };
|
|
29219
|
+
}
|
|
29220
|
+
function openApiIndexDocument(specs) {
|
|
29221
|
+
return JSON.stringify(buildOpenApiSpecIndex(specs), null, 2);
|
|
29222
|
+
}
|
|
29223
|
+
|
|
29224
|
+
// src/server/landscape.ts
|
|
29179
29225
|
var PROJECT_ADMIN_CAPABILITY3 = "project:admin";
|
|
29180
29226
|
var PROJECT_READ_CAPABILITY3 = "project:read";
|
|
29181
29227
|
var PROJECT_WRITE_CAPABILITY3 = "project:write";
|
|
@@ -29662,7 +29708,7 @@ function getProjectSurfaceForMcp(cfg, credential, currentProjectId, targetProjec
|
|
|
29662
29708
|
const result = runWithProjectRoot(record2.rootPath, () => hostSurfaces.exportBoundSurface(maxAudience, "native"));
|
|
29663
29709
|
return { ...result.snapshot, origin: "exchanged" };
|
|
29664
29710
|
}
|
|
29665
|
-
function exportProjectSurface(cfg, credential, projectId, format, maxAudience) {
|
|
29711
|
+
function exportProjectSurface(cfg, credential, projectId, format, maxAudience, portalId) {
|
|
29666
29712
|
const principal = requirePrincipal6(cfg, credential);
|
|
29667
29713
|
if (!permitsCap(cfg, principal, PROJECT_ADMIN_CAPABILITY3, "project", projectId)) {
|
|
29668
29714
|
throw new ForbiddenError(
|
|
@@ -29676,16 +29722,37 @@ function exportProjectSurface(cfg, credential, projectId, format, maxAudience) {
|
|
|
29676
29722
|
if (!root) throw new Error(`Unknown project "${projectId}".`);
|
|
29677
29723
|
const result = runWithProjectRoot(root, () => hostSurfaces.exportBoundSurface(maxAudience, format));
|
|
29678
29724
|
if (format === "openapi") {
|
|
29725
|
+
const specs = result.renderedSet ?? [];
|
|
29726
|
+
if (portalId) {
|
|
29727
|
+
const hit = specs.find((s) => s.portalId === portalId);
|
|
29728
|
+
if (!hit) {
|
|
29729
|
+
throw new Error(
|
|
29730
|
+
`Unknown portal "${portalId}" in project "${projectId}" (published: ${specs.map((s) => s.portalId).join(", ") || "none"}).`
|
|
29731
|
+
);
|
|
29732
|
+
}
|
|
29733
|
+
return {
|
|
29734
|
+
body: hit.document,
|
|
29735
|
+
contentType: "application/json",
|
|
29736
|
+
filename: `${safeFilenamePart(projectId)}-${safeFilenamePart(portalId)}-surface.openapi.json`
|
|
29737
|
+
};
|
|
29738
|
+
}
|
|
29739
|
+
if (specs.length === 1) {
|
|
29740
|
+
return {
|
|
29741
|
+
body: specs[0].document,
|
|
29742
|
+
contentType: "application/json",
|
|
29743
|
+
filename: `${safeFilenamePart(projectId)}-surface.openapi.json`
|
|
29744
|
+
};
|
|
29745
|
+
}
|
|
29679
29746
|
return {
|
|
29680
|
-
body:
|
|
29747
|
+
body: openApiIndexDocument(specs),
|
|
29681
29748
|
contentType: "application/json",
|
|
29682
|
-
filename: `${projectId}-surface.openapi.json`
|
|
29749
|
+
filename: `${safeFilenamePart(projectId)}-surface.openapi.index.json`
|
|
29683
29750
|
};
|
|
29684
29751
|
}
|
|
29685
29752
|
return {
|
|
29686
29753
|
body: yamlLib.dump(result.snapshot),
|
|
29687
29754
|
contentType: "application/yaml",
|
|
29688
|
-
filename: `${projectId}-surface.yaml`
|
|
29755
|
+
filename: `${safeFilenamePart(projectId)}-surface.yaml`
|
|
29689
29756
|
};
|
|
29690
29757
|
}
|
|
29691
29758
|
function removeRelation(cfg, credential, id) {
|
|
@@ -29729,7 +29796,8 @@ function handleLandscapeRequest(cfg, credential, req, res, body, url) {
|
|
|
29729
29796
|
credential,
|
|
29730
29797
|
parts[2],
|
|
29731
29798
|
url.searchParams.get("format") ?? "native",
|
|
29732
|
-
url.searchParams.get("audience") ?? "instance"
|
|
29799
|
+
url.searchParams.get("audience") ?? "instance",
|
|
29800
|
+
url.searchParams.get("spec") ?? void 0
|
|
29733
29801
|
);
|
|
29734
29802
|
res.writeHead(200, {
|
|
29735
29803
|
"content-type": artifact.contentType,
|
|
@@ -31804,6 +31872,19 @@ var ShareSnapshotRegistry = class {
|
|
|
31804
31872
|
return stored;
|
|
31805
31873
|
}
|
|
31806
31874
|
};
|
|
31875
|
+
function selectCapturedOpenApi(snap, portalId) {
|
|
31876
|
+
const specs = snap.openapiSet;
|
|
31877
|
+
if (!specs || specs.length === 0) {
|
|
31878
|
+
if (portalId) return null;
|
|
31879
|
+
return snap.openapi ?? null;
|
|
31880
|
+
}
|
|
31881
|
+
if (portalId) {
|
|
31882
|
+
const hit = specs.find((s) => s.portalId === portalId);
|
|
31883
|
+
return hit ? hit.document : null;
|
|
31884
|
+
}
|
|
31885
|
+
if (specs.length === 1) return specs[0].document;
|
|
31886
|
+
return openApiIndexDocument(specs);
|
|
31887
|
+
}
|
|
31807
31888
|
var ShareSnapshotIndex = class {
|
|
31808
31889
|
constructor(store) {
|
|
31809
31890
|
this.store = store;
|
|
@@ -31811,12 +31892,12 @@ var ShareSnapshotIndex = class {
|
|
|
31811
31892
|
get(snapshotId) {
|
|
31812
31893
|
return this.store.read(snapshotId);
|
|
31813
31894
|
}
|
|
31814
|
-
getArtifact(snapshotId, kind) {
|
|
31895
|
+
getArtifact(snapshotId, kind, portalId) {
|
|
31815
31896
|
const snap = this.store.read(snapshotId);
|
|
31816
31897
|
if (!snap) return null;
|
|
31817
31898
|
if (kind === "canvas") return snap.canvasModel ?? null;
|
|
31818
31899
|
if (kind === "html") return snap.html ?? null;
|
|
31819
|
-
if (kind === "openapi") return snap
|
|
31900
|
+
if (kind === "openapi") return selectCapturedOpenApi(snap, portalId);
|
|
31820
31901
|
return null;
|
|
31821
31902
|
}
|
|
31822
31903
|
};
|
|
@@ -31826,8 +31907,8 @@ function putSnapshot(dataDir, snapshot) {
|
|
|
31826
31907
|
function getSnapshot2(dataDir, snapshotId) {
|
|
31827
31908
|
return new ShareSnapshotIndex(new ShareSnapshotStore(dataDir)).get(snapshotId);
|
|
31828
31909
|
}
|
|
31829
|
-
function getSnapshotArtifact(dataDir, snapshotId, kind) {
|
|
31830
|
-
return new ShareSnapshotIndex(new ShareSnapshotStore(dataDir)).getArtifact(snapshotId, kind);
|
|
31910
|
+
function getSnapshotArtifact(dataDir, snapshotId, kind, portalId) {
|
|
31911
|
+
return new ShareSnapshotIndex(new ShareSnapshotStore(dataDir)).getArtifact(snapshotId, kind, portalId);
|
|
31831
31912
|
}
|
|
31832
31913
|
function captureSnapshot(dataDir, principal, projectId, view, artifacts) {
|
|
31833
31914
|
const root = resolveProjectRoot(dataDir, principal, projectId);
|
|
@@ -31846,7 +31927,11 @@ function captureSnapshot(dataDir, principal, projectId, view, artifacts) {
|
|
|
31846
31927
|
}
|
|
31847
31928
|
if (artifacts.includes("openapi")) {
|
|
31848
31929
|
const result = hostSurfaces.exportBoundSurface("project", "openapi");
|
|
31849
|
-
|
|
31930
|
+
const specs = result.renderedSet ?? [];
|
|
31931
|
+
if (specs.length) {
|
|
31932
|
+
snapshot.openapiSet = specs;
|
|
31933
|
+
if (specs.length === 1) snapshot.openapi = specs[0].document;
|
|
31934
|
+
}
|
|
31850
31935
|
}
|
|
31851
31936
|
return snapshot;
|
|
31852
31937
|
});
|
|
@@ -32407,10 +32492,10 @@ function getWebProjectOpenApi(cfg, sessionId, projectId, portalId) {
|
|
|
32407
32492
|
if (!root) throw new ForbiddenError("project not authorized or unknown");
|
|
32408
32493
|
const result = runWithProjectRoot(root, () => hostSurfaces.exportBoundSurface("project", "openapi"));
|
|
32409
32494
|
const specs = result.renderedSet ?? (result.rendered ? [{ portalId: "", name: projectId, document: result.rendered }] : []);
|
|
32410
|
-
if (specs.length === 0) return
|
|
32495
|
+
if (specs.length === 0) return openApiIndexPage(projectId, []);
|
|
32411
32496
|
if (portalId) {
|
|
32412
|
-
const sel = specs.find((s) => s.portalId === portalId)
|
|
32413
|
-
return swaggerUiPage(sel.document, sel.name);
|
|
32497
|
+
const sel = specs.find((s) => s.portalId === portalId);
|
|
32498
|
+
return sel ? swaggerUiPage(sel.document, sel.name) : openApiIndexPage(projectId, specs);
|
|
32414
32499
|
}
|
|
32415
32500
|
if (specs.length === 1) return swaggerUiPage(specs[0].document, specs[0].name);
|
|
32416
32501
|
return openApiIndexPage(projectId, specs);
|
|
@@ -32418,7 +32503,7 @@ function getWebProjectOpenApi(cfg, sessionId, projectId, portalId) {
|
|
|
32418
32503
|
function openApiIndexPage(projectId, specs) {
|
|
32419
32504
|
const esc2 = (s) => s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
32420
32505
|
const items = specs.map((s) => `<li><a href="/web/openapi?projectId=${encodeURIComponent(projectId)}&spec=${encodeURIComponent(s.portalId)}">${esc2(s.name)}</a> <code>${esc2(s.portalId)}</code></li>`).join("");
|
|
32421
|
-
return `<!doctype html><html><head><meta charset="utf-8"><title>${esc2(projectId)} \u2014 API specs</title><style>body{font-family:system-ui,sans-serif;max-width:680px;margin:48px auto;padding:0 20px;color:#e6e6e6;background:#161616}h1{font-size:20px}a{color:#6ea8fe;text-decoration:none}a:hover{text-decoration:underline}li{margin:10px 0}code{color:#8a94a6;font-size:12px;margin-left:8px}</style></head><body><h1>${esc2(projectId)} \u2014 API specs</h1
|
|
32506
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>${esc2(projectId)} \u2014 API specs</title><style>body{font-family:system-ui,sans-serif;max-width:680px;margin:48px auto;padding:0 20px;color:#e6e6e6;background:#161616}h1{font-size:20px}a{color:#6ea8fe;text-decoration:none}a:hover{text-decoration:underline}li{margin:10px 0}code{color:#8a94a6;font-size:12px;margin-left:8px}</style></head><body><h1>${esc2(projectId)} \u2014 API specs</h1>` + (specs.length ? `<p>This project exposes ${specs.length} separate public APIs, each with its own OpenAPI document and auth:</p><ul>${items}</ul>` : `<p>This project publishes no HTTP API \u2014 no public portal exposes one.</p>`) + `</body></html>`;
|
|
32422
32507
|
}
|
|
32423
32508
|
function reshapeLandscapeGraph(model, level) {
|
|
32424
32509
|
const unitNodeIds = new Set(model.nodes.filter((n) => n.nodeKind === "orgUnit").map((n) => n.id));
|
|
@@ -35544,7 +35629,7 @@ var CONTENT_TYPE = {
|
|
|
35544
35629
|
openapi: "application/json",
|
|
35545
35630
|
canvas: "application/json"
|
|
35546
35631
|
};
|
|
35547
|
-
function downloadArtifact(cfg, token, kind, meta) {
|
|
35632
|
+
function downloadArtifact(cfg, token, kind, meta, portalId) {
|
|
35548
35633
|
const link = linkByTokenHash(cfg.dataDir, hashToken(token));
|
|
35549
35634
|
const check = usable(link);
|
|
35550
35635
|
if ("outcome" in check) {
|
|
@@ -35556,7 +35641,7 @@ function downloadArtifact(cfg, token, kind, meta) {
|
|
|
35556
35641
|
record(cfg.dataDir, check.link.id, meta, "denied-download");
|
|
35557
35642
|
return { found: false, outcome: "denied-download" };
|
|
35558
35643
|
}
|
|
35559
|
-
const content = getSnapshotArtifact(cfg.dataDir, check.link.snapshotId, kind);
|
|
35644
|
+
const content = getSnapshotArtifact(cfg.dataDir, check.link.snapshotId, kind, portalId);
|
|
35560
35645
|
if (content === null) {
|
|
35561
35646
|
record(cfg.dataDir, check.link.id, meta, "not-found");
|
|
35562
35647
|
return { found: false, outcome: "not-found" };
|
|
@@ -35566,6 +35651,35 @@ function downloadArtifact(cfg, token, kind, meta) {
|
|
|
35566
35651
|
}
|
|
35567
35652
|
|
|
35568
35653
|
// src/server/sharehttp.ts
|
|
35654
|
+
init_filenames();
|
|
35655
|
+
function specParam(req) {
|
|
35656
|
+
const url = req.url ?? "";
|
|
35657
|
+
const q2 = url.indexOf("?");
|
|
35658
|
+
if (q2 < 0) return void 0;
|
|
35659
|
+
return new URLSearchParams(url.slice(q2 + 1)).get("spec") || void 0;
|
|
35660
|
+
}
|
|
35661
|
+
function asOpenApiIndex(payload) {
|
|
35662
|
+
try {
|
|
35663
|
+
const parsed = JSON.parse(payload);
|
|
35664
|
+
return parsed && parsed.openapiIndex === true && Array.isArray(parsed.specs) ? parsed : null;
|
|
35665
|
+
} catch {
|
|
35666
|
+
return null;
|
|
35667
|
+
}
|
|
35668
|
+
}
|
|
35669
|
+
function escapeHtml2(s) {
|
|
35670
|
+
return s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
35671
|
+
}
|
|
35672
|
+
function sharedOpenApiIndexPage(index) {
|
|
35673
|
+
const items = index.specs.map(
|
|
35674
|
+
(s) => `<li><a href="?spec=${encodeURIComponent(s.portalId)}">${escapeHtml2(s.name)}</a><code>${escapeHtml2(s.portalId)}</code></li>`
|
|
35675
|
+
).join("");
|
|
35676
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>Shared APIs</title><meta name="viewport" content="width=device-width, initial-scale=1"><style>body{font:15px/1.6 system-ui,sans-serif;max-width:680px;margin:48px auto;padding:0 20px;background:#0b1120;color:#e8e8f0}h1{font-size:20px}a{color:#6ea8fe;text-decoration:none}a:hover{text-decoration:underline}li{margin:10px 0}code{color:#9a9aab;font-size:12px;margin-left:8px}p{color:#9a9aab}</style></head><body><h1>Shared APIs</h1><p>This share exposes ${index.specs.length} separate APIs, each with its own OpenAPI document and auth:</p><ul>${items}</ul></body></html>`;
|
|
35677
|
+
}
|
|
35678
|
+
function downloadFilename(kind, portalId, payload) {
|
|
35679
|
+
if (kind !== "openapi") return `shared-canvas.${safeFilenamePart(kind)}`;
|
|
35680
|
+
if (portalId) return `shared-canvas.${safeFilenamePart(portalId)}.openapi.json`;
|
|
35681
|
+
return asOpenApiIndex(payload) ? "shared-canvas.openapi.index.json" : "shared-canvas.openapi.json";
|
|
35682
|
+
}
|
|
35569
35683
|
function shareRequestMeta(req) {
|
|
35570
35684
|
const fwd = req.headers["x-forwarded-for"];
|
|
35571
35685
|
const ip = (Array.isArray(fwd) ? fwd[0] : fwd)?.split(",")[0].trim() || req.socket?.remoteAddress || "unknown";
|
|
@@ -35617,14 +35731,16 @@ function serveSharedModel(cfg, token, req, res) {
|
|
|
35617
35731
|
);
|
|
35618
35732
|
}
|
|
35619
35733
|
function serveSharedOpenApi(cfg, token, req, res) {
|
|
35620
|
-
const result = downloadArtifact(cfg, token, "openapi", shareRequestMeta(req));
|
|
35734
|
+
const result = downloadArtifact(cfg, token, "openapi", shareRequestMeta(req), specParam(req));
|
|
35621
35735
|
if (!result.found || result.content === void 0) return notFoundPage(res);
|
|
35736
|
+
const index = asOpenApiIndex(result.content);
|
|
35622
35737
|
harden(res, void 0, "text/html; charset=utf-8");
|
|
35623
35738
|
res.statusCode = 200;
|
|
35624
|
-
res.end(swaggerUiPage(result.content, "Shared API"));
|
|
35739
|
+
res.end(index ? sharedOpenApiIndexPage(index) : swaggerUiPage(result.content, "Shared API"));
|
|
35625
35740
|
}
|
|
35626
35741
|
function serveSharedDownload(cfg, token, kind, req, res) {
|
|
35627
|
-
const
|
|
35742
|
+
const portalId = specParam(req);
|
|
35743
|
+
const result = downloadArtifact(cfg, token, kind, shareRequestMeta(req), portalId);
|
|
35628
35744
|
if (!result.found || result.content === void 0) {
|
|
35629
35745
|
if (result.outcome === "denied-download") {
|
|
35630
35746
|
harden(res, void 0, "text/plain");
|
|
@@ -35634,9 +35750,11 @@ function serveSharedDownload(cfg, token, kind, req, res) {
|
|
|
35634
35750
|
}
|
|
35635
35751
|
return notFoundPage(res);
|
|
35636
35752
|
}
|
|
35637
|
-
const ext = kind === "html" ? "html" : kind === "openapi" ? "openapi.json" : kind;
|
|
35638
35753
|
harden(res, void 0, result.contentType ?? "application/octet-stream");
|
|
35639
|
-
res.setHeader(
|
|
35754
|
+
res.setHeader(
|
|
35755
|
+
"content-disposition",
|
|
35756
|
+
`attachment; filename="${downloadFilename(kind, portalId, result.content)}"`
|
|
35757
|
+
);
|
|
35640
35758
|
res.statusCode = 200;
|
|
35641
35759
|
res.end(result.content);
|
|
35642
35760
|
}
|
|
@@ -37246,15 +37364,29 @@ async function runSurface(action, options = {}) {
|
|
|
37246
37364
|
if (format !== "native" && format !== "openapi") {
|
|
37247
37365
|
throw new WaironError(`Unknown format "${format}" (supported: native, openapi).`);
|
|
37248
37366
|
}
|
|
37249
|
-
|
|
37367
|
+
if (options.portal && format !== "openapi") {
|
|
37368
|
+
throw new WaironError("`--portal` selects one OpenAPI document and only applies to `--format openapi`.");
|
|
37369
|
+
}
|
|
37370
|
+
const result = exportSurface(audience, format, options.out, options.portal);
|
|
37250
37371
|
logger.success(
|
|
37251
37372
|
`Projected surface of "${result.snapshot.projectName}": ${result.snapshot.interfaces.length} interface(s), ${result.snapshot.types.length} type(s) at audience \u2265 ${audience}.`
|
|
37252
37373
|
);
|
|
37253
|
-
|
|
37254
|
-
|
|
37374
|
+
const written = result.writtenPaths ?? (result.writtenTo ? [result.writtenTo] : []);
|
|
37375
|
+
if (written.length === 1) {
|
|
37376
|
+
logger.info(`Written to ${written[0]}`);
|
|
37377
|
+
} else if (written.length > 1) {
|
|
37378
|
+
logger.info(`Written ${written.length} document(s) \u2014 one per portal:`);
|
|
37379
|
+
for (const p of written) logger.info(` ${p}`);
|
|
37255
37380
|
} else if (result.rendered) {
|
|
37256
37381
|
process.stdout.write(`${result.rendered}
|
|
37257
37382
|
`);
|
|
37383
|
+
} else if (result.renderedSet && result.renderedSet.length > 1) {
|
|
37384
|
+
logger.info(
|
|
37385
|
+
`This project publishes ${result.renderedSet.length} portals \u2014 pick one with \`--portal <id>\` (or use --out to write them all):`
|
|
37386
|
+
);
|
|
37387
|
+
for (const spec of result.renderedSet) {
|
|
37388
|
+
logger.info(` ${import_chalk19.default.cyan(spec.portalId)} \u2014 ${spec.name}`);
|
|
37389
|
+
}
|
|
37258
37390
|
} else {
|
|
37259
37391
|
for (const entry of result.snapshot.interfaces) {
|
|
37260
37392
|
logger.info(` ${import_chalk19.default.cyan(entry.id)} (${entry.type}, ${entry.audience}) \u2014 ${entry.methods.length} method(s)`);
|
|
@@ -37523,13 +37655,14 @@ mcpCmd.command("status").description("Show whether the wairon MCP server is regi
|
|
|
37523
37655
|
program.command("produce <target>").description("project the local project's specs to a producer target (notion | miro)").option("--page <id>", "parent page/board id in the target").option("--token <token>", "integration token (else env, else interactive prompt)").action(async (target, opts) => {
|
|
37524
37656
|
await runProduce(target, { page: opts.page, token: opts.token });
|
|
37525
37657
|
});
|
|
37526
|
-
program.command("surface <action>").description("public surface exchange: export | import | list | generate-children").option("--audience <level>", "export ceiling: project | department | instance | partner | external (default instance)").option("--format <fmt>", "export format: native | openapi (default native)").option("--out <path>", "export output path (else print)").option("--source <path>", "import: the surface document (native snapshot YAML or OpenAPI)").option("--origin <origin>", "import provenance: exchanged | authored (default authored)").action(async (action, opts) => {
|
|
37658
|
+
program.command("surface <action>").description("public surface exchange: export | import | list | generate-children").option("--audience <level>", "export ceiling: project | department | instance | partner | external (default instance)").option("--format <fmt>", "export format: native | openapi (default native)").option("--out <path>", "export output path (else print)").option("--portal <id>", "export: select one portal's OpenAPI spec (a multi-portal project renders one document per portal)").option("--source <path>", "import: the surface document (native snapshot YAML or OpenAPI)").option("--origin <origin>", "import provenance: exchanged | authored (default authored)").action(async (action, opts) => {
|
|
37527
37659
|
await runSurface(action, {
|
|
37528
37660
|
audience: opts.audience,
|
|
37529
37661
|
format: opts.format,
|
|
37530
37662
|
out: opts.out,
|
|
37531
37663
|
source: opts.source,
|
|
37532
|
-
origin: opts.origin
|
|
37664
|
+
origin: opts.origin,
|
|
37665
|
+
portal: opts.portal
|
|
37533
37666
|
});
|
|
37534
37667
|
});
|
|
37535
37668
|
program.command("serve").description("Run the wairon hosting server: HTTP MCP for many isolated projects + admin API").option("--host <host>", "data-plane bind host (default 0.0.0.0)").option("--port <port>", "data-plane port (default 8080)").option("--admin-host <host>", "admin-plane bind host (default 127.0.0.1)").option("--admin-port <port>", "admin-plane port (default 8081)").option("--data-dir <path>", "data root holding projects/ and auth/ (default WAIRON_DATA_DIR or ~/.wairon/data)").option("--no-auth", "disable data-plane auth (trusted networks only)").action(async (opts) => {
|