@treeseed/sdk 0.10.28 → 0.11.0
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 +207 -6
- package/dist/capacity-provider.d.ts +3 -1
- package/dist/capacity-provider.js +25 -5
- package/dist/control-plane.d.ts +1 -0
- package/dist/control-plane.js +38 -13
- package/dist/db/market-schema.d.ts +8860 -6172
- package/dist/db/market-schema.js +108 -0
- package/dist/db/node-sqlite.js +7 -2
- package/dist/hosting/apps.d.ts +12 -0
- package/dist/hosting/apps.js +107 -0
- package/dist/hosting/builtins.d.ts +25 -0
- package/dist/hosting/builtins.js +791 -0
- package/dist/hosting/contracts.d.ts +207 -0
- package/dist/hosting/contracts.js +0 -0
- package/dist/hosting/graph.d.ts +192 -0
- package/dist/hosting/graph.js +1106 -0
- package/dist/hosting/index.d.ts +4 -0
- package/dist/hosting/index.js +4 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +63 -6
- package/dist/managed-dependencies.js +1 -2
- package/dist/market-client.d.ts +63 -3
- package/dist/market-client.js +83 -11
- package/dist/operations/services/bootstrap-runner.d.ts +3 -1
- package/dist/operations/services/bootstrap-runner.js +22 -2
- package/dist/operations/services/config-runtime.d.ts +10 -5
- package/dist/operations/services/config-runtime.js +209 -66
- package/dist/operations/services/deploy.d.ts +70 -7
- package/dist/operations/services/deploy.js +579 -64
- package/dist/operations/services/deployment-readiness.d.ts +30 -0
- package/dist/operations/services/deployment-readiness.js +175 -0
- package/dist/operations/services/git-workflow.d.ts +2 -1
- package/dist/operations/services/git-workflow.js +9 -3
- package/dist/operations/services/github-actions-verification.d.ts +1 -0
- package/dist/operations/services/github-actions-verification.js +1 -0
- package/dist/operations/services/github-api.js +1 -1
- package/dist/operations/services/github-automation.d.ts +1 -1
- package/dist/operations/services/github-automation.js +4 -3
- package/dist/operations/services/github-credentials.d.ts +13 -0
- package/dist/operations/services/github-credentials.js +58 -0
- package/dist/operations/services/hosted-service-checks.d.ts +63 -0
- package/dist/operations/services/hosted-service-checks.js +327 -0
- package/dist/operations/services/hub-provider-launch.js +3 -3
- package/dist/operations/services/live-hosted-service-checks.d.ts +25 -0
- package/dist/operations/services/live-hosted-service-checks.js +350 -0
- package/dist/operations/services/managed-host-security.js +1 -1
- package/dist/operations/services/operations-runner-smoke.d.ts +30 -0
- package/dist/operations/services/operations-runner-smoke.js +180 -0
- package/dist/operations/services/package-adapters.d.ts +95 -0
- package/dist/operations/services/package-adapters.js +288 -0
- package/dist/operations/services/package-reference-policy.d.ts +1 -0
- package/dist/operations/services/package-reference-policy.js +15 -2
- package/dist/operations/services/project-platform.d.ts +80 -22
- package/dist/operations/services/project-platform.js +49 -8
- package/dist/operations/services/project-web-monitor.js +26 -4
- package/dist/operations/services/railway-api.d.ts +88 -5
- package/dist/operations/services/railway-api.js +626 -35
- package/dist/operations/services/railway-deploy.d.ts +46 -40
- package/dist/operations/services/railway-deploy.js +261 -293
- package/dist/operations/services/release-candidate.d.ts +19 -0
- package/dist/operations/services/release-candidate.js +375 -38
- package/dist/operations/services/repository-save-orchestrator.d.ts +3 -1
- package/dist/operations/services/repository-save-orchestrator.js +279 -66
- package/dist/operations/services/runtime-tools.d.ts +1 -0
- package/dist/operations/services/runtime-tools.js +10 -9
- package/dist/operations/services/verification-cache.d.ts +25 -0
- package/dist/operations/services/verification-cache.js +71 -0
- package/dist/operations/services/workspace-dependency-mode.js +9 -1
- package/dist/operations/services/workspace-save.js +1 -1
- package/dist/operations/services/workspace-tools.js +2 -1
- package/dist/platform/contracts.d.ts +32 -1
- package/dist/platform/deploy-config.js +73 -8
- package/dist/platform/env.yaml +163 -35
- package/dist/platform/environment.d.ts +1 -0
- package/dist/platform/environment.js +74 -5
- package/dist/platform/plugin.d.ts +9 -0
- package/dist/platform-operation-store.js +2 -2
- package/dist/platform-operations.js +1 -1
- package/dist/reconcile/bootstrap-systems.js +2 -2
- package/dist/reconcile/builtin-adapters.js +372 -189
- package/dist/reconcile/contracts.d.ts +9 -5
- package/dist/reconcile/desired-state.d.ts +1 -0
- package/dist/reconcile/desired-state.js +5 -5
- package/dist/reconcile/engine.d.ts +5 -2
- package/dist/reconcile/engine.js +53 -32
- package/dist/reconcile/index.d.ts +2 -0
- package/dist/reconcile/index.js +2 -0
- package/dist/reconcile/live-acceptance.d.ts +79 -0
- package/dist/reconcile/live-acceptance.js +1615 -0
- package/dist/reconcile/platform.d.ts +104 -0
- package/dist/reconcile/platform.js +100 -0
- package/dist/reconcile/state.js +4 -4
- package/dist/reconcile/units.js +2 -2
- package/dist/scripts/deployment-readiness.js +20 -0
- package/dist/scripts/generate-treedx-openapi-types.js +186 -0
- package/dist/scripts/operations-runner-smoke.js +16 -0
- package/dist/scripts/release-verify.js +4 -1
- package/dist/scripts/tenant-workflow-action.js +10 -1
- package/dist/sdk-types.d.ts +169 -4
- package/dist/sdk-types.js +20 -2
- package/dist/sdk.d.ts +35 -24
- package/dist/sdk.js +186 -17
- package/dist/template-launch-requirements.js +9 -0
- package/dist/treedx/adapters.d.ts +6 -0
- package/dist/treedx/adapters.js +36 -0
- package/dist/treedx/client.d.ts +222 -0
- package/dist/treedx/client.js +871 -0
- package/dist/treedx/errors.d.ts +13 -0
- package/dist/treedx/errors.js +17 -0
- package/dist/treedx/federated-client.d.ts +27 -0
- package/dist/treedx/federated-client.js +158 -0
- package/dist/treedx/generated/openapi-types.d.ts +3558 -0
- package/dist/treedx/generated/openapi-types.js +0 -0
- package/dist/treedx/graph-adapter.d.ts +33 -0
- package/dist/treedx/graph-adapter.js +156 -0
- package/dist/treedx/index.d.ts +14 -0
- package/dist/treedx/index.js +48 -0
- package/dist/treedx/market-integration.d.ts +27 -0
- package/dist/treedx/market-integration.js +131 -0
- package/dist/treedx/ports.d.ts +166 -0
- package/dist/treedx/ports.js +231 -0
- package/dist/treedx/query-adapter.d.ts +19 -0
- package/dist/treedx/query-adapter.js +62 -0
- package/dist/treedx/registry-client.d.ts +11 -0
- package/dist/treedx/registry-client.js +19 -0
- package/dist/treedx/repository-adapter.d.ts +45 -0
- package/dist/treedx/repository-adapter.js +308 -0
- package/dist/treedx/sdk-integration.d.ts +27 -0
- package/dist/treedx/sdk-integration.js +63 -0
- package/dist/treedx/types.d.ts +1084 -0
- package/dist/treedx/types.js +8 -0
- package/dist/treedx/workspace-adapter.d.ts +27 -0
- package/dist/treedx/workspace-adapter.js +65 -0
- package/dist/treedx-backends.d.ts +218 -0
- package/dist/treedx-backends.js +632 -0
- package/dist/treedx-client.d.ts +86 -0
- package/dist/treedx-client.js +175 -0
- package/dist/treeseed/template-catalog/catalog.fixture.json +23 -23
- package/dist/workflow/operations.d.ts +119 -13
- package/dist/workflow/operations.js +309 -53
- package/dist/workflow-state.d.ts +13 -0
- package/dist/workflow-state.js +43 -26
- package/dist/workflow-support.d.ts +11 -3
- package/dist/workflow-support.js +67 -3
- package/dist/workflow.d.ts +5 -0
- package/drizzle/market/0004_treedx_market_integration.sql +99 -0
- package/package.json +34 -3
- package/templates/github/deploy-web.workflow.yml +39 -6
|
@@ -53,7 +53,7 @@ const TREESEED_DEFAULT_PROVIDER_SELECTIONS = {
|
|
|
53
53
|
},
|
|
54
54
|
site: "default"
|
|
55
55
|
};
|
|
56
|
-
const TRESEED_MANAGED_SERVICE_KEYS = ["
|
|
56
|
+
const TRESEED_MANAGED_SERVICE_KEYS = ["treeseedDatabase", "api", "operationsRunner"];
|
|
57
57
|
const TRESEED_WORKSPACE_PACKAGE_DIRS = ["sdk", "core", "cli"];
|
|
58
58
|
const CLOUDFLARE_ACCOUNT_ID_PLACEHOLDER = "replace-with-cloudflare-account-id";
|
|
59
59
|
function normalizePlanesFromLegacyHosting(hosting) {
|
|
@@ -63,12 +63,12 @@ function normalizePlanesFromLegacyHosting(hosting) {
|
|
|
63
63
|
runtime: { mode: "none", registration: "none" }
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
if (hosting.kind === "
|
|
66
|
+
if (hosting.kind === "treeseed_control_plane" || hosting.kind === "hosted_project") {
|
|
67
67
|
return {
|
|
68
68
|
hub: { mode: "treeseed_hosted" },
|
|
69
69
|
runtime: {
|
|
70
70
|
mode: "treeseed_managed",
|
|
71
|
-
registration: hosting.kind === "
|
|
71
|
+
registration: hosting.kind === "treeseed_control_plane" ? "none" : hosting.registration ?? "none",
|
|
72
72
|
marketBaseUrl: hosting.marketBaseUrl,
|
|
73
73
|
teamId: hosting.teamId,
|
|
74
74
|
projectId: hosting.projectId
|
|
@@ -484,12 +484,12 @@ function parseFallbackDeployConfig(configPath) {
|
|
|
484
484
|
const hosting = optionalRecord(record.hosting, "hosting") ?? {};
|
|
485
485
|
const parsedHosting = Object.keys(hosting).length === 0 ? void 0 : {
|
|
486
486
|
kind: optionalEnum(hosting.kind, "hosting.kind", [
|
|
487
|
-
"
|
|
487
|
+
"treeseed_control_plane",
|
|
488
488
|
"hosted_project",
|
|
489
489
|
"self_hosted_project"
|
|
490
490
|
]) ?? "self_hosted_project",
|
|
491
491
|
registration: optionalEnum(hosting.registration, "hosting.registration", ["optional", "none"]) ?? "none",
|
|
492
|
-
marketBaseUrl: optionalString(process.env.
|
|
492
|
+
marketBaseUrl: optionalString(process.env.TREESEED_API_BASE_URL) ?? optionalString(hosting.marketBaseUrl),
|
|
493
493
|
teamId: optionalString(process.env.TREESEED_HOSTING_TEAM_ID) ?? optionalString(hosting.teamId),
|
|
494
494
|
projectId: optionalString(process.env.TREESEED_PROJECT_ID) ?? optionalString(hosting.projectId)
|
|
495
495
|
};
|
|
@@ -507,7 +507,7 @@ function parseFallbackDeployConfig(configPath) {
|
|
|
507
507
|
const runtime = {
|
|
508
508
|
mode: optionalEnum(runtimeRecord.mode, "runtime.mode", ["none", "byo_attached", "treeseed_managed"]) ?? inferredPlanes.runtime.mode,
|
|
509
509
|
registration: optionalEnum(runtimeRecord.registration, "runtime.registration", ["optional", "required", "none"]) ?? inferredPlanes.runtime.registration ?? "none",
|
|
510
|
-
marketBaseUrl: optionalString(process.env.
|
|
510
|
+
marketBaseUrl: optionalString(process.env.TREESEED_API_BASE_URL) ?? optionalString(runtimeRecord.marketBaseUrl) ?? inferredPlanes.runtime.marketBaseUrl,
|
|
511
511
|
teamId: optionalString(process.env.TREESEED_HOSTING_TEAM_ID) ?? optionalString(runtimeRecord.teamId) ?? inferredPlanes.runtime.teamId,
|
|
512
512
|
projectId: optionalString(process.env.TREESEED_PROJECT_ID) ?? optionalString(runtimeRecord.projectId) ?? inferredPlanes.runtime.projectId
|
|
513
513
|
};
|
|
@@ -520,7 +520,7 @@ function parseFallbackDeployConfig(configPath) {
|
|
|
520
520
|
slug: expectString(record.slug, "slug"),
|
|
521
521
|
siteUrl: expectString(record.siteUrl, "siteUrl"),
|
|
522
522
|
contactEmail: expectString(record.contactEmail, "contactEmail"),
|
|
523
|
-
hosting: parsedHosting?.kind === "
|
|
523
|
+
hosting: parsedHosting?.kind === "treeseed_control_plane" ? { ...parsedHosting, registration: "none" } : parsedHosting && record.hub === void 0 && record.runtime === void 0 ? parsedHosting : normalizeLegacyHostingFromPlanes(hub, runtime),
|
|
524
524
|
hub,
|
|
525
525
|
runtime,
|
|
526
526
|
cloudflare: {
|
|
@@ -532,10 +532,11 @@ function parseFallbackDeployConfig(configPath) {
|
|
|
532
532
|
d1Binding: optionalString(cloudflare.d1Binding),
|
|
533
533
|
queueBinding: optionalString(cloudflare.queueBinding),
|
|
534
534
|
pages: cloudflare.pages === void 0 ? void 0 : {
|
|
535
|
-
projectName: optionalString(
|
|
536
|
-
previewProjectName: optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PREVIEW_PROJECT_NAME) ?? optionalString(cloudflarePages.previewProjectName),
|
|
535
|
+
projectName: optionalString(cloudflarePages.projectName) ?? optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME),
|
|
536
|
+
previewProjectName: optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PREVIEW_PROJECT_NAME) ?? optionalString(cloudflarePages.previewProjectName) ?? optionalString(cloudflarePages.projectName) ?? optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME),
|
|
537
537
|
productionBranch: optionalString(cloudflarePages.productionBranch) ?? "main",
|
|
538
538
|
stagingBranch: optionalString(cloudflarePages.stagingBranch) ?? "staging",
|
|
539
|
+
buildCommand: optionalString(cloudflarePages.buildCommand),
|
|
539
540
|
buildOutputDir: optionalString(cloudflarePages.buildOutputDir)
|
|
540
541
|
},
|
|
541
542
|
r2: cloudflare.r2 === void 0 ? void 0 : {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface TreeseedVerificationCacheEntry {
|
|
2
|
+
key: string;
|
|
3
|
+
repoName: string;
|
|
4
|
+
repoPath: string;
|
|
5
|
+
headSha: string;
|
|
6
|
+
command: string;
|
|
7
|
+
status: 'passed' | 'failed';
|
|
8
|
+
createdAt: string;
|
|
9
|
+
durationMs: number;
|
|
10
|
+
logsPath?: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface TreeseedVerificationCacheInput {
|
|
13
|
+
workspaceRoot: string;
|
|
14
|
+
repoName: string;
|
|
15
|
+
repoPath: string;
|
|
16
|
+
command: string;
|
|
17
|
+
verifyMode: string;
|
|
18
|
+
env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
|
|
19
|
+
}
|
|
20
|
+
export declare function treeseedVerificationCacheKey(input: TreeseedVerificationCacheInput): {
|
|
21
|
+
key: string;
|
|
22
|
+
headSha: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function readTreeseedVerificationCache(input: TreeseedVerificationCacheInput): TreeseedVerificationCacheEntry | null;
|
|
25
|
+
export declare function writeTreeseedVerificationCache(input: TreeseedVerificationCacheInput, durationMs: number): TreeseedVerificationCacheEntry | null;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { headCommit } from "./git-workflow.js";
|
|
5
|
+
function sha256(value) {
|
|
6
|
+
return createHash("sha256").update(value).digest("hex");
|
|
7
|
+
}
|
|
8
|
+
function fileHash(path) {
|
|
9
|
+
if (!existsSync(path)) return null;
|
|
10
|
+
return sha256(readFileSync(path));
|
|
11
|
+
}
|
|
12
|
+
function cacheEnabled(env = process.env) {
|
|
13
|
+
const value = String(env.TREESEED_VERIFY_CACHE ?? "").trim().toLowerCase();
|
|
14
|
+
if (value === "0" || value === "false" || value === "off") return false;
|
|
15
|
+
if (env.GITHUB_ACTIONS === "true") return value === "1" || value === "true" || value === "on";
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
function treeseedVerificationCacheKey(input) {
|
|
19
|
+
const headSha = headCommit(input.repoPath);
|
|
20
|
+
const payload = {
|
|
21
|
+
repoPath: resolve(input.repoPath),
|
|
22
|
+
headSha,
|
|
23
|
+
packageJson: fileHash(resolve(input.repoPath, "package.json")),
|
|
24
|
+
packageLock: fileHash(resolve(input.repoPath, "package-lock.json")),
|
|
25
|
+
command: input.command,
|
|
26
|
+
nodeMajor: process.versions.node.split(".")[0],
|
|
27
|
+
verifyMode: input.verifyMode
|
|
28
|
+
};
|
|
29
|
+
return { key: sha256(JSON.stringify(payload)), headSha };
|
|
30
|
+
}
|
|
31
|
+
function cachePath(input, key) {
|
|
32
|
+
return resolve(input.workspaceRoot, ".treeseed", "cache", "verification", `${key}.json`);
|
|
33
|
+
}
|
|
34
|
+
function readTreeseedVerificationCache(input) {
|
|
35
|
+
if (!cacheEnabled(input.env)) return null;
|
|
36
|
+
const { key, headSha } = treeseedVerificationCacheKey(input);
|
|
37
|
+
const path = cachePath(input, key);
|
|
38
|
+
if (!existsSync(path)) return null;
|
|
39
|
+
try {
|
|
40
|
+
const entry = JSON.parse(readFileSync(path, "utf8"));
|
|
41
|
+
if (entry.key !== key || entry.headSha !== headSha || entry.status !== "passed") return null;
|
|
42
|
+
return entry;
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function writeTreeseedVerificationCache(input, durationMs) {
|
|
48
|
+
if (!cacheEnabled(input.env)) return null;
|
|
49
|
+
const { key, headSha } = treeseedVerificationCacheKey(input);
|
|
50
|
+
const path = cachePath(input, key);
|
|
51
|
+
const entry = {
|
|
52
|
+
key,
|
|
53
|
+
repoName: input.repoName,
|
|
54
|
+
repoPath: resolve(input.repoPath),
|
|
55
|
+
headSha,
|
|
56
|
+
command: input.command,
|
|
57
|
+
status: "passed",
|
|
58
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
59
|
+
durationMs,
|
|
60
|
+
logsPath: null
|
|
61
|
+
};
|
|
62
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
63
|
+
writeFileSync(path, `${JSON.stringify(entry, null, 2)}
|
|
64
|
+
`, "utf8");
|
|
65
|
+
return entry;
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
readTreeseedVerificationCache,
|
|
69
|
+
treeseedVerificationCacheKey,
|
|
70
|
+
writeTreeseedVerificationCache
|
|
71
|
+
};
|
|
@@ -128,6 +128,14 @@ function dependencySpec(packageJson, field, packageName) {
|
|
|
128
128
|
const value = deps[packageName];
|
|
129
129
|
return typeof value === "string" ? value : null;
|
|
130
130
|
}
|
|
131
|
+
function dependencySpecsMatch(manifestSpec, lockSpec) {
|
|
132
|
+
if (lockSpec === manifestSpec) return true;
|
|
133
|
+
const manifestVersion = manifestSpec.replace(/^[~^]/u, "");
|
|
134
|
+
const lockRef = lockSpec.includes("#") ? lockSpec.slice(lockSpec.lastIndexOf("#") + 1) : null;
|
|
135
|
+
return Boolean(
|
|
136
|
+
lockRef && manifestVersion.includes("-dev.") && lockRef === manifestVersion && /^(?:github:|git\+https:\/\/github\.com\/|git\+ssh:\/\/git@github\.com[:/])/u.test(lockSpec)
|
|
137
|
+
);
|
|
138
|
+
}
|
|
131
139
|
function normalizedPathValue(value) {
|
|
132
140
|
return value.replaceAll("\\", "/").replace(/^\.\//u, "").replace(/\/$/u, "");
|
|
133
141
|
}
|
|
@@ -175,7 +183,7 @@ function collectPackageLockConsistencyIssues(filePath, packageJson, packages, wo
|
|
|
175
183
|
const manifestSpec = dependencySpec(packageJson, field, packageName);
|
|
176
184
|
if (!manifestSpec) continue;
|
|
177
185
|
const lockSpec = dependencySpec(rootLockEntry ?? {}, field, packageName);
|
|
178
|
-
if (lockSpec
|
|
186
|
+
if (!lockSpec || !dependencySpecsMatch(manifestSpec, lockSpec)) {
|
|
179
187
|
issues.push({
|
|
180
188
|
filePath,
|
|
181
189
|
packageName,
|
|
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { changedWorkspacePackages, publishableWorkspacePackages, run, sortWorkspacePackages, workspacePackages, workspaceRoot } from "./workspace-tools.js";
|
|
4
4
|
const MERGE_CONFLICT_EXIT_CODE = 12;
|
|
5
|
-
const TREESEED_PUBLIC_RELEASE_PACKAGE_NAMES = ["@treeseed/sdk", "@treeseed/core", "@treeseed/cli", "@treeseed/agent"];
|
|
5
|
+
const TREESEED_PUBLIC_RELEASE_PACKAGE_NAMES = ["@treeseed/sdk", "@treeseed/ui", "@treeseed/core", "@treeseed/admin", "@treeseed/cli", "@treeseed/agent"];
|
|
6
6
|
function parseSemver(version) {
|
|
7
7
|
const match = String(version).trim().match(/^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/);
|
|
8
8
|
if (!match) {
|
|
@@ -177,7 +177,8 @@ function run(command, args, options = {}) {
|
|
|
177
177
|
env: { ...process.env, ...options.env ?? {} },
|
|
178
178
|
stdio: options.capture ? "pipe" : "inherit",
|
|
179
179
|
encoding: "utf8",
|
|
180
|
-
timeout: options.timeoutMs
|
|
180
|
+
timeout: options.timeoutMs,
|
|
181
|
+
maxBuffer: options.maxBuffer ?? 1024 * 1024 * 32
|
|
181
182
|
});
|
|
182
183
|
if (result.status !== 0) {
|
|
183
184
|
const message = (result.error?.message ? `${result.error.message}
|
|
@@ -177,9 +177,10 @@ export interface TreeseedCloudflarePagesConfig {
|
|
|
177
177
|
previewProjectName?: string;
|
|
178
178
|
productionBranch?: string;
|
|
179
179
|
stagingBranch?: string;
|
|
180
|
+
buildCommand?: string;
|
|
180
181
|
buildOutputDir?: string;
|
|
181
182
|
}
|
|
182
|
-
export type TreeseedHostingKind = '
|
|
183
|
+
export type TreeseedHostingKind = 'treeseed_control_plane' | 'hosted_project' | 'self_hosted_project';
|
|
183
184
|
export type TreeseedHostingRegistration = 'optional' | 'none';
|
|
184
185
|
export type TreeseedHubMode = 'treeseed_hosted' | 'customer_hosted';
|
|
185
186
|
export type TreeseedRuntimeMode = 'none' | 'byo_attached' | 'treeseed_managed';
|
|
@@ -232,6 +233,15 @@ export interface TreeseedManagedServiceRailwayConfig {
|
|
|
232
233
|
healthcheckIntervalSeconds?: number;
|
|
233
234
|
restartPolicy?: string;
|
|
234
235
|
runtimeMode?: string;
|
|
236
|
+
resourceType?: string;
|
|
237
|
+
environmentVariable?: string;
|
|
238
|
+
serviceTargets?: string[];
|
|
239
|
+
volumeMountPath?: string;
|
|
240
|
+
runnerPool?: {
|
|
241
|
+
bootstrapCount?: number;
|
|
242
|
+
maxRunners?: number;
|
|
243
|
+
volumeMountPath?: string;
|
|
244
|
+
};
|
|
235
245
|
schedule?: string | string[];
|
|
236
246
|
}
|
|
237
247
|
export interface TreeseedManagedServiceConfig {
|
|
@@ -248,6 +258,14 @@ export interface TreeseedManagedServicesConfig {
|
|
|
248
258
|
api?: TreeseedManagedServiceConfig;
|
|
249
259
|
[key: string]: TreeseedManagedServiceConfig | undefined;
|
|
250
260
|
}
|
|
261
|
+
export interface TreeseedPublicTreeDxFederationConfig {
|
|
262
|
+
railway?: {
|
|
263
|
+
nodePool?: {
|
|
264
|
+
bootstrapCount?: number;
|
|
265
|
+
maxNodes?: number;
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
}
|
|
251
269
|
export interface TreeseedPlatformSurfacesConfig {
|
|
252
270
|
web?: TreeseedPlatformSurfaceConfig;
|
|
253
271
|
api?: TreeseedPlatformSurfaceConfig;
|
|
@@ -278,6 +296,14 @@ export interface TreeseedExportConfig {
|
|
|
278
296
|
ignore?: string[];
|
|
279
297
|
bundledPaths?: string[];
|
|
280
298
|
}
|
|
299
|
+
export interface TreeseedApiConnectionConfig {
|
|
300
|
+
proxyPrefix?: string;
|
|
301
|
+
localBaseUrl?: string;
|
|
302
|
+
environments?: Partial<Record<'local' | 'staging' | 'prod', {
|
|
303
|
+
baseUrl?: string;
|
|
304
|
+
domain?: string;
|
|
305
|
+
}>>;
|
|
306
|
+
}
|
|
281
307
|
export interface TreeseedDeployConfig {
|
|
282
308
|
name: string;
|
|
283
309
|
slug: string;
|
|
@@ -302,6 +328,11 @@ export interface TreeseedDeployConfig {
|
|
|
302
328
|
providers: TreeseedProviderSelections;
|
|
303
329
|
surfaces?: TreeseedPlatformSurfacesConfig;
|
|
304
330
|
services?: TreeseedManagedServicesConfig;
|
|
331
|
+
publicTreeDxFederation?: TreeseedPublicTreeDxFederationConfig;
|
|
332
|
+
connections?: {
|
|
333
|
+
api?: TreeseedApiConnectionConfig;
|
|
334
|
+
[key: string]: unknown;
|
|
335
|
+
};
|
|
305
336
|
processing?: TreeseedProcessingConfig;
|
|
306
337
|
capacityProviders?: Record<string, CapacityProviderRegistrationRequest>;
|
|
307
338
|
smtp?: {
|
|
@@ -181,12 +181,12 @@ function parseHostingConfig(value) {
|
|
|
181
181
|
}
|
|
182
182
|
return {
|
|
183
183
|
kind: optionalEnum(record.kind, "hosting.kind", [
|
|
184
|
-
"
|
|
184
|
+
"treeseed_control_plane",
|
|
185
185
|
"hosted_project",
|
|
186
186
|
"self_hosted_project"
|
|
187
187
|
]) ?? "self_hosted_project",
|
|
188
188
|
registration: optionalEnum(record.registration, "hosting.registration", ["optional", "none"]) ?? "none",
|
|
189
|
-
marketBaseUrl: optionalString(process.env.
|
|
189
|
+
marketBaseUrl: optionalString(process.env.TREESEED_API_BASE_URL) ?? optionalString(record.marketBaseUrl),
|
|
190
190
|
teamId: optionalString(process.env.TREESEED_HOSTING_TEAM_ID) ?? optionalString(record.teamId),
|
|
191
191
|
projectId: optionalString(process.env.TREESEED_PROJECT_ID) ?? optionalString(record.projectId)
|
|
192
192
|
};
|
|
@@ -198,12 +198,12 @@ function normalizePlanesFromLegacyHosting(hosting) {
|
|
|
198
198
|
runtime: { mode: "none", registration: "none" }
|
|
199
199
|
};
|
|
200
200
|
}
|
|
201
|
-
if (hosting.kind === "
|
|
201
|
+
if (hosting.kind === "treeseed_control_plane" || hosting.kind === "hosted_project") {
|
|
202
202
|
return {
|
|
203
203
|
hub: { mode: "treeseed_hosted" },
|
|
204
204
|
runtime: {
|
|
205
205
|
mode: "treeseed_managed",
|
|
206
|
-
registration: hosting.kind === "
|
|
206
|
+
registration: hosting.kind === "treeseed_control_plane" ? "none" : hosting.registration ?? "none",
|
|
207
207
|
marketBaseUrl: hosting.marketBaseUrl,
|
|
208
208
|
teamId: hosting.teamId,
|
|
209
209
|
projectId: hosting.projectId
|
|
@@ -262,7 +262,7 @@ function parseRuntimeConfig(value, fallback) {
|
|
|
262
262
|
return {
|
|
263
263
|
mode: optionalEnum(record.mode, "runtime.mode", ["none", "byo_attached", "treeseed_managed"]) ?? fallback.mode,
|
|
264
264
|
registration: optionalEnum(record.registration, "runtime.registration", ["optional", "required", "none"]) ?? fallback.registration ?? "none",
|
|
265
|
-
marketBaseUrl: optionalString(process.env.
|
|
265
|
+
marketBaseUrl: optionalString(process.env.TREESEED_API_BASE_URL) ?? fallback.marketBaseUrl,
|
|
266
266
|
teamId: optionalString(process.env.TREESEED_HOSTING_TEAM_ID) ?? fallback.teamId,
|
|
267
267
|
projectId: optionalString(process.env.TREESEED_PROJECT_ID) ?? fallback.projectId
|
|
268
268
|
};
|
|
@@ -378,6 +378,21 @@ function parseManagedServiceConfig(value, label) {
|
|
|
378
378
|
),
|
|
379
379
|
restartPolicy: optionalString(railway.restartPolicy),
|
|
380
380
|
runtimeMode: optionalString(railway.runtimeMode),
|
|
381
|
+
resourceType: optionalString(railway.resourceType),
|
|
382
|
+
environmentVariable: optionalString(railway.environmentVariable),
|
|
383
|
+
serviceTargets: optionalStringArray(railway.serviceTargets, `${label}.railway.serviceTargets`),
|
|
384
|
+
volumeMountPath: optionalString(railway.volumeMountPath),
|
|
385
|
+
runnerPool: optionalRecord(railway.runnerPool, `${label}.railway.runnerPool`) ? {
|
|
386
|
+
bootstrapCount: optionalPositiveNumber(
|
|
387
|
+
optionalRecord(railway.runnerPool, `${label}.railway.runnerPool`)?.bootstrapCount,
|
|
388
|
+
`${label}.railway.runnerPool.bootstrapCount`
|
|
389
|
+
),
|
|
390
|
+
maxRunners: optionalPositiveNumber(
|
|
391
|
+
optionalRecord(railway.runnerPool, `${label}.railway.runnerPool`)?.maxRunners,
|
|
392
|
+
`${label}.railway.runnerPool.maxRunners`
|
|
393
|
+
),
|
|
394
|
+
volumeMountPath: optionalString(optionalRecord(railway.runnerPool, `${label}.railway.runnerPool`)?.volumeMountPath)
|
|
395
|
+
} : void 0,
|
|
381
396
|
schedule: Array.isArray(railway.schedule) ? railway.schedule.map((entry) => optionalString(entry)).filter(Boolean) : optionalString(railway.schedule)
|
|
382
397
|
},
|
|
383
398
|
local: parseLocalRuntimeConfig(record.local, `${label}.local`),
|
|
@@ -388,6 +403,28 @@ function parseManagedServiceConfig(value, label) {
|
|
|
388
403
|
}
|
|
389
404
|
};
|
|
390
405
|
}
|
|
406
|
+
function parsePublicTreeDxFederationConfig(value) {
|
|
407
|
+
const record = optionalRecord(value, "publicTreeDxFederation");
|
|
408
|
+
if (!record) {
|
|
409
|
+
return void 0;
|
|
410
|
+
}
|
|
411
|
+
const railway = optionalRecord(record.railway, "publicTreeDxFederation.railway") ?? {};
|
|
412
|
+
const nodePool = optionalRecord(railway.nodePool, "publicTreeDxFederation.railway.nodePool") ?? {};
|
|
413
|
+
return {
|
|
414
|
+
railway: {
|
|
415
|
+
nodePool: {
|
|
416
|
+
bootstrapCount: optionalPositiveNumber(
|
|
417
|
+
nodePool.bootstrapCount,
|
|
418
|
+
"publicTreeDxFederation.railway.nodePool.bootstrapCount"
|
|
419
|
+
),
|
|
420
|
+
maxNodes: optionalPositiveNumber(
|
|
421
|
+
nodePool.maxNodes,
|
|
422
|
+
"publicTreeDxFederation.railway.nodePool.maxNodes"
|
|
423
|
+
)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
}
|
|
391
428
|
function parseManagedServicesConfig(value) {
|
|
392
429
|
const record = optionalRecord(value, "services");
|
|
393
430
|
if (!record) {
|
|
@@ -420,6 +457,31 @@ function parseProcessingConfig(value, services) {
|
|
|
420
457
|
requiredCapabilities: optionalStringArray(record.requiredCapabilities, "processing.requiredCapabilities")
|
|
421
458
|
};
|
|
422
459
|
}
|
|
460
|
+
function parseConnectionsConfig(value) {
|
|
461
|
+
const record = optionalRecord(value, "connections") ?? {};
|
|
462
|
+
const api = optionalRecord(record.api, "connections.api");
|
|
463
|
+
if (!api) {
|
|
464
|
+
return Object.keys(record).length > 0 ? record : void 0;
|
|
465
|
+
}
|
|
466
|
+
const environmentsRaw = optionalRecord(api.environments, "connections.api.environments") ?? {};
|
|
467
|
+
const environments = Object.fromEntries(
|
|
468
|
+
["local", "staging", "prod"].map((scope) => {
|
|
469
|
+
const environment = optionalRecord(environmentsRaw[scope], `connections.api.environments.${scope}`);
|
|
470
|
+
return [scope, environment ? {
|
|
471
|
+
baseUrl: optionalString(environment.baseUrl),
|
|
472
|
+
domain: optionalString(environment.domain)
|
|
473
|
+
} : void 0];
|
|
474
|
+
}).filter(([, environment]) => environment)
|
|
475
|
+
);
|
|
476
|
+
return {
|
|
477
|
+
...record,
|
|
478
|
+
api: {
|
|
479
|
+
proxyPrefix: optionalString(api.proxyPrefix),
|
|
480
|
+
localBaseUrl: optionalString(api.localBaseUrl),
|
|
481
|
+
environments
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
}
|
|
423
485
|
function inferManagedRuntimeFromServices(services) {
|
|
424
486
|
return Object.values(services ?? {}).some(
|
|
425
487
|
(service) => service && service.enabled !== false && (service.provider ?? "railway") === "railway"
|
|
@@ -542,7 +604,7 @@ function parseDeployConfig(raw) {
|
|
|
542
604
|
const turnstile = optionalRecord(parsed.turnstile, "turnstile") ?? {};
|
|
543
605
|
optionalBoolean(turnstile.enabled, "turnstile.enabled");
|
|
544
606
|
const normalizedHosting = normalizeLegacyHostingFromPlanes(hub, runtime);
|
|
545
|
-
const compatibilityHosting = hosting?.kind === "
|
|
607
|
+
const compatibilityHosting = hosting?.kind === "treeseed_control_plane" ? { ...hosting, registration: "none" } : hosting && !parsed.hub && !parsed.runtime ? hosting : normalizedHosting;
|
|
546
608
|
return {
|
|
547
609
|
name: expectString(parsed.name, "name"),
|
|
548
610
|
slug: expectString(parsed.slug, "slug"),
|
|
@@ -561,10 +623,11 @@ function parseDeployConfig(raw) {
|
|
|
561
623
|
d1Binding: optionalString(cloudflare.d1Binding),
|
|
562
624
|
queueBinding: optionalString(cloudflare.queueBinding),
|
|
563
625
|
pages: cloudflare.pages === void 0 ? void 0 : {
|
|
564
|
-
projectName: optionalString(
|
|
565
|
-
previewProjectName: optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PREVIEW_PROJECT_NAME) ?? optionalString(cloudflarePages.previewProjectName),
|
|
626
|
+
projectName: optionalString(cloudflarePages.projectName) ?? optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME),
|
|
627
|
+
previewProjectName: optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PREVIEW_PROJECT_NAME) ?? optionalString(cloudflarePages.previewProjectName) ?? optionalString(cloudflarePages.projectName) ?? optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME),
|
|
566
628
|
productionBranch: optionalString(cloudflarePages.productionBranch) ?? "main",
|
|
567
629
|
stagingBranch: optionalString(cloudflarePages.stagingBranch) ?? "staging",
|
|
630
|
+
buildCommand: optionalString(cloudflarePages.buildCommand),
|
|
568
631
|
buildOutputDir: optionalString(cloudflarePages.buildOutputDir)
|
|
569
632
|
},
|
|
570
633
|
r2: cloudflare.r2 === void 0 ? void 0 : {
|
|
@@ -580,6 +643,8 @@ function parseDeployConfig(raw) {
|
|
|
580
643
|
providers: parseProviderSelections(parsed.providers),
|
|
581
644
|
surfaces: parsePlatformSurfacesConfig(parsed.surfaces),
|
|
582
645
|
services,
|
|
646
|
+
publicTreeDxFederation: parsePublicTreeDxFederationConfig(parsed.publicTreeDxFederation),
|
|
647
|
+
connections: parseConnectionsConfig(parsed.connections),
|
|
583
648
|
processing,
|
|
584
649
|
capacityProviders: optionalRecord(parsed.capacityProviders, "capacityProviders"),
|
|
585
650
|
smtp: {
|