spine-framework 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/.framework/README.md +129 -0
  2. package/.framework/cli/bin.cjs +14 -0
  3. package/.framework/cli/commands/agents.ts +153 -0
  4. package/.framework/cli/commands/auth.ts +94 -0
  5. package/.framework/cli/commands/create-app.ts +185 -0
  6. package/.framework/cli/commands/dev.ts +295 -0
  7. package/.framework/cli/commands/doctor.ts +442 -0
  8. package/.framework/cli/commands/generate.ts +332 -0
  9. package/.framework/cli/commands/init.ts +272 -0
  10. package/.framework/cli/commands/install-app.ts +391 -0
  11. package/.framework/cli/commands/items.ts +253 -0
  12. package/.framework/cli/commands/migrations.ts +141 -0
  13. package/.framework/cli/commands/pipelines.ts +166 -0
  14. package/.framework/cli/commands/status.ts +197 -0
  15. package/.framework/cli/commands/system.ts +184 -0
  16. package/.framework/cli/commands/test.ts +227 -0
  17. package/.framework/cli/commands/uninstall-app.ts +166 -0
  18. package/.framework/cli/context.ts +268 -0
  19. package/.framework/cli/env-loader.ts +36 -0
  20. package/.framework/cli/index.ts +106 -0
  21. package/.framework/cli/welcome.cjs +45 -0
  22. package/.framework/docs/API.md +384 -0
  23. package/.framework/docs/STABILITY.md +52 -0
  24. package/.framework/docs/admin-routes.md +76 -0
  25. package/.framework/docs/api-docs-progress.md +38 -0
  26. package/.framework/docs/api-governance.md +146 -0
  27. package/.framework/docs/api-testing-results.md +212 -0
  28. package/.framework/docs/apis/admin-configs.md +567 -0
  29. package/.framework/docs/apis/admin-data.md +272 -0
  30. package/.framework/docs/apis/index.md +231 -0
  31. package/.framework/docs/apis/internal.md +295 -0
  32. package/.framework/docs/apis/runtime.md +537 -0
  33. package/.framework/docs/assembly-launch-guide.md +138 -0
  34. package/.framework/docs/audit-results.md +590 -0
  35. package/.framework/docs/authorization-model.md +170 -0
  36. package/.framework/docs/db-api-inventory.md +95 -0
  37. package/.framework/docs/examples/custom-app/README.md +77 -0
  38. package/.framework/docs/examples/custom-function/README.md +27 -0
  39. package/.framework/docs/examples/custom-function/handler.ts +48 -0
  40. package/.framework/docs/examples/custom-webhook/README.md +68 -0
  41. package/.framework/docs/gap-remediation-backlog.md +103 -0
  42. package/.framework/docs/guides/cli-guide.md +224 -0
  43. package/.framework/docs/guides/getting-started.md +103 -0
  44. package/.framework/docs/guides/import-guide.md +193 -0
  45. package/.framework/docs/guides/testing-guide.md +229 -0
  46. package/.framework/docs/permission-examples.md +326 -0
  47. package/.framework/docs/ui-adoption-verification.md +111 -0
  48. package/.framework/docs/ui-api-coverage.md +84 -0
  49. package/.framework/docs/v2-compatibility-audit.md +228 -0
  50. package/.framework/functions/.gitkeep +1 -0
  51. package/.framework/functions/_shared/agent-runner.ts +1097 -0
  52. package/.framework/functions/_shared/app-manifest.ts +184 -0
  53. package/.framework/functions/_shared/audit.ts +150 -0
  54. package/.framework/functions/_shared/db.ts +174 -0
  55. package/.framework/functions/_shared/index.ts +382 -0
  56. package/.framework/functions/_shared/middleware.ts +490 -0
  57. package/.framework/functions/_shared/permissions.ts +1325 -0
  58. package/.framework/functions/_shared/pipeline-runner.ts +731 -0
  59. package/.framework/functions/_shared/principal.ts +760 -0
  60. package/.framework/functions/_shared/schema-utils.ts +967 -0
  61. package/.framework/functions/_shared/testing.ts +258 -0
  62. package/.framework/functions/_shared/trigger-engine.ts +425 -0
  63. package/.framework/functions/_shared/webhook-registration.ts +168 -0
  64. package/.framework/functions/_shared/webhook-registry.ts +129 -0
  65. package/.framework/functions/account-nodes.ts +111 -0
  66. package/.framework/functions/admin-data.ts +606 -0
  67. package/.framework/functions/ai-agents.ts +323 -0
  68. package/.framework/functions/api-keys.ts +376 -0
  69. package/.framework/functions/apps.ts +483 -0
  70. package/.framework/functions/auth.ts +196 -0
  71. package/.framework/functions/debug-auth.ts +107 -0
  72. package/.framework/functions/embeddings.ts +556 -0
  73. package/.framework/functions/integration-routes.ts +523 -0
  74. package/.framework/functions/integrations.ts +319 -0
  75. package/.framework/functions/item-progress.ts +272 -0
  76. package/.framework/functions/logs.ts +438 -0
  77. package/.framework/functions/observability.ts +275 -0
  78. package/.framework/functions/pipeline-executions.ts +494 -0
  79. package/.framework/functions/pipelines.ts +485 -0
  80. package/.framework/functions/prompt-configs.ts +339 -0
  81. package/.framework/functions/roles.ts +387 -0
  82. package/.framework/functions/system-cron.ts +742 -0
  83. package/.framework/functions/system.ts +323 -0
  84. package/.framework/functions/tests.ts +119 -0
  85. package/.framework/functions/timers.ts +357 -0
  86. package/.framework/functions/triggers.ts +563 -0
  87. package/.framework/functions/types.ts +604 -0
  88. package/.framework/migrations/000_foundation.sql +1256 -0
  89. package/.framework/migrations/001_seed.sql +92 -0
  90. package/.framework/migrations/002_seed_constraints.sql +13 -0
  91. package/.framework/migrations/003_auth_user_trigger.sql +59 -0
  92. package/.framework/src/App.tsx +126 -0
  93. package/.framework/src/apps/admin/index.tsx +173 -0
  94. package/.framework/src/components/AppWrapper.tsx +56 -0
  95. package/.framework/src/components/CustomAppLoader.tsx +116 -0
  96. package/.framework/src/components/admin/AdminListPage.tsx +151 -0
  97. package/.framework/src/components/admin/AdminSidebar.tsx +166 -0
  98. package/.framework/src/components/admin/AdminStatsCard.tsx +62 -0
  99. package/.framework/src/components/admin/SortableTableHeader.tsx +42 -0
  100. package/.framework/src/components/app-shell/GenericAppShell.tsx +181 -0
  101. package/.framework/src/components/app-shell/GenericDetailPage.tsx +200 -0
  102. package/.framework/src/components/app-shell/GenericListPage.tsx +116 -0
  103. package/.framework/src/components/app-sidebar.tsx +228 -0
  104. package/.framework/src/components/auth/ProtectedRoute.tsx +88 -0
  105. package/.framework/src/components/layout/AppShell.tsx +91 -0
  106. package/.framework/src/components/layout/Header.tsx +88 -0
  107. package/.framework/src/components/layout/Layout.tsx +95 -0
  108. package/.framework/src/components/layout/Sidebar.tsx +329 -0
  109. package/.framework/src/components/runtime/DataDetailHeader.tsx +77 -0
  110. package/.framework/src/components/runtime/DataDetailPage.tsx +171 -0
  111. package/.framework/src/components/runtime/DataFilters.tsx +91 -0
  112. package/.framework/src/components/runtime/DataHeader.tsx +68 -0
  113. package/.framework/src/components/runtime/DataListPage.tsx +124 -0
  114. package/.framework/src/components/runtime/DataStats.tsx +70 -0
  115. package/.framework/src/components/runtime/DataTable.tsx +174 -0
  116. package/.framework/src/components/runtime/SchemaDetailForm.tsx +134 -0
  117. package/.framework/src/components/runtime/index.ts +18 -0
  118. package/.framework/src/components/search-form.tsx +29 -0
  119. package/.framework/src/components/shared/AgentView.tsx +213 -0
  120. package/.framework/src/components/shared/FieldRenderer.tsx +478 -0
  121. package/.framework/src/components/shared/SchemaFields.tsx +226 -0
  122. package/.framework/src/components/ui/DataTable.tsx +343 -0
  123. package/.framework/src/components/ui/Form.tsx +281 -0
  124. package/.framework/src/components/ui/ItemCard.tsx +296 -0
  125. package/.framework/src/components/ui/ItemListView.tsx +308 -0
  126. package/.framework/src/components/ui/LoadingSpinner.tsx +52 -0
  127. package/.framework/src/components/ui/Modal.tsx +61 -0
  128. package/.framework/src/components/ui/RichTextEditor.tsx +210 -0
  129. package/.framework/src/components/ui/accordion.tsx +82 -0
  130. package/.framework/src/components/ui/alert-dialog.tsx +197 -0
  131. package/.framework/src/components/ui/alert.tsx +76 -0
  132. package/.framework/src/components/ui/aspect-ratio.tsx +11 -0
  133. package/.framework/src/components/ui/avatar.tsx +110 -0
  134. package/.framework/src/components/ui/badge.tsx +49 -0
  135. package/.framework/src/components/ui/breadcrumb.tsx +122 -0
  136. package/.framework/src/components/ui/button-group.tsx +83 -0
  137. package/.framework/src/components/ui/button.tsx +65 -0
  138. package/.framework/src/components/ui/calendar.tsx +222 -0
  139. package/.framework/src/components/ui/card.tsx +100 -0
  140. package/.framework/src/components/ui/carousel.tsx +240 -0
  141. package/.framework/src/components/ui/chart.tsx +373 -0
  142. package/.framework/src/components/ui/checkbox.tsx +31 -0
  143. package/.framework/src/components/ui/collapsible.tsx +33 -0
  144. package/.framework/src/components/ui/combobox.tsx +299 -0
  145. package/.framework/src/components/ui/command.tsx +193 -0
  146. package/.framework/src/components/ui/context-menu.tsx +261 -0
  147. package/.framework/src/components/ui/dialog.tsx +165 -0
  148. package/.framework/src/components/ui/direction.tsx +22 -0
  149. package/.framework/src/components/ui/drawer.tsx +132 -0
  150. package/.framework/src/components/ui/dropdown-menu.tsx +269 -0
  151. package/.framework/src/components/ui/empty.tsx +104 -0
  152. package/.framework/src/components/ui/field.tsx +238 -0
  153. package/.framework/src/components/ui/hover-card.tsx +42 -0
  154. package/.framework/src/components/ui/input-group.tsx +153 -0
  155. package/.framework/src/components/ui/input-otp.tsx +87 -0
  156. package/.framework/src/components/ui/input.tsx +19 -0
  157. package/.framework/src/components/ui/item.tsx +196 -0
  158. package/.framework/src/components/ui/kbd.tsx +26 -0
  159. package/.framework/src/components/ui/label.tsx +22 -0
  160. package/.framework/src/components/ui/menubar.tsx +277 -0
  161. package/.framework/src/components/ui/native-select.tsx +61 -0
  162. package/.framework/src/components/ui/navigation-menu.tsx +164 -0
  163. package/.framework/src/components/ui/pagination.tsx +129 -0
  164. package/.framework/src/components/ui/popover.tsx +87 -0
  165. package/.framework/src/components/ui/progress.tsx +31 -0
  166. package/.framework/src/components/ui/radio-group.tsx +42 -0
  167. package/.framework/src/components/ui/resizable.tsx +50 -0
  168. package/.framework/src/components/ui/scroll-area.tsx +53 -0
  169. package/.framework/src/components/ui/select.tsx +195 -0
  170. package/.framework/src/components/ui/separator.tsx +26 -0
  171. package/.framework/src/components/ui/sheet.tsx +145 -0
  172. package/.framework/src/components/ui/sidebar.tsx +706 -0
  173. package/.framework/src/components/ui/skeleton.tsx +13 -0
  174. package/.framework/src/components/ui/slider.tsx +59 -0
  175. package/.framework/src/components/ui/sonner.tsx +47 -0
  176. package/.framework/src/components/ui/spinner.tsx +10 -0
  177. package/.framework/src/components/ui/switch.tsx +33 -0
  178. package/.framework/src/components/ui/table-primitives.tsx +141 -0
  179. package/.framework/src/components/ui/table.tsx +114 -0
  180. package/.framework/src/components/ui/tabs.tsx +90 -0
  181. package/.framework/src/components/ui/textarea.tsx +18 -0
  182. package/.framework/src/components/ui/toggle-group.tsx +89 -0
  183. package/.framework/src/components/ui/toggle.tsx +45 -0
  184. package/.framework/src/components/ui/tooltip.tsx +57 -0
  185. package/.framework/src/contexts/AppContext.tsx +133 -0
  186. package/.framework/src/contexts/AuthContext.tsx +371 -0
  187. package/.framework/src/hooks/use-mobile.ts +19 -0
  188. package/.framework/src/hooks/useApi.ts +526 -0
  189. package/.framework/src/hooks/useApps.ts +114 -0
  190. package/.framework/src/hooks/useEntityList.ts +190 -0
  191. package/.framework/src/hooks/useEntityRecord.ts +308 -0
  192. package/.framework/src/hooks/useForm.ts +307 -0
  193. package/.framework/src/hooks/useListSchema.ts +264 -0
  194. package/.framework/src/hooks/useSchemaRecord.ts +223 -0
  195. package/.framework/src/index.css +128 -0
  196. package/.framework/src/lib/api.ts +156 -0
  197. package/.framework/src/lib/supabase.ts +94 -0
  198. package/.framework/src/lib/utils.ts +317 -0
  199. package/.framework/src/main.tsx +27 -0
  200. package/.framework/src/pages/DashboardPage.tsx +181 -0
  201. package/.framework/src/pages/NotFoundPage.tsx +39 -0
  202. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +161 -0
  203. package/.framework/src/pages/admin/AIAgentsPage.tsx +318 -0
  204. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +199 -0
  205. package/.framework/src/pages/admin/APIKeysPage.tsx +303 -0
  206. package/.framework/src/pages/admin/AlertsConfigPage.tsx +523 -0
  207. package/.framework/src/pages/admin/AppDetailPage.tsx +493 -0
  208. package/.framework/src/pages/admin/AppsPage.tsx +355 -0
  209. package/.framework/src/pages/admin/DesignedPage.tsx +491 -0
  210. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +534 -0
  211. package/.framework/src/pages/admin/EmbeddingsPage.tsx +424 -0
  212. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +176 -0
  213. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +109 -0
  214. package/.framework/src/pages/admin/IntegratedDashboard.tsx +402 -0
  215. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +187 -0
  216. package/.framework/src/pages/admin/IntegrationsPage.tsx +301 -0
  217. package/.framework/src/pages/admin/LogsPage.tsx +283 -0
  218. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +85 -0
  219. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +470 -0
  220. package/.framework/src/pages/admin/PipelineDetailPage.tsx +183 -0
  221. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +279 -0
  222. package/.framework/src/pages/admin/PipelinesPage.tsx +390 -0
  223. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +299 -0
  224. package/.framework/src/pages/admin/PromptConfigsPage.tsx +292 -0
  225. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +434 -0
  226. package/.framework/src/pages/admin/RoleDetailPage.tsx +273 -0
  227. package/.framework/src/pages/admin/RolesPage.tsx +292 -0
  228. package/.framework/src/pages/admin/SelectTestPage.tsx +61 -0
  229. package/.framework/src/pages/admin/ShadcnTestPage.tsx +588 -0
  230. package/.framework/src/pages/admin/SimpleDashboard.tsx +387 -0
  231. package/.framework/src/pages/admin/TestRunDetailPage.tsx +172 -0
  232. package/.framework/src/pages/admin/TestingDashboard.tsx +257 -0
  233. package/.framework/src/pages/admin/TimerDetailPage.tsx +151 -0
  234. package/.framework/src/pages/admin/TimersPage.tsx +376 -0
  235. package/.framework/src/pages/admin/TriggerDetailPage.tsx +149 -0
  236. package/.framework/src/pages/admin/TriggersPage.tsx +381 -0
  237. package/.framework/src/pages/admin/TypeDetailPage.tsx +694 -0
  238. package/.framework/src/pages/admin/TypesPage.tsx +295 -0
  239. package/.framework/src/pages/auth/LoginPage.tsx +188 -0
  240. package/.framework/src/pages/auth/RegisterPage.tsx +163 -0
  241. package/.framework/src/pages/spine-framework/APIPage.tsx +17 -0
  242. package/.framework/src/pages/spine-framework/CLIPage.tsx +25 -0
  243. package/.framework/src/types/auth.ts +125 -0
  244. package/.framework/src/types/types.ts +407 -0
  245. package/STRUCTURE.md +150 -0
  246. package/config/components.json +25 -0
  247. package/config/deno.lock +108 -0
  248. package/config/package-lock.json +17183 -0
  249. package/config/postcss.config.cjs +10 -0
  250. package/config/tailwind.config.cjs +78 -0
  251. package/config/tsconfig.build.json +32 -0
  252. package/config/tsconfig.cli.json +18 -0
  253. package/config/tsconfig.json +41 -0
  254. package/config/tsconfig.node.json +17 -0
  255. package/config/tsconfig.node.tsbuildinfo +1 -0
  256. package/config/tsconfig.tsbuildinfo +1 -0
  257. package/config/typedoc.json +16 -0
  258. package/config/vite.config.d.ts +2 -0
  259. package/config/vite.config.ts +72 -0
  260. package/dist/cli/commands/agents.d.ts +39 -0
  261. package/dist/cli/commands/agents.d.ts.map +1 -0
  262. package/dist/cli/commands/auth.d.ts +36 -0
  263. package/dist/cli/commands/auth.d.ts.map +1 -0
  264. package/dist/cli/commands/create-app.d.ts +23 -0
  265. package/dist/cli/commands/create-app.d.ts.map +1 -0
  266. package/dist/cli/commands/dev.d.ts +39 -0
  267. package/dist/cli/commands/dev.d.ts.map +1 -0
  268. package/dist/cli/commands/doctor.d.ts +42 -0
  269. package/dist/cli/commands/doctor.d.ts.map +1 -0
  270. package/dist/cli/commands/generate.d.ts +36 -0
  271. package/dist/cli/commands/generate.d.ts.map +1 -0
  272. package/dist/cli/commands/init.d.ts +30 -0
  273. package/dist/cli/commands/init.d.ts.map +1 -0
  274. package/dist/cli/commands/install-app.d.ts +30 -0
  275. package/dist/cli/commands/install-app.d.ts.map +1 -0
  276. package/dist/cli/commands/items.d.ts +45 -0
  277. package/dist/cli/commands/items.d.ts.map +1 -0
  278. package/dist/cli/commands/migrations.d.ts +41 -0
  279. package/dist/cli/commands/migrations.d.ts.map +1 -0
  280. package/dist/cli/commands/pipelines.d.ts +40 -0
  281. package/dist/cli/commands/pipelines.d.ts.map +1 -0
  282. package/dist/cli/commands/status.d.ts +23 -0
  283. package/dist/cli/commands/status.d.ts.map +1 -0
  284. package/dist/cli/commands/system.d.ts +29 -0
  285. package/dist/cli/commands/system.d.ts.map +1 -0
  286. package/dist/cli/commands/test.d.ts +46 -0
  287. package/dist/cli/commands/test.d.ts.map +1 -0
  288. package/dist/cli/commands/uninstall-app.d.ts +23 -0
  289. package/dist/cli/commands/uninstall-app.d.ts.map +1 -0
  290. package/dist/cli/context.d.ts +88 -0
  291. package/dist/cli/context.d.ts.map +1 -0
  292. package/dist/cli/env-loader.d.ts +14 -0
  293. package/dist/cli/env-loader.d.ts.map +1 -0
  294. package/dist/cli/index.d.ts +41 -0
  295. package/dist/cli/index.d.ts.map +1 -0
  296. package/dist/functions/_shared/agent-runner.d.ts +156 -0
  297. package/dist/functions/_shared/agent-runner.d.ts.map +1 -0
  298. package/dist/functions/_shared/app-manifest.d.ts +68 -0
  299. package/dist/functions/_shared/app-manifest.d.ts.map +1 -0
  300. package/dist/functions/_shared/audit.d.ts +91 -0
  301. package/dist/functions/_shared/audit.d.ts.map +1 -0
  302. package/dist/functions/_shared/db.d.ts +125 -0
  303. package/dist/functions/_shared/db.d.ts.map +1 -0
  304. package/dist/functions/_shared/index.d.ts +298 -0
  305. package/dist/functions/_shared/index.d.ts.map +1 -0
  306. package/dist/functions/_shared/middleware.d.ts +315 -0
  307. package/dist/functions/_shared/middleware.d.ts.map +1 -0
  308. package/dist/functions/_shared/permissions.d.ts +626 -0
  309. package/dist/functions/_shared/permissions.d.ts.map +1 -0
  310. package/dist/functions/_shared/pipeline-runner.d.ts +124 -0
  311. package/dist/functions/_shared/pipeline-runner.d.ts.map +1 -0
  312. package/dist/functions/_shared/principal.d.ts +284 -0
  313. package/dist/functions/_shared/principal.d.ts.map +1 -0
  314. package/dist/functions/_shared/schema-utils.d.ts +181 -0
  315. package/dist/functions/_shared/schema-utils.d.ts.map +1 -0
  316. package/dist/functions/_shared/testing.d.ts +172 -0
  317. package/dist/functions/_shared/testing.d.ts.map +1 -0
  318. package/dist/functions/_shared/trigger-engine.d.ts +140 -0
  319. package/dist/functions/_shared/trigger-engine.d.ts.map +1 -0
  320. package/dist/functions/_shared/webhook-registration.d.ts +81 -0
  321. package/dist/functions/_shared/webhook-registration.d.ts.map +1 -0
  322. package/dist/functions/_shared/webhook-registry.d.ts +57 -0
  323. package/dist/functions/_shared/webhook-registry.d.ts.map +1 -0
  324. package/dist/functions/account-nodes.d.ts +48 -0
  325. package/dist/functions/account-nodes.d.ts.map +1 -0
  326. package/dist/functions/admin-data.d.ts +178 -0
  327. package/dist/functions/admin-data.d.ts.map +1 -0
  328. package/dist/functions/ai-agents.d.ts +125 -0
  329. package/dist/functions/ai-agents.d.ts.map +1 -0
  330. package/dist/functions/api-keys.d.ts +140 -0
  331. package/dist/functions/api-keys.d.ts.map +1 -0
  332. package/dist/functions/apps.d.ts +163 -0
  333. package/dist/functions/apps.d.ts.map +1 -0
  334. package/dist/functions/auth.d.ts +74 -0
  335. package/dist/functions/auth.d.ts.map +1 -0
  336. package/dist/functions/debug-auth.d.ts +33 -0
  337. package/dist/functions/debug-auth.d.ts.map +1 -0
  338. package/dist/functions/embeddings.d.ts +205 -0
  339. package/dist/functions/embeddings.d.ts.map +1 -0
  340. package/dist/functions/integration-routes.d.ts +45 -0
  341. package/dist/functions/integration-routes.d.ts.map +1 -0
  342. package/dist/functions/integrations.d.ts +124 -0
  343. package/dist/functions/integrations.d.ts.map +1 -0
  344. package/dist/functions/item-progress.d.ts +41 -0
  345. package/dist/functions/item-progress.d.ts.map +1 -0
  346. package/dist/functions/logs.d.ts +162 -0
  347. package/dist/functions/logs.d.ts.map +1 -0
  348. package/dist/functions/observability.d.ts +123 -0
  349. package/dist/functions/observability.d.ts.map +1 -0
  350. package/dist/functions/pipeline-executions.d.ts +190 -0
  351. package/dist/functions/pipeline-executions.d.ts.map +1 -0
  352. package/dist/functions/pipelines.d.ts +171 -0
  353. package/dist/functions/pipelines.d.ts.map +1 -0
  354. package/dist/functions/prompt-configs.d.ts +125 -0
  355. package/dist/functions/prompt-configs.d.ts.map +1 -0
  356. package/dist/functions/roles.d.ts +118 -0
  357. package/dist/functions/roles.d.ts.map +1 -0
  358. package/dist/functions/system-cron.d.ts +65 -0
  359. package/dist/functions/system-cron.d.ts.map +1 -0
  360. package/dist/functions/system.d.ts +29 -0
  361. package/dist/functions/system.d.ts.map +1 -0
  362. package/dist/functions/tests.d.ts +28 -0
  363. package/dist/functions/tests.d.ts.map +1 -0
  364. package/dist/functions/timers.d.ts +139 -0
  365. package/dist/functions/timers.d.ts.map +1 -0
  366. package/dist/functions/triggers.d.ts +203 -0
  367. package/dist/functions/triggers.d.ts.map +1 -0
  368. package/dist/functions/types.d.ts +151 -0
  369. package/dist/functions/types.d.ts.map +1 -0
  370. package/dist/src/types/types.d.ts +364 -0
  371. package/dist/src/types/types.d.ts.map +1 -0
  372. package/package.json +192 -0
  373. package/scripts/app-install-cli.ts +286 -0
  374. package/scripts/assemble-frontend.sh +79 -0
  375. package/scripts/assemble-functions.sh +62 -0
  376. package/scripts/assemble.sh +35 -0
  377. package/scripts/boundary-check.sh +106 -0
  378. package/scripts/build-manifest.sh +80 -0
  379. package/scripts/check-core-integrity.sh +82 -0
  380. package/scripts/ingest-chunks.cjs +202 -0
  381. package/scripts/kb-chunk-parser.cjs +312 -0
  382. package/scripts/kb-chunk-parser.ts +330 -0
  383. package/scripts/load-test-app-install.ts +484 -0
  384. package/scripts/netlify-dev-wrapper.sh +22 -0
  385. package/scripts/verify-integrity.sh +69 -0
@@ -0,0 +1,332 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * @module cli/commands/generate
4
+ * @audience installer
5
+ * @layer cli
6
+ * @stability stable
7
+ *
8
+ * `spine generate` command — code scaffolding for extending Spine safely.
9
+ * Generates type definitions, handlers, and UI pages in v2-custom/ only.
10
+ *
11
+ * **Commands:**
12
+ * | Subcommand | Description |
13
+ * |-------------------------|-------------------------------------------------------|
14
+ * | `generate type <slug>` | Create new type with handler and UI stubs |
15
+ * | `generate function <name>` | Create new Netlify function stub |
16
+ *
17
+ * **What gets generated for `type`:**
18
+ * 1. Type record in database (item type by default)
19
+ * 2. Handler stub: `v2-custom/functions/{slug}.ts`
20
+ * 3. UI page stub: `v2-custom/src/pages/{slug}/index.tsx`
21
+ *
22
+ * **What gets generated for `function`:**
23
+ * 1. Netlify function stub: `v2-custom/functions/{name}.ts`
24
+ * 2. Basic handler structure with middleware imports
25
+ *
26
+ * **Usage:**
27
+ * ```bash
28
+ * spine generate type ticket-v2
29
+ * spine generate function webhook-handler
30
+ * ```
31
+ *
32
+ * @seeAlso functions/types.ts (type CRUD API)
33
+ * @seeAlso functions/_shared/middleware.ts (handler structure)
34
+ */
35
+
36
+ import type { Command } from 'commander'
37
+ import { buildCliContext, handleError } from '../context.ts'
38
+ import { adminDb } from '../../functions/_shared/index.ts'
39
+ import { existsSync, mkdirSync, writeFileSync } from 'fs'
40
+ import { resolve, dirname } from 'path'
41
+ import { fileURLToPath } from 'url'
42
+
43
+ const __filename = fileURLToPath(import.meta.url)
44
+ const __dirname = dirname(__filename)
45
+ const PROJECT_ROOT = resolve(__dirname, '../../../')
46
+
47
+ // ─── TYPE GENERATION ─────────────────────────────────────────────────────────
48
+
49
+ async function generateType(ctx: any, slug: string, options: any): Promise<void> {
50
+ const name = options.name || slug.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ')
51
+ const kind = options.kind || 'item'
52
+ const description = options.description || `${name} type generated by spine CLI`
53
+
54
+ console.log(`\nšŸ”§ Generating type '${slug}'...`)
55
+
56
+ // Step 1: Create type record in database
57
+ console.log(' Step 1: Creating type record in database...')
58
+
59
+ const { data: existing, error: checkErr } = await adminDb
60
+ .from('types')
61
+ .select('id')
62
+ .eq('slug', slug)
63
+ .eq('kind', kind)
64
+ .single()
65
+
66
+ if (checkErr && checkErr.code !== 'PGRST116') { // PGRST116 = not found
67
+ throw new Error(`Failed to check existing type: ${checkErr.message}`)
68
+ }
69
+
70
+ if (existing) {
71
+ console.log(` āš ļø Type '${slug}' already exists (skipping DB creation)`)
72
+ } else {
73
+ const designSchema = {
74
+ fields: {
75
+ title: {
76
+ type: 'string',
77
+ required: true,
78
+ label: 'Title',
79
+ description: `Title for this ${name}`
80
+ },
81
+ status: {
82
+ type: 'select',
83
+ options: ['open', 'in_progress', 'closed'],
84
+ default: 'open',
85
+ label: 'Status'
86
+ }
87
+ },
88
+ layout: {
89
+ detail: ['title', 'status'],
90
+ list: ['title', 'status']
91
+ }
92
+ }
93
+
94
+ const { error: insertErr } = await adminDb
95
+ .from('types')
96
+ .insert({
97
+ kind,
98
+ slug,
99
+ name,
100
+ description,
101
+ design_schema: designSchema,
102
+ validation_schema: {},
103
+ ownership: 'system',
104
+ is_active: true
105
+ })
106
+
107
+ if (insertErr) {
108
+ throw new Error(`Failed to create type: ${insertErr.message}`)
109
+ }
110
+
111
+ console.log(' āœ“ Type record created')
112
+ }
113
+
114
+ // Step 2: Generate handler stub
115
+ console.log(' Step 2: Generating handler stub...')
116
+ const handlerPath = resolve(PROJECT_ROOT, `v2-custom/functions/${slug}.ts`)
117
+
118
+ if (existsSync(handlerPath) && !options.force) {
119
+ console.log(` āš ļø Handler stub already exists: ${handlerPath}`)
120
+ } else {
121
+ const handlerCode = generateHandlerStub(slug, kind, name)
122
+ writeFileSync(handlerPath, handlerCode)
123
+ console.log(` āœ“ Handler stub created: v2-custom/functions/${slug}.ts`)
124
+ }
125
+
126
+ // Step 3: Generate UI page stub
127
+ console.log(' Step 3: Generating UI page stub...')
128
+ const pageDir = resolve(PROJECT_ROOT, `v2-custom/src/pages/${slug}`)
129
+ const pagePath = resolve(pageDir, 'index.tsx')
130
+
131
+ if (existsSync(pagePath) && !options.force) {
132
+ console.log(` āš ļø UI page stub already exists: ${pagePath}`)
133
+ } else {
134
+ mkdirSync(pageDir, { recursive: true })
135
+ const pageCode = generatePageStub(slug, name, kind)
136
+ writeFileSync(pagePath, pageCode)
137
+ console.log(` āœ“ UI page stub created: v2-custom/src/pages/${slug}/index.tsx`)
138
+ }
139
+
140
+ console.log(`\nāœ… Type '${slug}' generation complete!`)
141
+ console.log(` Next steps:`)
142
+ console.log(` 1. Edit v2-custom/functions/${slug}.ts to implement custom logic`)
143
+ console.log(` 2. Edit v2-custom/src/pages/${slug}/index.tsx to customize the UI`)
144
+ console.log(` 3. Run 'spine dev' to see your changes`)
145
+ }
146
+
147
+ function generateHandlerStub(slug: string, kind: string, name: string): string {
148
+ return `/**
149
+ * @module ${slug}
150
+ * @audience custom
151
+ * @layer api-handler
152
+ * @stability experimental
153
+ *
154
+ * Custom handler for ${name} (${kind} type).
155
+ * Generated by spine CLI on ${new Date().toISOString()}.
156
+ *
157
+ * Extend this handler to add custom logic for your type.
158
+ */
159
+
160
+ import { createHandler } from '../v2-core/functions/_shared/middleware'
161
+
162
+ export const handler = createHandler(async (ctx) => {
163
+ const method = ctx.query?.method || 'GET'
164
+
165
+ switch (method) {
166
+ case 'GET':
167
+ // TODO: Implement GET logic
168
+ return { message: '${name} handler - GET not implemented' }
169
+
170
+ case 'POST':
171
+ // TODO: Implement POST logic
172
+ return { message: '${name} handler - POST not implemented' }
173
+
174
+ case 'PATCH':
175
+ // TODO: Implement PATCH logic
176
+ return { message: '${name} handler - PATCH not implemented' }
177
+
178
+ case 'DELETE':
179
+ // TODO: Implement DELETE logic
180
+ return { message: '${name} handler - DELETE not implemented' }
181
+
182
+ default:
183
+ throw new Error('Unsupported method: ' + method)
184
+ }
185
+ })
186
+ `
187
+ }
188
+
189
+ function generatePageStub(slug: string, name: string, kind: string): string {
190
+ return `/**
191
+ * @page ${slug}/index
192
+ * @audience custom
193
+ * @layer page
194
+ * @stability experimental
195
+ *
196
+ * UI page for ${name} (${kind} type).
197
+ * Generated by spine CLI on ${new Date().toISOString()}.
198
+ */
199
+
200
+ import React from 'react'
201
+ import { useParams } from 'react-router-dom'
202
+ import { useApi } from '../../v2-core/src/hooks/useApi'
203
+ import { apiFetch } from '../../v2-core/src/lib/api'
204
+
205
+ export default function ${name.replace(/\s+/g, '')}Page() {
206
+ const { id } = useParams()
207
+
208
+ const { data, loading, error } = useApi(
209
+ () => apiFetch('/.netlify/functions/${slug}' + (id ? '?id=' + id : '')),
210
+ { immediate: true }
211
+ )
212
+
213
+ if (loading) return <div>Loading...</div>
214
+ if (error) return <div>Error: {error.message}</div>
215
+
216
+ return (
217
+ <div className="p-6">
218
+ <h1 className="text-2xl font-bold mb-4">${name}</h1>
219
+ <pre className="bg-gray-100 p-4 rounded">
220
+ {JSON.stringify(data, null, 2)}
221
+ </pre>
222
+ <p className="mt-4 text-gray-600">
223
+ Edit v2-custom/src/pages/${slug}/index.tsx to customize this page.
224
+ </p>
225
+ </div>
226
+ )
227
+ }
228
+ `
229
+ }
230
+
231
+ // ─── FUNCTION GENERATION ─────────────────────────────────────────────────────
232
+
233
+ async function generateFunction(name: string, options: any): Promise<void> {
234
+ console.log(`\nšŸ”§ Generating function '${name}'...`)
235
+
236
+ const handlerPath = resolve(PROJECT_ROOT, `v2-custom/functions/${name}.ts`)
237
+
238
+ if (existsSync(handlerPath) && !options.force) {
239
+ console.log(` āš ļø Function already exists: ${handlerPath}`)
240
+ console.log(` Use --force to overwrite`)
241
+ return
242
+ }
243
+
244
+ const handlerCode = generateFunctionStub(name, options.description)
245
+ writeFileSync(handlerPath, handlerCode)
246
+
247
+ console.log(`āœ… Function '${name}' created!`)
248
+ console.log(` Location: v2-custom/functions/${name}.ts`)
249
+ console.log(` Next steps:`)
250
+ console.log(` 1. Edit the handler to implement your logic`)
251
+ console.log(` 2. Run 'spine dev' to see your changes`)
252
+ }
253
+
254
+ function generateFunctionStub(name: string, description?: string): string {
255
+ return `/**
256
+ * @module ${name}
257
+ * @audience custom
258
+ * @layer api-handler
259
+ * @stability experimental
260
+ *
261
+ * ${description || `Custom Netlify function: ${name}`}
262
+ * Generated by spine CLI on ${new Date().toISOString()}.
263
+ */
264
+
265
+ import { createHandler } from '../v2-core/functions/_shared/middleware'
266
+
267
+ export const handler = createHandler(async (ctx) => {
268
+ // Access principal: ctx.principal (human, machine, or system)
269
+ // Access database: ctx.db (RLS-scoped) or import { adminDb } for admin access
270
+ // Access query params: ctx.query
271
+
272
+ const q = ctx.query || {}
273
+ const action = q.action || 'default'
274
+
275
+ switch (action) {
276
+ case 'default':
277
+ return {
278
+ message: 'Hello from ${name}',
279
+ principal: ctx.principal?.id,
280
+ timestamp: new Date().toISOString()
281
+ }
282
+
283
+ // TODO: Add more actions here
284
+ // case 'custom':
285
+ // return { data: await yourCustomLogic(ctx) }
286
+
287
+ default:
288
+ return {
289
+ error: 'Unknown action: ' + action,
290
+ available_actions: ['default']
291
+ }
292
+ }
293
+ })
294
+ `
295
+ }
296
+
297
+ // ─── COMMAND REGISTRATION ────────────────────────────────────────────────────
298
+
299
+ export function registerGenerateCommands(program: Command) {
300
+ const generate = program
301
+ .command('generate')
302
+ .description('Generate code stubs for extending Spine')
303
+
304
+ generate
305
+ .command('type <slug>')
306
+ .description('Generate a new type with handler and UI stubs')
307
+ .option('--name <name>', 'Display name for the type')
308
+ .option('--kind <kind>', 'Type kind (item, account, person)', 'item')
309
+ .option('--description <desc>', 'Type description')
310
+ .option('--force', 'Overwrite existing files', false)
311
+ .action(async (slug, opts) => {
312
+ try {
313
+ const ctx = await buildCliContext()
314
+ await generateType(ctx, slug, opts)
315
+ } catch (err: any) {
316
+ handleError(err)
317
+ }
318
+ })
319
+
320
+ generate
321
+ .command('function <name>')
322
+ .description('Generate a new Netlify function stub')
323
+ .option('--description <desc>', 'Function description')
324
+ .option('--force', 'Overwrite existing file', false)
325
+ .action(async (name, opts) => {
326
+ try {
327
+ await generateFunction(name, opts)
328
+ } catch (err: any) {
329
+ handleError(err)
330
+ }
331
+ })
332
+ }
@@ -0,0 +1,272 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * @module cli/commands/init
4
+ * @audience installer
5
+ * @layer cli
6
+ * @stability stable
7
+ *
8
+ * `spine-framework init` — Bootstrap a fresh Spine installation.
9
+ *
10
+ * Runs the foundation schema (000_foundation.sql) and seed data (001_seed.sql)
11
+ * against the configured Supabase project, then scaffolds the custom/ workspace
12
+ * if it doesn't already exist.
13
+ *
14
+ * **Usage:**
15
+ * ```bash
16
+ * # Fresh install (agent provides credentials from Supabase dashboard)
17
+ * spine-framework init --url https://xyz.supabase.co --anon-key eyJ... --service-role-key eyJ...
18
+ *
19
+ * # Already have .env configured
20
+ * spine-framework init
21
+ *
22
+ * # DB only, no filesystem changes
23
+ * spine-framework init --skip-scaffold
24
+ * ```
25
+ *
26
+ * When --url/--anon-key/--service-role-key are provided, init writes .env before
27
+ * running migrations — so it works on a completely fresh checkout with no prior config.
28
+ */
29
+
30
+ import type { Command } from 'commander'
31
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'
32
+ import { resolve, dirname } from 'path'
33
+ import { fileURLToPath } from 'url'
34
+ import { adminDb } from '../../functions/_shared/index.ts'
35
+
36
+ const __filename = fileURLToPath(import.meta.url)
37
+ const __dirname = dirname(__filename)
38
+ const PROJECT_ROOT = resolve(__dirname, '../../../')
39
+ const MIGRATIONS_DIR = resolve(__dirname, '../../migrations')
40
+
41
+ interface InitOptions {
42
+ skipScaffold: boolean
43
+ dryRun: boolean
44
+ url?: string
45
+ anonKey?: string
46
+ serviceRoleKey?: string
47
+ }
48
+
49
+ async function runMigration(filename: string, dryRun: boolean): Promise<boolean> {
50
+ const filePath = resolve(MIGRATIONS_DIR, filename)
51
+ if (!existsSync(filePath)) {
52
+ console.error(` āŒ Migration file not found: ${filename}`)
53
+ return false
54
+ }
55
+
56
+ const sql = readFileSync(filePath, 'utf8')
57
+
58
+ if (dryRun) {
59
+ console.log(` [dry-run] Would execute: ${filename} (${sql.length} chars)`)
60
+ return true
61
+ }
62
+
63
+ // Use the Supabase SQL endpoint to execute raw DDL.
64
+ // This works on blank projects (no exec_sql RPC needed).
65
+ const supabaseUrl = process.env.SUPABASE_URL
66
+ const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY
67
+
68
+ if (!supabaseUrl || !serviceKey) {
69
+ console.error(` āŒ Missing SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY`)
70
+ return false
71
+ }
72
+
73
+ // Try exec_sql RPC first (works if schema already has it)
74
+ const { error } = await adminDb.rpc('exec_sql', { query: sql }).single()
75
+ if (!error) return true
76
+
77
+ // Fallback: use the Supabase /pg/query endpoint for raw SQL execution
78
+ console.log(` āš ļø exec_sql not available, using direct SQL endpoint...`)
79
+
80
+ const pgResponse = await fetch(`${supabaseUrl}/pg/query`, {
81
+ method: 'POST',
82
+ headers: {
83
+ 'Content-Type': 'application/json',
84
+ 'apikey': serviceKey,
85
+ 'Authorization': `Bearer ${serviceKey}`,
86
+ },
87
+ body: JSON.stringify({ query: sql })
88
+ })
89
+
90
+ if (pgResponse.ok) return true
91
+
92
+ // Second fallback: use the Supabase Management API SQL endpoint
93
+ // Extract project ref from URL (e.g. https://abcdef.supabase.co → abcdef)
94
+ const projectRef = supabaseUrl.replace('https://', '').split('.')[0]
95
+
96
+ const mgmtResponse = await fetch(
97
+ `https://api.supabase.com/v1/projects/${projectRef}/database/query`,
98
+ {
99
+ method: 'POST',
100
+ headers: {
101
+ 'Content-Type': 'application/json',
102
+ 'Authorization': `Bearer ${serviceKey}`,
103
+ },
104
+ body: JSON.stringify({ query: sql })
105
+ }
106
+ )
107
+
108
+ if (mgmtResponse.ok) return true
109
+
110
+ const text = await mgmtResponse.text()
111
+ console.error(` āŒ Migration ${filename} failed: ${text}`)
112
+ return false
113
+ }
114
+
115
+ function scaffoldCustomWorkspace(dryRun: boolean): void {
116
+ const dirs = [
117
+ 'custom/apps',
118
+ 'custom/functions',
119
+ 'custom/components',
120
+ 'custom/migrations',
121
+ 'custom/tests',
122
+ ]
123
+
124
+ for (const dir of dirs) {
125
+ const fullPath = resolve(PROJECT_ROOT, dir)
126
+ if (existsSync(fullPath)) {
127
+ console.log(` ā­ļø ${dir}/ already exists`)
128
+ } else if (dryRun) {
129
+ console.log(` [dry-run] Would create: ${dir}/`)
130
+ } else {
131
+ mkdirSync(fullPath, { recursive: true })
132
+ writeFileSync(resolve(fullPath, '.gitkeep'), '')
133
+ console.log(` āœ“ Created ${dir}/`)
134
+ }
135
+ }
136
+ }
137
+
138
+ async function checkAlreadyInitialized(): Promise<boolean> {
139
+ try {
140
+ const { data, error } = await adminDb
141
+ .from('apps')
142
+ .select('slug')
143
+ .eq('slug', 'spine-core')
144
+ .single()
145
+
146
+ return !error && !!data
147
+ } catch {
148
+ return false
149
+ }
150
+ }
151
+
152
+ function writeEnvFile(url: string, anonKey: string, serviceRoleKey: string, dryRun: boolean): void {
153
+ const envPath = resolve(PROJECT_ROOT, '.env')
154
+ const envContent = [
155
+ `VITE_SUPABASE_URL=${url}`,
156
+ `VITE_SUPABASE_ANON_KEY=${anonKey}`,
157
+ `SUPABASE_URL=${url}`,
158
+ `SUPABASE_ANON_KEY=${anonKey}`,
159
+ `SUPABASE_SERVICE_ROLE_KEY=${serviceRoleKey}`,
160
+ `VITE_APP_NAME=Spine`,
161
+ `DB_SCHEMA=public`,
162
+ ].join('\n') + '\n'
163
+
164
+ if (dryRun) {
165
+ console.log(` [dry-run] Would write .env with SUPABASE_URL=${url}`)
166
+ return
167
+ }
168
+
169
+ const existed = existsSync(envPath)
170
+ writeFileSync(envPath, envContent, 'utf8')
171
+ console.log(` āœ“ ${existed ? 'Updated' : 'Created'} .env`)
172
+
173
+ // Also inject into process.env for the rest of this run
174
+ process.env.SUPABASE_URL = url
175
+ process.env.SUPABASE_ANON_KEY = anonKey
176
+ process.env.SUPABASE_SERVICE_ROLE_KEY = serviceRoleKey
177
+ process.env.VITE_SUPABASE_URL = url
178
+ process.env.VITE_SUPABASE_ANON_KEY = anonKey
179
+ }
180
+
181
+ async function initCommand(options: InitOptions): Promise<void> {
182
+ console.log('\nšŸš€ Spine Framework — Init\n')
183
+
184
+ // Step 0: Write .env if credentials were provided via flags
185
+ if (options.url && options.anonKey && options.serviceRoleKey) {
186
+ console.log('šŸ”‘ Step 0: Writing environment configuration...')
187
+ writeEnvFile(options.url, options.anonKey, options.serviceRoleKey, options.dryRun)
188
+ } else if (!process.env.SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE_KEY) {
189
+ console.error('āŒ No Supabase credentials found.')
190
+ console.error(' Provide them via flags:')
191
+ console.error(' spine-framework init --url <url> --anon-key <key> --service-role-key <key>')
192
+ console.error(' Or set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY in .env')
193
+ process.exit(1)
194
+ }
195
+
196
+ // Check if already initialized
197
+ const alreadyInit = await checkAlreadyInitialized()
198
+ if (alreadyInit) {
199
+ console.log(' āš ļø Database already initialized (spine-core app exists)')
200
+ console.log(' Skipping schema migration. Use "spine-framework migrations" to manage updates.\n')
201
+
202
+ if (!options.skipScaffold) {
203
+ console.log('šŸ“ Checking workspace scaffold...')
204
+ scaffoldCustomWorkspace(options.dryRun)
205
+ }
206
+
207
+ console.log('\nāœ… Init complete (already initialized)')
208
+ return
209
+ }
210
+
211
+ // Step 1: Foundation schema
212
+ console.log('šŸ“¦ Step 1: Applying foundation schema (000_foundation.sql)...')
213
+ const foundationOk = await runMigration('000_foundation.sql', options.dryRun)
214
+ if (!foundationOk && !options.dryRun) {
215
+ console.error('\nāŒ Init failed at foundation schema. Check your Supabase connection.')
216
+ process.exit(1)
217
+ }
218
+ console.log(' āœ“ Foundation schema applied')
219
+
220
+ // Step 2: Seed data
221
+ console.log('\n🌱 Step 2: Applying seed data (001_seed.sql)...')
222
+ const seedOk = await runMigration('001_seed.sql', options.dryRun)
223
+ if (!seedOk && !options.dryRun) {
224
+ console.error('\nāŒ Init failed at seed data.')
225
+ process.exit(1)
226
+ }
227
+ console.log(' āœ“ Seed data applied')
228
+
229
+ // Step 3: Record migration versions
230
+ if (!options.dryRun) {
231
+ console.log('\nšŸ“ Step 3: Recording migration versions...')
232
+ await adminDb
233
+ .from('schema_migrations')
234
+ .upsert([
235
+ { version: '000_foundation', applied_at: new Date().toISOString() },
236
+ { version: '001_seed', applied_at: new Date().toISOString() },
237
+ ], { onConflict: 'version' })
238
+ console.log(' āœ“ Migration versions recorded')
239
+ }
240
+
241
+ // Step 4: Scaffold custom workspace
242
+ if (!options.skipScaffold) {
243
+ console.log('\nšŸ“ Step 4: Scaffolding custom workspace...')
244
+ scaffoldCustomWorkspace(options.dryRun)
245
+ }
246
+
247
+ console.log('\nāœ… Spine initialized successfully!')
248
+ console.log('\n Next steps:')
249
+ console.log(' 1. spine-framework install-app <app-slug> # Install an app')
250
+ console.log(' 2. spine-framework create-app my-app # Or scaffold a new one')
251
+ console.log(' 3. npm run assemble && netlify dev # Start developing')
252
+ }
253
+
254
+ export function registerInitCommands(program: Command) {
255
+ program
256
+ .command('init')
257
+ .description('Initialize a fresh Spine installation (schema + seed + scaffold)')
258
+ .option('--url <url>', 'Supabase project URL (writes .env if provided)')
259
+ .option('--anon-key <key>', 'Supabase anon key')
260
+ .option('--service-role-key <key>', 'Supabase service role key')
261
+ .option('--skip-scaffold', 'Skip creating custom/ workspace directories', false)
262
+ .option('--dry-run', 'Show what would happen without making changes', false)
263
+ .action(async (opts) => {
264
+ try {
265
+ await initCommand(opts)
266
+ } catch (err: any) {
267
+ console.error('Error:', err.message)
268
+ if (process.env.SPINE_CLI_DEBUG) console.error(err.stack)
269
+ process.exit(1)
270
+ }
271
+ })
272
+ }