@treeseed/sdk 0.4.12 → 0.5.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/dist/control-plane-client.d.ts +60 -1
- package/dist/control-plane-client.js +59 -0
- package/dist/control-plane.d.ts +1 -1
- package/dist/control-plane.js +11 -4
- package/dist/d1-store.d.ts +58 -0
- package/dist/d1-store.js +64 -0
- package/dist/dispatch.js +6 -0
- package/dist/graph/schema.js +4 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +32 -0
- package/dist/knowledge-coop.d.ts +223 -0
- package/dist/knowledge-coop.js +82 -0
- package/dist/model-registry.js +79 -0
- package/dist/operations/providers/default.js +128 -7
- package/dist/operations/services/config-runtime.d.ts +102 -24
- package/dist/operations/services/config-runtime.js +896 -160
- package/dist/operations/services/deploy.d.ts +223 -15
- package/dist/operations/services/deploy.js +626 -55
- package/dist/operations/services/git-workflow.d.ts +47 -3
- package/dist/operations/services/git-workflow.js +125 -19
- package/dist/operations/services/github-automation.d.ts +85 -0
- package/dist/operations/services/github-automation.js +220 -1
- package/dist/operations/services/key-agent.d.ts +118 -0
- package/dist/operations/services/key-agent.js +476 -0
- package/dist/operations/services/knowledge-coop-launch.d.ts +90 -0
- package/dist/operations/services/knowledge-coop-launch.js +753 -0
- package/dist/operations/services/knowledge-coop-packaging.d.ts +59 -0
- package/dist/operations/services/knowledge-coop-packaging.js +234 -0
- package/dist/operations/services/local-dev.d.ts +0 -1
- package/dist/operations/services/local-dev.js +1 -14
- package/dist/operations/services/project-platform.d.ts +42 -182
- package/dist/operations/services/project-platform.js +162 -59
- package/dist/operations/services/railway-deploy.d.ts +1 -0
- package/dist/operations/services/railway-deploy.js +31 -13
- package/dist/operations/services/runtime-tools.d.ts +52 -5
- package/dist/operations/services/runtime-tools.js +186 -26
- package/dist/operations/services/watch-dev.js +2 -4
- package/dist/operations/services/workspace-preflight.d.ts +4 -4
- package/dist/operations/services/workspace-preflight.js +22 -20
- package/dist/operations/services/workspace-save.d.ts +10 -1
- package/dist/operations/services/workspace-save.js +54 -3
- package/dist/operations/services/workspace-tools.d.ts +1 -0
- package/dist/operations/services/workspace-tools.js +20 -5
- package/dist/operations-registry.js +15 -8
- package/dist/operations-types.d.ts +2 -2
- package/dist/platform/contracts.d.ts +39 -3
- package/dist/platform/deploy-config.d.ts +12 -1
- package/dist/platform/deploy-config.js +214 -15
- package/dist/platform/deploy-runtime.d.ts +1 -0
- package/dist/platform/deploy-runtime.js +10 -2
- package/dist/platform/env.yaml +93 -61
- package/dist/platform/environment.d.ts +13 -2
- package/dist/platform/environment.js +90 -20
- package/dist/platform/plugins/constants.d.ts +1 -0
- package/dist/platform/plugins/constants.js +7 -6
- package/dist/platform/tenant/runtime-config.js +8 -1
- package/dist/platform/tenant-config.js +4 -0
- package/dist/platform/utils/site-config-schema.js +18 -0
- package/dist/plugin-default.js +2 -2
- package/dist/scripts/key-agent.js +165 -0
- package/dist/scripts/tenant-build.js +4 -1
- package/dist/scripts/tenant-check.js +4 -1
- package/dist/scripts/tenant-deploy.js +43 -4
- package/dist/scripts/tenant-dev.js +0 -1
- package/dist/scripts/workspace-start-warning.js +2 -2
- package/dist/sdk-types.d.ts +2 -2
- package/dist/sdk-types.js +2 -0
- package/dist/sdk.d.ts +13 -0
- package/dist/sdk.js +40 -0
- package/dist/stores/knowledge-coop-store.d.ts +56 -0
- package/dist/stores/knowledge-coop-store.js +482 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +6 -2
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/api/server.js +4 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +25 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/decisions/adopt-initial-proposal-loop.mdx +22 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/people/starter-steward.mdx +11 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/proposals/establish-initial-proposal-loop.mdx +17 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +17 -10
- package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +69 -7
- package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +1 -0
- package/dist/workflow/operations.d.ts +592 -243
- package/dist/workflow/operations.js +1908 -219
- package/dist/workflow/runs.d.ts +90 -0
- package/dist/workflow/runs.js +242 -0
- package/dist/workflow/session.d.ts +31 -0
- package/dist/workflow/session.js +97 -0
- package/dist/workflow-state.d.ts +88 -2
- package/dist/workflow-state.js +288 -26
- package/dist/workflow-support.d.ts +1 -1
- package/dist/workflow-support.js +32 -2
- package/dist/workflow.d.ts +93 -3
- package/dist/workflow.js +12 -0
- package/package.json +1 -1
- package/templates/github/deploy.workflow.yml +11 -1
- package/dist/scripts/sync-dev-vars.js +0 -6
- package/dist/scripts/workspace-close.js +0 -24
- package/dist/scripts/workspace-release.js +0 -42
- package/dist/scripts/workspace-start.js +0 -71
|
@@ -37,12 +37,12 @@ const TREESEED_DEFAULT_PLUGIN_REFERENCES = [
|
|
|
37
37
|
const TREESEED_DEFAULT_PROVIDER_SELECTIONS = {
|
|
38
38
|
forms: "store_only",
|
|
39
39
|
agents: {
|
|
40
|
-
execution: "
|
|
40
|
+
execution: "copilot",
|
|
41
41
|
mutation: "local_branch",
|
|
42
|
-
repository: "
|
|
43
|
-
verification: "
|
|
44
|
-
notification: "
|
|
45
|
-
research: "
|
|
42
|
+
repository: "git",
|
|
43
|
+
verification: "local",
|
|
44
|
+
notification: "sdk_message",
|
|
45
|
+
research: "project_graph"
|
|
46
46
|
},
|
|
47
47
|
deploy: "cloudflare",
|
|
48
48
|
content: {
|
|
@@ -52,9 +52,57 @@ const TREESEED_DEFAULT_PROVIDER_SELECTIONS = {
|
|
|
52
52
|
},
|
|
53
53
|
site: "default"
|
|
54
54
|
};
|
|
55
|
-
const TRESEED_MANAGED_SERVICE_KEYS = ["api", "
|
|
55
|
+
const TRESEED_MANAGED_SERVICE_KEYS = ["api", "manager", "worker", "workdayStart", "workdayReport"];
|
|
56
56
|
const TRESEED_WORKSPACE_PACKAGE_DIRS = ["sdk", "core", "cli"];
|
|
57
57
|
const CLOUDFLARE_ACCOUNT_ID_PLACEHOLDER = "replace-with-cloudflare-account-id";
|
|
58
|
+
function normalizePlanesFromLegacyHosting(hosting) {
|
|
59
|
+
if (!hosting || Object.keys(hosting).length === 0) {
|
|
60
|
+
return {
|
|
61
|
+
hub: { mode: "treeseed_hosted" },
|
|
62
|
+
runtime: { mode: "none", registration: "none" }
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (hosting.kind === "market_control_plane" || hosting.kind === "hosted_project") {
|
|
66
|
+
return {
|
|
67
|
+
hub: { mode: "treeseed_hosted" },
|
|
68
|
+
runtime: {
|
|
69
|
+
mode: "treeseed_managed",
|
|
70
|
+
registration: hosting.kind === "market_control_plane" ? "none" : hosting.registration ?? "none",
|
|
71
|
+
marketBaseUrl: hosting.marketBaseUrl,
|
|
72
|
+
teamId: hosting.teamId,
|
|
73
|
+
projectId: hosting.projectId
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
hub: { mode: "customer_hosted" },
|
|
79
|
+
runtime: {
|
|
80
|
+
mode: "byo_attached",
|
|
81
|
+
registration: hosting.registration ?? "none",
|
|
82
|
+
marketBaseUrl: hosting.marketBaseUrl,
|
|
83
|
+
teamId: hosting.teamId,
|
|
84
|
+
projectId: hosting.projectId
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function normalizeLegacyHostingFromPlanes(hub, runtime) {
|
|
89
|
+
if (runtime.mode === "treeseed_managed" && hub.mode === "treeseed_hosted") {
|
|
90
|
+
return {
|
|
91
|
+
kind: "hosted_project",
|
|
92
|
+
registration: runtime.registration === "required" ? "optional" : runtime.registration ?? "none",
|
|
93
|
+
marketBaseUrl: runtime.marketBaseUrl,
|
|
94
|
+
teamId: runtime.teamId,
|
|
95
|
+
projectId: runtime.projectId
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
kind: "self_hosted_project",
|
|
100
|
+
registration: runtime.registration === "required" ? "optional" : runtime.registration ?? "none",
|
|
101
|
+
marketBaseUrl: runtime.marketBaseUrl,
|
|
102
|
+
teamId: runtime.teamId,
|
|
103
|
+
projectId: runtime.projectId
|
|
104
|
+
};
|
|
105
|
+
}
|
|
58
106
|
function parseServiceEnvironmentConfig(value) {
|
|
59
107
|
const record = optionalRecord(value, "service environment") ?? {};
|
|
60
108
|
return {
|
|
@@ -108,6 +156,81 @@ function parseManagedServicesConfig(value) {
|
|
|
108
156
|
])
|
|
109
157
|
);
|
|
110
158
|
}
|
|
159
|
+
function parseWebSurfaceCacheConfig(value, label) {
|
|
160
|
+
const record = optionalRecord(value, label) ?? {};
|
|
161
|
+
if (Object.keys(record).length === 0) {
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
sourcePages: parseWebCachePolicyRecord(record.sourcePages ?? record.source_pages, `${label}.sourcePages`, {
|
|
166
|
+
paths: ["/", "/contact", "/404"]
|
|
167
|
+
}),
|
|
168
|
+
contentPages: parseWebCachePolicyRecord(record.contentPages ?? record.content_pages, `${label}.contentPages`),
|
|
169
|
+
r2PublishedObjects: parseWebCachePolicyRecord(
|
|
170
|
+
record.r2PublishedObjects ?? record.r2_published_objects,
|
|
171
|
+
`${label}.r2PublishedObjects`
|
|
172
|
+
)
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function parseWebCachePolicyRecord(value, label, options = {}) {
|
|
176
|
+
const record = optionalRecord(value, label) ?? {};
|
|
177
|
+
if (Object.keys(record).length === 0) {
|
|
178
|
+
return options.paths ? { paths: [...options.paths] } : void 0;
|
|
179
|
+
}
|
|
180
|
+
const parsed = {
|
|
181
|
+
browserTtlSeconds: optionalNonNegativeNumber(
|
|
182
|
+
record.browserTtlSeconds ?? record.browser_ttl_seconds,
|
|
183
|
+
`${label}.browserTtlSeconds`
|
|
184
|
+
),
|
|
185
|
+
edgeTtlSeconds: optionalNonNegativeNumber(
|
|
186
|
+
record.edgeTtlSeconds ?? record.edge_ttl_seconds,
|
|
187
|
+
`${label}.edgeTtlSeconds`
|
|
188
|
+
),
|
|
189
|
+
staleWhileRevalidateSeconds: optionalNonNegativeNumber(
|
|
190
|
+
record.staleWhileRevalidateSeconds ?? record.stale_while_revalidate_seconds,
|
|
191
|
+
`${label}.staleWhileRevalidateSeconds`
|
|
192
|
+
),
|
|
193
|
+
staleIfErrorSeconds: optionalNonNegativeNumber(
|
|
194
|
+
record.staleIfErrorSeconds ?? record.stale_if_error_seconds,
|
|
195
|
+
`${label}.staleIfErrorSeconds`
|
|
196
|
+
)
|
|
197
|
+
};
|
|
198
|
+
if (options.paths) {
|
|
199
|
+
parsed.paths = [...new Set(Array.isArray(record.paths) ? record.paths.map((entry) => optionalString(entry)).filter(Boolean) : options.paths)];
|
|
200
|
+
}
|
|
201
|
+
return parsed;
|
|
202
|
+
}
|
|
203
|
+
function parseSurfaceConfig(value, label) {
|
|
204
|
+
const record = optionalRecord(value, label);
|
|
205
|
+
if (!record) {
|
|
206
|
+
return void 0;
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
enabled: record.enabled === void 0 ? void 0 : optionalBoolean(record.enabled, `${label}.enabled`),
|
|
210
|
+
provider: optionalString(record.provider),
|
|
211
|
+
rootDir: optionalString(record.rootDir),
|
|
212
|
+
publicBaseUrl: optionalString(record.publicBaseUrl),
|
|
213
|
+
localBaseUrl: optionalString(record.localBaseUrl),
|
|
214
|
+
cache: parseWebSurfaceCacheConfig(record.cache, `${label}.cache`)
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function parsePlatformSurfacesConfig(value) {
|
|
218
|
+
const record = optionalRecord(value, "surfaces");
|
|
219
|
+
if (!record) {
|
|
220
|
+
return void 0;
|
|
221
|
+
}
|
|
222
|
+
return Object.fromEntries(
|
|
223
|
+
Object.entries(record).map(([surfaceKey, surfaceValue]) => [
|
|
224
|
+
surfaceKey,
|
|
225
|
+
parseSurfaceConfig(surfaceValue, `surfaces.${surfaceKey}`)
|
|
226
|
+
])
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
function inferManagedRuntimeFromServices(services) {
|
|
230
|
+
return Object.values(services ?? {}).some(
|
|
231
|
+
(service) => service && service.enabled !== false && (service.provider ?? "railway") === "railway"
|
|
232
|
+
);
|
|
233
|
+
}
|
|
111
234
|
const packageRoot = packageRootFromSource;
|
|
112
235
|
const packageScriptRoot = resolve(packageRoot, "scripts");
|
|
113
236
|
const packageDistScriptRoot = resolve(packageRoot, "dist", "scripts");
|
|
@@ -272,6 +395,15 @@ function optionalPositiveNumber(value, label) {
|
|
|
272
395
|
}
|
|
273
396
|
return value;
|
|
274
397
|
}
|
|
398
|
+
function optionalNonNegativeNumber(value, label) {
|
|
399
|
+
if (value === void 0) {
|
|
400
|
+
return void 0;
|
|
401
|
+
}
|
|
402
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
403
|
+
throw new Error(`Invalid deploy config: expected ${label} to be a non-negative number when provided.`);
|
|
404
|
+
}
|
|
405
|
+
return value;
|
|
406
|
+
}
|
|
275
407
|
function optionalEnum(value, label, allowed) {
|
|
276
408
|
const normalized = optionalString(value);
|
|
277
409
|
if (!normalized) {
|
|
@@ -314,6 +446,35 @@ function parseFallbackDeployConfig(configPath) {
|
|
|
314
446
|
const cloudflarePages = optionalRecord(cloudflare.pages, "cloudflare.pages") ?? {};
|
|
315
447
|
const cloudflareR2 = optionalRecord(cloudflare.r2, "cloudflare.r2") ?? {};
|
|
316
448
|
const hosting = optionalRecord(record.hosting, "hosting") ?? {};
|
|
449
|
+
const parsedHosting = Object.keys(hosting).length === 0 ? void 0 : {
|
|
450
|
+
kind: optionalEnum(hosting.kind, "hosting.kind", [
|
|
451
|
+
"market_control_plane",
|
|
452
|
+
"hosted_project",
|
|
453
|
+
"self_hosted_project"
|
|
454
|
+
]) ?? "self_hosted_project",
|
|
455
|
+
registration: optionalEnum(hosting.registration, "hosting.registration", ["optional", "none"]) ?? "none",
|
|
456
|
+
marketBaseUrl: optionalString(process.env.TREESEED_MARKET_API_BASE_URL),
|
|
457
|
+
teamId: optionalString(process.env.TREESEED_HOSTING_TEAM_ID),
|
|
458
|
+
projectId: optionalString(process.env.TREESEED_PROJECT_ID)
|
|
459
|
+
};
|
|
460
|
+
const services = parseManagedServicesConfig(record.services);
|
|
461
|
+
const normalizedPlanes = normalizePlanesFromLegacyHosting(parsedHosting);
|
|
462
|
+
const inferredPlanes = !parsedHosting && record.hub === void 0 && record.runtime === void 0 && inferManagedRuntimeFromServices(services) ? {
|
|
463
|
+
hub: { mode: "customer_hosted" },
|
|
464
|
+
runtime: { mode: "treeseed_managed", registration: "none" }
|
|
465
|
+
} : normalizedPlanes;
|
|
466
|
+
const hubRecord = optionalRecord(record.hub, "hub") ?? {};
|
|
467
|
+
const runtimeRecord = optionalRecord(record.runtime, "runtime") ?? {};
|
|
468
|
+
const hub = {
|
|
469
|
+
mode: optionalEnum(hubRecord.mode, "hub.mode", ["treeseed_hosted", "customer_hosted"]) ?? inferredPlanes.hub.mode
|
|
470
|
+
};
|
|
471
|
+
const runtime = {
|
|
472
|
+
mode: optionalEnum(runtimeRecord.mode, "runtime.mode", ["none", "byo_attached", "treeseed_managed"]) ?? inferredPlanes.runtime.mode,
|
|
473
|
+
registration: optionalEnum(runtimeRecord.registration, "runtime.registration", ["optional", "required", "none"]) ?? inferredPlanes.runtime.registration ?? "none",
|
|
474
|
+
marketBaseUrl: optionalString(process.env.TREESEED_MARKET_API_BASE_URL) ?? inferredPlanes.runtime.marketBaseUrl,
|
|
475
|
+
teamId: optionalString(process.env.TREESEED_HOSTING_TEAM_ID) ?? inferredPlanes.runtime.teamId,
|
|
476
|
+
projectId: optionalString(process.env.TREESEED_PROJECT_ID) ?? inferredPlanes.runtime.projectId
|
|
477
|
+
};
|
|
317
478
|
const smtp = optionalRecord(record.smtp, "smtp") ?? {};
|
|
318
479
|
const turnstile = optionalRecord(record.turnstile, "turnstile") ?? {};
|
|
319
480
|
const agentProviders = optionalRecord(optionalRecord(record.providers, "providers")?.agents, "providers.agents") ?? {};
|
|
@@ -323,35 +484,28 @@ function parseFallbackDeployConfig(configPath) {
|
|
|
323
484
|
slug: expectString(record.slug, "slug"),
|
|
324
485
|
siteUrl: expectString(record.siteUrl, "siteUrl"),
|
|
325
486
|
contactEmail: expectString(record.contactEmail, "contactEmail"),
|
|
326
|
-
hosting:
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
"hosted_project",
|
|
330
|
-
"self_hosted_project"
|
|
331
|
-
]) ?? "self_hosted_project",
|
|
332
|
-
registration: optionalEnum(hosting.registration, "hosting.registration", ["optional", "none"]) ?? "none",
|
|
333
|
-
marketBaseUrl: optionalString(hosting.marketBaseUrl),
|
|
334
|
-
teamId: optionalString(hosting.teamId),
|
|
335
|
-
projectId: optionalString(hosting.projectId)
|
|
336
|
-
},
|
|
487
|
+
hosting: parsedHosting && record.hub === void 0 && record.runtime === void 0 ? parsedHosting : normalizeLegacyHostingFromPlanes(hub, runtime),
|
|
488
|
+
hub,
|
|
489
|
+
runtime,
|
|
337
490
|
cloudflare: {
|
|
338
|
-
accountId: optionalCloudflareAccountId(
|
|
491
|
+
accountId: optionalCloudflareAccountId(process.env.CLOUDFLARE_ACCOUNT_ID) ?? CLOUDFLARE_ACCOUNT_ID_PLACEHOLDER,
|
|
492
|
+
zoneId: optionalString(cloudflare.zoneId ?? cloudflare.zone_id),
|
|
339
493
|
workerName: optionalString(cloudflare.workerName),
|
|
340
494
|
queueName: optionalString(cloudflare.queueName),
|
|
341
495
|
dlqName: optionalString(cloudflare.dlqName),
|
|
342
496
|
d1Binding: optionalString(cloudflare.d1Binding),
|
|
343
497
|
queueBinding: optionalString(cloudflare.queueBinding),
|
|
344
498
|
pages: cloudflare.pages === void 0 ? void 0 : {
|
|
345
|
-
projectName: optionalString(
|
|
346
|
-
previewProjectName: optionalString(
|
|
499
|
+
projectName: optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME) ?? optionalString(cloudflarePages.projectName),
|
|
500
|
+
previewProjectName: optionalString(process.env.TREESEED_CLOUDFLARE_PAGES_PREVIEW_PROJECT_NAME) ?? optionalString(cloudflarePages.previewProjectName),
|
|
347
501
|
productionBranch: optionalString(cloudflarePages.productionBranch) ?? "main",
|
|
348
502
|
stagingBranch: optionalString(cloudflarePages.stagingBranch) ?? "staging",
|
|
349
503
|
buildOutputDir: optionalString(cloudflarePages.buildOutputDir)
|
|
350
504
|
},
|
|
351
505
|
r2: cloudflare.r2 === void 0 ? void 0 : {
|
|
352
|
-
binding: optionalString(
|
|
353
|
-
bucketName: optionalString(
|
|
354
|
-
publicBaseUrl: optionalString(
|
|
506
|
+
binding: optionalString(process.env.TREESEED_CONTENT_BUCKET_BINDING),
|
|
507
|
+
bucketName: optionalString(process.env.TREESEED_CONTENT_BUCKET_NAME),
|
|
508
|
+
publicBaseUrl: optionalString(process.env.TREESEED_CONTENT_PUBLIC_BASE_URL),
|
|
355
509
|
manifestKeyTemplate: optionalString(cloudflareR2.manifestKeyTemplate ?? cloudflareR2.manifestKey) ?? "teams/{teamId}/published/common.json",
|
|
356
510
|
previewRootTemplate: optionalString(cloudflareR2.previewRootTemplate ?? cloudflareR2.previewRoot) ?? "teams/{teamId}/previews",
|
|
357
511
|
previewTtlHours: optionalPositiveNumber(cloudflareR2.previewTtlHours, "cloudflare.r2.previewTtlHours") ?? 168
|
|
@@ -381,16 +535,22 @@ function parseFallbackDeployConfig(configPath) {
|
|
|
381
535
|
docs: expectString(
|
|
382
536
|
contentProviders.docs ?? contentProviders.runtime ?? TREESEED_DEFAULT_PROVIDER_SELECTIONS.content.docs ?? TREESEED_DEFAULT_PROVIDER_SELECTIONS.content.runtime,
|
|
383
537
|
"providers.content.docs"
|
|
384
|
-
)
|
|
538
|
+
),
|
|
539
|
+
serving: optionalEnum(
|
|
540
|
+
contentProviders.serving,
|
|
541
|
+
"providers.content.serving",
|
|
542
|
+
["local_collections", "published_runtime"]
|
|
543
|
+
) ?? TREESEED_DEFAULT_PROVIDER_SELECTIONS.content.serving
|
|
385
544
|
},
|
|
386
545
|
site: expectString(record.providers?.site ?? TREESEED_DEFAULT_PROVIDER_SELECTIONS.site, "providers.site")
|
|
387
546
|
},
|
|
388
|
-
|
|
547
|
+
surfaces: parsePlatformSurfacesConfig(record.surfaces),
|
|
548
|
+
services,
|
|
389
549
|
smtp: {
|
|
390
550
|
enabled: optionalBoolean(smtp.enabled, "smtp.enabled")
|
|
391
551
|
},
|
|
392
552
|
turnstile: {
|
|
393
|
-
enabled: optionalBoolean(turnstile.enabled, "turnstile.enabled") ??
|
|
553
|
+
enabled: optionalBoolean(turnstile.enabled, "turnstile.enabled") ?? false
|
|
394
554
|
}
|
|
395
555
|
};
|
|
396
556
|
Object.defineProperty(deployConfig, "__tenantRoot", {
|
|
@@ -40,7 +40,7 @@ function shouldIgnoreWatchPath(filePath, rootPath) {
|
|
|
40
40
|
return false;
|
|
41
41
|
}
|
|
42
42
|
const normalized = rel.split(sep).join("/");
|
|
43
|
-
return normalized === ".git" || normalized.startsWith(".git/") || normalized === "node_modules" || normalized.startsWith("node_modules/") || normalized === ".astro" || normalized.startsWith(".astro/") || normalized === ".wrangler" || normalized.startsWith(".wrangler/") || normalized === ".local" || normalized.startsWith(".local/") || normalized === ".treeseed" || normalized.startsWith(".treeseed/") || normalized === "dist" || normalized.startsWith("dist/") || normalized === "coverage" || normalized.startsWith("coverage/") || normalized === "
|
|
43
|
+
return normalized === ".git" || normalized.startsWith(".git/") || normalized === "node_modules" || normalized.startsWith("node_modules/") || normalized === ".astro" || normalized.startsWith(".astro/") || normalized === ".wrangler" || normalized.startsWith(".wrangler/") || normalized === ".local" || normalized.startsWith(".local/") || normalized === ".treeseed" || normalized.startsWith(".treeseed/") || normalized === "dist" || normalized.startsWith("dist/") || normalized === "coverage" || normalized.startsWith("coverage/") || normalized === "books" || normalized.startsWith("books/") || normalized === "__treeseed" || normalized.startsWith("__treeseed/") || normalized.startsWith("public/books/") || normalized.startsWith("public/__treeseed/");
|
|
44
44
|
}
|
|
45
45
|
function collectRootSnapshot(rootPath, snapshot) {
|
|
46
46
|
if (!existsSync(rootPath)) {
|
|
@@ -135,9 +135,7 @@ function createTenantWatchEntries(tenantRoot) {
|
|
|
135
135
|
{ kind: "tenant", root: resolve(tenantRoot, "src") },
|
|
136
136
|
{ kind: "tenant", root: resolve(tenantRoot, "public") },
|
|
137
137
|
{ kind: "tenant", root: resolve(tenantRoot, "astro.config.ts") },
|
|
138
|
-
{ kind: "tenant", root: resolve(tenantRoot, "treeseed.site.yaml") }
|
|
139
|
-
{ kind: "tenant", root: resolve(tenantRoot, ".env.local") },
|
|
140
|
-
{ kind: "tenant", root: resolve(tenantRoot, ".env.local.example") }
|
|
138
|
+
{ kind: "tenant", root: resolve(tenantRoot, "treeseed.site.yaml") }
|
|
141
139
|
];
|
|
142
140
|
if (isEditablePackageWorkspace()) {
|
|
143
141
|
const sdkRoot = workspaceSdkRoot();
|
|
@@ -2,19 +2,19 @@ export declare function createWranglerCommandEnv(overrides?: {}): {
|
|
|
2
2
|
XDG_CONFIG_HOME: string;
|
|
3
3
|
WRANGLER_SEND_METRICS: string;
|
|
4
4
|
};
|
|
5
|
-
export declare function parseGitHubAuthStatus(): {
|
|
5
|
+
export declare function parseGitHubAuthStatus(values?: NodeJS.ProcessEnv): {
|
|
6
6
|
authenticated: boolean;
|
|
7
7
|
detail: string;
|
|
8
8
|
};
|
|
9
|
-
export declare function parseWranglerWhoAmI(): {
|
|
9
|
+
export declare function parseWranglerWhoAmI(values?: NodeJS.ProcessEnv): {
|
|
10
10
|
authenticated: boolean;
|
|
11
11
|
detail: string;
|
|
12
12
|
};
|
|
13
|
-
export declare function parseRailwayWhoAmI(): {
|
|
13
|
+
export declare function parseRailwayWhoAmI(values?: NodeJS.ProcessEnv): {
|
|
14
14
|
authenticated: boolean;
|
|
15
15
|
detail: string;
|
|
16
16
|
};
|
|
17
|
-
export declare function parseCopilotSessionStatus(): {
|
|
17
|
+
export declare function parseCopilotSessionStatus(values?: NodeJS.ProcessEnv): {
|
|
18
18
|
configured: boolean;
|
|
19
19
|
detail: string;
|
|
20
20
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { collectTreeseedConfigSeedValues } from "./config-runtime.js";
|
|
4
5
|
import { createTempDir } from "./workspace-tools.js";
|
|
5
6
|
function runCapture(command, args, options = {}) {
|
|
6
7
|
const result = spawnSync(command, args, {
|
|
@@ -32,43 +33,44 @@ function createWranglerCommandEnv(overrides = {}) {
|
|
|
32
33
|
...overrides
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
|
-
function envTokenStatus(keys, label) {
|
|
36
|
+
function envTokenStatus(keys, label, values = process.env) {
|
|
36
37
|
const foundKey = keys.find((key) => {
|
|
37
|
-
const value =
|
|
38
|
+
const value = values[key];
|
|
38
39
|
return typeof value === "string" && value.trim().length > 0;
|
|
39
40
|
}) ?? null;
|
|
40
41
|
return {
|
|
41
42
|
ready: Boolean(foundKey),
|
|
42
|
-
detail: foundKey ? `${label} token detected from ${foundKey}.` : `${label} token is not configured. Set ${keys.join(" or ")}.`,
|
|
43
|
-
source: foundKey ? "
|
|
43
|
+
detail: foundKey ? `${label} token detected from configured Treeseed environment (${foundKey}).` : `${label} token is not configured. Set ${keys.join(" or ")}.`,
|
|
44
|
+
source: foundKey ? "config" : "missing"
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
|
-
function parseGitHubAuthStatus() {
|
|
47
|
+
function parseGitHubAuthStatus(values = process.env) {
|
|
47
48
|
return {
|
|
48
|
-
authenticated: envTokenStatus(["GH_TOKEN"], "GitHub").ready,
|
|
49
|
-
detail: envTokenStatus(["GH_TOKEN"], "GitHub").detail
|
|
49
|
+
authenticated: envTokenStatus(["GH_TOKEN"], "GitHub", values).ready,
|
|
50
|
+
detail: envTokenStatus(["GH_TOKEN"], "GitHub", values).detail
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
|
-
function parseWranglerWhoAmI() {
|
|
53
|
+
function parseWranglerWhoAmI(values = process.env) {
|
|
53
54
|
return {
|
|
54
|
-
authenticated: envTokenStatus(["CLOUDFLARE_API_TOKEN"], "Cloudflare").ready,
|
|
55
|
-
detail: envTokenStatus(["CLOUDFLARE_API_TOKEN"], "Cloudflare").detail
|
|
55
|
+
authenticated: envTokenStatus(["CLOUDFLARE_API_TOKEN"], "Cloudflare", values).ready,
|
|
56
|
+
detail: envTokenStatus(["CLOUDFLARE_API_TOKEN"], "Cloudflare", values).detail
|
|
56
57
|
};
|
|
57
58
|
}
|
|
58
|
-
function parseRailwayWhoAmI() {
|
|
59
|
+
function parseRailwayWhoAmI(values = process.env) {
|
|
59
60
|
return {
|
|
60
|
-
authenticated: envTokenStatus(["RAILWAY_API_TOKEN"], "Railway").ready,
|
|
61
|
-
detail: envTokenStatus(["RAILWAY_API_TOKEN"], "Railway").detail
|
|
61
|
+
authenticated: envTokenStatus(["RAILWAY_API_TOKEN", "RAILWAY_TOKEN"], "Railway", values).ready,
|
|
62
|
+
detail: envTokenStatus(["RAILWAY_API_TOKEN", "RAILWAY_TOKEN"], "Railway", values).detail
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
|
-
function parseCopilotSessionStatus() {
|
|
65
|
-
const status = envTokenStatus(["GH_TOKEN"], "GitHub");
|
|
65
|
+
function parseCopilotSessionStatus(values = process.env) {
|
|
66
|
+
const status = envTokenStatus(["GH_TOKEN"], "GitHub", values);
|
|
66
67
|
return {
|
|
67
68
|
configured: status.ready,
|
|
68
|
-
detail: status.ready ? "GitHub token detected from
|
|
69
|
+
detail: status.ready ? "GitHub token detected from configured Treeseed environment for Copilot-backed workflows." : "GitHub token is not configured. Set GH_TOKEN for Copilot-backed workflows."
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
function collectCliPreflight({ cwd = process.cwd(), requireAuth = false } = {}) {
|
|
73
|
+
const configuredValues = collectTreeseedConfigSeedValues(cwd, "local");
|
|
72
74
|
const binaries = {
|
|
73
75
|
git: locateBinary("git"),
|
|
74
76
|
npm: locateBinary("npm"),
|
|
@@ -87,22 +89,22 @@ function collectCliPreflight({ cwd = process.cwd(), requireAuth = false } = {})
|
|
|
87
89
|
auth: {}
|
|
88
90
|
};
|
|
89
91
|
if (binaries.gh) {
|
|
90
|
-
checks.auth.gh = parseGitHubAuthStatus();
|
|
92
|
+
checks.auth.gh = parseGitHubAuthStatus(configuredValues);
|
|
91
93
|
} else {
|
|
92
94
|
checks.auth.gh = { authenticated: false, detail: "GitHub CLI is not installed." };
|
|
93
95
|
}
|
|
94
96
|
if (binaries.wrangler) {
|
|
95
|
-
checks.auth.wrangler = parseWranglerWhoAmI();
|
|
97
|
+
checks.auth.wrangler = parseWranglerWhoAmI(configuredValues);
|
|
96
98
|
} else {
|
|
97
99
|
checks.auth.wrangler = { authenticated: false, detail: "Wrangler CLI is not installed." };
|
|
98
100
|
}
|
|
99
101
|
if (binaries.railway) {
|
|
100
|
-
checks.auth.railway = parseRailwayWhoAmI();
|
|
102
|
+
checks.auth.railway = parseRailwayWhoAmI(configuredValues);
|
|
101
103
|
} else {
|
|
102
104
|
checks.auth.railway = { authenticated: false, detail: "Railway CLI is not installed." };
|
|
103
105
|
}
|
|
104
106
|
if (binaries.copilot) {
|
|
105
|
-
checks.auth.copilot = parseCopilotSessionStatus();
|
|
107
|
+
checks.auth.copilot = parseCopilotSessionStatus(configuredValues);
|
|
106
108
|
} else {
|
|
107
109
|
checks.auth.copilot = { configured: false, detail: "Copilot CLI is not installed." };
|
|
108
110
|
}
|
|
@@ -8,12 +8,21 @@ export declare function planWorkspaceVersionChanges(root?: any): {
|
|
|
8
8
|
touched: Set<unknown>;
|
|
9
9
|
};
|
|
10
10
|
export declare function applyWorkspaceVersionChanges(plan: any): any;
|
|
11
|
-
export declare function planWorkspaceReleaseBump(level?: string, root?: any): {
|
|
11
|
+
export declare function planWorkspaceReleaseBump(level?: string, root?: any, options?: {}): {
|
|
12
12
|
packages: any[];
|
|
13
13
|
touched: Set<unknown>;
|
|
14
14
|
versions: Map<any, any>;
|
|
15
15
|
level: string;
|
|
16
|
+
selected: Set<any>;
|
|
16
17
|
};
|
|
18
|
+
export declare function collectWorkspaceVersionConsistencyIssues(root?: any): {
|
|
19
|
+
packageName: any;
|
|
20
|
+
dependencyName: string;
|
|
21
|
+
field: string;
|
|
22
|
+
currentSpec: unknown;
|
|
23
|
+
expectedSpec: string;
|
|
24
|
+
}[];
|
|
25
|
+
export declare function assertWorkspaceVersionConsistency(root?: any): void;
|
|
17
26
|
export declare function repoRoot(cwd?: any): string;
|
|
18
27
|
export declare function currentBranch(repoDir: any): string;
|
|
19
28
|
export declare function originRemoteUrl(repoDir: any): string;
|
|
@@ -113,17 +113,20 @@ function applyWorkspaceVersionChanges(plan) {
|
|
|
113
113
|
}
|
|
114
114
|
return plan;
|
|
115
115
|
}
|
|
116
|
-
function planWorkspaceReleaseBump(level = "patch", root = workspaceRoot()) {
|
|
116
|
+
function planWorkspaceReleaseBump(level = "patch", root = workspaceRoot(), options = {}) {
|
|
117
117
|
const packages = workspacePackages(root).map((pkg) => ({
|
|
118
118
|
...pkg,
|
|
119
119
|
packageJsonPath: resolve(pkg.dir, "package.json"),
|
|
120
120
|
packageJson: readPackageJson(resolve(pkg.dir, "package.json"))
|
|
121
121
|
}));
|
|
122
122
|
const publishable = new Set(publishableWorkspacePackages(root).map((pkg) => pkg.name));
|
|
123
|
+
const selected = options.selectedPackageNames ? new Set(
|
|
124
|
+
[...options.selectedPackageNames].map((name) => String(name)).filter((name) => publishable.has(name))
|
|
125
|
+
) : new Set(publishable);
|
|
123
126
|
const touched = /* @__PURE__ */ new Set();
|
|
124
127
|
const versions = /* @__PURE__ */ new Map();
|
|
125
128
|
for (const pkg of packages) {
|
|
126
|
-
if (!publishable.has(pkg.name)) {
|
|
129
|
+
if (!publishable.has(pkg.name) || !selected.has(pkg.name)) {
|
|
127
130
|
continue;
|
|
128
131
|
}
|
|
129
132
|
const nextVersion = incrementVersion(pkg.packageJson.version, level);
|
|
@@ -132,6 +135,9 @@ function planWorkspaceReleaseBump(level = "patch", root = workspaceRoot()) {
|
|
|
132
135
|
touched.add(pkg.name);
|
|
133
136
|
}
|
|
134
137
|
for (const pkg of packages) {
|
|
138
|
+
if (!selected.has(pkg.name)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
135
141
|
for (const field of internalDependencyFields(pkg.packageJson)) {
|
|
136
142
|
for (const depName of Object.keys(pkg.packageJson[field] ?? {})) {
|
|
137
143
|
if (!versions.has(depName)) {
|
|
@@ -146,9 +152,52 @@ function planWorkspaceReleaseBump(level = "patch", root = workspaceRoot()) {
|
|
|
146
152
|
packages,
|
|
147
153
|
touched,
|
|
148
154
|
versions,
|
|
149
|
-
level
|
|
155
|
+
level,
|
|
156
|
+
selected
|
|
150
157
|
};
|
|
151
158
|
}
|
|
159
|
+
function collectWorkspaceVersionConsistencyIssues(root = workspaceRoot()) {
|
|
160
|
+
const packages = workspacePackages(root).map((pkg) => ({
|
|
161
|
+
...pkg,
|
|
162
|
+
packageJson: readPackageJson(resolve(pkg.dir, "package.json"))
|
|
163
|
+
}));
|
|
164
|
+
const versions = new Map(packages.map((pkg) => [pkg.name, pkg.packageJson.version]));
|
|
165
|
+
const issues = [];
|
|
166
|
+
for (const pkg of packages) {
|
|
167
|
+
for (const field of internalDependencyFields(pkg.packageJson)) {
|
|
168
|
+
for (const [depName, currentSpec] of Object.entries(pkg.packageJson[field] ?? {})) {
|
|
169
|
+
if (!versions.has(depName)) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const expectedSpec = `^${versions.get(depName)}`;
|
|
173
|
+
if (currentSpec !== expectedSpec) {
|
|
174
|
+
issues.push({
|
|
175
|
+
packageName: pkg.name,
|
|
176
|
+
dependencyName: depName,
|
|
177
|
+
field,
|
|
178
|
+
currentSpec,
|
|
179
|
+
expectedSpec
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return issues;
|
|
186
|
+
}
|
|
187
|
+
function assertWorkspaceVersionConsistency(root = workspaceRoot()) {
|
|
188
|
+
const issues = collectWorkspaceVersionConsistencyIssues(root);
|
|
189
|
+
if (issues.length === 0) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const rendered = issues.map((issue) => `${issue.packageName} ${issue.field}.${issue.dependencyName}=${issue.currentSpec} expected ${issue.expectedSpec}`).join("\n");
|
|
193
|
+
throw new Error(
|
|
194
|
+
[
|
|
195
|
+
"Treeseed save found inconsistent checked-out package dependency versions.",
|
|
196
|
+
"Resolve the package manifest drift before saving.",
|
|
197
|
+
rendered
|
|
198
|
+
].join("\n")
|
|
199
|
+
);
|
|
200
|
+
}
|
|
152
201
|
function repoRoot(cwd = workspaceRoot()) {
|
|
153
202
|
return run("git", ["rev-parse", "--show-toplevel"], { cwd, capture: true }).trim();
|
|
154
203
|
}
|
|
@@ -220,7 +269,9 @@ function formatMergeConflictReport(report, repoDir, targetBranch = "main") {
|
|
|
220
269
|
export {
|
|
221
270
|
MERGE_CONFLICT_EXIT_CODE,
|
|
222
271
|
applyWorkspaceVersionChanges,
|
|
272
|
+
assertWorkspaceVersionConsistency,
|
|
223
273
|
collectMergeConflictReport,
|
|
274
|
+
collectWorkspaceVersionConsistencyIssues,
|
|
224
275
|
countConflictMarkers,
|
|
225
276
|
currentBranch,
|
|
226
277
|
formatMergeConflictReport,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const TREESEED_WORKSPACE_PACKAGE_DIRS: string[];
|
|
1
2
|
export declare function workspaceRoot(startCwd?: string): any;
|
|
2
3
|
export declare function findNearestTreeseedRoot(startCwd?: string): string | null;
|
|
3
4
|
export declare function isWorkspaceRoot(root?: string): any;
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
3
|
import { join, relative, resolve } from "node:path";
|
|
4
|
-
const TREESEED_WORKSPACE_PACKAGE_DIRS = ["sdk", "core", "cli"
|
|
4
|
+
const TREESEED_WORKSPACE_PACKAGE_DIRS = ["sdk", "core", "cli"];
|
|
5
|
+
function packageSortWeight(pkg) {
|
|
6
|
+
const relativeDir = String(pkg.relativeDir ?? "");
|
|
7
|
+
const dirName = relativeDir.split("/").pop() ?? "";
|
|
8
|
+
const index = TREESEED_WORKSPACE_PACKAGE_DIRS.indexOf(dirName);
|
|
9
|
+
return index >= 0 ? index : Number.MAX_SAFE_INTEGER;
|
|
10
|
+
}
|
|
11
|
+
function compareWorkspacePackages(left, right) {
|
|
12
|
+
const leftWeight = packageSortWeight(left);
|
|
13
|
+
const rightWeight = packageSortWeight(right);
|
|
14
|
+
if (leftWeight !== rightWeight) {
|
|
15
|
+
return leftWeight - rightWeight;
|
|
16
|
+
}
|
|
17
|
+
return left.name.localeCompare(right.name);
|
|
18
|
+
}
|
|
5
19
|
function escapeRegex(source) {
|
|
6
20
|
return source.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
|
|
7
21
|
}
|
|
@@ -103,7 +117,7 @@ function workspacePackages(root = workspaceRoot()) {
|
|
|
103
117
|
});
|
|
104
118
|
}
|
|
105
119
|
}
|
|
106
|
-
return [...discovered.values()].sort(
|
|
120
|
+
return [...discovered.values()].sort(compareWorkspacePackages);
|
|
107
121
|
}
|
|
108
122
|
function internalDependenciesFor(pkg, packageNames) {
|
|
109
123
|
const internalDeps = /* @__PURE__ */ new Set();
|
|
@@ -127,7 +141,7 @@ function sortWorkspacePackages(packages) {
|
|
|
127
141
|
indegree.set(pkg.name, (indegree.get(pkg.name) ?? 0) + 1);
|
|
128
142
|
}
|
|
129
143
|
}
|
|
130
|
-
const ready = [...packages].filter((pkg) => (indegree.get(pkg.name) ?? 0) === 0).sort(
|
|
144
|
+
const ready = [...packages].filter((pkg) => (indegree.get(pkg.name) ?? 0) === 0).sort(compareWorkspacePackages);
|
|
131
145
|
const ordered = [];
|
|
132
146
|
while (ready.length > 0) {
|
|
133
147
|
const next = ready.shift();
|
|
@@ -142,13 +156,13 @@ function sortWorkspacePackages(packages) {
|
|
|
142
156
|
const dependent = packageMap.get(dependentName);
|
|
143
157
|
if (dependent) {
|
|
144
158
|
ready.push(dependent);
|
|
145
|
-
ready.sort(
|
|
159
|
+
ready.sort(compareWorkspacePackages);
|
|
146
160
|
}
|
|
147
161
|
}
|
|
148
162
|
}
|
|
149
163
|
}
|
|
150
164
|
if (ordered.length !== packages.length) {
|
|
151
|
-
return [...packages].sort(
|
|
165
|
+
return [...packages].sort(compareWorkspacePackages);
|
|
152
166
|
}
|
|
153
167
|
return ordered;
|
|
154
168
|
}
|
|
@@ -251,6 +265,7 @@ function cleanupDir(dirPath) {
|
|
|
251
265
|
}
|
|
252
266
|
}
|
|
253
267
|
export {
|
|
268
|
+
TREESEED_WORKSPACE_PACKAGE_DIRS,
|
|
254
269
|
changedWorkspacePackages,
|
|
255
270
|
cleanupDir,
|
|
256
271
|
createTempDir,
|