@treeseed/cli 0.1.1 → 0.4.2

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 (200) hide show
  1. package/README.md +27 -26
  2. package/dist/cli/handlers/auth-login.d.ts +2 -0
  3. package/dist/cli/handlers/auth-login.js +67 -0
  4. package/dist/cli/handlers/auth-logout.d.ts +2 -0
  5. package/dist/cli/handlers/auth-logout.js +20 -0
  6. package/dist/cli/handlers/auth-whoami.d.ts +2 -0
  7. package/dist/cli/handlers/auth-whoami.js +24 -0
  8. package/dist/cli/handlers/close.js +19 -53
  9. package/dist/cli/handlers/config.js +33 -53
  10. package/dist/cli/handlers/destroy.js +34 -79
  11. package/dist/{src/cli/handlers/ship.d.ts → cli/handlers/dev.d.ts} +1 -1
  12. package/dist/cli/handlers/dev.js +19 -0
  13. package/dist/cli/handlers/doctor.js +13 -6
  14. package/dist/cli/handlers/init.js +32 -8
  15. package/dist/cli/handlers/release.js +21 -53
  16. package/dist/cli/handlers/rollback.js +8 -8
  17. package/dist/cli/handlers/save.js +21 -79
  18. package/dist/cli/handlers/stage.d.ts +2 -0
  19. package/dist/cli/handlers/stage.js +28 -0
  20. package/dist/cli/handlers/status.js +35 -26
  21. package/dist/{src/cli/handlers/deploy.d.ts → cli/handlers/switch.d.ts} +1 -1
  22. package/dist/cli/handlers/switch.js +29 -0
  23. package/dist/{src/cli/handlers/next.d.ts → cli/handlers/sync.d.ts} +1 -1
  24. package/dist/cli/handlers/sync.js +26 -0
  25. package/dist/cli/handlers/tasks.d.ts +2 -0
  26. package/dist/cli/handlers/tasks.js +31 -0
  27. package/dist/cli/handlers/template.d.ts +2 -0
  28. package/dist/cli/handlers/template.js +27 -0
  29. package/dist/cli/handlers/workflow.d.ts +6 -0
  30. package/dist/cli/handlers/workflow.js +71 -0
  31. package/dist/{src/cli → cli}/help.d.ts +2 -2
  32. package/dist/cli/help.js +36 -24
  33. package/dist/cli/main.d.ts +6 -0
  34. package/dist/cli/main.js +14 -19
  35. package/dist/cli/operations-help.d.ts +1 -0
  36. package/dist/cli/operations-help.js +1 -0
  37. package/dist/cli/operations-parser.d.ts +1 -0
  38. package/dist/cli/operations-parser.js +1 -0
  39. package/dist/cli/operations-registry.d.ts +5 -0
  40. package/dist/cli/operations-registry.js +260 -0
  41. package/dist/cli/operations-types.d.ts +72 -0
  42. package/dist/cli/parser.d.ts +3 -0
  43. package/dist/cli/parser.js +1 -6
  44. package/dist/cli/registry.d.ts +25 -0
  45. package/dist/cli/registry.js +28 -416
  46. package/dist/cli/repair.js +6 -4
  47. package/dist/cli/runtime.d.ts +31 -0
  48. package/dist/cli/runtime.js +240 -111
  49. package/dist/cli/types.d.ts +1 -0
  50. package/dist/{src/cli → cli}/workflow-state.d.ts +9 -0
  51. package/dist/cli/workflow-state.js +45 -21
  52. package/package.json +13 -13
  53. package/dist/cli/handlers/continue.js +0 -23
  54. package/dist/cli/handlers/deploy.js +0 -139
  55. package/dist/cli/handlers/next.js +0 -27
  56. package/dist/cli/handlers/prepare.js +0 -8
  57. package/dist/cli/handlers/promote.js +0 -8
  58. package/dist/cli/handlers/publish.js +0 -8
  59. package/dist/cli/handlers/setup.js +0 -48
  60. package/dist/cli/handlers/ship.js +0 -49
  61. package/dist/cli/handlers/start.js +0 -97
  62. package/dist/cli/handlers/teardown.js +0 -50
  63. package/dist/cli/handlers/work.js +0 -85
  64. package/dist/scripts/aggregate-book.d.ts +0 -1
  65. package/dist/scripts/aggregate-book.js +0 -121
  66. package/dist/scripts/assert-release-tag-version.d.ts +0 -1
  67. package/dist/scripts/assert-release-tag-version.js +0 -21
  68. package/dist/scripts/build-dist.d.ts +0 -1
  69. package/dist/scripts/build-dist.js +0 -108
  70. package/dist/scripts/build-tenant-worker.d.ts +0 -1
  71. package/dist/scripts/build-tenant-worker.js +0 -36
  72. package/dist/scripts/cleanup-markdown.d.ts +0 -2
  73. package/dist/scripts/cleanup-markdown.js +0 -373
  74. package/dist/scripts/config-runtime-lib.d.ts +0 -122
  75. package/dist/scripts/config-runtime-lib.js +0 -505
  76. package/dist/scripts/config-treeseed.d.ts +0 -2
  77. package/dist/scripts/config-treeseed.js +0 -81
  78. package/dist/scripts/d1-migration-lib.d.ts +0 -6
  79. package/dist/scripts/d1-migration-lib.js +0 -90
  80. package/dist/scripts/deploy-lib.d.ts +0 -127
  81. package/dist/scripts/deploy-lib.js +0 -841
  82. package/dist/scripts/ensure-mailpit.d.ts +0 -1
  83. package/dist/scripts/ensure-mailpit.js +0 -29
  84. package/dist/scripts/git-workflow-lib.d.ts +0 -25
  85. package/dist/scripts/git-workflow-lib.js +0 -136
  86. package/dist/scripts/github-automation-lib.d.ts +0 -156
  87. package/dist/scripts/github-automation-lib.js +0 -242
  88. package/dist/scripts/local-dev-lib.d.ts +0 -9
  89. package/dist/scripts/local-dev-lib.js +0 -84
  90. package/dist/scripts/local-dev.d.ts +0 -1
  91. package/dist/scripts/local-dev.js +0 -129
  92. package/dist/scripts/logs-mailpit.d.ts +0 -1
  93. package/dist/scripts/logs-mailpit.js +0 -2
  94. package/dist/scripts/mailpit-runtime.d.ts +0 -4
  95. package/dist/scripts/mailpit-runtime.js +0 -57
  96. package/dist/scripts/package-tools.d.ts +0 -22
  97. package/dist/scripts/package-tools.js +0 -255
  98. package/dist/scripts/patch-starlight-content-path.d.ts +0 -1
  99. package/dist/scripts/patch-starlight-content-path.js +0 -172
  100. package/dist/scripts/paths.d.ts +0 -17
  101. package/dist/scripts/paths.js +0 -26
  102. package/dist/scripts/publish-package.d.ts +0 -1
  103. package/dist/scripts/publish-package.js +0 -19
  104. package/dist/scripts/release-verify.d.ts +0 -1
  105. package/dist/scripts/release-verify.js +0 -136
  106. package/dist/scripts/run-fixture-astro-command.d.ts +0 -1
  107. package/dist/scripts/run-fixture-astro-command.js +0 -18
  108. package/dist/scripts/save-deploy-preflight-lib.d.ts +0 -34
  109. package/dist/scripts/save-deploy-preflight-lib.js +0 -69
  110. package/dist/scripts/scaffold-site.d.ts +0 -2
  111. package/dist/scripts/scaffold-site.js +0 -92
  112. package/dist/scripts/stop-mailpit.d.ts +0 -1
  113. package/dist/scripts/stop-mailpit.js +0 -5
  114. package/dist/scripts/sync-dev-vars.d.ts +0 -1
  115. package/dist/scripts/sync-dev-vars.js +0 -6
  116. package/dist/scripts/template-registry-lib.d.ts +0 -47
  117. package/dist/scripts/template-registry-lib.js +0 -137
  118. package/dist/scripts/tenant-astro-command.d.ts +0 -1
  119. package/dist/scripts/tenant-astro-command.js +0 -3
  120. package/dist/scripts/tenant-build.d.ts +0 -1
  121. package/dist/scripts/tenant-build.js +0 -16
  122. package/dist/scripts/tenant-check.d.ts +0 -1
  123. package/dist/scripts/tenant-check.js +0 -7
  124. package/dist/scripts/tenant-d1-migrate-local.d.ts +0 -1
  125. package/dist/scripts/tenant-d1-migrate-local.js +0 -11
  126. package/dist/scripts/tenant-deploy.d.ts +0 -2
  127. package/dist/scripts/tenant-deploy.js +0 -180
  128. package/dist/scripts/tenant-destroy.d.ts +0 -2
  129. package/dist/scripts/tenant-destroy.js +0 -104
  130. package/dist/scripts/tenant-dev.d.ts +0 -1
  131. package/dist/scripts/tenant-dev.js +0 -171
  132. package/dist/scripts/tenant-lint.d.ts +0 -1
  133. package/dist/scripts/tenant-lint.js +0 -4
  134. package/dist/scripts/tenant-test.d.ts +0 -1
  135. package/dist/scripts/tenant-test.js +0 -4
  136. package/dist/scripts/test-cloudflare-local.d.ts +0 -1
  137. package/dist/scripts/test-cloudflare-local.js +0 -212
  138. package/dist/scripts/test-scaffold.d.ts +0 -2
  139. package/dist/scripts/test-scaffold.js +0 -297
  140. package/dist/scripts/treeseed.d.ts +0 -2
  141. package/dist/scripts/treeseed.js +0 -4
  142. package/dist/scripts/validate-templates.d.ts +0 -2
  143. package/dist/scripts/validate-templates.js +0 -4
  144. package/dist/scripts/watch-dev-lib.d.ts +0 -21
  145. package/dist/scripts/watch-dev-lib.js +0 -277
  146. package/dist/scripts/workspace-close.d.ts +0 -2
  147. package/dist/scripts/workspace-close.js +0 -24
  148. package/dist/scripts/workspace-command-e2e.d.ts +0 -2
  149. package/dist/scripts/workspace-command-e2e.js +0 -718
  150. package/dist/scripts/workspace-lint.d.ts +0 -1
  151. package/dist/scripts/workspace-lint.js +0 -9
  152. package/dist/scripts/workspace-preflight-lib.d.ts +0 -36
  153. package/dist/scripts/workspace-preflight-lib.js +0 -179
  154. package/dist/scripts/workspace-preflight.d.ts +0 -2
  155. package/dist/scripts/workspace-preflight.js +0 -22
  156. package/dist/scripts/workspace-publish-changed-packages.d.ts +0 -1
  157. package/dist/scripts/workspace-publish-changed-packages.js +0 -16
  158. package/dist/scripts/workspace-release-verify.d.ts +0 -1
  159. package/dist/scripts/workspace-release-verify.js +0 -81
  160. package/dist/scripts/workspace-release.d.ts +0 -2
  161. package/dist/scripts/workspace-release.js +0 -42
  162. package/dist/scripts/workspace-save-lib.d.ts +0 -42
  163. package/dist/scripts/workspace-save-lib.js +0 -220
  164. package/dist/scripts/workspace-save.d.ts +0 -2
  165. package/dist/scripts/workspace-save.js +0 -124
  166. package/dist/scripts/workspace-start-warning.js +0 -3
  167. package/dist/scripts/workspace-start.d.ts +0 -2
  168. package/dist/scripts/workspace-start.js +0 -71
  169. package/dist/scripts/workspace-test-unit.d.ts +0 -1
  170. package/dist/scripts/workspace-test-unit.js +0 -4
  171. package/dist/scripts/workspace-test.d.ts +0 -1
  172. package/dist/scripts/workspace-test.js +0 -11
  173. package/dist/scripts/workspace-tools.d.ts +0 -13
  174. package/dist/scripts/workspace-tools.js +0 -226
  175. package/dist/src/cli/handlers/continue.d.ts +0 -2
  176. package/dist/src/cli/handlers/prepare.d.ts +0 -2
  177. package/dist/src/cli/handlers/promote.d.ts +0 -2
  178. package/dist/src/cli/handlers/publish.d.ts +0 -2
  179. package/dist/src/cli/handlers/setup.d.ts +0 -2
  180. package/dist/src/cli/handlers/start.d.ts +0 -3
  181. package/dist/src/cli/handlers/teardown.d.ts +0 -2
  182. package/dist/src/cli/handlers/work.d.ts +0 -2
  183. package/dist/src/cli/main.d.ts +0 -6
  184. package/dist/src/cli/parser.d.ts +0 -3
  185. package/dist/src/cli/registry.d.ts +0 -27
  186. package/dist/src/cli/runtime.d.ts +0 -4
  187. package/dist/src/cli/types.d.ts +0 -71
  188. /package/dist/{src/cli → cli}/handlers/close.d.ts +0 -0
  189. /package/dist/{src/cli → cli}/handlers/config.d.ts +0 -0
  190. /package/dist/{src/cli → cli}/handlers/destroy.d.ts +0 -0
  191. /package/dist/{src/cli → cli}/handlers/doctor.d.ts +0 -0
  192. /package/dist/{src/cli → cli}/handlers/init.d.ts +0 -0
  193. /package/dist/{src/cli → cli}/handlers/release.d.ts +0 -0
  194. /package/dist/{src/cli → cli}/handlers/rollback.d.ts +0 -0
  195. /package/dist/{src/cli → cli}/handlers/save.d.ts +0 -0
  196. /package/dist/{src/cli → cli}/handlers/status.d.ts +0 -0
  197. /package/dist/{src/cli → cli}/handlers/utils.d.ts +0 -0
  198. /package/dist/{scripts/workspace-start-warning.d.ts → cli/operations-types.js} +0 -0
  199. /package/dist/{src/cli → cli}/repair.d.ts +0 -0
  200. /package/dist/{src/index.d.ts → index.d.ts} +0 -0
@@ -1,212 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { mkdirSync } from 'node:fs';
3
- import { resolve } from 'node:path';
4
- import { setTimeout as delay } from 'node:timers/promises';
5
- import { prepareCloudflareLocalRuntime, spawnProcess, startWranglerDev } from './local-dev-lib.js';
6
- import { fixtureRoot, fixtureWranglerConfig } from './paths.js';
7
- const TEST_PORT = 8791;
8
- const BASE_URL = `http://127.0.0.1:${TEST_PORT}`;
9
- const RUN_ID = `${Date.now()}-${process.pid}`;
10
- const ipSeed = Date.now() + process.pid;
11
- const TEST_IP = `198.51.${(ipSeed >>> 8) % 250}.${ipSeed % 250}`;
12
- const TEST_EMAIL = `integration-subscriber-${RUN_ID}@localhost.test`;
13
- const PERSIST_TO = resolve(process.cwd(), '.local', 'cloudflare-integration', RUN_ID);
14
- const workerLogs = [];
15
- mkdirSync(PERSIST_TO, { recursive: true });
16
- function captureLogs(stream, label) {
17
- if (!stream) {
18
- return;
19
- }
20
- stream.setEncoding('utf8');
21
- stream.on('data', (chunk) => {
22
- workerLogs.push(`[${label}] ${chunk}`);
23
- if (workerLogs.length > 40) {
24
- workerLogs.shift();
25
- }
26
- });
27
- }
28
- function readBody(message) {
29
- return new Promise((resolve) => {
30
- let body = '';
31
- message.setEncoding('utf8');
32
- message.on('data', (chunk) => {
33
- body += chunk;
34
- });
35
- message.on('end', () => resolve(body));
36
- });
37
- }
38
- function extractSetCookie(response) {
39
- if (typeof response.headers.getSetCookie === 'function') {
40
- return response.headers.getSetCookie();
41
- }
42
- const cookie = response.headers.get('set-cookie');
43
- return cookie ? [cookie] : [];
44
- }
45
- async function waitForWorker(worker) {
46
- for (let attempt = 0; attempt < 60; attempt += 1) {
47
- if (worker.exitCode !== null) {
48
- throw new Error(`Wrangler exited before the worker became ready (exit ${worker.exitCode}).\n${workerLogs.join('')}`);
49
- }
50
- try {
51
- const response = await fetch(`${BASE_URL}/api/form/submit?formType=subscribe`, {
52
- signal: AbortSignal.timeout(5000),
53
- headers: {
54
- 'x-forwarded-for': TEST_IP,
55
- },
56
- });
57
- if (response.ok) {
58
- return;
59
- }
60
- }
61
- catch {
62
- // Keep polling until the local worker is ready.
63
- }
64
- await delay(1000);
65
- }
66
- throw new Error(`Timed out waiting for local Wrangler dev to start.\n${workerLogs.join('')}`);
67
- }
68
- async function issueToken() {
69
- const response = await fetch(`${BASE_URL}/api/form/submit?formType=subscribe`, {
70
- signal: AbortSignal.timeout(10000),
71
- headers: {
72
- 'x-forwarded-for': TEST_IP,
73
- },
74
- });
75
- assert.equal(response.status, 200, 'token endpoint should return HTTP 200');
76
- const payload = await response.json();
77
- const cookies = extractSetCookie(response);
78
- assert.equal(payload.ok, true, 'token payload should be ok');
79
- assert.ok(payload.formToken, 'token endpoint should return a form token');
80
- assert.ok(payload.sessionId, 'token endpoint should return a session id');
81
- assert.ok(cookies.length > 0, 'token endpoint should set a session cookie');
82
- return {
83
- formToken: payload.formToken,
84
- sessionId: payload.sessionId,
85
- cookieHeader: cookies.map((cookie) => cookie.split(';', 1)[0]).join('; '),
86
- };
87
- }
88
- async function submitSubscribeForm({ formToken, sessionId, cookieHeader }, email = TEST_EMAIL) {
89
- const form = new FormData();
90
- form.set('formType', 'subscribe');
91
- form.set('name', 'Integration Test');
92
- form.set('email', email);
93
- form.set('formToken', formToken);
94
- form.set('formSession', sessionId);
95
- form.set('redirectTo', '/');
96
- return fetch(`${BASE_URL}/api/form/submit`, {
97
- method: 'POST',
98
- redirect: 'manual',
99
- signal: AbortSignal.timeout(10000),
100
- headers: {
101
- cookie: cookieHeader,
102
- origin: BASE_URL,
103
- referer: `${BASE_URL}/`,
104
- 'x-forwarded-for': TEST_IP,
105
- },
106
- body: form,
107
- });
108
- }
109
- async function querySubscribers() {
110
- const query = `SELECT lookup_key AS email, status, json_extract(payload_json, '$.source') AS source FROM runtime_records WHERE record_type = 'subscription' AND lookup_key = '${TEST_EMAIL}'`;
111
- const child = spawnProcess('wrangler', [
112
- 'd1',
113
- 'execute',
114
- 'karyon-docs-site-data',
115
- '--local',
116
- '--config',
117
- fixtureWranglerConfig,
118
- '--persist-to',
119
- PERSIST_TO,
120
- '--json',
121
- '--command',
122
- query,
123
- ], { stdio: ['ignore', 'pipe', 'inherit'], cwd: fixtureRoot });
124
- const stdout = await readBody(child.stdout);
125
- const exitCode = await new Promise((resolve) => {
126
- child.on('exit', resolve);
127
- });
128
- assert.equal(exitCode, 0, 'local D1 query should succeed');
129
- const parsed = JSON.parse(stdout);
130
- const results = Array.isArray(parsed) ? parsed : [parsed];
131
- const rows = results.flatMap((entry) => entry.results ?? []);
132
- return rows;
133
- }
134
- async function main() {
135
- prepareCloudflareLocalRuntime({
136
- persistTo: PERSIST_TO,
137
- envOverrides: {
138
- TREESEED_LOCAL_DEV_MODE: 'cloudflare',
139
- TREESEED_FORMS_LOCAL_BYPASS_TURNSTILE: 'true',
140
- TREESEED_PUBLIC_FORMS_LOCAL_BYPASS_TURNSTILE: 'true',
141
- TREESEED_FORMS_LOCAL_BYPASS_CLOUDFLARE_GUARDS: 'false',
142
- TREESEED_FORMS_LOCAL_USE_MAILPIT: 'true',
143
- TREESEED_MAILPIT_SMTP_HOST: '127.0.0.1',
144
- TREESEED_MAILPIT_SMTP_PORT: '1025',
145
- },
146
- });
147
- const worker = startWranglerDev(['--port', String(TEST_PORT), '--persist-to', PERSIST_TO], {
148
- stdio: ['ignore', 'pipe', 'pipe'],
149
- });
150
- captureLogs(worker.stdout, 'stdout');
151
- captureLogs(worker.stderr, 'stderr');
152
- const teardown = async () => {
153
- if (worker.exitCode === null && !worker.killed) {
154
- worker.kill('SIGTERM');
155
- await Promise.race([
156
- new Promise((resolve) => worker.once('exit', resolve)),
157
- delay(5000),
158
- ]);
159
- if (worker.exitCode === null && !worker.killed) {
160
- worker.kill('SIGKILL');
161
- await Promise.race([
162
- new Promise((resolve) => worker.once('exit', resolve)),
163
- delay(5000),
164
- ]);
165
- }
166
- }
167
- };
168
- process.on('SIGINT', async () => {
169
- await teardown();
170
- process.exit(130);
171
- });
172
- process.on('SIGTERM', async () => {
173
- await teardown();
174
- process.exit(143);
175
- });
176
- let shouldQuerySubscribers = false;
177
- try {
178
- await waitForWorker(worker);
179
- const firstToken = await issueToken();
180
- const firstResponse = await submitSubscribeForm(firstToken);
181
- assert.equal(firstResponse.status, 303, 'subscribe submit should redirect');
182
- assert.match(firstResponse.headers.get('location') ?? '', /\/\?formStatus=success&formCode=success#site-subscribe$/, 'subscribe success redirect should include success markers');
183
- shouldQuerySubscribers = true;
184
- const replayResponse = await submitSubscribeForm(firstToken);
185
- assert.equal(replayResponse.status, 303, 'replayed submit should still redirect');
186
- assert.match(replayResponse.headers.get('location') ?? '', /\/\?formStatus=error&formCode=token_replayed#site-subscribe$/, 'replayed token should be rejected by KV-backed nonce storage');
187
- for (let attempt = 0; attempt < 2; attempt += 1) {
188
- const token = await issueToken();
189
- const response = await submitSubscribeForm(token);
190
- assert.equal(response.status, 303, 'pre-limit submissions should redirect');
191
- assert.match(response.headers.get('location') ?? '', /\/\?formStatus=success&formCode=success#site-subscribe$/, 'pre-limit submissions should succeed');
192
- }
193
- const limitedToken = await issueToken();
194
- const limitedResponse = await submitSubscribeForm(limitedToken);
195
- assert.equal(limitedResponse.status, 303, 'rate-limited submit should redirect');
196
- assert.match(limitedResponse.headers.get('location') ?? '', /\/\?formStatus=error&formCode=rate_limited#site-subscribe$/, 'local KV-backed rate limiting should reject the fourth submission');
197
- }
198
- finally {
199
- await teardown();
200
- }
201
- if (shouldQuerySubscribers) {
202
- const rows = await querySubscribers();
203
- assert.equal(rows.length, 1, 'subscriber should be written to local D1');
204
- assert.equal(rows[0].email, TEST_EMAIL, 'subscriber email should match the submitted address');
205
- assert.equal(rows[0].status, 'active', 'subscriber should be active');
206
- assert.equal(rows[0].source, 'footer', 'subscriber source should be tracked');
207
- }
208
- }
209
- main().catch((error) => {
210
- console.error(error);
211
- process.exit(1);
212
- });
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,297 +0,0 @@
1
- #!/usr/bin/env node
2
- import { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { dirname, join, resolve } from 'node:path';
5
- import { spawnSync } from 'node:child_process';
6
- import { agentPackageRoot, corePackageRoot, packageRoot, packageScriptPath, sdkPackageRoot } from './package-tools.js';
7
- import { validateAllTemplateDefinitions } from './template-registry-lib.js';
8
- const npmCacheDir = process.env.TREESEED_SCAFFOLD_NPM_CACHE_DIR
9
- ? resolve(process.env.TREESEED_SCAFFOLD_NPM_CACHE_DIR)
10
- : resolve(tmpdir(), 'treeseed-npm-cache');
11
- const packageJson = JSON.parse(readFileSync(resolve(corePackageRoot, 'package.json'), 'utf8'));
12
- const sdkPackageJson = JSON.parse(readFileSync(resolve(sdkPackageRoot, 'package.json'), 'utf8'));
13
- const cliPackageJson = JSON.parse(readFileSync(resolve(packageRoot, 'package.json'), 'utf8'));
14
- const agentPackageJson = JSON.parse(readFileSync(resolve(agentPackageRoot, 'package.json'), 'utf8'));
15
- const workspaceTarballs = (() => {
16
- try {
17
- return JSON.parse(process.env.TREESEED_WORKSPACE_TARBALLS ?? '{}');
18
- }
19
- catch {
20
- return {};
21
- }
22
- })();
23
- const externalCoreTarball = process.env.TREESEED_SCAFFOLD_CORE_TARBALL
24
- ? resolve(process.env.TREESEED_SCAFFOLD_CORE_TARBALL)
25
- : typeof workspaceTarballs['@treeseed/core'] === 'string'
26
- ? resolve(workspaceTarballs['@treeseed/core'])
27
- : null;
28
- const externalSdkTarball = process.env.TREESEED_SCAFFOLD_SDK_TARBALL
29
- ? resolve(process.env.TREESEED_SCAFFOLD_SDK_TARBALL)
30
- : typeof workspaceTarballs['@treeseed/sdk'] === 'string'
31
- ? resolve(workspaceTarballs['@treeseed/sdk'])
32
- : null;
33
- const externalCliTarball = process.env.TREESEED_SCAFFOLD_CLI_TARBALL
34
- ? resolve(process.env.TREESEED_SCAFFOLD_CLI_TARBALL)
35
- : typeof workspaceTarballs['@treeseed/cli'] === 'string'
36
- ? resolve(workspaceTarballs['@treeseed/cli'])
37
- : null;
38
- const externalAgentTarball = process.env.TREESEED_SCAFFOLD_AGENT_TARBALL
39
- ? resolve(process.env.TREESEED_SCAFFOLD_AGENT_TARBALL)
40
- : typeof workspaceTarballs['@treeseed/agent'] === 'string'
41
- ? resolve(workspaceTarballs['@treeseed/agent'])
42
- : null;
43
- const reusesExternalTarballs = Boolean(externalCoreTarball || externalSdkTarball || externalCliTarball || externalAgentTarball);
44
- const scaffoldChecks = new Set((process.env.TREESEED_SCAFFOLD_CHECKS ?? 'build,deploy')
45
- .split(',')
46
- .map((value) => value.trim())
47
- .filter(Boolean));
48
- const timings = [];
49
- const resetScaffoldCache = process.env.TREESEED_SCAFFOLD_RESET_CACHE === '1';
50
- const scaffoldTempRoot = resolve(process.env.TREESEED_SCAFFOLD_TEMP_ROOT ?? resolve(packageRoot, '.local', 'tmp'));
51
- mkdirSync(scaffoldTempRoot, { recursive: true });
52
- function logStep(message) {
53
- console.log(`[treeseed:test-scaffold] ${message}`);
54
- }
55
- function withTiming(label, action) {
56
- const startedAt = Date.now();
57
- logStep(`${label} started`);
58
- try {
59
- const result = action();
60
- const durationMs = Date.now() - startedAt;
61
- timings.push({ label, durationMs, status: 'completed' });
62
- logStep(`${label} completed in ${(durationMs / 1000).toFixed(1)}s`);
63
- return result;
64
- }
65
- catch (error) {
66
- const durationMs = Date.now() - startedAt;
67
- timings.push({ label, durationMs, status: 'failed' });
68
- logStep(`${label} failed in ${(durationMs / 1000).toFixed(1)}s`);
69
- throw error;
70
- }
71
- }
72
- function printSummary() {
73
- if (timings.length === 0) {
74
- return;
75
- }
76
- console.log('[treeseed:test-scaffold] Stage summary');
77
- for (const entry of timings) {
78
- console.log(`[treeseed:test-scaffold] ${entry.status === 'completed' ? 'ok ' : 'fail'} ${entry.label} (${(entry.durationMs / 1000).toFixed(1)}s)`);
79
- }
80
- }
81
- function resetNpmCache() {
82
- rmSync(npmCacheDir, { recursive: true, force: true });
83
- }
84
- function runStep(command, args, { cwd = packageRoot, env = {}, capture = false } = {}) {
85
- const result = spawnSync(command, args, {
86
- cwd,
87
- env: { ...process.env, ...env },
88
- stdio: capture ? 'pipe' : 'inherit',
89
- encoding: 'utf8',
90
- });
91
- if (result.status !== 0) {
92
- const message = capture ? (result.stderr?.trim() || result.stdout?.trim() || `${command} ${args.join(' ')} failed`) : `${command} ${args.join(' ')} failed`;
93
- throw new Error(message);
94
- }
95
- return result;
96
- }
97
- function createTempSiteRoot() {
98
- return mkdtempSync(join(scaffoldTempRoot, 'treeseed-scaffold-'));
99
- }
100
- function rewriteScaffoldDependency(siteRoot, tarballPath, cliTarballPath) {
101
- const packageJsonPath = resolve(siteRoot, 'package.json');
102
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
103
- packageJson.dependencies = packageJson.dependencies ?? {};
104
- packageJson.dependencies['@treeseed/core'] = tarballPath;
105
- packageJson.dependencies['@treeseed/cli'] = cliTarballPath;
106
- writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8');
107
- }
108
- function installManualPackageTarball(siteRoot, tarballPath, packageName) {
109
- const extractRoot = mkdtempSync(join(scaffoldTempRoot, 'treeseed-scaffold-package-'));
110
- try {
111
- runStep('tar', ['-xzf', tarballPath, '-C', extractRoot]);
112
- const scopeRoot = resolve(siteRoot, 'node_modules', '@treeseed');
113
- mkdirSync(scopeRoot, { recursive: true });
114
- cpSync(resolve(extractRoot, 'package'), resolve(scopeRoot, packageName.split('/')[1]), { recursive: true });
115
- }
116
- finally {
117
- rmSync(extractRoot, { recursive: true, force: true });
118
- }
119
- }
120
- function linkWorkspacePackage(siteRoot, packageName, sourceRoot) {
121
- const scopeRoot = resolve(siteRoot, 'node_modules', '@treeseed');
122
- mkdirSync(scopeRoot, { recursive: true });
123
- symlinkSync(sourceRoot, resolve(scopeRoot, packageName.split('/')[1]), 'dir');
124
- }
125
- function resolveSharedNodeModulesRoot() {
126
- let current = packageRoot;
127
- while (true) {
128
- const candidate = resolve(current, 'node_modules');
129
- if (existsSync(candidate)) {
130
- return candidate;
131
- }
132
- const parent = resolve(current, '..');
133
- if (parent === current) {
134
- break;
135
- }
136
- current = parent;
137
- }
138
- throw new Error(`Unable to locate a shared node_modules directory for ${packageRoot}.`);
139
- }
140
- function mirrorSharedNodeModules(siteRoot) {
141
- const sharedNodeModules = resolveSharedNodeModulesRoot();
142
- for (const entry of readdirSync(sharedNodeModules, { withFileTypes: true })) {
143
- if (entry.name === '.bin' || entry.name === '@treeseed' || entry.name === '@astrojs') {
144
- continue;
145
- }
146
- const sourcePath = resolve(sharedNodeModules, entry.name);
147
- const targetPath = resolve(siteRoot, 'node_modules', entry.name);
148
- mkdirSync(dirname(targetPath), { recursive: true });
149
- if (entry.name === 'astro') {
150
- cpSync(sourcePath, targetPath, { recursive: true });
151
- continue;
152
- }
153
- symlinkSync(sourcePath, targetPath, 'dir');
154
- }
155
- const sharedAstroScope = resolve(sharedNodeModules, '@astrojs');
156
- const targetAstroScope = resolve(siteRoot, 'node_modules', '@astrojs');
157
- mkdirSync(targetAstroScope, { recursive: true });
158
- for (const packageName of ['cloudflare', 'mdx', 'sitemap', 'starlight']) {
159
- cpSync(resolve(sharedAstroScope, packageName), resolve(targetAstroScope, packageName), { recursive: true });
160
- }
161
- }
162
- function linkTreeseedBins(siteRoot) {
163
- const binRoot = resolve(siteRoot, 'node_modules', '.bin');
164
- mkdirSync(binRoot, { recursive: true });
165
- for (const [name, relativeTarget] of [
166
- ['treeseed', '../@treeseed/cli/dist/cli/main.js'],
167
- ['treeseed-agents', '../@treeseed/agent/dist/scripts/treeseed-agents.js'],
168
- ]) {
169
- symlinkSync(relativeTarget, resolve(binRoot, name));
170
- }
171
- }
172
- function createTarball(root, pkg) {
173
- return withTiming(`${pkg.name} build+pack`, () => {
174
- runStep('npm', ['run', 'build:dist'], { cwd: root });
175
- const output = runStep('npm', ['pack', '--silent', '--ignore-scripts', '--cache', npmCacheDir], {
176
- cwd: root,
177
- capture: true,
178
- env: {
179
- npm_config_cache: npmCacheDir,
180
- NPM_CONFIG_CACHE: npmCacheDir,
181
- },
182
- });
183
- const filename = output.stdout
184
- .split('\n')
185
- .map((line) => line.trim())
186
- .filter(Boolean)
187
- .at(-1)
188
- || `${pkg.name.replace(/^@/, '').replaceAll('/', '-')}-${pkg.version}.tgz`;
189
- return resolve(root, filename);
190
- });
191
- }
192
- function scaffoldSite(siteRoot) {
193
- validateAllTemplateDefinitions();
194
- runStep(process.execPath, [packageScriptPath('scaffold-site'), siteRoot, '--template', 'starter-basic', '--name', 'Smoke Site', '--site-url', 'https://smoke.example.com', '--contact-email', 'hello@example.com']);
195
- }
196
- function installScaffold(siteRoot, { coreTarballPath, sdkTarballPath, cliTarballPath, agentTarballPath }) {
197
- if (coreTarballPath && sdkTarballPath && cliTarballPath && agentTarballPath) {
198
- linkWorkspacePackage(siteRoot, sdkPackageJson.name, sdkPackageRoot);
199
- linkWorkspacePackage(siteRoot, packageJson.name, corePackageRoot);
200
- linkWorkspacePackage(siteRoot, cliPackageJson.name, packageRoot);
201
- linkWorkspacePackage(siteRoot, agentPackageJson.name, agentPackageRoot);
202
- mirrorSharedNodeModules(siteRoot);
203
- linkTreeseedBins(siteRoot);
204
- return;
205
- }
206
- runStep('npm', ['install', '--cache', npmCacheDir, '--prefer-offline', '--no-audit', '--no-fund'], {
207
- cwd: siteRoot,
208
- env: {
209
- npm_config_cache: npmCacheDir,
210
- NPM_CONFIG_CACHE: npmCacheDir,
211
- npm_config_prefer_offline: 'true',
212
- npm_config_audit: 'false',
213
- npm_config_fund: 'false',
214
- },
215
- });
216
- }
217
- function runScaffoldChecks(siteRoot) {
218
- if (scaffoldChecks.has('build')) {
219
- withTiming('scaffold build', () => {
220
- runStep('npm', ['run', 'build'], { cwd: siteRoot });
221
- });
222
- }
223
- if (scaffoldChecks.has('deploy')) {
224
- withTiming('scaffold deploy dry-run', () => {
225
- runStep('npm', ['run', 'deploy', '--', '--dry-run'], { cwd: siteRoot });
226
- });
227
- }
228
- }
229
- const siteRoot = createTempSiteRoot();
230
- let tarballPath = externalCoreTarball;
231
- let sdkTarballPath = externalSdkTarball;
232
- let cliTarballPath = externalCliTarball;
233
- let agentTarballPath = externalAgentTarball;
234
- try {
235
- if (!reusesExternalTarballs && resetScaffoldCache) {
236
- logStep(`resetting npm cache at ${npmCacheDir}`);
237
- resetNpmCache();
238
- }
239
- if (!sdkTarballPath) {
240
- logStep('building and packing @treeseed/sdk');
241
- sdkTarballPath = createTarball(sdkPackageRoot, sdkPackageJson);
242
- }
243
- else {
244
- logStep(`reusing provided @treeseed/sdk tarball: ${sdkTarballPath}`);
245
- }
246
- if (!tarballPath) {
247
- logStep('building and packing @treeseed/core');
248
- tarballPath = createTarball(corePackageRoot, packageJson);
249
- }
250
- else {
251
- logStep(`reusing provided @treeseed/core tarball: ${tarballPath}`);
252
- }
253
- if (!agentTarballPath) {
254
- logStep('building and packing @treeseed/agent');
255
- agentTarballPath = createTarball(agentPackageRoot, agentPackageJson);
256
- }
257
- else {
258
- logStep(`reusing provided @treeseed/agent tarball: ${agentTarballPath}`);
259
- }
260
- if (!cliTarballPath) {
261
- logStep('building and packing @treeseed/cli');
262
- cliTarballPath = createTarball(packageRoot, cliPackageJson);
263
- }
264
- else {
265
- logStep(`reusing provided @treeseed/cli tarball: ${cliTarballPath}`);
266
- }
267
- logStep(`scaffolding temporary tenant at ${siteRoot}`);
268
- withTiming('scaffold tenant generation', () => {
269
- scaffoldSite(siteRoot);
270
- });
271
- rewriteScaffoldDependency(siteRoot, tarballPath, cliTarballPath);
272
- logStep(`installing scaffolded tenant dependencies with checks: ${[...scaffoldChecks].join(', ') || 'none'}`);
273
- withTiming('scaffold dependency install', () => {
274
- installScaffold(siteRoot, {
275
- coreTarballPath: tarballPath,
276
- sdkTarballPath,
277
- cliTarballPath,
278
- agentTarballPath,
279
- });
280
- });
281
- logStep('running scaffold smoke checks');
282
- runScaffoldChecks(siteRoot);
283
- console.log(`Scaffold smoke test passed in ${dirname(siteRoot) ? siteRoot : '.'}`);
284
- }
285
- finally {
286
- printSummary();
287
- rmSync(siteRoot, { recursive: true, force: true });
288
- if (sdkTarballPath && !externalSdkTarball) {
289
- rmSync(sdkTarballPath, { force: true });
290
- }
291
- if (tarballPath && !externalCoreTarball) {
292
- rmSync(tarballPath, { force: true });
293
- }
294
- if (!reusesExternalTarballs && resetScaffoldCache) {
295
- resetNpmCache();
296
- }
297
- }
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { runTreeseedCli } from '../cli/main.js';
3
- const exitCode = await runTreeseedCli(process.argv.slice(2));
4
- process.exit(exitCode);
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { validateAllTemplateDefinitions } from './template-registry-lib.js';
3
- const definitions = validateAllTemplateDefinitions();
4
- console.log(`Validated ${definitions.length} template definition${definitions.length === 1 ? '' : 's'}.`);
@@ -1,21 +0,0 @@
1
- export declare function isEditablePackageWorkspace(): boolean;
2
- export declare function workspaceSdkRoot(): string | null;
3
- export declare function writeDevReloadStamp(projectRoot: any): void;
4
- export declare function readDevReloadState(projectRoot: any): any;
5
- export declare function createTenantWatchEntries(tenantRoot: any): {
6
- kind: string;
7
- root: string;
8
- }[];
9
- export declare function startPollingWatch({ watchEntries, onChange }: {
10
- watchEntries: any;
11
- onChange: any;
12
- }): () => void;
13
- export declare function stopManagedProcess(child: any, signal?: string): Promise<void>;
14
- export declare function createWatchBuildPaths(projectRoot: any): {
15
- watchRoot: string;
16
- stagedDistRoot: string;
17
- backupDistRoot: string;
18
- liveDistRoot: string;
19
- };
20
- export declare function swapStagedBuildOutput(projectRoot: any): void;
21
- export declare function clearStagedBuildOutput(projectRoot: any): void;