@treeseed/sdk 0.1.2 → 0.3.1

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.
Files changed (237) hide show
  1. package/README.md +97 -506
  2. package/dist/{src/cli-tools.d.ts → cli-tools.d.ts} +1 -1
  3. package/dist/cli-tools.js +5 -3
  4. package/dist/{src/content-store.d.ts → content-store.d.ts} +3 -2
  5. package/dist/content-store.js +52 -20
  6. package/dist/{src/d1-store.d.ts → d1-store.d.ts} +62 -1
  7. package/dist/d1-store.js +625 -65
  8. package/dist/field-aliases.d.ts +11 -0
  9. package/dist/field-aliases.js +41 -0
  10. package/dist/graph/build.d.ts +19 -0
  11. package/dist/graph/build.js +949 -0
  12. package/dist/graph/dsl.d.ts +2 -0
  13. package/dist/graph/dsl.js +243 -0
  14. package/dist/graph/query.d.ts +47 -0
  15. package/dist/graph/query.js +447 -0
  16. package/dist/graph/ranking.d.ts +3 -0
  17. package/dist/graph/ranking.js +483 -0
  18. package/dist/graph/schema.d.ts +142 -0
  19. package/dist/graph/schema.js +133 -0
  20. package/dist/graph.d.ts +52 -0
  21. package/dist/graph.js +133 -0
  22. package/dist/index.d.ts +28 -0
  23. package/dist/index.js +91 -2
  24. package/dist/model-registry.d.ts +8 -0
  25. package/dist/model-registry.js +351 -25
  26. package/dist/operations/providers/default.d.ts +10 -0
  27. package/dist/operations/providers/default.js +514 -0
  28. package/dist/operations/runtime.d.ts +7 -0
  29. package/dist/operations/runtime.js +60 -0
  30. package/dist/operations/services/config-runtime.d.ts +269 -0
  31. package/dist/operations/services/config-runtime.js +1397 -0
  32. package/dist/operations/services/d1-migration.d.ts +6 -0
  33. package/dist/operations/services/d1-migration.js +89 -0
  34. package/dist/operations/services/deploy.d.ts +371 -0
  35. package/dist/operations/services/deploy.js +981 -0
  36. package/dist/operations/services/git-workflow.d.ts +49 -0
  37. package/dist/operations/services/git-workflow.js +218 -0
  38. package/dist/operations/services/github-automation.d.ts +156 -0
  39. package/dist/operations/services/github-automation.js +256 -0
  40. package/dist/operations/services/local-dev.d.ts +9 -0
  41. package/dist/operations/services/local-dev.js +106 -0
  42. package/dist/operations/services/mailpit-runtime.d.ts +4 -0
  43. package/dist/operations/services/mailpit-runtime.js +59 -0
  44. package/dist/operations/services/railway-deploy.d.ts +53 -0
  45. package/dist/operations/services/railway-deploy.js +123 -0
  46. package/dist/operations/services/runtime-paths.d.ts +19 -0
  47. package/dist/operations/services/runtime-paths.js +54 -0
  48. package/dist/operations/services/runtime-tools.d.ts +117 -0
  49. package/dist/operations/services/runtime-tools.js +358 -0
  50. package/dist/operations/services/save-deploy-preflight.d.ts +34 -0
  51. package/dist/operations/services/save-deploy-preflight.js +76 -0
  52. package/dist/operations/services/template-registry.d.ts +88 -0
  53. package/dist/operations/services/template-registry.js +407 -0
  54. package/dist/operations/services/watch-dev.d.ts +21 -0
  55. package/dist/operations/services/watch-dev.js +284 -0
  56. package/dist/operations/services/workspace-preflight.d.ts +40 -0
  57. package/dist/operations/services/workspace-preflight.js +165 -0
  58. package/dist/operations/services/workspace-save.d.ts +42 -0
  59. package/dist/operations/services/workspace-save.js +235 -0
  60. package/dist/operations/services/workspace-tools.d.ts +16 -0
  61. package/dist/operations/services/workspace-tools.js +270 -0
  62. package/dist/operations-registry.d.ts +5 -0
  63. package/dist/operations-registry.js +68 -0
  64. package/dist/operations-types.d.ts +71 -0
  65. package/dist/operations-types.js +17 -0
  66. package/dist/operations.d.ts +6 -0
  67. package/dist/operations.js +16 -0
  68. package/dist/platform/books-data.d.ts +1 -0
  69. package/dist/platform/books-data.js +1 -0
  70. package/dist/platform/contracts.d.ts +158 -0
  71. package/dist/platform/contracts.js +0 -0
  72. package/dist/platform/deploy/config.d.ts +4 -0
  73. package/dist/platform/deploy/config.js +222 -0
  74. package/dist/platform/deploy-config.d.ts +1 -0
  75. package/dist/platform/deploy-config.js +1 -0
  76. package/dist/platform/deploy-runtime.d.ts +18 -0
  77. package/dist/platform/deploy-runtime.js +78 -0
  78. package/dist/platform/env.yaml +394 -0
  79. package/dist/platform/environment.d.ts +130 -0
  80. package/dist/platform/environment.js +331 -0
  81. package/dist/platform/plugin.d.ts +2 -0
  82. package/dist/platform/plugin.js +4 -0
  83. package/dist/platform/plugins/constants.d.ts +22 -0
  84. package/dist/platform/plugins/constants.js +29 -0
  85. package/dist/platform/plugins/plugin.d.ts +51 -0
  86. package/dist/platform/plugins/plugin.js +6 -0
  87. package/dist/platform/plugins/runtime.d.ts +35 -0
  88. package/dist/platform/plugins/runtime.js +161 -0
  89. package/dist/platform/plugins.d.ts +6 -0
  90. package/dist/platform/plugins.js +38 -0
  91. package/dist/platform/site-config-schema.js +1 -0
  92. package/dist/platform/tenant/config.d.ts +9 -0
  93. package/dist/platform/tenant/config.js +154 -0
  94. package/dist/platform/tenant/runtime-config.d.ts +4 -0
  95. package/dist/platform/tenant/runtime-config.js +20 -0
  96. package/dist/platform/tenant-config.d.ts +1 -0
  97. package/dist/platform/tenant-config.js +1 -0
  98. package/dist/platform/utils/books-data.d.ts +29 -0
  99. package/dist/platform/utils/books-data.js +82 -0
  100. package/dist/platform/utils/site-config-schema.js +321 -0
  101. package/dist/remote.d.ts +175 -0
  102. package/dist/remote.js +202 -0
  103. package/dist/runtime.js +35 -22
  104. package/dist/scripts/aggregate-book.js +121 -0
  105. package/dist/scripts/build-dist.js +54 -13
  106. package/dist/scripts/build-tenant-worker.js +36 -0
  107. package/dist/scripts/cleanup-markdown.js +373 -0
  108. package/dist/scripts/cli-test-fixtures.js +48 -0
  109. package/dist/scripts/config-treeseed.js +95 -0
  110. package/dist/scripts/ensure-mailpit.js +29 -0
  111. package/dist/scripts/local-dev.js +129 -0
  112. package/dist/scripts/logs-mailpit.js +2 -0
  113. package/dist/scripts/patch-starlight-content-path.js +172 -0
  114. package/dist/scripts/release-verify.js +34 -6
  115. package/dist/scripts/run-fixture-astro-command.js +18 -0
  116. package/dist/scripts/scaffold-site.js +65 -0
  117. package/dist/scripts/stop-mailpit.js +5 -0
  118. package/dist/scripts/sync-dev-vars.js +6 -0
  119. package/dist/scripts/sync-template.js +20 -0
  120. package/dist/scripts/template-catalog.test.js +100 -0
  121. package/dist/scripts/template-command.js +31 -0
  122. package/dist/scripts/tenant-astro-command.js +3 -0
  123. package/dist/scripts/tenant-build.js +16 -0
  124. package/dist/scripts/tenant-check.js +7 -0
  125. package/dist/scripts/tenant-d1-migrate-local.js +11 -0
  126. package/dist/scripts/tenant-deploy.js +180 -0
  127. package/dist/scripts/tenant-destroy.js +104 -0
  128. package/dist/scripts/tenant-dev.js +171 -0
  129. package/dist/scripts/tenant-lint.js +4 -0
  130. package/dist/scripts/tenant-test.js +4 -0
  131. package/dist/scripts/test-cloudflare-local.js +212 -0
  132. package/dist/scripts/test-scaffold.js +314 -0
  133. package/dist/scripts/test-smoke.js +71 -13
  134. package/dist/scripts/treeseed-assert-release-tag-version.js +21 -0
  135. package/dist/scripts/treeseed-build-dist.js +134 -0
  136. package/dist/scripts/treeseed-publish-package.js +19 -0
  137. package/dist/scripts/treeseed-release-verify.js +131 -0
  138. package/dist/scripts/treeseed-run-ts.js +45 -0
  139. package/dist/scripts/validate-templates.js +6 -0
  140. package/dist/scripts/verify-driver.js +29 -0
  141. package/dist/scripts/workflow-commands.test.js +39 -0
  142. package/dist/scripts/workspace-close.js +24 -0
  143. package/dist/scripts/workspace-command-e2e.js +718 -0
  144. package/dist/scripts/workspace-lint.js +9 -0
  145. package/dist/scripts/workspace-preflight.js +22 -0
  146. package/dist/scripts/workspace-publish-changed-packages.js +16 -0
  147. package/dist/scripts/workspace-release-verify.js +81 -0
  148. package/dist/scripts/workspace-release.js +42 -0
  149. package/dist/scripts/workspace-save.js +124 -0
  150. package/dist/scripts/workspace-start-warning.js +3 -0
  151. package/dist/scripts/workspace-start.js +71 -0
  152. package/dist/scripts/workspace-test-unit.js +4 -0
  153. package/dist/scripts/workspace-test.js +11 -0
  154. package/dist/sdk-fields.d.ts +11 -0
  155. package/dist/sdk-fields.js +169 -0
  156. package/dist/sdk-filters.d.ts +4 -0
  157. package/dist/sdk-filters.js +12 -15
  158. package/dist/sdk-types.d.ts +796 -0
  159. package/dist/sdk-types.js +7 -1
  160. package/dist/sdk-version.d.ts +2 -0
  161. package/dist/sdk-version.js +42 -0
  162. package/dist/sdk.d.ts +215 -0
  163. package/dist/sdk.js +235 -11
  164. package/dist/stores/cursor-store.js +9 -3
  165. package/dist/stores/lease-store.js +8 -2
  166. package/dist/{src/stores → stores}/message-store.d.ts +1 -1
  167. package/dist/stores/message-store.js +27 -3
  168. package/dist/stores/operational-store.d.ts +24 -0
  169. package/dist/stores/operational-store.js +279 -0
  170. package/dist/stores/run-store.js +8 -1
  171. package/dist/stores/subscription-store.js +7 -5
  172. package/dist/template-catalog.d.ts +13 -0
  173. package/dist/template-catalog.js +141 -0
  174. package/dist/treeseed/services/compose.yml +7 -0
  175. package/dist/treeseed/template-catalog/catalog.fixture.json +55 -0
  176. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.d.ts +2 -0
  177. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.ts +3 -0
  178. package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +32 -0
  179. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +40 -0
  180. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/empty/.gitkeep +1 -0
  181. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/knowledge/handbook/index.mdx +11 -0
  182. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/pages/welcome.mdx +11 -0
  183. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.d.ts +1 -0
  184. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.ts +3 -0
  185. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/env.yaml +1 -0
  186. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +19 -0
  187. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +26 -0
  188. package/dist/treeseed/template-catalog/templates/starter-basic/template/tsconfig.json +9 -0
  189. package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +90 -0
  190. package/dist/utils/agents/contracts/messages.d.ts +88 -0
  191. package/dist/utils/agents/contracts/messages.js +138 -0
  192. package/dist/utils/agents/contracts/run.d.ts +20 -0
  193. package/dist/utils/agents/contracts/run.js +0 -0
  194. package/dist/utils/agents/runtime-types.d.ts +117 -0
  195. package/dist/utils/agents/runtime-types.js +4 -0
  196. package/dist/verification.d.ts +20 -0
  197. package/dist/verification.js +98 -0
  198. package/dist/workflow/operations.d.ts +396 -0
  199. package/dist/workflow/operations.js +841 -0
  200. package/dist/workflow-state.d.ts +56 -0
  201. package/dist/workflow-state.js +195 -0
  202. package/dist/workflow-support.d.ts +9 -0
  203. package/dist/workflow-support.js +176 -0
  204. package/dist/workflow.d.ts +111 -0
  205. package/dist/workflow.js +97 -0
  206. package/package.json +111 -5
  207. package/scripts/verify-driver.mjs +29 -0
  208. package/dist/scripts/.ts-run-1775630384291-crtqr3izsa.js +0 -22
  209. package/dist/scripts/.ts-run-1775630388025-vnjle0z75a.js +0 -129
  210. package/dist/scripts/assert-release-tag-version.d.ts +0 -1
  211. package/dist/scripts/build-dist.d.ts +0 -1
  212. package/dist/scripts/fixture-tools.d.ts +0 -5
  213. package/dist/scripts/package-tools.d.ts +0 -15
  214. package/dist/scripts/publish-package.d.ts +0 -1
  215. package/dist/scripts/release-verify.d.ts +0 -1
  216. package/dist/scripts/test-smoke.d.ts +0 -1
  217. package/dist/src/index.d.ts +0 -6
  218. package/dist/src/model-registry.d.ts +0 -4
  219. package/dist/src/sdk-filters.d.ts +0 -4
  220. package/dist/src/sdk-types.d.ts +0 -285
  221. package/dist/src/sdk.d.ts +0 -109
  222. package/dist/test/test-fixture.d.ts +0 -1
  223. package/dist/test/utils/envelopes.test.d.ts +0 -1
  224. package/dist/test/utils/sdk.test.d.ts +0 -1
  225. package/dist/vitest.config.d.ts +0 -2
  226. /package/dist/{src/frontmatter.d.ts → frontmatter.d.ts} +0 -0
  227. /package/dist/{src/git-runtime.d.ts → git-runtime.d.ts} +0 -0
  228. /package/dist/{src/runtime.d.ts → runtime.d.ts} +0 -0
  229. /package/dist/{src/stores → stores}/cursor-store.d.ts +0 -0
  230. /package/dist/{src/stores → stores}/envelopes.d.ts +0 -0
  231. /package/dist/{src/stores → stores}/helpers.d.ts +0 -0
  232. /package/dist/{src/stores → stores}/lease-store.d.ts +0 -0
  233. /package/dist/{src/stores → stores}/run-store.d.ts +0 -0
  234. /package/dist/{src/stores → stores}/subscription-store.d.ts +0 -0
  235. /package/dist/{src/types → types}/agents.d.ts +0 -0
  236. /package/dist/{src/types → types}/cloudflare.d.ts +0 -0
  237. /package/dist/{src/wrangler-d1.d.ts → wrangler-d1.d.ts} +0 -0
@@ -0,0 +1,514 @@
1
+ import { existsSync, mkdtempSync, mkdirSync, readdirSync, readFileSync, symlinkSync, writeFileSync } from "node:fs";
2
+ import { spawnSync } from "node:child_process";
3
+ import { join, relative, resolve } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { RemoteTreeseedAuthClient, RemoteTreeseedClient } from "../../remote.js";
6
+ import {
7
+ findTreeseedOperation,
8
+ TRESEED_OPERATION_SPECS
9
+ } from "../../operations-registry.js";
10
+ import {
11
+ clearTreeseedRemoteSession,
12
+ resolveTreeseedRemoteConfig,
13
+ setTreeseedRemoteSession
14
+ } from "../../operations/services/config-runtime.js";
15
+ import {
16
+ createPersistentDeployTarget,
17
+ deployTargetLabel,
18
+ ensureGeneratedWranglerConfig,
19
+ finalizeDeploymentState,
20
+ loadDeployState
21
+ } from "../../operations/services/deploy.js";
22
+ import {
23
+ dockerIsAvailable,
24
+ findRunningMailpitContainer,
25
+ stopKnownMailpitContainers
26
+ } from "../../operations/services/mailpit-runtime.js";
27
+ import {
28
+ loadCliDeployConfig,
29
+ packageScriptPath,
30
+ resolveWranglerBin
31
+ } from "../../operations/services/runtime-tools.js";
32
+ import {
33
+ scaffoldTemplateProject,
34
+ listTemplateProducts,
35
+ resolveTemplateProduct,
36
+ serializeTemplateRegistryEntry,
37
+ syncTemplateProject,
38
+ validateTemplateProduct
39
+ } from "../../operations/services/template-registry.js";
40
+ import {
41
+ collectCliPreflight,
42
+ formatCliPreflightReport
43
+ } from "../../operations/services/workspace-preflight.js";
44
+ import { repoRoot } from "../../operations/services/workspace-save.js";
45
+ import { run } from "../../operations/services/workspace-tools.js";
46
+ import { resolveTreeseedWorkflowState } from "../../workflow-state.js";
47
+ import { TreeseedWorkflowError, TreeseedWorkflowSdk } from "../../workflow.js";
48
+ function operationResult(metadata, payload, options = {}) {
49
+ return {
50
+ operation: metadata.id,
51
+ ok: options.ok ?? true,
52
+ payload,
53
+ meta: options.meta,
54
+ nextSteps: options.nextSteps,
55
+ exitCode: options.exitCode ?? (options.ok === false ? 1 : 0),
56
+ stdout: options.stdout,
57
+ stderr: options.stderr
58
+ };
59
+ }
60
+ function failureResult(metadata, message, options = {}) {
61
+ return operationResult(metadata, null, {
62
+ ok: false,
63
+ exitCode: options.exitCode ?? 1,
64
+ stderr: [message],
65
+ meta: options.meta
66
+ });
67
+ }
68
+ function contextEnv(context) {
69
+ return { ...process.env, ...context.env ?? {} };
70
+ }
71
+ function runNodeScript(metadata, scriptName, args, context) {
72
+ if (context.spawn) {
73
+ const result2 = context.spawn(process.execPath, [packageScriptPath(scriptName), ...args], {
74
+ cwd: context.cwd,
75
+ env: contextEnv(context),
76
+ stdio: "inherit"
77
+ });
78
+ return operationResult(metadata, {
79
+ script: scriptName,
80
+ args
81
+ }, {
82
+ ok: (result2.status ?? 1) === 0,
83
+ exitCode: result2.status ?? 1
84
+ });
85
+ }
86
+ const result = spawnSync(process.execPath, [packageScriptPath(scriptName), ...args], {
87
+ cwd: context.cwd,
88
+ env: contextEnv(context),
89
+ encoding: "utf8",
90
+ stdio: "pipe"
91
+ });
92
+ const stdout = (result.stdout ?? "").split(/\r?\n/).filter(Boolean);
93
+ const stderr = (result.stderr ?? "").split(/\r?\n/).filter(Boolean);
94
+ for (const line of stdout) context.write?.(line, "stdout");
95
+ for (const line of stderr) context.write?.(line, "stderr");
96
+ return operationResult(metadata, {
97
+ script: scriptName,
98
+ args
99
+ }, {
100
+ ok: (result.status ?? 1) === 0,
101
+ exitCode: result.status ?? 1,
102
+ stdout,
103
+ stderr
104
+ });
105
+ }
106
+ function copyTreeseedOperationalState(sourceRoot, targetRoot) {
107
+ const sourceTreeseedRoot = resolve(sourceRoot, ".treeseed");
108
+ if (!existsSync(sourceTreeseedRoot)) {
109
+ return;
110
+ }
111
+ copyDirectory(sourceTreeseedRoot, resolve(targetRoot, ".treeseed"));
112
+ }
113
+ function copyDirectory(sourceDir, targetDir) {
114
+ mkdirSync(targetDir, { recursive: true });
115
+ for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {
116
+ const sourcePath = resolve(sourceDir, entry.name);
117
+ const targetPath = resolve(targetDir, entry.name);
118
+ if (entry.isDirectory()) {
119
+ copyDirectory(sourcePath, targetPath);
120
+ continue;
121
+ }
122
+ writeFileSync(targetPath, readFileSync(sourcePath));
123
+ }
124
+ }
125
+ function workflowInputForOperation(name, input) {
126
+ switch (name) {
127
+ case "status":
128
+ case "tasks":
129
+ return {};
130
+ case "dev:watch":
131
+ return { ...input, watch: true };
132
+ default:
133
+ return input;
134
+ }
135
+ }
136
+ class BaseOperation {
137
+ metadata;
138
+ constructor(name) {
139
+ const metadata = findTreeseedOperation(name);
140
+ if (!metadata) {
141
+ throw new Error(`Unknown operation metadata for "${name}".`);
142
+ }
143
+ this.metadata = metadata;
144
+ }
145
+ }
146
+ class WorkflowOperation extends BaseOperation {
147
+ workflowName;
148
+ constructor(name, workflowName) {
149
+ super(name);
150
+ this.workflowName = workflowName ?? (name === "switch" ? "switch" : name);
151
+ }
152
+ async execute(input, context) {
153
+ try {
154
+ const workflow = new TreeseedWorkflowSdk({
155
+ cwd: context.cwd,
156
+ env: context.env,
157
+ write: context.write,
158
+ prompt: context.prompt,
159
+ confirm: context.confirm,
160
+ transport: context.transport ?? "sdk"
161
+ });
162
+ return await workflow.execute(this.workflowName, workflowInputForOperation(this.metadata.name, input));
163
+ } catch (error) {
164
+ if (error instanceof TreeseedWorkflowError) {
165
+ return failureResult(this.metadata, error.message, {
166
+ exitCode: error.exitCode ?? 1,
167
+ meta: {
168
+ code: error.code,
169
+ details: error.details ?? null
170
+ }
171
+ });
172
+ }
173
+ throw error;
174
+ }
175
+ }
176
+ }
177
+ class ScriptOperation extends BaseOperation {
178
+ constructor(name, scriptName, extraArgs = []) {
179
+ super(name);
180
+ this.scriptName = scriptName;
181
+ this.extraArgs = extraArgs;
182
+ }
183
+ scriptName;
184
+ extraArgs;
185
+ async execute(input, context) {
186
+ const args = Array.isArray(input.args) ? input.args.map(String) : [];
187
+ return runNodeScript(this.metadata, this.scriptName, [...this.extraArgs, ...args], context);
188
+ }
189
+ }
190
+ class PreflightOperation extends BaseOperation {
191
+ constructor(name, requireAuth = false) {
192
+ super(name);
193
+ this.requireAuth = requireAuth;
194
+ }
195
+ requireAuth;
196
+ async execute(input, context) {
197
+ const report = collectCliPreflight({
198
+ cwd: context.cwd,
199
+ requireAuth: input.requireAuth ?? this.requireAuth
200
+ });
201
+ const stdout = [formatCliPreflightReport(report)];
202
+ for (const line of stdout) context.write?.(line, "stdout");
203
+ return operationResult(this.metadata, report, {
204
+ ok: report.ok,
205
+ exitCode: report.ok ? 0 : 1,
206
+ stdout,
207
+ stderr: []
208
+ });
209
+ }
210
+ }
211
+ class InitOperation extends BaseOperation {
212
+ async execute(input, context) {
213
+ const directory = String(input.directory ?? input.target ?? "").trim();
214
+ if (!directory) {
215
+ return failureResult(this.metadata, "Init requires a target directory.");
216
+ }
217
+ const definition = await scaffoldTemplateProject(
218
+ String(input.template ?? "starter-basic"),
219
+ resolve(context.cwd, directory),
220
+ {
221
+ target: directory,
222
+ name: typeof input.name === "string" ? input.name : null,
223
+ slug: typeof input.slug === "string" ? input.slug : null,
224
+ siteUrl: typeof input.siteUrl === "string" ? input.siteUrl : null,
225
+ contactEmail: typeof input.contactEmail === "string" ? input.contactEmail : null,
226
+ repositoryUrl: typeof input.repositoryUrl === "string" ? input.repositoryUrl : typeof input.repo === "string" ? input.repo : null,
227
+ discordUrl: typeof input.discordUrl === "string" ? input.discordUrl : typeof input.discord === "string" ? input.discord : void 0
228
+ },
229
+ { writeWarning: (message) => context.write?.(message, "stderr") }
230
+ );
231
+ return operationResult(this.metadata, {
232
+ directory,
233
+ template: definition.id
234
+ });
235
+ }
236
+ }
237
+ class TemplateOperation extends BaseOperation {
238
+ async execute(input, context) {
239
+ const action = String(input.action ?? "list");
240
+ const target = typeof input.id === "string" ? input.id : typeof input.target === "string" ? input.target : void 0;
241
+ const writeWarning = (message) => context.write?.(message, "stderr");
242
+ if (action === "show") {
243
+ if (!target) {
244
+ return failureResult(this.metadata, "Template show requires an id.");
245
+ }
246
+ return operationResult(this.metadata, {
247
+ action,
248
+ template: serializeTemplateRegistryEntry(await resolveTemplateProduct(target, { writeWarning }))
249
+ });
250
+ }
251
+ if (action === "validate") {
252
+ const products = target ? [await resolveTemplateProduct(target, { writeWarning })] : await listTemplateProducts({ writeWarning });
253
+ for (const product of products) {
254
+ await validateTemplateProduct(product, { writeWarning });
255
+ }
256
+ return operationResult(this.metadata, {
257
+ action,
258
+ validated: products.map((product) => product.id)
259
+ });
260
+ }
261
+ return operationResult(this.metadata, {
262
+ action: "list",
263
+ templates: (await listTemplateProducts({ writeWarning })).map((product) => serializeTemplateRegistryEntry(product))
264
+ });
265
+ }
266
+ }
267
+ class SyncTemplateOperation extends BaseOperation {
268
+ async execute(input, context) {
269
+ const changed = await syncTemplateProject(context.cwd, {
270
+ check: input.check === true,
271
+ writeWarning: (message) => context.write?.(message, "stderr")
272
+ });
273
+ return operationResult(this.metadata, {
274
+ check: input.check === true,
275
+ changed
276
+ }, {
277
+ ok: input.check === true ? changed.length === 0 : true,
278
+ exitCode: input.check === true && changed.length > 0 ? 1 : 0
279
+ });
280
+ }
281
+ }
282
+ class DoctorOperation extends BaseOperation {
283
+ async execute(_input, context) {
284
+ const state = resolveTreeseedWorkflowState(context.cwd);
285
+ const preflight = collectCliPreflight({ cwd: context.cwd, requireAuth: false });
286
+ return operationResult(this.metadata, {
287
+ state,
288
+ preflight
289
+ }, {
290
+ ok: preflight.ok,
291
+ exitCode: preflight.ok ? 0 : 1
292
+ });
293
+ }
294
+ }
295
+ class AuthLoginOperation extends BaseOperation {
296
+ async execute(input, context) {
297
+ const tenantRoot = context.cwd;
298
+ const remoteConfig = resolveTreeseedRemoteConfig(tenantRoot, context.env);
299
+ const hostId = typeof input.host === "string" ? input.host : remoteConfig.activeHostId;
300
+ const client = new RemoteTreeseedAuthClient(new RemoteTreeseedClient({
301
+ ...remoteConfig,
302
+ activeHostId: hostId
303
+ }));
304
+ const started = await client.startDeviceFlow({
305
+ clientName: "treeseed-sdk",
306
+ scopes: ["auth:me", "sdk", "operations"]
307
+ });
308
+ const deadline = Date.parse(started.expiresAt);
309
+ while (Date.now() < deadline) {
310
+ const response = await client.pollDeviceFlow({ deviceCode: started.deviceCode });
311
+ if (response.ok && response.status === "approved") {
312
+ setTreeseedRemoteSession(tenantRoot, {
313
+ hostId,
314
+ accessToken: response.accessToken,
315
+ refreshToken: response.refreshToken,
316
+ expiresAt: response.expiresAt,
317
+ principal: response.principal
318
+ });
319
+ return operationResult(this.metadata, {
320
+ hostId,
321
+ verificationUriComplete: started.verificationUriComplete,
322
+ userCode: started.userCode,
323
+ principal: response.principal
324
+ });
325
+ }
326
+ if (!response.ok && response.status !== "already_used") {
327
+ return failureResult(this.metadata, response.error);
328
+ }
329
+ await new Promise((resolveTimer) => setTimeout(resolveTimer, started.intervalSeconds * 1e3));
330
+ }
331
+ return failureResult(this.metadata, "Treeseed API login expired before approval completed.");
332
+ }
333
+ }
334
+ class AuthLogoutOperation extends BaseOperation {
335
+ async execute(input, context) {
336
+ const remoteConfig = resolveTreeseedRemoteConfig(context.cwd, context.env);
337
+ const hostId = typeof input.host === "string" ? input.host : remoteConfig.activeHostId;
338
+ clearTreeseedRemoteSession(context.cwd, hostId);
339
+ return operationResult(this.metadata, { hostId });
340
+ }
341
+ }
342
+ class AuthWhoAmIOperation extends BaseOperation {
343
+ async execute(_input, context) {
344
+ const remoteConfig = resolveTreeseedRemoteConfig(context.cwd, context.env);
345
+ const client = new RemoteTreeseedAuthClient(new RemoteTreeseedClient(remoteConfig));
346
+ const response = await client.whoAmI();
347
+ return operationResult(this.metadata, {
348
+ hostId: remoteConfig.activeHostId,
349
+ principal: response.payload
350
+ });
351
+ }
352
+ }
353
+ class RollbackOperation extends BaseOperation {
354
+ async execute(input, context) {
355
+ const scope = typeof input.environment === "string" ? input.environment : null;
356
+ if (scope !== "staging" && scope !== "prod") {
357
+ return failureResult(this.metadata, 'Rollback requires environment "staging" or "prod".');
358
+ }
359
+ const requestedCommit = typeof input.to === "string" ? input.to : null;
360
+ const tenantRoot = context.cwd;
361
+ const deployConfig = loadCliDeployConfig(tenantRoot);
362
+ const target = createPersistentDeployTarget(scope);
363
+ const state = loadDeployState(tenantRoot, deployConfig, { target });
364
+ const history = Array.isArray(state.deploymentHistory) ? state.deploymentHistory : [];
365
+ const latestCommit = typeof state.lastDeployedCommit === "string" ? state.lastDeployedCommit : null;
366
+ const rollbackEntry = requestedCommit ? history.find((entry) => entry.commit === requestedCommit) ?? null : [...history].reverse().find((entry) => typeof entry.commit === "string" && entry.commit !== latestCommit) ?? null;
367
+ const rollbackCommit = requestedCommit ?? (typeof rollbackEntry?.commit === "string" ? rollbackEntry.commit : latestCommit);
368
+ if (!rollbackCommit) {
369
+ return failureResult(this.metadata, `No rollback candidate is recorded for ${scope}.`);
370
+ }
371
+ const gitRoot = repoRoot(tenantRoot);
372
+ const tenantRelativePath = relative(gitRoot, tenantRoot);
373
+ const tempRoot = mkdtempSync(join(tmpdir(), "treeseed-rollback-"));
374
+ const tempTenantRoot = resolve(tempRoot, tenantRelativePath);
375
+ const currentNodeModules = resolve(tenantRoot, "node_modules");
376
+ let finalizedState = null;
377
+ try {
378
+ run("git", ["worktree", "add", "--detach", tempRoot, rollbackCommit], { cwd: gitRoot, capture: true });
379
+ copyTreeseedOperationalState(tenantRoot, tempTenantRoot);
380
+ if (existsSync(currentNodeModules) && !existsSync(resolve(tempTenantRoot, "node_modules"))) {
381
+ symlinkSync(currentNodeModules, resolve(tempTenantRoot, "node_modules"), "dir");
382
+ }
383
+ const { wranglerPath } = ensureGeneratedWranglerConfig(tempTenantRoot, { target });
384
+ const buildResult = spawnSync(process.execPath, [packageScriptPath("tenant-build")], {
385
+ cwd: tempTenantRoot,
386
+ env: contextEnv(context),
387
+ stdio: "inherit"
388
+ });
389
+ if ((buildResult.status ?? 1) !== 0) {
390
+ return failureResult(this.metadata, "Rollback build failed.", { exitCode: buildResult.status ?? 1 });
391
+ }
392
+ const publishResult = spawnSync(process.execPath, [resolveWranglerBin(), "deploy", "--config", wranglerPath], {
393
+ cwd: tempTenantRoot,
394
+ env: contextEnv(context),
395
+ stdio: "inherit"
396
+ });
397
+ if ((publishResult.status ?? 1) !== 0) {
398
+ return failureResult(this.metadata, "Rollback deploy failed.", { exitCode: publishResult.status ?? 1 });
399
+ }
400
+ const previousCommit = process.env.TREESEED_DEPLOY_COMMIT;
401
+ process.env.TREESEED_DEPLOY_COMMIT = rollbackCommit;
402
+ try {
403
+ finalizedState = finalizeDeploymentState(tenantRoot, { target });
404
+ } finally {
405
+ if (previousCommit) process.env.TREESEED_DEPLOY_COMMIT = previousCommit;
406
+ else delete process.env.TREESEED_DEPLOY_COMMIT;
407
+ }
408
+ } finally {
409
+ try {
410
+ run("git", ["worktree", "remove", "--force", tempRoot], { cwd: gitRoot, capture: true });
411
+ } catch {
412
+ }
413
+ }
414
+ return operationResult(this.metadata, {
415
+ scope,
416
+ target: deployTargetLabel(target),
417
+ rollbackCommit,
418
+ rollbackEntry,
419
+ finalizedState
420
+ });
421
+ }
422
+ }
423
+ class MailpitUpOperation extends BaseOperation {
424
+ async execute(_input, context) {
425
+ if (!dockerIsAvailable()) {
426
+ return failureResult(this.metadata, "Docker is required for Treeseed form email testing.");
427
+ }
428
+ const existing = findRunningMailpitContainer();
429
+ if (existing) {
430
+ return operationResult(this.metadata, { reused: true, container: existing });
431
+ }
432
+ return runNodeScript(this.metadata, "ensure-mailpit", [], context);
433
+ }
434
+ }
435
+ class MailpitDownOperation extends BaseOperation {
436
+ async execute(_input, _context) {
437
+ const stopped = stopKnownMailpitContainers();
438
+ return operationResult(this.metadata, { stopped }, { ok: stopped, exitCode: stopped ? 0 : 1 });
439
+ }
440
+ }
441
+ class MailpitLogsOperation extends BaseOperation {
442
+ async execute(_input, context) {
443
+ return runNodeScript(this.metadata, "logs-mailpit", [], context);
444
+ }
445
+ }
446
+ class DefaultTreeseedOperationsProvider {
447
+ id = "default";
448
+ operations;
449
+ constructor() {
450
+ this.operations = [
451
+ new WorkflowOperation("status"),
452
+ new WorkflowOperation("tasks"),
453
+ new WorkflowOperation("switch", "switch"),
454
+ new WorkflowOperation("save"),
455
+ new WorkflowOperation("close"),
456
+ new WorkflowOperation("stage"),
457
+ new WorkflowOperation("config"),
458
+ new WorkflowOperation("release"),
459
+ new WorkflowOperation("destroy"),
460
+ new WorkflowOperation("dev"),
461
+ new WorkflowOperation("dev:watch", "dev"),
462
+ new InitOperation("init"),
463
+ new TemplateOperation("template"),
464
+ new SyncTemplateOperation("sync"),
465
+ new DoctorOperation("doctor"),
466
+ new AuthLoginOperation("auth:login"),
467
+ new AuthLogoutOperation("auth:logout"),
468
+ new AuthWhoAmIOperation("auth:whoami"),
469
+ new RollbackOperation("rollback"),
470
+ new ScriptOperation("build", "tenant-build"),
471
+ new ScriptOperation("check", "tenant-check"),
472
+ new ScriptOperation("preview", "tenant-astro-command"),
473
+ new ScriptOperation("lint", "workspace-lint"),
474
+ new ScriptOperation("test", "workspace-test"),
475
+ new ScriptOperation("test:unit", "workspace-test-unit"),
476
+ new PreflightOperation("preflight", false),
477
+ new PreflightOperation("auth:check", true),
478
+ new ScriptOperation("test:e2e", "workspace-command-e2e"),
479
+ new ScriptOperation("test:e2e:local", "workspace-command-e2e", ["--mode=local"]),
480
+ new ScriptOperation("test:e2e:staging", "workspace-command-e2e", ["--mode=staging"]),
481
+ new ScriptOperation("test:e2e:full", "workspace-command-e2e", ["--mode=full"]),
482
+ new ScriptOperation("test:release", "workspace-release-verify"),
483
+ new ScriptOperation("test:release:full", "workspace-release-verify", ["--full-smoke"]),
484
+ new ScriptOperation("release:publish:changed", "workspace-publish-changed-packages"),
485
+ new ScriptOperation("astro", "tenant-astro-command"),
486
+ new ScriptOperation("sync:devvars", "sync-dev-vars"),
487
+ new MailpitUpOperation("mailpit:up"),
488
+ new MailpitDownOperation("mailpit:down"),
489
+ new MailpitLogsOperation("mailpit:logs"),
490
+ new ScriptOperation("d1:migrate:local", "tenant-d1-migrate-local"),
491
+ new ScriptOperation("cleanup:markdown", "cleanup-markdown", ["--write"]),
492
+ new ScriptOperation("cleanup:markdown:check", "cleanup-markdown", ["--check"]),
493
+ new ScriptOperation("starlight:patch", "patch-starlight-content-path")
494
+ ];
495
+ }
496
+ listOperations() {
497
+ return [...this.operations];
498
+ }
499
+ findOperation(name) {
500
+ if (!name) return null;
501
+ return this.operations.find((operation) => operation.metadata.name === name || operation.metadata.aliases.includes(name)) ?? null;
502
+ }
503
+ }
504
+ function createDefaultTreeseedOperationsProvider() {
505
+ return new DefaultTreeseedOperationsProvider();
506
+ }
507
+ function listDefaultOperationMetadata() {
508
+ return TRESEED_OPERATION_SPECS;
509
+ }
510
+ export {
511
+ DefaultTreeseedOperationsProvider,
512
+ createDefaultTreeseedOperationsProvider,
513
+ listDefaultOperationMetadata
514
+ };
@@ -0,0 +1,7 @@
1
+ import { type TreeseedOperationContext, type TreeseedOperationRequest } from '../operations-types.ts';
2
+ export declare class TreeseedOperationsSdk {
3
+ listOperations(): import("../operations-types.ts").TreeseedOperationMetadata[];
4
+ findOperation(name: string | null | undefined): import("../operations-types.ts").TreeseedOperationMetadata | null;
5
+ resolveProvider(cwd?: string): any;
6
+ execute(request: TreeseedOperationRequest, contextOverrides?: Partial<TreeseedOperationContext>): Promise<any>;
7
+ }
@@ -0,0 +1,60 @@
1
+ import { loadTreeseedDeployConfig } from "../platform/deploy/config.js";
2
+ import { createDefaultTreeseedOperationsProvider } from "./providers/default.js";
3
+ import { withProcessCwd } from "../operations/services/runtime-tools.js";
4
+ import {
5
+ findTreeseedOperation,
6
+ TRESEED_OPERATION_SPECS
7
+ } from "../operations-registry.js";
8
+ import {
9
+ TreeseedOperationError
10
+ } from "../operations-types.js";
11
+ function defaultContext(overrides = {}) {
12
+ return {
13
+ cwd: overrides.cwd ?? process.cwd(),
14
+ env: overrides.env ?? process.env,
15
+ write: overrides.write,
16
+ spawn: overrides.spawn,
17
+ outputFormat: overrides.outputFormat ?? "human",
18
+ prompt: overrides.prompt,
19
+ confirm: overrides.confirm,
20
+ transport: overrides.transport ?? "sdk"
21
+ };
22
+ }
23
+ function resolveBuiltinProvider(providerId) {
24
+ if (providerId === "default") {
25
+ return createDefaultTreeseedOperationsProvider();
26
+ }
27
+ throw new TreeseedOperationError("operations", "provider_resolution_failed", `Unknown Treeseed operations provider "${providerId}".`);
28
+ }
29
+ class TreeseedOperationsSdk {
30
+ listOperations() {
31
+ return [...TRESEED_OPERATION_SPECS];
32
+ }
33
+ findOperation(name) {
34
+ return findTreeseedOperation(name);
35
+ }
36
+ resolveProvider(cwd = process.cwd()) {
37
+ return withProcessCwd(cwd, () => {
38
+ const deployConfig = loadTreeseedDeployConfig();
39
+ const selectedProviderId = deployConfig.providers.operations ?? "default";
40
+ return resolveBuiltinProvider(selectedProviderId);
41
+ });
42
+ }
43
+ async execute(request, contextOverrides = {}) {
44
+ const context = defaultContext(contextOverrides);
45
+ const provider = this.resolveProvider(context.cwd);
46
+ const operation = provider.findOperation(request.operationName);
47
+ if (!operation) {
48
+ throw new TreeseedOperationError(
49
+ request.operationName,
50
+ "validation_failed",
51
+ `Unknown Treeseed operation "${request.operationName}".`,
52
+ { exitCode: 1 }
53
+ );
54
+ }
55
+ return operation.execute(request.input ?? {}, context);
56
+ }
57
+ }
58
+ export {
59
+ TreeseedOperationsSdk
60
+ };