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,91 @@
1
+ /**
2
+ * @module src/components/layout/AppShell
3
+ * @audience installer
4
+ * @layer frontend-component
5
+ * @stability stable
6
+ *
7
+ * Application shell with Sidebar-05 layout for professional SaaS look.
8
+ * Wraps page content with collapsible sidebar navigation.
9
+ */
10
+
11
+ import * as React from "react"
12
+ import { Link } from 'react-router-dom'
13
+ import { SidebarProvider, SidebarInset, SidebarTrigger } from "../ui/sidebar"
14
+ import { Separator } from "../ui/separator"
15
+ import {
16
+ Breadcrumb,
17
+ BreadcrumbItem,
18
+ BreadcrumbLink,
19
+ BreadcrumbList,
20
+ BreadcrumbPage,
21
+ BreadcrumbSeparator,
22
+ } from "../ui/breadcrumb"
23
+
24
+ interface AppShellProps {
25
+ sidebar: React.ReactNode
26
+ children: React.ReactNode
27
+ breadcrumbs?: { title: string; url?: string }[]
28
+ headerActions?: React.ReactNode
29
+ }
30
+
31
+ export function AppShell({
32
+ sidebar,
33
+ children,
34
+ breadcrumbs,
35
+ headerActions,
36
+ }: AppShellProps) {
37
+ return (
38
+ <SidebarProvider>
39
+ {sidebar}
40
+ <SidebarInset>
41
+ {/* Header */}
42
+ <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
43
+ <div className="flex items-center gap-2 px-4">
44
+ <SidebarTrigger className="-ml-1" />
45
+ <Separator orientation="vertical" className="mr-2 h-4" />
46
+ {breadcrumbs && (
47
+ <Breadcrumb>
48
+ <BreadcrumbList>
49
+ {breadcrumbs.map((crumb, index) => (
50
+ <React.Fragment key={crumb.title}>
51
+ <BreadcrumbItem
52
+ className={
53
+ index === breadcrumbs.length - 1
54
+ ? "hidden md:block"
55
+ : ""
56
+ }
57
+ >
58
+ {index === breadcrumbs.length - 1 ? (
59
+ <BreadcrumbPage>{crumb.title}</BreadcrumbPage>
60
+ ) : (
61
+ <BreadcrumbLink asChild>
62
+ <Link to={crumb.url || "#"}>
63
+ {crumb.title}
64
+ </Link>
65
+ </BreadcrumbLink>
66
+ )}
67
+ </BreadcrumbItem>
68
+ {index < breadcrumbs.length - 1 && (
69
+ <BreadcrumbSeparator className="hidden md:block" />
70
+ )}
71
+ </React.Fragment>
72
+ ))}
73
+ </BreadcrumbList>
74
+ </Breadcrumb>
75
+ )}
76
+ </div>
77
+ {headerActions && (
78
+ <div className="ml-auto flex items-center gap-2 px-4">
79
+ {headerActions}
80
+ </div>
81
+ )}
82
+ </header>
83
+
84
+ {/* Main Content */}
85
+ <main className="flex-1 overflow-auto p-4 md:p-6 lg:p-8">
86
+ {children}
87
+ </main>
88
+ </SidebarInset>
89
+ </SidebarProvider>
90
+ )
91
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @module src/components/layout/Header
3
+ * @audience installer
4
+ * @layer frontend-component
5
+ * @stability stable
6
+ *
7
+ * Sticky top bar rendered inside the main content area. Contains:
8
+ * - **Mobile hamburger** (`Bars3Icon`) — visible below `lg` breakpoint;
9
+ * calls `onMenuClick` to open the slide-over sidebar
10
+ * - **Search input** — hidden on small screens (placeholder only; not wired)
11
+ * - **Notification bell** — placeholder; not yet wired to a backend
12
+ * - **User avatar + name** — derived from `user.full_name` / `user.email`
13
+ *
14
+ * @seeAlso src/components/layout/Layout.tsx (mounts this component)
15
+ * @seeAlso src/types/auth.ts (User)
16
+ */
17
+
18
+ import { Menu, Bell, Search, User } from 'lucide-react';
19
+ import { User } from '../../types/auth'
20
+
21
+ /**
22
+ * Props for `Header`.
23
+ *
24
+ * @prop onMenuClick - Callback to open the mobile sidebar
25
+ * @prop user - Currently logged-in user (null while loading)
26
+ */
27
+ interface HeaderProps {
28
+ onMenuClick: () => void
29
+ user: User | null
30
+ }
31
+
32
+ /**
33
+ * Sticky top bar.
34
+ *
35
+ * @param props - `HeaderProps`
36
+ * @returns Header element with menu toggle, search, notifications, and avatar
37
+ * @sideEffects none (delegates menu open to `onMenuClick`)
38
+ */
39
+ export function Header({ onMenuClick, user }: HeaderProps) {
40
+ return (
41
+ <header className="sticky top-0 z-20 flex h-14 shrink-0 items-center gap-4 border-b border-slate-200 bg-white/80 backdrop-blur-md px-4 sm:px-6 lg:pl-72 lg:pr-8">
42
+ {/* Logo + Mobile hamburger — only visible below lg */}
43
+ <div className="flex items-center gap-3">
44
+ <button
45
+ onClick={onMenuClick}
46
+ className="rounded-md p-1.5 text-slate-500 hover:bg-slate-100 hover:text-slate-700 transition-colors lg:hidden"
47
+ aria-label="Open menu"
48
+ >
49
+ <Menu className="h-5 w-5" />
50
+ </button>
51
+ </div>
52
+
53
+ {/* Spacer */}
54
+ <div className="flex-1" />
55
+
56
+ {/* Right actions */}
57
+ <div className="flex items-center gap-3">
58
+ {/* Search */}
59
+ <div className="relative hidden sm:block">
60
+ <MagnifyingGlassIcon className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400" />
61
+ <input
62
+ type="text"
63
+ placeholder="Search..."
64
+ className="h-9 w-48 rounded-lg border border-slate-200 bg-slate-50 pl-9 pr-3 text-sm text-slate-900 placeholder:text-slate-400 focus:border-accent-blue focus:bg-white focus:outline-none focus:ring-1 focus:ring-accent-blue transition-colors"
65
+ />
66
+ </div>
67
+
68
+ {/* Notifications */}
69
+ <button
70
+ className="relative rounded-lg p-2 text-slate-400 hover:bg-slate-100 hover:text-slate-600 transition-colors"
71
+ aria-label="Notifications"
72
+ >
73
+ <Bell className="h-5 w-5" />
74
+ </button>
75
+
76
+ {/* User avatar */}
77
+ <div className="flex items-center gap-2 pl-2 border-l border-slate-200">
78
+ <div className="flex h-7 w-7 items-center justify-center rounded-full bg-navy text-xs font-medium text-white">
79
+ {user?.full_name?.charAt(0) || user?.email?.charAt(0) || '?'}
80
+ </div>
81
+ <span className="hidden sm:block text-sm font-medium text-slate-700">
82
+ {user?.full_name}
83
+ </span>
84
+ </div>
85
+ </div>
86
+ </header>
87
+ )
88
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @module src/components/layout/Layout
3
+ * @audience installer
4
+ * @layer frontend-component
5
+ * @stability stable
6
+ *
7
+ * Root app shell providing the two-pane admin layout:
8
+ * - **Desktop (`lg+`):** fixed 60-wide `<Sidebar>` on the left, scrollable
9
+ * main content area padded with `lg:pl-60`.
10
+ * - **Mobile (`< lg`):** top bar with hamburger button that opens a
11
+ * slide-over `<Sidebar>` with a backdrop overlay.
12
+ *
13
+ * `isActive` is computed from the current `location.pathname` and passed
14
+ * to `SidebarContent` for active-link highlighting.
15
+ *
16
+ * @seeAlso src/components/layout/Sidebar.tsx
17
+ * @seeAlso src/contexts/AuthContext.tsx (provides `user` and `logout`)
18
+ */
19
+
20
+ import React, { useState } from 'react'
21
+ import { Sidebar, SidebarContent } from './Sidebar'
22
+ import { useAuth } from '../../contexts/AuthContext'
23
+ import { useLocation } from 'react-router-dom'
24
+
25
+ /** Props for `Layout`. */
26
+ interface LayoutProps {
27
+ children: React.ReactNode
28
+ }
29
+
30
+ /**
31
+ * Root two-pane admin shell.
32
+ *
33
+ * @param props - `LayoutProps`
34
+ * @returns Full-page layout with sidebar + main content area
35
+ * @sideEffects none (sidebar open state is local)
36
+ */
37
+ export function Layout({ children }: LayoutProps) {
38
+ const [sidebarOpen, setSidebarOpen] = useState(false)
39
+ const { user, logout } = useAuth()
40
+ const location = useLocation()
41
+
42
+ const isActive = (href: string) =>
43
+ location.pathname === href || location.pathname.startsWith(href + '/')
44
+
45
+ return (
46
+ <div className="min-h-screen bg-[#F2F3F8] flex lg:top-0">
47
+ {/* Mobile overlay */}
48
+ {sidebarOpen && (
49
+ <>
50
+ <div
51
+ className="fixed inset-0 z-40 bg-slate-900/30 backdrop-blur-sm lg:hidden"
52
+ onClick={() => setSidebarOpen(false)}
53
+ />
54
+ <Sidebar open={sidebarOpen} onClose={() => setSidebarOpen(false)} />
55
+ </>
56
+ )}
57
+
58
+ {/* Desktop sidebar — visible at lg+ */}
59
+ <aside className="hidden lg:flex lg:fixed lg:inset-y-0 lg:left-0 lg:z-30 lg:w-60 lg:flex-col lg:shrink-0 bg-white border-r border-slate-200 lg:top-0">
60
+ <SidebarContent
61
+ isActive={isActive}
62
+ user={user}
63
+ logout={logout}
64
+ onClose={() => {}}
65
+ />
66
+ </aside>
67
+
68
+ {/* Mobile sidebar with menu button */}
69
+ <div className="lg:hidden flex items-center justify-between p-4 bg-white border-b border-slate-200">
70
+ <button
71
+ onClick={() => setSidebarOpen(true)}
72
+ className="rounded-md p-2 text-slate-500 hover:bg-slate-100 hover:text-slate-700"
73
+ aria-label="Open menu"
74
+ >
75
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
76
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
77
+ </svg>
78
+ </button>
79
+ <div className="flex items-center gap-3">
80
+ <img src="/spine-logo.jpg" alt="Spine Framework" className="h-8 w-auto" />
81
+ <span className="text-lg font-semibold tracking-tight text-slate-900">Spine Framework</span>
82
+ </div>
83
+ </div>
84
+
85
+ {/* Main content area */}
86
+ <div className="flex-1 flex flex-col min-w-0 lg:pl-60">
87
+ <main className="flex-1 py-6 px-4 sm:px-6 lg:px-8 xl:px-12">
88
+ <div className="max-w-6xl mx-auto">
89
+ {children}
90
+ </div>
91
+ </main>
92
+ </div>
93
+ </div>
94
+ )
95
+ }
@@ -0,0 +1,329 @@
1
+ import { useState } from 'react'
2
+ import { Link, useLocation } from 'react-router-dom'
3
+ import { useAuth } from '../../contexts/AuthContext'
4
+ import { Popover, PopoverTrigger, PopoverContent } from '../ui/popover'
5
+ import {
6
+ Home,
7
+ Box,
8
+ Users,
9
+ Settings,
10
+ FileText,
11
+ Sparkles,
12
+ LogOut,
13
+ Building2,
14
+ RefreshCw,
15
+ Zap,
16
+ Clock,
17
+ ChevronDown,
18
+ ChevronRight,
19
+ X,
20
+ Link as LinkIcon,
21
+ User,
22
+ MoreVertical,
23
+ ShieldCheck,
24
+ Key,
25
+ FlaskConical,
26
+ BarChart3,
27
+ Bell
28
+ } from 'lucide-react'
29
+
30
+ interface SidebarProps {
31
+ open: boolean
32
+ onClose: () => void
33
+ }
34
+
35
+ const navigation = [
36
+ { name: 'Dashboard', href: '/spine-framework/admin/configs/types', icon: Home },
37
+ ]
38
+
39
+ const configsNavigation = [
40
+ { name: 'Item Types', href: '/spine-framework/admin/configs/types', icon: Box },
41
+ { divider: true },
42
+ { name: 'Apps', href: '/spine-framework/admin/configs/apps', icon: Settings },
43
+ { name: 'Roles', href: '/spine-framework/admin/configs/roles', icon: ShieldCheck },
44
+ { divider: true },
45
+ { name: 'AI Agents', href: '/spine-framework/admin/configs/ai-agents', icon: Sparkles },
46
+ { name: 'Prompt Configs', href: '/spine-framework/admin/configs/prompts', icon: FileText },
47
+ { name: 'Embeddings', href: '/spine-framework/admin/configs/embeddings', icon: FileText },
48
+ { divider: true },
49
+ { name: 'Pipelines', href: '/spine-framework/admin/configs/pipelines', icon: RefreshCw },
50
+ { name: 'Triggers', href: '/spine-framework/admin/configs/triggers', icon: Zap },
51
+ { name: 'Timers', href: '/spine-framework/admin/configs/timers', icon: Clock },
52
+ { divider: true },
53
+ { name: 'Integrations', href: '/spine-framework/admin/configs/integrations', icon: LinkIcon },
54
+ { name: 'API Keys', href: '/spine-framework/admin/configs/api-keys', icon: Key },
55
+ ] as const
56
+
57
+ const observabilityNavigation = [
58
+ { name: 'Dashboard', href: '/spine-framework/admin/observability', icon: BarChart3 },
59
+ { name: 'Alerts', href: '/spine-framework/admin/observability/alerts', icon: Bell },
60
+ { name: 'Executions', href: '/spine-framework/admin/observability/executions', icon: FlaskConical },
61
+ { name: 'Logs', href: '/spine-framework/admin/observability/logs', icon: FileText },
62
+ ]
63
+
64
+ // Database entities that should be shown in runtime navigation
65
+ const runtimeEntities = [
66
+ { name: 'Items', href: '/spine-framework/admin/runtime/items', icon: Box },
67
+ { name: 'Accounts', href: '/spine-framework/admin/runtime/accounts', icon: Building2 },
68
+ { name: 'People', href: '/spine-framework/admin/runtime/people', icon: User },
69
+ { name: 'Person Types', href: '/spine-framework/admin/runtime/person-types', icon: Users },
70
+ ]
71
+
72
+ function classNames(...classes: (string | false | undefined)[]) {
73
+ return classes.filter(Boolean).join(' ')
74
+ }
75
+
76
+ export function Sidebar({ open, onClose }: SidebarProps) {
77
+ return (
78
+ <>
79
+ {/* Mobile sidebar */}
80
+ <div className={classNames(open && 'fixed inset-0 z-40 flex')}>
81
+ {open && (
82
+ <div className="fixed inset-0 z-40 flex">
83
+ <div
84
+ className="fixed inset-0 bg-black/50 transition-opacity"
85
+ onClick={onClose}
86
+ />
87
+ <div className="relative flex w-full max-w-xs flex-1 flex-col bg-sidebar pb-4">
88
+ <div className="absolute right-0 top-0 -mr-12 pt-2">
89
+ <button
90
+ type="button"
91
+ className="ml-1 flex h-10 w-10 items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
92
+ onClick={onClose}
93
+ >
94
+ <span className="sr-only">Close sidebar</span>
95
+ <X className="h-6 w-6 text-white" aria-hidden="true" />
96
+ </button>
97
+ </div>
98
+ <div className="h-0 flex-1 overflow-y-auto pt-5">
99
+ <div className="flex flex-shrink-0 items-center px-4">
100
+ <span className="text-xl font-bold text-sidebar-foreground">Spine</span>
101
+ </div>
102
+ <SidebarContent onNavClick={onClose} />
103
+ </div>
104
+ </div>
105
+ </div>
106
+ )}
107
+ </div>
108
+ </>
109
+ )
110
+ }
111
+
112
+ interface SidebarContentProps {
113
+ onNavClick?: () => void
114
+ }
115
+
116
+ export function SidebarContent({ onNavClick }: SidebarContentProps) {
117
+ const location = useLocation()
118
+ const { user, logout } = useAuth()
119
+ const isSystemAdmin = user?.roles?.includes('system_admin')
120
+
121
+ // Collapsible sections state
122
+ const [configsOpen, setConfigsOpen] = useState(() =>
123
+ location.pathname.includes('/admin/configs')
124
+ )
125
+ const [runtimeOpen, setRuntimeOpen] = useState(() =>
126
+ location.pathname.includes('/admin/runtime')
127
+ )
128
+ const [observabilityOpen, setObservabilityOpen] = useState(() =>
129
+ location.pathname.includes('/admin/observability')
130
+ )
131
+
132
+ const isActive = (href: string) => {
133
+ return location.pathname === href || location.pathname.startsWith(href + '/')
134
+ }
135
+
136
+ return (
137
+ <nav className="mt-5 flex flex-1 flex-col px-2">
138
+ {/* Main nav */}
139
+ <div className="space-y-1">
140
+ {navigation.map((item) => (
141
+ <Link
142
+ key={item.name}
143
+ to={item.href}
144
+ onClick={onNavClick}
145
+ className={classNames(
146
+ isActive(item.href)
147
+ ? 'bg-sidebar-accent text-sidebar-accent-foreground'
148
+ : 'text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
149
+ 'group flex items-center rounded-md px-2 py-2 text-sm font-medium'
150
+ )}
151
+ >
152
+ <item.icon
153
+ className={classNames(
154
+ isActive(item.href) ? 'text-sidebar-accent-foreground' : 'text-sidebar-foreground',
155
+ 'mr-3 h-5 w-5 flex-shrink-0'
156
+ )}
157
+ aria-hidden="true"
158
+ />
159
+ {item.name}
160
+ </Link>
161
+ ))}
162
+ </div>
163
+
164
+ {/* Configs Section */}
165
+ {isSystemAdmin && (
166
+ <>
167
+ <div className="mt-6">
168
+ <button
169
+ onClick={() => setConfigsOpen(!configsOpen)}
170
+ className="flex w-full items-center justify-between px-2 py-2 text-sm font-medium text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground rounded-md"
171
+ >
172
+ <span>Configuration</span>
173
+ {configsOpen ? (
174
+ <ChevronDown className="h-4 w-4" />
175
+ ) : (
176
+ <ChevronRight className="h-4 w-4" />
177
+ )}
178
+ </button>
179
+
180
+ {configsOpen && (
181
+ <div className="mt-1 space-y-1">
182
+ {configsNavigation.map((item, index) => (
183
+ 'divider' in item ? (
184
+ <div key={`divider-${index}`} className="my-2 border-t border-sidebar-border" />
185
+ ) : (
186
+ <Link
187
+ key={item.name}
188
+ to={item.href}
189
+ onClick={onNavClick}
190
+ className={classNames(
191
+ isActive(item.href)
192
+ ? 'bg-sidebar-accent text-sidebar-accent-foreground'
193
+ : 'text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
194
+ 'group flex items-center rounded-md px-2 py-2 text-sm font-medium pl-4'
195
+ )}
196
+ >
197
+ <item.icon
198
+ className={classNames(
199
+ isActive(item.href) ? 'text-sidebar-accent-foreground' : 'text-sidebar-foreground',
200
+ 'mr-3 h-4 w-4 flex-shrink-0'
201
+ )}
202
+ aria-hidden="true"
203
+ />
204
+ {item.name}
205
+ </Link>
206
+ )
207
+ ))}
208
+ </div>
209
+ )}
210
+ </div>
211
+
212
+ {/* Runtime Section */}
213
+ <div className="mt-4">
214
+ <button
215
+ onClick={() => setRuntimeOpen(!runtimeOpen)}
216
+ className="flex w-full items-center justify-between px-2 py-2 text-sm font-medium text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground rounded-md"
217
+ >
218
+ <span>Data</span>
219
+ {runtimeOpen ? (
220
+ <ChevronDown className="h-4 w-4" />
221
+ ) : (
222
+ <ChevronRight className="h-4 w-4" />
223
+ )}
224
+ </button>
225
+
226
+ {runtimeOpen && (
227
+ <div className="mt-1 space-y-1">
228
+ {runtimeEntities.map((item) => (
229
+ <Link
230
+ key={item.name}
231
+ to={item.href}
232
+ onClick={onNavClick}
233
+ className={classNames(
234
+ isActive(item.href)
235
+ ? 'bg-sidebar-accent text-sidebar-accent-foreground'
236
+ : 'text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
237
+ 'group flex items-center rounded-md px-2 py-2 text-sm font-medium pl-4'
238
+ )}
239
+ >
240
+ <item.icon
241
+ className={classNames(
242
+ isActive(item.href) ? 'text-sidebar-accent-foreground' : 'text-sidebar-foreground',
243
+ 'mr-3 h-4 w-4 flex-shrink-0'
244
+ )}
245
+ aria-hidden="true"
246
+ />
247
+ {item.name}
248
+ </Link>
249
+ ))}
250
+ </div>
251
+ )}
252
+ </div>
253
+
254
+ {/* Observability Section */}
255
+ <div className="mt-4">
256
+ <button
257
+ onClick={() => setObservabilityOpen(!observabilityOpen)}
258
+ className="flex w-full items-center justify-between px-2 py-2 text-sm font-medium text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground rounded-md"
259
+ >
260
+ <span>Observability</span>
261
+ {observabilityOpen ? (
262
+ <ChevronDown className="h-4 w-4" />
263
+ ) : (
264
+ <ChevronRight className="h-4 w-4" />
265
+ )}
266
+ </button>
267
+
268
+ {observabilityOpen && (
269
+ <div className="mt-1 space-y-1">
270
+ {observabilityNavigation.map((item) => (
271
+ <Link
272
+ key={item.name}
273
+ to={item.href}
274
+ onClick={onNavClick}
275
+ className={classNames(
276
+ isActive(item.href)
277
+ ? 'bg-sidebar-accent text-sidebar-accent-foreground'
278
+ : 'text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
279
+ 'group flex items-center rounded-md px-2 py-2 text-sm font-medium pl-4'
280
+ )}
281
+ >
282
+ <item.icon
283
+ className={classNames(
284
+ isActive(item.href) ? 'text-sidebar-accent-foreground' : 'text-sidebar-foreground',
285
+ 'mr-3 h-4 w-4 flex-shrink-0'
286
+ )}
287
+ aria-hidden="true"
288
+ />
289
+ {item.name}
290
+ </Link>
291
+ ))}
292
+ </div>
293
+ )}
294
+ </div>
295
+ </>
296
+ )}
297
+
298
+ {/* User section */}
299
+ <div className="mt-auto border-t border-sidebar-border pt-4">
300
+ <Popover>
301
+ <PopoverTrigger asChild>
302
+ <button className="flex w-full items-center gap-3 rounded-md px-2 py-2 text-sm font-medium text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground">
303
+ <div className="flex h-8 w-8 items-center justify-center rounded-full bg-sidebar-primary text-sidebar-primary-foreground">
304
+ <User className="h-4 w-4" />
305
+ </div>
306
+ <div className="flex-1 text-left">
307
+ <p className="truncate text-sm font-medium">{user?.email || 'User'}</p>
308
+ </div>
309
+ <MoreVertical className="h-4 w-4" />
310
+ </button>
311
+ </PopoverTrigger>
312
+ <PopoverContent align="end" className="w-56">
313
+ <div className="space-y-1">
314
+ <button
315
+ onClick={() => {
316
+ logout()
317
+ }}
318
+ className="flex w-full items-center rounded-md px-2 py-2 text-sm font-medium text-destructive hover:bg-destructive/10"
319
+ >
320
+ <LogOut className="mr-2 h-4 w-4" />
321
+ Sign out
322
+ </button>
323
+ </div>
324
+ </PopoverContent>
325
+ </Popover>
326
+ </div>
327
+ </nav>
328
+ )
329
+ }
@@ -0,0 +1,77 @@
1
+ import React from 'react'
2
+ import { Button } from '../ui/button'
3
+ import * as Icons from 'lucide-react'
4
+
5
+ interface DataDetailHeaderProps {
6
+ entity: string
7
+ icon: string
8
+ title: string
9
+ isEditing: boolean
10
+ isCreating: boolean
11
+ onEdit: () => void
12
+ onSave: () => void
13
+ onCancel: () => void
14
+ onDelete?: () => void
15
+ saving?: boolean
16
+ deleting?: boolean
17
+ }
18
+
19
+ export function DataDetailHeader({
20
+ entity,
21
+ icon,
22
+ title,
23
+ isEditing,
24
+ isCreating,
25
+ onEdit,
26
+ onSave,
27
+ onCancel,
28
+ onDelete,
29
+ saving,
30
+ deleting
31
+ }: DataDetailHeaderProps) {
32
+ const IconComponent = (Icons as Record<string, React.ComponentType<{ className?: string }>>)[icon] || Icons.Box
33
+
34
+ return (
35
+ <div className="flex justify-between items-start">
36
+ <div className="flex items-center gap-3">
37
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10">
38
+ <IconComponent className="h-6 w-6 text-primary" />
39
+ </div>
40
+ <div>
41
+ <h1 className="text-xl font-semibold text-foreground">
42
+ {title}
43
+ </h1>
44
+ <p className="mt-0.5 text-sm text-muted-foreground capitalize">
45
+ {isCreating ? `Create new ${entity.slice(0, -1)}` : entity}
46
+ </p>
47
+ </div>
48
+ </div>
49
+
50
+ <div className="flex items-center gap-2">
51
+ {isEditing ? (
52
+ <>
53
+ <Button variant="secondary" onClick={onCancel}>
54
+ Cancel
55
+ </Button>
56
+ <Button onClick={onSave} disabled={saving}>
57
+ {saving ? 'Saving...' : isCreating ? 'Create' : 'Save'}
58
+ </Button>
59
+ </>
60
+ ) : (
61
+ <>
62
+ <Button variant="secondary" onClick={onEdit}>
63
+ <Icons.Pencil className="h-4 w-4 mr-1" />
64
+ Edit
65
+ </Button>
66
+ {onDelete && (
67
+ <Button variant="destructive" onClick={onDelete} disabled={deleting}>
68
+ <Icons.Trash2 className="h-4 w-4 mr-1" />
69
+ Delete
70
+ </Button>
71
+ )}
72
+ </>
73
+ )}
74
+ </div>
75
+ </div>
76
+ )
77
+ }