@wairon/cli 5.0.2-dev.10 → 5.0.2-dev.11
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 +176 -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.11";
|
|
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,7 @@ function audienceDistance(resolution, targetProjectId) {
|
|
|
29176
29211
|
|
|
29177
29212
|
// src/server/landscape.ts
|
|
29178
29213
|
var yamlLib = __toESM(require("js-yaml"));
|
|
29214
|
+
init_filenames();
|
|
29179
29215
|
var PROJECT_ADMIN_CAPABILITY3 = "project:admin";
|
|
29180
29216
|
var PROJECT_READ_CAPABILITY3 = "project:read";
|
|
29181
29217
|
var PROJECT_WRITE_CAPABILITY3 = "project:write";
|
|
@@ -29662,7 +29698,7 @@ function getProjectSurfaceForMcp(cfg, credential, currentProjectId, targetProjec
|
|
|
29662
29698
|
const result = runWithProjectRoot(record2.rootPath, () => hostSurfaces.exportBoundSurface(maxAudience, "native"));
|
|
29663
29699
|
return { ...result.snapshot, origin: "exchanged" };
|
|
29664
29700
|
}
|
|
29665
|
-
function exportProjectSurface(cfg, credential, projectId, format, maxAudience) {
|
|
29701
|
+
function exportProjectSurface(cfg, credential, projectId, format, maxAudience, portalId) {
|
|
29666
29702
|
const principal = requirePrincipal6(cfg, credential);
|
|
29667
29703
|
if (!permitsCap(cfg, principal, PROJECT_ADMIN_CAPABILITY3, "project", projectId)) {
|
|
29668
29704
|
throw new ForbiddenError(
|
|
@@ -29676,16 +29712,41 @@ function exportProjectSurface(cfg, credential, projectId, format, maxAudience) {
|
|
|
29676
29712
|
if (!root) throw new Error(`Unknown project "${projectId}".`);
|
|
29677
29713
|
const result = runWithProjectRoot(root, () => hostSurfaces.exportBoundSurface(maxAudience, format));
|
|
29678
29714
|
if (format === "openapi") {
|
|
29715
|
+
const specs = result.renderedSet ?? [];
|
|
29716
|
+
if (portalId) {
|
|
29717
|
+
const hit = specs.find((s) => s.portalId === portalId);
|
|
29718
|
+
if (!hit) {
|
|
29719
|
+
throw new Error(
|
|
29720
|
+
`Unknown portal "${portalId}" in project "${projectId}" (published: ${specs.map((s) => s.portalId).join(", ") || "none"}).`
|
|
29721
|
+
);
|
|
29722
|
+
}
|
|
29723
|
+
return {
|
|
29724
|
+
body: hit.document,
|
|
29725
|
+
contentType: "application/json",
|
|
29726
|
+
filename: `${safeFilenamePart(projectId)}-${safeFilenamePart(portalId)}-surface.openapi.json`
|
|
29727
|
+
};
|
|
29728
|
+
}
|
|
29729
|
+
if (specs.length === 1) {
|
|
29730
|
+
return {
|
|
29731
|
+
body: specs[0].document,
|
|
29732
|
+
contentType: "application/json",
|
|
29733
|
+
filename: `${safeFilenamePart(projectId)}-surface.openapi.json`
|
|
29734
|
+
};
|
|
29735
|
+
}
|
|
29679
29736
|
return {
|
|
29680
|
-
body:
|
|
29737
|
+
body: JSON.stringify(
|
|
29738
|
+
{ openapiIndex: true, specs: specs.map((s) => ({ portalId: s.portalId, name: s.name })) },
|
|
29739
|
+
null,
|
|
29740
|
+
2
|
|
29741
|
+
),
|
|
29681
29742
|
contentType: "application/json",
|
|
29682
|
-
filename: `${projectId}-surface.openapi.json`
|
|
29743
|
+
filename: `${safeFilenamePart(projectId)}-surface.openapi.index.json`
|
|
29683
29744
|
};
|
|
29684
29745
|
}
|
|
29685
29746
|
return {
|
|
29686
29747
|
body: yamlLib.dump(result.snapshot),
|
|
29687
29748
|
contentType: "application/yaml",
|
|
29688
|
-
filename: `${projectId}-surface.yaml`
|
|
29749
|
+
filename: `${safeFilenamePart(projectId)}-surface.yaml`
|
|
29689
29750
|
};
|
|
29690
29751
|
}
|
|
29691
29752
|
function removeRelation(cfg, credential, id) {
|
|
@@ -29729,7 +29790,8 @@ function handleLandscapeRequest(cfg, credential, req, res, body, url) {
|
|
|
29729
29790
|
credential,
|
|
29730
29791
|
parts[2],
|
|
29731
29792
|
url.searchParams.get("format") ?? "native",
|
|
29732
|
-
url.searchParams.get("audience") ?? "instance"
|
|
29793
|
+
url.searchParams.get("audience") ?? "instance",
|
|
29794
|
+
url.searchParams.get("spec") ?? void 0
|
|
29733
29795
|
);
|
|
29734
29796
|
res.writeHead(200, {
|
|
29735
29797
|
"content-type": artifact.contentType,
|
|
@@ -31804,6 +31866,26 @@ var ShareSnapshotRegistry = class {
|
|
|
31804
31866
|
return stored;
|
|
31805
31867
|
}
|
|
31806
31868
|
};
|
|
31869
|
+
function openApiIndexDocument(specs) {
|
|
31870
|
+
return JSON.stringify(
|
|
31871
|
+
{ openapiIndex: true, specs: specs.map((s) => ({ portalId: s.portalId, name: s.name })) },
|
|
31872
|
+
null,
|
|
31873
|
+
2
|
|
31874
|
+
);
|
|
31875
|
+
}
|
|
31876
|
+
function selectCapturedOpenApi(snap, portalId) {
|
|
31877
|
+
const specs = snap.openapiSet;
|
|
31878
|
+
if (!specs || specs.length === 0) {
|
|
31879
|
+
if (portalId) return null;
|
|
31880
|
+
return snap.openapi ?? null;
|
|
31881
|
+
}
|
|
31882
|
+
if (portalId) {
|
|
31883
|
+
const hit = specs.find((s) => s.portalId === portalId);
|
|
31884
|
+
return hit ? hit.document : null;
|
|
31885
|
+
}
|
|
31886
|
+
if (specs.length === 1) return specs[0].document;
|
|
31887
|
+
return openApiIndexDocument(specs);
|
|
31888
|
+
}
|
|
31807
31889
|
var ShareSnapshotIndex = class {
|
|
31808
31890
|
constructor(store) {
|
|
31809
31891
|
this.store = store;
|
|
@@ -31811,12 +31893,12 @@ var ShareSnapshotIndex = class {
|
|
|
31811
31893
|
get(snapshotId) {
|
|
31812
31894
|
return this.store.read(snapshotId);
|
|
31813
31895
|
}
|
|
31814
|
-
getArtifact(snapshotId, kind) {
|
|
31896
|
+
getArtifact(snapshotId, kind, portalId) {
|
|
31815
31897
|
const snap = this.store.read(snapshotId);
|
|
31816
31898
|
if (!snap) return null;
|
|
31817
31899
|
if (kind === "canvas") return snap.canvasModel ?? null;
|
|
31818
31900
|
if (kind === "html") return snap.html ?? null;
|
|
31819
|
-
if (kind === "openapi") return snap
|
|
31901
|
+
if (kind === "openapi") return selectCapturedOpenApi(snap, portalId);
|
|
31820
31902
|
return null;
|
|
31821
31903
|
}
|
|
31822
31904
|
};
|
|
@@ -31826,8 +31908,8 @@ function putSnapshot(dataDir, snapshot) {
|
|
|
31826
31908
|
function getSnapshot2(dataDir, snapshotId) {
|
|
31827
31909
|
return new ShareSnapshotIndex(new ShareSnapshotStore(dataDir)).get(snapshotId);
|
|
31828
31910
|
}
|
|
31829
|
-
function getSnapshotArtifact(dataDir, snapshotId, kind) {
|
|
31830
|
-
return new ShareSnapshotIndex(new ShareSnapshotStore(dataDir)).getArtifact(snapshotId, kind);
|
|
31911
|
+
function getSnapshotArtifact(dataDir, snapshotId, kind, portalId) {
|
|
31912
|
+
return new ShareSnapshotIndex(new ShareSnapshotStore(dataDir)).getArtifact(snapshotId, kind, portalId);
|
|
31831
31913
|
}
|
|
31832
31914
|
function captureSnapshot(dataDir, principal, projectId, view, artifacts) {
|
|
31833
31915
|
const root = resolveProjectRoot(dataDir, principal, projectId);
|
|
@@ -31846,7 +31928,11 @@ function captureSnapshot(dataDir, principal, projectId, view, artifacts) {
|
|
|
31846
31928
|
}
|
|
31847
31929
|
if (artifacts.includes("openapi")) {
|
|
31848
31930
|
const result = hostSurfaces.exportBoundSurface("project", "openapi");
|
|
31849
|
-
|
|
31931
|
+
const specs = result.renderedSet ?? [];
|
|
31932
|
+
if (specs.length) {
|
|
31933
|
+
snapshot.openapiSet = specs;
|
|
31934
|
+
if (specs.length === 1) snapshot.openapi = specs[0].document;
|
|
31935
|
+
}
|
|
31850
31936
|
}
|
|
31851
31937
|
return snapshot;
|
|
31852
31938
|
});
|
|
@@ -32407,10 +32493,10 @@ function getWebProjectOpenApi(cfg, sessionId, projectId, portalId) {
|
|
|
32407
32493
|
if (!root) throw new ForbiddenError("project not authorized or unknown");
|
|
32408
32494
|
const result = runWithProjectRoot(root, () => hostSurfaces.exportBoundSurface("project", "openapi"));
|
|
32409
32495
|
const specs = result.renderedSet ?? (result.rendered ? [{ portalId: "", name: projectId, document: result.rendered }] : []);
|
|
32410
|
-
if (specs.length === 0) return
|
|
32496
|
+
if (specs.length === 0) return openApiIndexPage(projectId, []);
|
|
32411
32497
|
if (portalId) {
|
|
32412
|
-
const sel = specs.find((s) => s.portalId === portalId)
|
|
32413
|
-
return swaggerUiPage(sel.document, sel.name);
|
|
32498
|
+
const sel = specs.find((s) => s.portalId === portalId);
|
|
32499
|
+
return sel ? swaggerUiPage(sel.document, sel.name) : openApiIndexPage(projectId, specs);
|
|
32414
32500
|
}
|
|
32415
32501
|
if (specs.length === 1) return swaggerUiPage(specs[0].document, specs[0].name);
|
|
32416
32502
|
return openApiIndexPage(projectId, specs);
|
|
@@ -32418,7 +32504,7 @@ function getWebProjectOpenApi(cfg, sessionId, projectId, portalId) {
|
|
|
32418
32504
|
function openApiIndexPage(projectId, specs) {
|
|
32419
32505
|
const esc2 = (s) => s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
32420
32506
|
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
|
|
32507
|
+
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
32508
|
}
|
|
32423
32509
|
function reshapeLandscapeGraph(model, level) {
|
|
32424
32510
|
const unitNodeIds = new Set(model.nodes.filter((n) => n.nodeKind === "orgUnit").map((n) => n.id));
|
|
@@ -35544,7 +35630,7 @@ var CONTENT_TYPE = {
|
|
|
35544
35630
|
openapi: "application/json",
|
|
35545
35631
|
canvas: "application/json"
|
|
35546
35632
|
};
|
|
35547
|
-
function downloadArtifact(cfg, token, kind, meta) {
|
|
35633
|
+
function downloadArtifact(cfg, token, kind, meta, portalId) {
|
|
35548
35634
|
const link = linkByTokenHash(cfg.dataDir, hashToken(token));
|
|
35549
35635
|
const check = usable(link);
|
|
35550
35636
|
if ("outcome" in check) {
|
|
@@ -35556,7 +35642,7 @@ function downloadArtifact(cfg, token, kind, meta) {
|
|
|
35556
35642
|
record(cfg.dataDir, check.link.id, meta, "denied-download");
|
|
35557
35643
|
return { found: false, outcome: "denied-download" };
|
|
35558
35644
|
}
|
|
35559
|
-
const content = getSnapshotArtifact(cfg.dataDir, check.link.snapshotId, kind);
|
|
35645
|
+
const content = getSnapshotArtifact(cfg.dataDir, check.link.snapshotId, kind, portalId);
|
|
35560
35646
|
if (content === null) {
|
|
35561
35647
|
record(cfg.dataDir, check.link.id, meta, "not-found");
|
|
35562
35648
|
return { found: false, outcome: "not-found" };
|
|
@@ -35566,6 +35652,35 @@ function downloadArtifact(cfg, token, kind, meta) {
|
|
|
35566
35652
|
}
|
|
35567
35653
|
|
|
35568
35654
|
// src/server/sharehttp.ts
|
|
35655
|
+
init_filenames();
|
|
35656
|
+
function specParam(req) {
|
|
35657
|
+
const url = req.url ?? "";
|
|
35658
|
+
const q2 = url.indexOf("?");
|
|
35659
|
+
if (q2 < 0) return void 0;
|
|
35660
|
+
return new URLSearchParams(url.slice(q2 + 1)).get("spec") || void 0;
|
|
35661
|
+
}
|
|
35662
|
+
function asOpenApiIndex(payload) {
|
|
35663
|
+
try {
|
|
35664
|
+
const parsed = JSON.parse(payload);
|
|
35665
|
+
return parsed && parsed.openapiIndex === true && Array.isArray(parsed.specs) ? parsed : null;
|
|
35666
|
+
} catch {
|
|
35667
|
+
return null;
|
|
35668
|
+
}
|
|
35669
|
+
}
|
|
35670
|
+
function escapeHtml2(s) {
|
|
35671
|
+
return s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
35672
|
+
}
|
|
35673
|
+
function sharedOpenApiIndexPage(index) {
|
|
35674
|
+
const items = index.specs.map(
|
|
35675
|
+
(s) => `<li><a href="?spec=${encodeURIComponent(s.portalId)}">${escapeHtml2(s.name)}</a><code>${escapeHtml2(s.portalId)}</code></li>`
|
|
35676
|
+
).join("");
|
|
35677
|
+
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>`;
|
|
35678
|
+
}
|
|
35679
|
+
function downloadFilename(kind, portalId, payload) {
|
|
35680
|
+
if (kind !== "openapi") return `shared-canvas.${safeFilenamePart(kind)}`;
|
|
35681
|
+
if (portalId) return `shared-canvas.${safeFilenamePart(portalId)}.openapi.json`;
|
|
35682
|
+
return asOpenApiIndex(payload) ? "shared-canvas.openapi.index.json" : "shared-canvas.openapi.json";
|
|
35683
|
+
}
|
|
35569
35684
|
function shareRequestMeta(req) {
|
|
35570
35685
|
const fwd = req.headers["x-forwarded-for"];
|
|
35571
35686
|
const ip = (Array.isArray(fwd) ? fwd[0] : fwd)?.split(",")[0].trim() || req.socket?.remoteAddress || "unknown";
|
|
@@ -35617,14 +35732,16 @@ function serveSharedModel(cfg, token, req, res) {
|
|
|
35617
35732
|
);
|
|
35618
35733
|
}
|
|
35619
35734
|
function serveSharedOpenApi(cfg, token, req, res) {
|
|
35620
|
-
const result = downloadArtifact(cfg, token, "openapi", shareRequestMeta(req));
|
|
35735
|
+
const result = downloadArtifact(cfg, token, "openapi", shareRequestMeta(req), specParam(req));
|
|
35621
35736
|
if (!result.found || result.content === void 0) return notFoundPage(res);
|
|
35737
|
+
const index = asOpenApiIndex(result.content);
|
|
35622
35738
|
harden(res, void 0, "text/html; charset=utf-8");
|
|
35623
35739
|
res.statusCode = 200;
|
|
35624
|
-
res.end(swaggerUiPage(result.content, "Shared API"));
|
|
35740
|
+
res.end(index ? sharedOpenApiIndexPage(index) : swaggerUiPage(result.content, "Shared API"));
|
|
35625
35741
|
}
|
|
35626
35742
|
function serveSharedDownload(cfg, token, kind, req, res) {
|
|
35627
|
-
const
|
|
35743
|
+
const portalId = specParam(req);
|
|
35744
|
+
const result = downloadArtifact(cfg, token, kind, shareRequestMeta(req), portalId);
|
|
35628
35745
|
if (!result.found || result.content === void 0) {
|
|
35629
35746
|
if (result.outcome === "denied-download") {
|
|
35630
35747
|
harden(res, void 0, "text/plain");
|
|
@@ -35634,9 +35751,11 @@ function serveSharedDownload(cfg, token, kind, req, res) {
|
|
|
35634
35751
|
}
|
|
35635
35752
|
return notFoundPage(res);
|
|
35636
35753
|
}
|
|
35637
|
-
const ext = kind === "html" ? "html" : kind === "openapi" ? "openapi.json" : kind;
|
|
35638
35754
|
harden(res, void 0, result.contentType ?? "application/octet-stream");
|
|
35639
|
-
res.setHeader(
|
|
35755
|
+
res.setHeader(
|
|
35756
|
+
"content-disposition",
|
|
35757
|
+
`attachment; filename="${downloadFilename(kind, portalId, result.content)}"`
|
|
35758
|
+
);
|
|
35640
35759
|
res.statusCode = 200;
|
|
35641
35760
|
res.end(result.content);
|
|
35642
35761
|
}
|
|
@@ -37246,15 +37365,29 @@ async function runSurface(action, options = {}) {
|
|
|
37246
37365
|
if (format !== "native" && format !== "openapi") {
|
|
37247
37366
|
throw new WaironError(`Unknown format "${format}" (supported: native, openapi).`);
|
|
37248
37367
|
}
|
|
37249
|
-
|
|
37368
|
+
if (options.portal && format !== "openapi") {
|
|
37369
|
+
throw new WaironError("`--portal` selects one OpenAPI document and only applies to `--format openapi`.");
|
|
37370
|
+
}
|
|
37371
|
+
const result = exportSurface(audience, format, options.out, options.portal);
|
|
37250
37372
|
logger.success(
|
|
37251
37373
|
`Projected surface of "${result.snapshot.projectName}": ${result.snapshot.interfaces.length} interface(s), ${result.snapshot.types.length} type(s) at audience \u2265 ${audience}.`
|
|
37252
37374
|
);
|
|
37253
|
-
|
|
37254
|
-
|
|
37375
|
+
const written = result.writtenPaths ?? (result.writtenTo ? [result.writtenTo] : []);
|
|
37376
|
+
if (written.length === 1) {
|
|
37377
|
+
logger.info(`Written to ${written[0]}`);
|
|
37378
|
+
} else if (written.length > 1) {
|
|
37379
|
+
logger.info(`Written ${written.length} document(s) \u2014 one per portal:`);
|
|
37380
|
+
for (const p of written) logger.info(` ${p}`);
|
|
37255
37381
|
} else if (result.rendered) {
|
|
37256
37382
|
process.stdout.write(`${result.rendered}
|
|
37257
37383
|
`);
|
|
37384
|
+
} else if (result.renderedSet && result.renderedSet.length > 1) {
|
|
37385
|
+
logger.info(
|
|
37386
|
+
`This project publishes ${result.renderedSet.length} portals \u2014 pick one with \`--portal <id>\` (or use --out to write them all):`
|
|
37387
|
+
);
|
|
37388
|
+
for (const spec of result.renderedSet) {
|
|
37389
|
+
logger.info(` ${import_chalk19.default.cyan(spec.portalId)} \u2014 ${spec.name}`);
|
|
37390
|
+
}
|
|
37258
37391
|
} else {
|
|
37259
37392
|
for (const entry of result.snapshot.interfaces) {
|
|
37260
37393
|
logger.info(` ${import_chalk19.default.cyan(entry.id)} (${entry.type}, ${entry.audience}) \u2014 ${entry.methods.length} method(s)`);
|
|
@@ -37523,13 +37656,14 @@ mcpCmd.command("status").description("Show whether the wairon MCP server is regi
|
|
|
37523
37656
|
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
37657
|
await runProduce(target, { page: opts.page, token: opts.token });
|
|
37525
37658
|
});
|
|
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) => {
|
|
37659
|
+
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
37660
|
await runSurface(action, {
|
|
37528
37661
|
audience: opts.audience,
|
|
37529
37662
|
format: opts.format,
|
|
37530
37663
|
out: opts.out,
|
|
37531
37664
|
source: opts.source,
|
|
37532
|
-
origin: opts.origin
|
|
37665
|
+
origin: opts.origin,
|
|
37666
|
+
portal: opts.portal
|
|
37533
37667
|
});
|
|
37534
37668
|
});
|
|
37535
37669
|
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) => {
|