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,694 @@
1
+ /**
2
+ * @module src/pages/admin/TypeDetailPage
3
+ * @audience installer
4
+ * @layer frontend-page
5
+ * @stability stable
6
+ *
7
+ * Create / view / edit / delete page for a single type record.
8
+ */
9
+
10
+ import React, { useState, useEffect } from 'react'
11
+ import { useParams, useNavigate } from 'react-router-dom'
12
+ import { useApi } from '../../hooks/useApi'
13
+ import { useMutation } from '../../hooks/useApi'
14
+ import { apiFetch } from '../../lib/api'
15
+ import { Button } from '../../components/ui/button'
16
+ import { Modal } from '../../components/ui/Modal'
17
+ import { Badge } from '../../components/ui/badge'
18
+ import { Input } from '../../components/ui/input'
19
+ import { Textarea } from '../../components/ui/textarea'
20
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../components/ui/select'
21
+ import { Checkbox } from '../../components/ui/checkbox'
22
+ import { Label } from '../../components/ui/label'
23
+ import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/card'
24
+ import { Skeleton } from '../../components/ui/skeleton'
25
+ import { Alert, AlertDescription, AlertTitle } from '../../components/ui/alert'
26
+ import { DataTable } from '../../components/ui/DataTable'
27
+ import { ArrowLeft, Pencil, Trash2, AlertCircle } from 'lucide-react'
28
+ import { formatDateTime } from '../../lib/utils'
29
+
30
+ interface Type {
31
+ id: string
32
+ name: string
33
+ slug: string
34
+ kind: string
35
+ description?: string
36
+ icon?: string
37
+ color?: string
38
+ design_schema?: {
39
+ fields: Record<string, any>
40
+ record_permissions?: Record<string, string[]>
41
+ }
42
+ ownership: string
43
+ is_active: boolean
44
+ app_id?: string
45
+ app?: any
46
+ created_at: string
47
+ updated_at: string
48
+ }
49
+
50
+ interface TypeItem {
51
+ id: string
52
+ item_type_id: string
53
+ data: Record<string, any>
54
+ metadata: Record<string, any>
55
+ created_at: string
56
+ updated_at: string
57
+ created_by: string
58
+ account_id: string
59
+ }
60
+
61
+ export function TypeDetailPage() {
62
+ const { id, kind } = useParams<{ id: string, kind: string }>()
63
+ const navigate = useNavigate()
64
+ const isCreateMode = !id || id === 'new'
65
+ const typeKind = kind || 'item'
66
+
67
+ const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false)
68
+ const [isEditing, setIsEditing] = useState(isCreateMode)
69
+ const [editData, setEditData] = useState<Record<string, any>>({
70
+ name: '',
71
+ slug: '',
72
+ description: '',
73
+ icon: '',
74
+ color: '',
75
+ kind: typeKind,
76
+ schema: { fields: {} },
77
+ ownership: 'app',
78
+ app_id: '',
79
+ is_active: true
80
+ })
81
+ const [schemaText, setSchemaText] = useState(JSON.stringify({ fields: {} }, null, 2))
82
+ const [availableApps, setAvailableApps] = useState<Array<{id: string, name: string}>>([])
83
+
84
+ React.useEffect(() => {
85
+ const fetchApps = async () => {
86
+ try {
87
+ const response = await apiFetch('/api/apps?action=list')
88
+ if (response.ok) {
89
+ const data = await response.json()
90
+ setAvailableApps(data.data || [])
91
+ }
92
+ } catch (error) {
93
+ console.error('Error fetching apps:', error)
94
+ }
95
+ }
96
+ fetchApps()
97
+ }, [])
98
+
99
+ const getKindDefaults = () => {
100
+ switch (typeKind) {
101
+ case 'account':
102
+ return { kind: 'account', ownership: 'app', icon: 'building-office', color: 'green' }
103
+ case 'person':
104
+ return { kind: 'person', ownership: 'app', icon: 'user', color: 'purple' }
105
+ default:
106
+ return { kind: 'item', ownership: 'app', icon: 'cube', color: 'blue' }
107
+ }
108
+ }
109
+
110
+ const { data: type, loading, error, refetch } = useApi<Type>(
111
+ async () => {
112
+ if (isCreateMode) {
113
+ const defaults = getKindDefaults()
114
+ return {
115
+ id: '',
116
+ name: '',
117
+ slug: '',
118
+ description: '',
119
+ icon: defaults.icon,
120
+ color: defaults.color,
121
+ kind: defaults.kind,
122
+ design_schema: { fields: {} },
123
+ ownership: defaults.ownership,
124
+ app_id: '',
125
+ is_active: true,
126
+ created_at: '',
127
+ updated_at: ''
128
+ }
129
+ } else {
130
+ if (!id) throw new Error('Type ID or slug is required')
131
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
132
+ const url = uuidRegex.test(id)
133
+ ? `/api/types?action=get&id=${id}`
134
+ : `/api/types?action=get&slug=${id}`
135
+ const response = await apiFetch(url)
136
+ if (!response.ok) {
137
+ throw new Error(response.status === 500 ? 'Type not found' : 'Failed to fetch type')
138
+ }
139
+ const json = await response.json()
140
+ return json.data as Type
141
+ }
142
+ },
143
+ { immediate: true }
144
+ )
145
+
146
+ React.useEffect(() => {
147
+ if (type) {
148
+ setEditData({
149
+ name: type.name,
150
+ slug: type.slug,
151
+ description: type.description || '',
152
+ icon: type.icon || '',
153
+ color: type.color || '',
154
+ kind: type.kind || 'item',
155
+ design_schema: type.design_schema || { fields: {} },
156
+ ownership: type.ownership || 'system',
157
+ app_id: type.app_id || '',
158
+ is_active: type.is_active ?? true
159
+ })
160
+ setSchemaText(JSON.stringify(type.design_schema || { fields: {} }, null, 2))
161
+ }
162
+ }, [type])
163
+
164
+ const handleSave = async () => {
165
+ try {
166
+ const { app_id } = editData
167
+ const ownership = (editData.ownership || '').toLowerCase()
168
+ if (ownership !== 'system' && !app_id) {
169
+ throw new Error('App selection is required when ownership is not "System"')
170
+ }
171
+ let parsedSchema = { fields: {} }
172
+ try {
173
+ parsedSchema = JSON.parse(schemaText)
174
+ } catch (error) {
175
+ console.warn('Invalid JSON in schema field, using default:', error)
176
+ }
177
+ const saveData = {
178
+ ...editData,
179
+ design_schema: parsedSchema,
180
+ app_id: editData.app_id || null
181
+ }
182
+ const url = isCreateMode
183
+ ? '/api/types?action=create'
184
+ : `/api/types?action=update&id=${id}`
185
+ const method = isCreateMode ? 'POST' : 'PATCH'
186
+ const response = await apiFetch(url, {
187
+ method,
188
+ headers: { 'Content-Type': 'application/json' },
189
+ body: JSON.stringify(saveData)
190
+ })
191
+ if (!response.ok) throw new Error(`Failed to ${isCreateMode ? 'create' : 'update'} type`)
192
+ if (isCreateMode) {
193
+ const result = await response.json()
194
+ const newId = result.data?.id || result.id
195
+ navigate(`/spine-framework/admin/configs/${kind || 'types'}/${newId}`)
196
+ } else {
197
+ await refetch()
198
+ setIsEditing(false)
199
+ }
200
+ } catch (error) {
201
+ console.error(`Error ${isCreateMode ? 'creating' : 'updating'} type:`, error)
202
+ alert(error instanceof Error ? error.message : 'Unknown error occurred')
203
+ }
204
+ }
205
+
206
+ const handleCancel = () => {
207
+ if (isCreateMode) {
208
+ navigate('/spine-framework/admin/configs/types')
209
+ return
210
+ }
211
+ if (type) {
212
+ setEditData({
213
+ name: type.name,
214
+ slug: type.slug,
215
+ description: type.description || '',
216
+ icon: type.icon || '',
217
+ color: type.color || '',
218
+ design_schema: type.design_schema || { fields: {} },
219
+ ownership: type.ownership || 'system',
220
+ app_id: type.app_id || '',
221
+ is_active: type.is_active ?? true
222
+ })
223
+ setSchemaText(JSON.stringify(type.design_schema || { fields: {} }, null, 2))
224
+ }
225
+ setIsEditing(false)
226
+ }
227
+
228
+ const handleEdit = () => {
229
+ setIsEditing(true)
230
+ }
231
+
232
+ const { data: items, loading: itemsLoading, execute: fetchItems } = useApi<TypeItem[]>(
233
+ async () => {
234
+ if (isCreateMode || !type?.id) {
235
+ return []
236
+ }
237
+ const response = await apiFetch(`/api/admin-data?entity=items&type_id=${type.id}`)
238
+ if (!response.ok) throw new Error('Failed to fetch items')
239
+ const result = await response.json()
240
+ return result.data || []
241
+ },
242
+ { immediate: !isCreateMode }
243
+ )
244
+
245
+ useEffect(() => {
246
+ if (!isCreateMode && type?.id) fetchItems()
247
+ }, [type?.id])
248
+
249
+ const deleteMutation = useMutation(
250
+ async () => {
251
+ const response = await apiFetch(`/api/types?action=delete&id=${id}`, {
252
+ method: 'DELETE'
253
+ })
254
+ if (!response.ok) throw new Error('Failed to delete type')
255
+ return response.json()
256
+ },
257
+ {
258
+ onSuccess: () => {
259
+ navigate(`/spine-framework/admin/configs/${kind || 'types'}`)
260
+ }
261
+ }
262
+ )
263
+
264
+ if (loading) {
265
+ return (
266
+ <div className="space-y-6">
267
+ <Skeleton className="h-8 w-48" />
268
+ <Card>
269
+ <CardHeader><Skeleton className="h-6 w-32" /></CardHeader>
270
+ <CardContent className="space-y-4">
271
+ <Skeleton className="h-4 w-full" />
272
+ <Skeleton className="h-4 w-full" />
273
+ <Skeleton className="h-4 w-2/3" />
274
+ </CardContent>
275
+ </Card>
276
+ </div>
277
+ )
278
+ }
279
+
280
+ if (error || (!type && !isCreateMode)) {
281
+ return (
282
+ <Alert variant="destructive">
283
+ <AlertCircle className="h-4 w-4" />
284
+ <AlertTitle>Failed to load type details</AlertTitle>
285
+ <AlertDescription>{error || 'Type not found'}</AlertDescription>
286
+ <Button onClick={() => refetch()} variant="outline" className="mt-4">Retry</Button>
287
+ </Alert>
288
+ )
289
+ }
290
+
291
+ const itemColumns = [
292
+ {
293
+ key: 'id' as keyof TypeItem,
294
+ title: 'ID',
295
+ render: (row: any) => (
296
+ <span className="font-mono text-xs">{row.id?.slice(0, 8)}...</span>
297
+ )
298
+ },
299
+ {
300
+ key: 'data' as keyof TypeItem,
301
+ title: 'Data',
302
+ render: (row: any) => {
303
+ const firstFieldKey = Object.keys(type?.design_schema?.fields || {})[0]
304
+ const displayValue = firstFieldKey ? row.data?.[firstFieldKey] : 'No data'
305
+ return (
306
+ <div>
307
+ <div className="font-medium">{displayValue}</div>
308
+ <div className="text-xs text-muted-foreground">
309
+ {Object.keys(row.data || {}).length} fields
310
+ </div>
311
+ </div>
312
+ )
313
+ }
314
+ },
315
+ {
316
+ key: 'created_at' as keyof TypeItem,
317
+ title: 'Created',
318
+ render: (row: any) => formatDateTime(row.created_at)
319
+ },
320
+ {
321
+ key: 'updated_at' as keyof TypeItem,
322
+ title: 'Updated',
323
+ render: (row: any) => formatDateTime(row.updated_at)
324
+ }
325
+ ]
326
+
327
+ return (
328
+ <div className="space-y-6">
329
+ <div className="flex items-center justify-between">
330
+ <div className="flex items-center gap-4">
331
+ <Button
332
+ variant="ghost"
333
+ onClick={() => isCreateMode ? navigate('/spine-framework/admin/configs/types') : navigate(-1)}
334
+ >
335
+ <ArrowLeft className="h-5 w-5" />
336
+ </Button>
337
+ <div>
338
+ <h1 className="text-2xl font-bold">
339
+ {isCreateMode ? 'Create Type' : type?.name}
340
+ </h1>
341
+ <p className="text-sm text-muted-foreground">
342
+ {isCreateMode ? 'Type Configuration' : 'Type Details'}
343
+ </p>
344
+ </div>
345
+ </div>
346
+
347
+ <div className="flex space-x-2">
348
+ {isEditing ? (
349
+ <>
350
+ <Button variant="outline" onClick={handleCancel}>Cancel</Button>
351
+ <Button onClick={handleSave}>
352
+ {isCreateMode ? 'Create' : 'Save Changes'}
353
+ </Button>
354
+ </>
355
+ ) : (
356
+ !isCreateMode && (
357
+ <>
358
+ <Button variant="outline" onClick={handleEdit}>
359
+ <Pencil className="h-4 w-4 mr-2" />
360
+ Edit
361
+ </Button>
362
+ <Button
363
+ variant="outline"
364
+ onClick={() => setIsDeleteModalOpen(true)}
365
+ disabled={type?.ownership === 'system'}
366
+ >
367
+ <Trash2 className="h-4 w-4 mr-2" />
368
+ Delete
369
+ </Button>
370
+ </>
371
+ )
372
+ )}
373
+ </div>
374
+ </div>
375
+
376
+ {isEditing ? (
377
+ <>
378
+ <Card>
379
+ <CardHeader>
380
+ <CardTitle>
381
+ {isCreateMode ? `Create New ${typeKind.charAt(0).toUpperCase() + typeKind.slice(1)}` : `Edit ${type?.name || 'Type'}`}
382
+ </CardTitle>
383
+ </CardHeader>
384
+ <CardContent>
385
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
386
+ <div className="space-y-4">
387
+ <h3 className="text-sm font-medium text-muted-foreground">Type Details</h3>
388
+ <div className="space-y-4">
389
+ <div className="space-y-2">
390
+ <Label>Name</Label>
391
+ <Input
392
+ value={editData.name}
393
+ onChange={(e) => setEditData({...editData, name: e.target.value})}
394
+ />
395
+ </div>
396
+ <div className="space-y-2">
397
+ <Label>Slug</Label>
398
+ <Input
399
+ value={editData.slug}
400
+ onChange={(e) => setEditData({...editData, slug: e.target.value})}
401
+ />
402
+ </div>
403
+ <div className="space-y-2">
404
+ <Label>Description</Label>
405
+ <Input
406
+ value={editData.description}
407
+ onChange={(e) => setEditData({...editData, description: e.target.value})}
408
+ placeholder="Enter description"
409
+ />
410
+ </div>
411
+ <div className="space-y-2">
412
+ <Label>Kind</Label>
413
+ <Select value={editData.kind} onValueChange={(v) => setEditData({...editData, kind: v})}>
414
+ <SelectTrigger>
415
+ <SelectValue />
416
+ </SelectTrigger>
417
+ <SelectContent>
418
+ {typeKind ? (
419
+ <SelectItem value={typeKind}>{typeKind.charAt(0).toUpperCase() + typeKind.slice(1)}</SelectItem>
420
+ ) : (
421
+ <>
422
+ <SelectItem value="item">Item</SelectItem>
423
+ <SelectItem value="account">Account</SelectItem>
424
+ <SelectItem value="person">Person</SelectItem>
425
+ <SelectItem value="thread">Thread</SelectItem>
426
+ <SelectItem value="message">Message</SelectItem>
427
+ </>
428
+ )}
429
+ </SelectContent>
430
+ </Select>
431
+ </div>
432
+ <div className="space-y-2">
433
+ <Label>Ownership</Label>
434
+ <Select value={editData.ownership} onValueChange={(v) => setEditData({...editData, ownership: v})}>
435
+ <SelectTrigger>
436
+ <SelectValue />
437
+ </SelectTrigger>
438
+ <SelectContent>
439
+ <SelectItem value="system">System</SelectItem>
440
+ <SelectItem value="app">App</SelectItem>
441
+ <SelectItem value="tenant">Tenant</SelectItem>
442
+ </SelectContent>
443
+ </Select>
444
+ </div>
445
+ <div className="flex items-center gap-2">
446
+ <Checkbox
447
+ id="is_active"
448
+ checked={editData.is_active}
449
+ onCheckedChange={(checked) => setEditData({...editData, is_active: checked === true})}
450
+ />
451
+ <Label htmlFor="is_active">Is Active</Label>
452
+ </div>
453
+ </div>
454
+ </div>
455
+
456
+ <div className="space-y-4">
457
+ <h3 className="text-sm font-medium text-muted-foreground">Metadata</h3>
458
+ <div className="space-y-4">
459
+ <div className="space-y-2">
460
+ <Label>ID</Label>
461
+ <div className="text-sm font-mono text-muted-foreground">{type?.id || 'Auto-generated'}</div>
462
+ </div>
463
+ <div className="space-y-2">
464
+ <Label>App ID</Label>
465
+ <Select value={editData.app_id || ''} onValueChange={(v) => setEditData({...editData, app_id: v})}>
466
+ <SelectTrigger>
467
+ <SelectValue placeholder="None (System Types)" />
468
+ </SelectTrigger>
469
+ <SelectContent>
470
+ {availableApps.map(app => (
471
+ <SelectItem key={app.id} value={app.id}>{app.name}</SelectItem>
472
+ ))}
473
+ </SelectContent>
474
+ </Select>
475
+ </div>
476
+ <div className="space-y-2">
477
+ <Label>Icon</Label>
478
+ <Input
479
+ value={editData.icon || ''}
480
+ onChange={(e) => setEditData({...editData, icon: e.target.value})}
481
+ placeholder="Enter icon name"
482
+ />
483
+ </div>
484
+ <div className="space-y-2">
485
+ <Label>Color</Label>
486
+ <Select value={editData.color || ''} onValueChange={(v) => setEditData({...editData, color: v})}>
487
+ <SelectTrigger>
488
+ <SelectValue placeholder="Select color" />
489
+ </SelectTrigger>
490
+ <SelectContent>
491
+ <SelectItem value="blue">Blue</SelectItem>
492
+ <SelectItem value="green">Green</SelectItem>
493
+ <SelectItem value="red">Red</SelectItem>
494
+ <SelectItem value="yellow">Yellow</SelectItem>
495
+ <SelectItem value="purple">Purple</SelectItem>
496
+ <SelectItem value="pink">Pink</SelectItem>
497
+ <SelectItem value="indigo">Indigo</SelectItem>
498
+ <SelectItem value="gray">Gray</SelectItem>
499
+ <SelectItem value="slate">Slate</SelectItem>
500
+ </SelectContent>
501
+ </Select>
502
+ </div>
503
+ <div className="space-y-2">
504
+ <Label>Created</Label>
505
+ <div className="text-sm text-muted-foreground">{formatDateTime(type?.created_at) || 'Not yet created'}</div>
506
+ </div>
507
+ <div className="space-y-2">
508
+ <Label>Updated</Label>
509
+ <div className="text-sm text-muted-foreground">{formatDateTime(type?.updated_at) || 'Not yet updated'}</div>
510
+ </div>
511
+ </div>
512
+ </div>
513
+ </div>
514
+
515
+ <div className="mt-8 space-y-2">
516
+ <h3 className="text-sm font-medium text-muted-foreground">Schema Definition</h3>
517
+ <Label>Schema</Label>
518
+ <Textarea
519
+ value={schemaText}
520
+ onChange={(e) => setSchemaText(e.target.value)}
521
+ className="font-mono text-sm"
522
+ rows={8}
523
+ placeholder='Enter JSON schema with fields object'
524
+ />
525
+ <p className="text-xs text-muted-foreground">JSON schema defining the fields for this type.</p>
526
+ </div>
527
+ </CardContent>
528
+ </Card>
529
+ </>
530
+ ) : (
531
+ <>
532
+ <Card>
533
+ <CardHeader>
534
+ <CardTitle>Type Information</CardTitle>
535
+ </CardHeader>
536
+ <CardContent>
537
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
538
+ <div className="space-y-4">
539
+ <h3 className="text-sm font-medium text-muted-foreground">Type Details</h3>
540
+ <div className="space-y-4">
541
+ <div className="flex justify-between items-center">
542
+ <span className="text-sm text-muted-foreground">Name:</span>
543
+ <span className="text-sm">{type?.name}</span>
544
+ </div>
545
+ <div className="flex justify-between items-center">
546
+ <span className="text-sm text-muted-foreground">Slug:</span>
547
+ <span className="text-sm font-mono">{type?.slug}</span>
548
+ </div>
549
+ <div className="flex justify-between items-center">
550
+ <span className="text-sm text-muted-foreground">Description:</span>
551
+ <span className="text-sm">{type?.description || 'No description'}</span>
552
+ </div>
553
+ <div className="flex justify-between items-center">
554
+ <span className="text-sm text-muted-foreground">Kind:</span>
555
+ <Badge>{type?.kind}</Badge>
556
+ </div>
557
+ <div className="flex justify-between items-center">
558
+ <span className="text-sm text-muted-foreground">Ownership:</span>
559
+ <Badge variant="outline">{type?.ownership}</Badge>
560
+ </div>
561
+ <div className="flex justify-between items-center">
562
+ <span className="text-sm text-muted-foreground">Status:</span>
563
+ <Badge variant={type?.is_active ? 'default' : 'secondary'}>
564
+ {type?.is_active ? 'Active' : 'Inactive'}
565
+ </Badge>
566
+ </div>
567
+ </div>
568
+ </div>
569
+
570
+ <div className="space-y-4">
571
+ <h3 className="text-sm font-medium text-muted-foreground">Metadata</h3>
572
+ <div className="space-y-4">
573
+ <div className="flex justify-between items-center">
574
+ <span className="text-sm text-muted-foreground">ID:</span>
575
+ <span className="text-sm font-mono">{type?.id}</span>
576
+ </div>
577
+ <div className="flex justify-between items-center">
578
+ <span className="text-sm text-muted-foreground">App ID:</span>
579
+ <span className="text-sm font-mono">{type?.app_id || 'None'}</span>
580
+ </div>
581
+ <div className="flex justify-between items-center">
582
+ <span className="text-sm text-muted-foreground">Icon:</span>
583
+ <span className="text-sm">{type?.icon || 'None'}</span>
584
+ </div>
585
+ <div className="flex justify-between items-center">
586
+ <span className="text-sm text-muted-foreground">Color:</span>
587
+ <div className="flex items-center gap-2">
588
+ {type?.color && (
589
+ <span className="inline-block w-3 h-3 rounded-full" style={{backgroundColor: type?.color}}></span>
590
+ )}
591
+ <span className="text-sm">{type?.color || 'None'}</span>
592
+ </div>
593
+ </div>
594
+ <div className="flex justify-between items-center">
595
+ <span className="text-sm text-muted-foreground">Created:</span>
596
+ <span className="text-sm">{formatDateTime(type?.created_at)}</span>
597
+ </div>
598
+ <div className="flex justify-between items-center">
599
+ <span className="text-sm text-muted-foreground">Updated:</span>
600
+ <span className="text-sm">{formatDateTime(type?.updated_at)}</span>
601
+ </div>
602
+ </div>
603
+ </div>
604
+ </div>
605
+
606
+ <div className="mt-8 space-y-2">
607
+ <h3 className="text-sm font-medium text-muted-foreground">Schema Definition</h3>
608
+ <pre className="text-xs bg-muted p-3 rounded border overflow-auto max-h-48">
609
+ {JSON.stringify(type?.design_schema || { fields: {} }, null, 2)}
610
+ </pre>
611
+ </div>
612
+ </CardContent>
613
+ </Card>
614
+
615
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
616
+ <Card>
617
+ <CardContent className="p-6">
618
+ <div className="flex items-center gap-4">
619
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10">
620
+ <span className="text-primary font-semibold">{Object.keys(type?.design_schema?.fields || {}).length}</span>
621
+ </div>
622
+ <div>
623
+ <h3 className="text-sm font-medium">Fields</h3>
624
+ <p className="text-sm text-muted-foreground">Schema field definitions</p>
625
+ </div>
626
+ </div>
627
+ </CardContent>
628
+ </Card>
629
+
630
+ <Card>
631
+ <CardContent className="p-6">
632
+ <div className="flex items-center gap-4">
633
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-green-500/10">
634
+ <span className="text-green-600 font-semibold">{items?.length || 0}</span>
635
+ </div>
636
+ <div>
637
+ <h3 className="text-sm font-medium">Items</h3>
638
+ <p className="text-sm text-muted-foreground">Items using this type</p>
639
+ </div>
640
+ </div>
641
+ </CardContent>
642
+ </Card>
643
+ </div>
644
+
645
+ <Card>
646
+ <CardHeader>
647
+ <CardTitle>Items ({items?.length || 0})</CardTitle>
648
+ </CardHeader>
649
+ <CardContent>
650
+ {itemsLoading ? (
651
+ <div className="space-y-2">
652
+ <Skeleton className="h-8 w-full" />
653
+ <Skeleton className="h-8 w-full" />
654
+ <Skeleton className="h-8 w-full" />
655
+ </div>
656
+ ) : items && items.length > 0 ? (
657
+ <DataTable
658
+ data={items}
659
+ columns={itemColumns as any}
660
+ searchable={false}
661
+ />
662
+ ) : (
663
+ <div className="text-center py-8 text-muted-foreground">
664
+ No items found for this type
665
+ </div>
666
+ )}
667
+ </CardContent>
668
+ </Card>
669
+ </>
670
+ )}
671
+
672
+ <Modal
673
+ isOpen={isDeleteModalOpen}
674
+ onClose={() => setIsDeleteModalOpen(false)}
675
+ title="Delete Type"
676
+ description="Are you sure you want to delete this type? This action cannot be undone."
677
+ size="sm"
678
+ >
679
+ <div className="flex justify-end space-x-3">
680
+ <Button variant="outline" onClick={() => setIsDeleteModalOpen(false)}>
681
+ Cancel
682
+ </Button>
683
+ <Button
684
+ variant="destructive"
685
+ onClick={() => deleteMutation.mutate()}
686
+ disabled={deleteMutation.loading}
687
+ >
688
+ {deleteMutation.loading ? 'Deleting...' : 'Delete Type'}
689
+ </Button>
690
+ </div>
691
+ </Modal>
692
+ </div>
693
+ )
694
+ }