@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,407 @@
1
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { basename, dirname, relative, resolve } from "node:path";
3
+ import {
4
+ RemoteTemplateCatalogClient
5
+ } from "@treeseed/sdk";
6
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
7
+ import {
8
+ resolveTreeseedTemplateCatalogCachePath,
9
+ resolveTreeseedTemplateCatalogEndpoint
10
+ } from "./config-runtime.js";
11
+ import {
12
+ cliPackageVersion,
13
+ corePackageVersion,
14
+ localTemplateArtifactsRoot
15
+ } from "./runtime-paths.js";
16
+ const TEMPLATE_CATEGORIES = ["starter", "example", "fixture", "reference-app"];
17
+ function loadJsonFile(filePath) {
18
+ return JSON.parse(readFileSync(filePath, "utf8"));
19
+ }
20
+ function ensureDir(filePath) {
21
+ mkdirSync(dirname(filePath), { recursive: true });
22
+ }
23
+ function listFiles(root) {
24
+ if (!existsSync(root)) {
25
+ return [];
26
+ }
27
+ const files = [];
28
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
29
+ const fullPath = resolve(root, entry.name);
30
+ if (entry.isDirectory()) {
31
+ files.push(...listFiles(fullPath));
32
+ continue;
33
+ }
34
+ files.push(fullPath);
35
+ }
36
+ return files;
37
+ }
38
+ function listTemplateArtifactIds() {
39
+ if (!existsSync(localTemplateArtifactsRoot)) {
40
+ return [];
41
+ }
42
+ return readdirSync(localTemplateArtifactsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => left.localeCompare(right, void 0, { sensitivity: "base" }));
43
+ }
44
+ function isTextFile(filePath) {
45
+ return !/\.(png|jpe?g|gif|webp|ico|woff2?|ttf|eot|pdf|zip|gz)$/iu.test(filePath);
46
+ }
47
+ function validateTemplateProductShape(product) {
48
+ if (!product.id || !product.displayName || !product.description || !product.summary) {
49
+ throw new Error(`Template product ${product.id || "(unknown)"} is missing required identity metadata.`);
50
+ }
51
+ if (!TEMPLATE_CATEGORIES.includes(product.category)) {
52
+ throw new Error(`Template product ${product.id} uses unsupported category "${product.category}".`);
53
+ }
54
+ if (product.status !== "draft" && product.status !== "live" && product.status !== "archived") {
55
+ throw new Error(`Template product ${product.id} uses unsupported status "${product.status}".`);
56
+ }
57
+ if (!existsSync(product.artifactManifestPath)) {
58
+ throw new Error(`Template product ${product.id} points to a missing artifact manifest: ${product.artifactManifestPath}`);
59
+ }
60
+ if (!existsSync(product.templateRoot)) {
61
+ throw new Error(`Template product ${product.id} points to a missing template payload: ${product.templateRoot}`);
62
+ }
63
+ }
64
+ function validateTemplateManifest(definition) {
65
+ const { manifest, templateRoot, manifestPath, product } = definition;
66
+ if (!TEMPLATE_CATEGORIES.includes(manifest.category)) {
67
+ throw new Error(`Invalid template category in ${manifestPath}: ${manifest.category}`);
68
+ }
69
+ if (!manifest.id || !manifest.displayName || !manifest.description) {
70
+ throw new Error(`Template manifest ${manifestPath} is missing required metadata fields.`);
71
+ }
72
+ if (manifest.id !== product.id) {
73
+ throw new Error(`Template product ${product.id} does not match artifact id ${manifest.id}.`);
74
+ }
75
+ if (!existsSync(templateRoot)) {
76
+ throw new Error(`Template ${manifest.id} is missing template/ at ${templateRoot}.`);
77
+ }
78
+ validateTemplatePlaceholders(definition);
79
+ }
80
+ function validateTemplatePlaceholders(definition) {
81
+ const declaredTokens = new Set(definition.manifest.variables.map((variable) => variable.token));
82
+ const discoveredTokens = /* @__PURE__ */ new Set();
83
+ for (const filePath of listFiles(definition.templateRoot)) {
84
+ if (!isTextFile(filePath)) {
85
+ continue;
86
+ }
87
+ const contents = readFileSync(filePath, "utf8");
88
+ for (const match of contents.matchAll(/__[A-Z0-9_]+__/g)) {
89
+ discoveredTokens.add(match[0]);
90
+ }
91
+ }
92
+ for (const token of discoveredTokens) {
93
+ if (!declaredTokens.has(token)) {
94
+ throw new Error(`Template ${definition.manifest.id} uses undeclared token ${token}.`);
95
+ }
96
+ }
97
+ }
98
+ function normalizeTemplateProduct(remoteProduct) {
99
+ const artifactRoot = resolve(localTemplateArtifactsRoot, remoteProduct.id);
100
+ return {
101
+ ...remoteProduct,
102
+ contentPath: `${remoteProduct.fulfillment.source.repoUrl}#${remoteProduct.id}`,
103
+ artifactRoot,
104
+ artifactManifestPath: resolve(artifactRoot, "template.config.json"),
105
+ templateRoot: resolve(artifactRoot, "template")
106
+ };
107
+ }
108
+ function readTemplateCatalogCache(cachePath) {
109
+ if (!existsSync(cachePath)) {
110
+ return null;
111
+ }
112
+ return loadJsonFile(cachePath);
113
+ }
114
+ function writeTemplateCatalogCache(cachePath, endpoint, response) {
115
+ ensureDir(cachePath);
116
+ const payload = {
117
+ endpoint,
118
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
119
+ items: response.items
120
+ };
121
+ writeFileSync(cachePath, `${JSON.stringify(payload, null, 2)}
122
+ `, "utf8");
123
+ }
124
+ async function loadRemoteTemplateCatalog(options = {}) {
125
+ const cwd = options.cwd ?? process.cwd();
126
+ const env = options.env ?? process.env;
127
+ const endpoint = resolveTreeseedTemplateCatalogEndpoint(cwd, env);
128
+ const cachePath = resolveTreeseedTemplateCatalogCachePath(cwd);
129
+ try {
130
+ const response = await new RemoteTemplateCatalogClient({ endpoint }).listTemplates();
131
+ writeTemplateCatalogCache(cachePath, endpoint, response);
132
+ return {
133
+ items: response.items,
134
+ endpoint,
135
+ usedCache: false
136
+ };
137
+ } catch (error) {
138
+ const cached = readTemplateCatalogCache(cachePath);
139
+ if (!cached) {
140
+ throw error;
141
+ }
142
+ options.writeWarning?.(
143
+ `Using cached template catalog from ${cached.fetchedAt} because the remote endpoint could not be reached.`
144
+ );
145
+ return {
146
+ items: cached.items,
147
+ endpoint: cached.endpoint,
148
+ usedCache: true
149
+ };
150
+ }
151
+ }
152
+ function loadTemplateState(siteRoot) {
153
+ const statePath = resolve(siteRoot, ".treeseed", "template-state.json");
154
+ if (!existsSync(statePath)) {
155
+ throw new Error(`Template state is missing at ${statePath}. This site may not have been created from a Treeseed template.`);
156
+ }
157
+ return loadJsonFile(statePath);
158
+ }
159
+ function writeTemplateState(siteRoot, state) {
160
+ const statePath = resolve(siteRoot, ".treeseed", "template-state.json");
161
+ ensureDir(statePath);
162
+ writeFileSync(statePath, `${JSON.stringify(state, null, 2)}
163
+ `, "utf8");
164
+ }
165
+ function toTitleCase(value) {
166
+ return value.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
167
+ }
168
+ function inferSlug(target, explicitSlug) {
169
+ return (explicitSlug ?? target).toLowerCase().replace(/[^a-z0-9-]+/g, "-");
170
+ }
171
+ function inferName(target, explicitName) {
172
+ return explicitName ?? toTitleCase(target);
173
+ }
174
+ function resolveVariableValue(variable, input) {
175
+ switch (variable.deriveFrom) {
176
+ case "slug":
177
+ return inferSlug(input.target, input.slug);
178
+ case "name":
179
+ return inferName(input.target, input.name);
180
+ case "siteUrl":
181
+ return input.siteUrl ?? variable.default ?? "";
182
+ case "contactEmail":
183
+ return input.contactEmail ?? variable.default ?? "";
184
+ case "repositoryUrl":
185
+ return input.repositoryUrl ?? variable.default ?? "";
186
+ case "discordUrl":
187
+ return input.discordUrl ?? variable.default ?? "";
188
+ case "cliVersion":
189
+ return `^${cliPackageVersion}`;
190
+ case "coreVersion":
191
+ return `^${corePackageVersion}`;
192
+ default:
193
+ return variable.default ?? "";
194
+ }
195
+ }
196
+ function applyReplacements(source, replacements) {
197
+ let output = source;
198
+ for (const [token, value] of Object.entries(replacements)) {
199
+ output = output.split(token).join(value);
200
+ }
201
+ return output;
202
+ }
203
+ function renderTemplateFile(filePath, replacements) {
204
+ return applyReplacements(readFileSync(filePath, "utf8"), replacements);
205
+ }
206
+ function copyTemplateTree(templateRoot, targetRoot, replacements) {
207
+ for (const filePath of listFiles(templateRoot)) {
208
+ const relativePath = relative(templateRoot, filePath);
209
+ const outputPath = resolve(targetRoot, relativePath);
210
+ ensureDir(outputPath);
211
+ if (isTextFile(filePath)) {
212
+ writeFileSync(outputPath, renderTemplateFile(filePath, replacements), "utf8");
213
+ continue;
214
+ }
215
+ cpSync(filePath, outputPath, { recursive: false });
216
+ }
217
+ }
218
+ function syncManagedPackageJson(targetPath, sourcePath, replacements, check) {
219
+ const currentJson = existsSync(targetPath) ? loadJsonFile(targetPath) : {};
220
+ const templateJson = JSON.parse(renderTemplateFile(sourcePath, replacements));
221
+ const nextJson = {
222
+ ...currentJson,
223
+ type: templateJson.type ?? currentJson.type,
224
+ scripts: typeof templateJson.scripts === "object" && templateJson.scripts !== null ? { ...currentJson.scripts ?? {}, ...templateJson.scripts } : currentJson.scripts,
225
+ dependencies: {
226
+ ...currentJson.dependencies ?? {},
227
+ ...Object.fromEntries(
228
+ Object.entries(templateJson.dependencies ?? {}).filter(([name]) => name.startsWith("@treeseed/"))
229
+ )
230
+ }
231
+ };
232
+ const currentSerialized = `${JSON.stringify(currentJson, null, 2)}
233
+ `;
234
+ const nextSerialized = `${JSON.stringify(nextJson, null, 2)}
235
+ `;
236
+ if (currentSerialized === nextSerialized) {
237
+ return false;
238
+ }
239
+ if (!check) {
240
+ writeFileSync(targetPath, nextSerialized, "utf8");
241
+ }
242
+ return true;
243
+ }
244
+ function validateYamlFile(filePath) {
245
+ parseYaml(readFileSync(filePath, "utf8"));
246
+ }
247
+ async function listTemplateProducts(options = {}) {
248
+ const remoteCatalog = await loadRemoteTemplateCatalog(options);
249
+ return remoteCatalog.items.map((entry) => normalizeTemplateProduct(entry)).sort((left, right) => {
250
+ const featuredDiff = Number(Boolean(right.featured)) - Number(Boolean(left.featured));
251
+ if (featuredDiff !== 0) {
252
+ return featuredDiff;
253
+ }
254
+ return left.displayName.localeCompare(right.displayName, void 0, { sensitivity: "base" });
255
+ });
256
+ }
257
+ async function resolveTemplateProduct(id, options = {}) {
258
+ const product = (await listTemplateProducts(options)).find((entry) => entry.id === id);
259
+ if (!product) {
260
+ throw new Error(`Unable to resolve remote template product "${id}".`);
261
+ }
262
+ return product;
263
+ }
264
+ async function resolveTemplateDefinition(id, options = {}, category) {
265
+ const product = await resolveTemplateProduct(id, options);
266
+ if (category && product.category !== category) {
267
+ throw new Error(`Unable to resolve template "${id}" in category "${category}".`);
268
+ }
269
+ validateTemplateProductShape(product);
270
+ const manifest = loadJsonFile(product.artifactManifestPath);
271
+ const definition = {
272
+ product,
273
+ manifestPath: product.artifactManifestPath,
274
+ templateRoot: product.templateRoot,
275
+ manifest
276
+ };
277
+ validateTemplateManifest(definition);
278
+ return definition;
279
+ }
280
+ async function validateTemplateProduct(product, options = {}) {
281
+ const definition = await resolveTemplateDefinition(product.id, options);
282
+ if (definition.manifest.templateApiVersion !== definition.product.templateApiVersion) {
283
+ throw new Error(`Template product ${definition.product.id} and artifact templateApiVersion do not match.`);
284
+ }
285
+ if ((definition.manifest.templateVersion ?? "") && definition.manifest.templateVersion !== definition.product.templateVersion) {
286
+ throw new Error(`Template product ${definition.product.id} and artifact templateVersion do not match.`);
287
+ }
288
+ if (definition.manifest.minCliVersion !== definition.product.minCliVersion) {
289
+ throw new Error(`Template product ${definition.product.id} and artifact minCliVersion do not match.`);
290
+ }
291
+ if ((definition.manifest.minCoreVersion ?? "") && definition.manifest.minCoreVersion !== definition.product.minCoreVersion) {
292
+ throw new Error(`Template product ${definition.product.id} and artifact minCoreVersion do not match.`);
293
+ }
294
+ return definition;
295
+ }
296
+ async function validateAllTemplateDefinitions(options = {}) {
297
+ const ids = listTemplateArtifactIds();
298
+ return Promise.all(ids.map((id) => validateTemplateProduct({ id }, options)));
299
+ }
300
+ function buildTemplateReplacements(manifest, input) {
301
+ const replacements = {};
302
+ for (const variable of manifest.variables) {
303
+ const value = resolveVariableValue(variable, input);
304
+ if (variable.required && !value) {
305
+ throw new Error(`Template "${manifest.id}" requires a value for "${variable.name}".`);
306
+ }
307
+ replacements[variable.token] = value;
308
+ }
309
+ return replacements;
310
+ }
311
+ async function scaffoldTemplateProject(templateId, targetRoot, input, options = {}) {
312
+ const definition = await resolveTemplateDefinition(templateId, options);
313
+ const replacements = buildTemplateReplacements(definition.manifest, {
314
+ ...input,
315
+ target: basename(targetRoot)
316
+ });
317
+ copyTemplateTree(definition.templateRoot, targetRoot, replacements);
318
+ writeTemplateState(targetRoot, {
319
+ templateId: definition.product.id,
320
+ templateVersion: definition.product.templateVersion,
321
+ sourceRef: definition.product.fulfillment.source.ref,
322
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
323
+ lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString(),
324
+ replacements
325
+ });
326
+ return definition.product;
327
+ }
328
+ async function syncTemplateProject(siteRoot, options = {}) {
329
+ const check = options.check === true;
330
+ const state = loadTemplateState(siteRoot);
331
+ const definition = await resolveTemplateDefinition(state.templateId, options);
332
+ const managedSurface = definition.manifest.managedSurface ?? {};
333
+ const changes = [];
334
+ for (const relativePath of managedSurface.coreManaged ?? []) {
335
+ const targetPath = resolve(siteRoot, relativePath);
336
+ const sourcePath = resolve(definition.templateRoot, relativePath);
337
+ if (!existsSync(sourcePath)) {
338
+ throw new Error(`Managed template file is missing from artifact: ${relativePath}`);
339
+ }
340
+ if (relativePath === "package.json") {
341
+ if (syncManagedPackageJson(targetPath, sourcePath, state.replacements, check)) {
342
+ changes.push(relativePath);
343
+ }
344
+ continue;
345
+ }
346
+ const nextContent = renderTemplateFile(sourcePath, state.replacements);
347
+ const currentContent = existsSync(targetPath) ? readFileSync(targetPath, "utf8") : "";
348
+ if (currentContent === nextContent) {
349
+ continue;
350
+ }
351
+ if (!check) {
352
+ ensureDir(targetPath);
353
+ writeFileSync(targetPath, nextContent, "utf8");
354
+ }
355
+ changes.push(relativePath);
356
+ }
357
+ for (const relativePath of managedSurface.validatedOnly ?? []) {
358
+ const targetPath = resolve(siteRoot, relativePath);
359
+ if (!existsSync(targetPath)) {
360
+ throw new Error(`Validated file is missing from generated site: ${relativePath}`);
361
+ }
362
+ validateYamlFile(targetPath);
363
+ }
364
+ if (!check) {
365
+ writeTemplateState(siteRoot, {
366
+ ...state,
367
+ templateVersion: definition.product.templateVersion,
368
+ sourceRef: definition.product.fulfillment.source.ref,
369
+ lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString()
370
+ });
371
+ }
372
+ return changes;
373
+ }
374
+ function serializeTemplateRegistryEntry(product) {
375
+ return {
376
+ id: product.id,
377
+ displayName: product.displayName,
378
+ description: product.description,
379
+ summary: product.summary,
380
+ status: product.status,
381
+ featured: Boolean(product.featured),
382
+ category: product.category,
383
+ tags: product.tags ?? [],
384
+ publisher: product.publisher,
385
+ templateVersion: product.templateVersion,
386
+ templateApiVersion: product.templateApiVersion,
387
+ minCliVersion: product.minCliVersion,
388
+ minCoreVersion: product.minCoreVersion,
389
+ source: product.fulfillment.source
390
+ };
391
+ }
392
+ async function exportTemplateCatalogYaml(options = {}) {
393
+ return stringifyYaml((await listTemplateProducts(options)).map(serializeTemplateRegistryEntry));
394
+ }
395
+ export {
396
+ TEMPLATE_CATEGORIES,
397
+ buildTemplateReplacements,
398
+ exportTemplateCatalogYaml,
399
+ listTemplateProducts,
400
+ resolveTemplateDefinition,
401
+ resolveTemplateProduct,
402
+ scaffoldTemplateProject,
403
+ serializeTemplateRegistryEntry,
404
+ syncTemplateProject,
405
+ validateAllTemplateDefinitions,
406
+ validateTemplateProduct
407
+ };
@@ -0,0 +1,21 @@
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;