@treeseed/sdk 0.10.24 → 0.10.25
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/index.d.ts +12 -2
- package/dist/index.js +42 -1
- package/dist/market-client.d.ts +23 -0
- package/dist/market-client.js +30 -0
- package/dist/operations/providers/default.js +103 -10
- package/dist/operations/repository-operations.d.ts +6 -1
- package/dist/operations/repository-operations.js +44 -0
- package/dist/operations/services/config-runtime.d.ts +24 -9
- package/dist/operations/services/config-runtime.js +60 -12
- package/dist/operations/services/deploy.js +6 -1
- package/dist/operations/services/hub-launch.js +1 -0
- package/dist/operations/services/hub-provider-launch.d.ts +11 -1
- package/dist/operations/services/hub-provider-launch.js +81 -8
- package/dist/operations/services/project-host-operations.d.ts +153 -0
- package/dist/operations/services/project-host-operations.js +365 -0
- package/dist/operations/services/project-platform.d.ts +198 -193
- package/dist/operations/services/project-platform.js +29 -14
- package/dist/operations/services/railway-deploy.d.ts +3 -0
- package/dist/operations/services/railway-deploy.js +74 -35
- package/dist/operations/services/release-candidate.js +8 -2
- package/dist/operations/services/template-host-bindings.d.ts +68 -0
- package/dist/operations/services/template-host-bindings.js +400 -0
- package/dist/operations/services/template-registry.d.ts +22 -2
- package/dist/operations/services/template-registry.js +60 -3
- package/dist/operations/services/template-secret-sync.d.ts +97 -0
- package/dist/operations/services/template-secret-sync.js +292 -0
- package/dist/platform/environment.d.ts +3 -0
- package/dist/project-workflow.d.ts +7 -1
- package/dist/scripts/scaffold-site.js +3 -2
- package/dist/scripts/test-scaffold.js +2 -1
- package/dist/sdk-types.d.ts +87 -0
- package/dist/sdk-types.js +29 -0
- package/dist/template-catalog.js +3 -1
- package/dist/template-launch-requirements.d.ts +118 -0
- package/dist/template-launch-requirements.js +759 -0
- package/dist/template-launch-ui.d.ts +85 -0
- package/dist/template-launch-ui.js +189 -0
- package/dist/treeseed/template-catalog/catalog.fixture.json +330 -3
- package/package.json +13 -1
|
@@ -87,6 +87,30 @@ function configuredEnvValue(env, name) {
|
|
|
87
87
|
const value = env?.[name];
|
|
88
88
|
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
89
89
|
}
|
|
90
|
+
async function timedRailwayPhase(timings, name, run, metadata) {
|
|
91
|
+
const startMs = performance.now();
|
|
92
|
+
try {
|
|
93
|
+
const result = await Promise.resolve(run());
|
|
94
|
+
timings.push({
|
|
95
|
+
name,
|
|
96
|
+
durationMs: elapsedMs(startMs),
|
|
97
|
+
status: "success",
|
|
98
|
+
...metadata ? { metadata } : {}
|
|
99
|
+
});
|
|
100
|
+
return result;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
timings.push({
|
|
103
|
+
name,
|
|
104
|
+
durationMs: elapsedMs(startMs),
|
|
105
|
+
status: "failed",
|
|
106
|
+
metadata: {
|
|
107
|
+
...metadata ?? {},
|
|
108
|
+
error: error instanceof Error ? error.name || "Error" : "Error"
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
90
114
|
function parseRailwayJsonOutput(output) {
|
|
91
115
|
const trimmed = typeof output === "string" ? output.trim() : "";
|
|
92
116
|
if (!trimmed) {
|
|
@@ -1967,6 +1991,7 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
1967
1991
|
prefix,
|
|
1968
1992
|
env = process.env
|
|
1969
1993
|
} = {}) {
|
|
1994
|
+
const timings = [];
|
|
1970
1995
|
if (dryRun) {
|
|
1971
1996
|
const plan2 = planRailwayServiceDeploy(service, { env });
|
|
1972
1997
|
return {
|
|
@@ -1974,10 +1999,13 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
1974
1999
|
status: "planned",
|
|
1975
2000
|
command: [plan2.command, ...plan2.args].join(" "),
|
|
1976
2001
|
cwd: plan2.cwd,
|
|
1977
|
-
publicBaseUrl: service.publicBaseUrl
|
|
2002
|
+
publicBaseUrl: service.publicBaseUrl,
|
|
2003
|
+
timings
|
|
1978
2004
|
};
|
|
1979
2005
|
}
|
|
1980
|
-
const deployService = await resolveRailwayDeployProjectContext(service, { env })
|
|
2006
|
+
const deployService = await timedRailwayPhase(timings, "railway:resolve-context", () => resolveRailwayDeployProjectContext(service, { env }), {
|
|
2007
|
+
service: service.key
|
|
2008
|
+
});
|
|
1981
2009
|
const commandEnv = buildRailwayCommandEnv({ ...process.env, ...env });
|
|
1982
2010
|
let railwayDeployEnv = buildRailwayDeployCommandEnv(commandEnv);
|
|
1983
2011
|
const railway = resolveTreeseedToolCommand("railway", { env: commandEnv });
|
|
@@ -1990,9 +2018,9 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
1990
2018
|
task: `${deployService.key}-railway-deploy`,
|
|
1991
2019
|
stage: "deploy"
|
|
1992
2020
|
};
|
|
1993
|
-
const runtimeConfiguration = await syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, deployService, {
|
|
2021
|
+
const runtimeConfiguration = await timedRailwayPhase(timings, "railway:sync-runtime-config", () => syncRailwayServiceRuntimeConfigurationAfterDeploy(tenantRoot, deployService, {
|
|
1994
2022
|
env: commandEnv
|
|
1995
|
-
});
|
|
2023
|
+
}), { service: deployService.key });
|
|
1996
2024
|
const cliDeployService = {
|
|
1997
2025
|
...deployService,
|
|
1998
2026
|
projectId: runtimeConfiguration?.projectId ?? deployService.projectId,
|
|
@@ -2002,14 +2030,19 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
2002
2030
|
serviceName: runtimeConfiguration?.serviceName ?? deployService.serviceName,
|
|
2003
2031
|
railwayEnvironment: runtimeConfiguration?.environmentName ?? runtimeConfiguration?.environmentId ?? deployService.railwayEnvironment
|
|
2004
2032
|
};
|
|
2005
|
-
await syncRailwayApiDeviceLoginVariables(cliDeployService, commandEnv, write, taskPrefix)
|
|
2033
|
+
await timedRailwayPhase(timings, "railway:device-login-vars", () => syncRailwayApiDeviceLoginVariables(cliDeployService, commandEnv, write, taskPrefix), {
|
|
2034
|
+
service: cliDeployService.key
|
|
2035
|
+
});
|
|
2006
2036
|
railwayDeployEnv = buildRailwayCliContextEnv(railwayDeployEnv, cliDeployService);
|
|
2007
2037
|
const hasCommandApiToken = Boolean(configuredEnvValue(commandEnv, "RAILWAY_API_TOKEN"));
|
|
2008
2038
|
let usesProjectToken = Boolean(configuredEnvValue(railwayDeployEnv, "RAILWAY_TOKEN"));
|
|
2009
2039
|
if (usesProjectToken) {
|
|
2010
2040
|
railwayDeployEnv = { ...railwayDeployEnv, RAILWAY_API_TOKEN: void 0 };
|
|
2011
2041
|
}
|
|
2012
|
-
|
|
2042
|
+
await timedRailwayPhase(timings, "railway:project-token", async () => {
|
|
2043
|
+
if (usesProjectToken || hasCommandApiToken) {
|
|
2044
|
+
return null;
|
|
2045
|
+
}
|
|
2013
2046
|
const projectToken = await createRailwayCliProjectToken(cliDeployService, { env: commandEnv });
|
|
2014
2047
|
if (projectToken) {
|
|
2015
2048
|
railwayDeployEnv = buildRailwayCliContextEnv({ ...railwayDeployEnv, RAILWAY_API_TOKEN: void 0, RAILWAY_TOKEN: projectToken }, cliDeployService);
|
|
@@ -2017,16 +2050,17 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
2017
2050
|
} else if (configuredEnvValue(commandEnv, "CI") === "true") {
|
|
2018
2051
|
throw new Error(`Railway CI deploy requires a project token for ${cliDeployService.serviceName ?? cliDeployService.key}. Automatic project token creation did not return a token.`);
|
|
2019
2052
|
}
|
|
2020
|
-
|
|
2053
|
+
return null;
|
|
2054
|
+
}, { service: cliDeployService.key });
|
|
2021
2055
|
const linkPlan = planRailwayServiceLink(cliDeployService, { env: commandEnv });
|
|
2022
2056
|
const plan = planRailwayServiceDeploy(cliDeployService, { env, projectTokenMode: usesProjectToken });
|
|
2023
2057
|
if (deployService.buildCommand && shouldRunRailwayPredeployBuild(commandEnv)) {
|
|
2024
|
-
const buildResult = await runPrefixedCommand("bash", ["-lc", deployService.buildCommand], {
|
|
2058
|
+
const buildResult = await timedRailwayPhase(timings, "railway:predeploy-build", () => runPrefixedCommand("bash", ["-lc", deployService.buildCommand], {
|
|
2025
2059
|
cwd: deployService.rootDir,
|
|
2026
2060
|
env: commandEnv,
|
|
2027
2061
|
write,
|
|
2028
2062
|
prefix: { ...taskPrefix, stage: "build" }
|
|
2029
|
-
});
|
|
2063
|
+
}), { service: deployService.key });
|
|
2030
2064
|
if (buildResult.status !== 0) {
|
|
2031
2065
|
throw new Error(`Railway ${deployService.key} build command failed.`);
|
|
2032
2066
|
}
|
|
@@ -2035,9 +2069,11 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
2035
2069
|
const cliConfig = configuredEnvValue(commandEnv, "CI") === "true" ? writeRailwayCliProjectConfig(cliDeployService, { env: railwayDeployEnv, cwd: plan.cwd }) : null;
|
|
2036
2070
|
const effectiveLinkPlan = hasRailwayApiToken ? linkPlan : usesProjectToken ? planRailwayProjectEnvironmentLink(cliDeployService) : linkPlan;
|
|
2037
2071
|
const railwayLinkEnv = hasRailwayApiToken ? buildRailwayLinkCommandEnv(commandEnv, cliDeployService) : railwayDeployEnv;
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2072
|
+
await timedRailwayPhase(timings, "railway:link", async () => {
|
|
2073
|
+
if (cliConfig) {
|
|
2074
|
+
write ? write(`[${taskPrefix.scope}][${taskPrefix.system}][${taskPrefix.task}][link] Wrote Railway CLI project context for ${cliConfig.projectPath}.`, "stdout") : null;
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
2041
2077
|
const linkResult = await runPrefixedCommand(railway.command, [...railway.argsPrefix, ...effectiveLinkPlan.args], {
|
|
2042
2078
|
cwd: effectiveLinkPlan.cwd,
|
|
2043
2079
|
env: railwayLinkEnv,
|
|
@@ -2047,37 +2083,40 @@ async function deployRailwayService(tenantRoot, service, {
|
|
|
2047
2083
|
if (linkResult.status !== 0) {
|
|
2048
2084
|
throw new Error(linkResult.stderr?.trim() || linkResult.stdout?.trim() || `railway ${effectiveLinkPlan.args.join(" ")} failed with exit code ${linkResult.status ?? "unknown"} in ${effectiveLinkPlan.cwd}`);
|
|
2049
2085
|
}
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2086
|
+
}, { service: cliDeployService.key });
|
|
2087
|
+
await timedRailwayPhase(timings, "railway:deploy", async () => {
|
|
2088
|
+
let lastFailure = null;
|
|
2089
|
+
for (let attempt = 1; attempt <= 5; attempt += 1) {
|
|
2090
|
+
const result = await runPrefixedCommand(railway.command, [...railway.argsPrefix, ...plan.args], {
|
|
2091
|
+
cwd: plan.cwd,
|
|
2092
|
+
env: railwayDeployEnv,
|
|
2093
|
+
write,
|
|
2094
|
+
prefix: taskPrefix
|
|
2095
|
+
});
|
|
2096
|
+
if (result.status === 0) {
|
|
2097
|
+
lastFailure = null;
|
|
2098
|
+
break;
|
|
2099
|
+
}
|
|
2100
|
+
lastFailure = result;
|
|
2101
|
+
if (!isRailwayTransientFailure(result) || attempt === 5) {
|
|
2102
|
+
throw new Error(result.stderr?.trim() || result.stdout?.trim() || `railway ${plan.args.join(" ")} failed with exit code ${result.status ?? "unknown"} in ${plan.cwd}`);
|
|
2103
|
+
}
|
|
2104
|
+
const backoffMs = 5e3 * attempt;
|
|
2105
|
+
const warning = `Railway deploy for ${deployService.serviceName ?? deployService.serviceId ?? deployService.key} hit a transient failure; retrying in ${Math.round(backoffMs / 1e3)}s...`;
|
|
2106
|
+
write ? write(`[${taskPrefix.scope}][${taskPrefix.system}][${taskPrefix.task}][retry] ${warning}`, "stderr") : console.warn(warning);
|
|
2107
|
+
await sleep(backoffMs);
|
|
2062
2108
|
}
|
|
2063
|
-
lastFailure
|
|
2064
|
-
|
|
2065
|
-
throw new Error(result.stderr?.trim() || result.stdout?.trim() || `railway ${plan.args.join(" ")} failed with exit code ${result.status ?? "unknown"} in ${plan.cwd}`);
|
|
2109
|
+
if (lastFailure) {
|
|
2110
|
+
throw new Error(lastFailure.stderr?.trim() || lastFailure.stdout?.trim() || `railway ${plan.args.join(" ")} failed`);
|
|
2066
2111
|
}
|
|
2067
|
-
|
|
2068
|
-
const warning = `Railway deploy for ${deployService.serviceName ?? deployService.serviceId ?? deployService.key} hit a transient failure; retrying in ${Math.round(backoffMs / 1e3)}s...`;
|
|
2069
|
-
write ? write(`[${taskPrefix.scope}][${taskPrefix.system}][${taskPrefix.task}][retry] ${warning}`, "stderr") : console.warn(warning);
|
|
2070
|
-
await sleep(backoffMs);
|
|
2071
|
-
}
|
|
2072
|
-
if (lastFailure) {
|
|
2073
|
-
throw new Error(lastFailure.stderr?.trim() || lastFailure.stdout?.trim() || `railway ${plan.args.join(" ")} failed`);
|
|
2074
|
-
}
|
|
2112
|
+
}, { service: cliDeployService.key });
|
|
2075
2113
|
return {
|
|
2076
2114
|
service: deployService.key,
|
|
2077
2115
|
status: "deployed",
|
|
2078
2116
|
command: [plan.command, ...plan.args].join(" "),
|
|
2079
2117
|
cwd: plan.cwd,
|
|
2080
2118
|
publicBaseUrl: deployService.publicBaseUrl,
|
|
2119
|
+
timings,
|
|
2081
2120
|
runtimeConfiguration: runtimeConfiguration ? {
|
|
2082
2121
|
updated: runtimeConfiguration.updated,
|
|
2083
2122
|
healthcheckPath: runtimeConfiguration.instance?.healthcheckPath ?? null,
|
|
@@ -244,7 +244,7 @@ function rehearsalVerifyScript(root) {
|
|
|
244
244
|
function runNpmRehearsalCommand(args, options) {
|
|
245
245
|
const result = spawnSync("npm", args, {
|
|
246
246
|
cwd: options.cwd,
|
|
247
|
-
env: process.env,
|
|
247
|
+
env: options.env ?? process.env,
|
|
248
248
|
stdio: "pipe",
|
|
249
249
|
encoding: "utf8",
|
|
250
250
|
timeout: options.timeoutMs
|
|
@@ -320,7 +320,13 @@ function runProductionDependencyRehearsal(root, plannedVersions, selectedPackage
|
|
|
320
320
|
buildRehearsalWorkspacePackageArtifacts(copied.tempRoot);
|
|
321
321
|
const scriptName = rehearsalVerifyScript(copied.tempRoot);
|
|
322
322
|
if (scriptName) {
|
|
323
|
-
|
|
323
|
+
const packageJson = safePackageJson(resolve(copied.tempRoot, "package.json"));
|
|
324
|
+
const parallelMarketVerify = packageJson?.name === "@treeseed/market" && (scriptName === "verify:direct" || scriptName === "verify:local" || scriptName === "verify");
|
|
325
|
+
runNpmRehearsalCommand(["run", scriptName], {
|
|
326
|
+
cwd: copied.tempRoot,
|
|
327
|
+
timeoutMs: 9e5,
|
|
328
|
+
env: parallelMarketVerify ? { ...process.env, TREESEED_VERIFY_PARALLEL: "1" } : process.env
|
|
329
|
+
});
|
|
324
330
|
}
|
|
325
331
|
const postInstallIssues = collectInternalDevReferenceIssues(copied.tempRoot, selectedPackageSet);
|
|
326
332
|
if (postInstallIssues.length > 0) {
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { type ProjectEnvironmentName, type TemplateConfigMergeStrategy, type TemplateConfigWriteTarget, type TemplateSecretSensitivity } from '../../sdk-types.ts';
|
|
2
|
+
import type { ProjectLaunchConfigWritePlanItem, ProjectLaunchResolvedHostBinding, ProjectLaunchSecretDeploymentPlanItem } from '../../template-launch-requirements.ts';
|
|
3
|
+
export interface ApplyProjectLaunchHostBindingConfigOptions {
|
|
4
|
+
projectRoot: string;
|
|
5
|
+
hostBindings?: Record<string, ProjectLaunchResolvedHostBinding> | null;
|
|
6
|
+
hostBindingPlans?: {
|
|
7
|
+
configWrites?: ProjectLaunchConfigWritePlanItem[];
|
|
8
|
+
secretDeployment?: {
|
|
9
|
+
items?: ProjectLaunchSecretDeploymentPlanItem[];
|
|
10
|
+
};
|
|
11
|
+
} | null;
|
|
12
|
+
launchInput?: {
|
|
13
|
+
projectSlug?: string | null;
|
|
14
|
+
projectName?: string | null;
|
|
15
|
+
repoName?: string | null;
|
|
16
|
+
domains?: Record<string, unknown> | null;
|
|
17
|
+
} | null;
|
|
18
|
+
derived?: {
|
|
19
|
+
projectSlug?: string | null;
|
|
20
|
+
projectName?: string | null;
|
|
21
|
+
repositoryName?: string | null;
|
|
22
|
+
} | null;
|
|
23
|
+
}
|
|
24
|
+
export interface ProjectLaunchHostBindingConfigWriteSummary {
|
|
25
|
+
target: TemplateConfigWriteTarget;
|
|
26
|
+
path: string;
|
|
27
|
+
requirementKey: string;
|
|
28
|
+
requirementKind: string;
|
|
29
|
+
provider: string;
|
|
30
|
+
operation: TemplateConfigMergeStrategy;
|
|
31
|
+
valuePreview: string | number | boolean | null;
|
|
32
|
+
}
|
|
33
|
+
export interface ProjectLaunchHostBindingEnvironmentWriteSummary {
|
|
34
|
+
env: string;
|
|
35
|
+
requirementKey: string;
|
|
36
|
+
requirementKind: string;
|
|
37
|
+
sourceHostType?: string | null;
|
|
38
|
+
sourceProvider?: string | null;
|
|
39
|
+
sensitivity: TemplateSecretSensitivity | string;
|
|
40
|
+
targets: string[];
|
|
41
|
+
scopes: ProjectEnvironmentName[];
|
|
42
|
+
}
|
|
43
|
+
export interface ProjectLaunchHostBindingConfigApplyResult {
|
|
44
|
+
configWrites: ProjectLaunchHostBindingConfigWriteSummary[];
|
|
45
|
+
environmentWrites: ProjectLaunchHostBindingEnvironmentWriteSummary[];
|
|
46
|
+
targets: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface ProjectLaunchHostBindingConfigAuditDiagnostic {
|
|
49
|
+
code: 'missing_config_target' | 'stale_config_target' | 'invalid_config_target';
|
|
50
|
+
status: 'ok' | 'warning' | 'blocked';
|
|
51
|
+
target: TemplateConfigWriteTarget;
|
|
52
|
+
message: string;
|
|
53
|
+
}
|
|
54
|
+
export interface ProjectLaunchHostBindingConfigAuditResult {
|
|
55
|
+
status: 'ok' | 'warning' | 'blocked';
|
|
56
|
+
checkedTargets: TemplateConfigWriteTarget[];
|
|
57
|
+
changedTargets: TemplateConfigWriteTarget[];
|
|
58
|
+
diagnostics: ProjectLaunchHostBindingConfigAuditDiagnostic[];
|
|
59
|
+
expected: ProjectLaunchHostBindingConfigApplyResult;
|
|
60
|
+
}
|
|
61
|
+
export declare function applyProjectLaunchHostBindingConfig(options: ApplyProjectLaunchHostBindingConfigOptions): ProjectLaunchHostBindingConfigApplyResult;
|
|
62
|
+
export declare function auditProjectLaunchHostBindingConfig(options: ApplyProjectLaunchHostBindingConfigOptions): ProjectLaunchHostBindingConfigAuditResult;
|
|
63
|
+
export declare function preserveProjectLaunchHostBindingConfigOverlay(options: {
|
|
64
|
+
target: TemplateConfigWriteTarget;
|
|
65
|
+
currentContent: string;
|
|
66
|
+
nextContent: string;
|
|
67
|
+
hostBindingPlans?: ApplyProjectLaunchHostBindingConfigOptions['hostBindingPlans'];
|
|
68
|
+
}): string;
|