源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { dirname, resolve } from "node:path";
|
||||
|
||||
export function normalizeOpenApiFragmentRefs(value, extensionKey) {
|
||||
if (value == null) {
|
||||
return [];
|
||||
}
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error(`${extensionKey} must be an array`);
|
||||
}
|
||||
return value.map((entry) => normalizeOpenApiFragmentRef(entry, extensionKey));
|
||||
}
|
||||
|
||||
export function resolveOpenApiFragmentPath(
|
||||
fragmentRef,
|
||||
{ repoRoot, specPath, resolvePackageSpecifier }
|
||||
) {
|
||||
if (typeof fragmentRef === "string") {
|
||||
if (fragmentRef.startsWith(".")) {
|
||||
return resolve(dirname(specPath), fragmentRef);
|
||||
}
|
||||
return resolve(repoRoot, fragmentRef);
|
||||
}
|
||||
|
||||
const specifier = `${fragmentRef.package}/${fragmentRef.path}`;
|
||||
try {
|
||||
return resolvePackageSpecifier(specifier);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Cannot resolve OpenAPI fragment ${specifier}; install an exact released package version before generation`,
|
||||
{ cause: error }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeOpenApiFragmentRef(entry, extensionKey) {
|
||||
if (typeof entry === "string") {
|
||||
const value = entry.trim();
|
||||
if (value === "") {
|
||||
throw new Error(`${extensionKey} cannot contain empty entries`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
||||
throw new Error(
|
||||
`${extensionKey} entries must be paths or package/path objects`
|
||||
);
|
||||
}
|
||||
const packageName = String(entry.package ?? "").trim();
|
||||
const packagePath = String(entry.path ?? "").trim();
|
||||
const keys = Object.keys(entry);
|
||||
if (
|
||||
packageName === "" ||
|
||||
packagePath === "" ||
|
||||
keys.some((key) => key !== "package" && key !== "path")
|
||||
) {
|
||||
throw new Error(
|
||||
`${extensionKey} package entries require only non-empty package and path fields`
|
||||
);
|
||||
}
|
||||
const packagePathSegments = packagePath.split(/[\\/]/u);
|
||||
if (
|
||||
packagePath.startsWith("/") ||
|
||||
packagePathSegments.some((segment) => segment === "." || segment === "..")
|
||||
) {
|
||||
throw new Error(`${extensionKey} package paths must be package-relative`);
|
||||
}
|
||||
return { package: packageName, path: packagePath };
|
||||
}
|
||||
Reference in New Issue
Block a user