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,296 @@
1
+ /**
2
+ * @module src/components/ui/ItemCard
3
+ * @audience installer
4
+ * @layer frontend-component
5
+ * @stability stable
6
+ *
7
+ * Item display components for grid-based views.
8
+ *
9
+ * **`ItemCard`** — renders a single `Item` in either full (`compact=false`)
10
+ * or compact (`compact=true`) form. Derives its display values from
11
+ * `item.title`, `item.description`, and the first 3 entries of `item.data`.
12
+ * Optional action buttons (`onView`, `onEdit`, `onDelete`) are shown when
13
+ * `showActions=true`.
14
+ *
15
+ * **`ItemGrid`** — renders a responsive grid of `ItemCard` instances.
16
+ * Shows a spinner on `loading=true` and an empty state with a doc icon
17
+ * when `items` is empty.
18
+ *
19
+ * @seeAlso src/components/ui/ItemListView.tsx (combines with DataTable)
20
+ * @seeAlso src/types/types.ts (Item, ItemType)
21
+ * @seeAlso src/lib/utils.ts (formatDateTime, truncateText)
22
+ */
23
+
24
+ import React from 'react'
25
+ import { Item, ItemType } from '../../types/types'
26
+ import { Badge } from './badge'
27
+ import { Button } from './button'
28
+ import { Box, FileText, Calendar, User, MoreVertical } from 'lucide-react';
29
+ import { formatDateTime, truncateText } from '../../lib/utils'
30
+
31
+ /**
32
+ * Props for `ItemCard`.
33
+ *
34
+ * @prop item - `Item` with optional resolved `item_type` relation
35
+ * @prop onEdit - Edit action callback
36
+ * @prop onDelete - Delete action callback
37
+ * @prop onView - View action callback
38
+ * @prop showActions - Shows action buttons (default: `true`)
39
+ * @prop compact - Condensed single-line layout (default: `false`)
40
+ */
41
+ interface ItemCardProps {
42
+ item: Item & { item_type?: ItemType | string }
43
+ onEdit?: (item: Item) => void
44
+ onDelete?: (item: Item) => void
45
+ onView?: (item: Item) => void
46
+ showActions?: boolean
47
+ compact?: boolean
48
+ }
49
+
50
+ /**
51
+ * Item card with optional action buttons.
52
+ *
53
+ * @param props - `ItemCardProps`
54
+ * @returns White rounded card in full or compact layout
55
+ * @sideEffects none (delegates actions to `onEdit` / `onDelete` / `onView`)
56
+ */
57
+ export function ItemCard({
58
+ item,
59
+ onEdit,
60
+ onDelete,
61
+ onView,
62
+ showActions = true,
63
+ compact = false
64
+ }: ItemCardProps) {
65
+ const getPrimaryValue = () => item.title || 'Untitled Item'
66
+
67
+ const getSecondaryValue = () => {
68
+ if (item.description) return truncateText(item.description, 100)
69
+ return null
70
+ }
71
+
72
+ const getTypeIcon = () => {
73
+ return <Box className="h-5 w-5 text-blue-500" />
74
+ }
75
+
76
+ const getTypeName = () => {
77
+ if (!item.item_type) return item.item_type_slug || ''
78
+ if (typeof item.item_type === 'string') return item.item_type
79
+ return (item.item_type as ItemType).name || ''
80
+ }
81
+
82
+ const getTypeBadgeColor = () => {
83
+ if (!item.item_type || typeof item.item_type === 'string') return 'info'
84
+ return (item.item_type as ItemType).is_active ? 'success' : 'default'
85
+ }
86
+
87
+ if (compact) {
88
+ return (
89
+ <div className="bg-white border border-slate-200 rounded-lg p-4 hover:shadow-md transition-shadow">
90
+ <div className="flex items-start justify-between">
91
+ <div className="flex items-start space-x-3 flex-1">
92
+ <div className="flex-shrink-0">
93
+ {getTypeIcon()}
94
+ </div>
95
+ <div className="flex-1 min-w-0">
96
+ <div className="flex items-center space-x-2">
97
+ <h3 className="text-sm font-medium text-slate-900 truncate">
98
+ {getPrimaryValue()}
99
+ </h3>
100
+ <Badge variant={getTypeBadgeColor()}>
101
+ {getTypeName()}
102
+ </Badge>
103
+ </div>
104
+ {getSecondaryValue() && (
105
+ <p className="text-xs text-slate-500 mt-1">
106
+ {getSecondaryValue()}
107
+ </p>
108
+ )}
109
+ <div className="flex items-center space-x-4 mt-2 text-xs text-slate-500">
110
+ <span>Updated {formatDateTime(item.updated_at)}</span>
111
+ </div>
112
+ </div>
113
+ </div>
114
+
115
+ {showActions && (
116
+ <div className="flex items-center space-x-1">
117
+ {onView && (
118
+ <Button
119
+ variant="ghost"
120
+ size="sm"
121
+ onClick={() => onView(item)}
122
+ >
123
+ View
124
+ </Button>
125
+ )}
126
+ <Button
127
+ variant="ghost"
128
+ size="sm"
129
+ >
130
+ <MoreVertical className="h-4 w-4" />
131
+ </Button>
132
+ </div>
133
+ )}
134
+ </div>
135
+ </div>
136
+ )
137
+ }
138
+
139
+ return (
140
+ <div className="bg-white border border-slate-200 rounded-lg p-6 hover:shadow-md transition-shadow">
141
+ <div className="flex items-start justify-between">
142
+ <div className="flex items-start space-x-4 flex-1">
143
+ <div className="flex-shrink-0">
144
+ {getTypeIcon()}
145
+ </div>
146
+ <div className="flex-1 min-w-0">
147
+ <div className="flex items-center space-x-2 mb-2">
148
+ <h3 className="text-lg font-medium text-slate-900 truncate">
149
+ {getPrimaryValue()}
150
+ </h3>
151
+ <Badge variant={getTypeBadgeColor()}>
152
+ {getTypeName()}
153
+ </Badge>
154
+ </div>
155
+
156
+ {getSecondaryValue() && (
157
+ <p className="text-sm text-slate-600 mb-3">
158
+ {getSecondaryValue()}
159
+ </p>
160
+ )}
161
+
162
+ {/* Additional data fields */}
163
+ {Object.keys(item.data || {}).length > 0 && (
164
+ <div className="space-y-2 mb-4">
165
+ {Object.entries(item.data)
166
+ .filter(([, v]) => v !== undefined && v !== null && v !== '')
167
+ .slice(0, 3)
168
+ .map(([key, value]) => (
169
+ <div key={key} className="flex items-center space-x-2">
170
+ <span className="text-xs font-medium text-slate-500">{key}:</span>
171
+ <span className="text-xs text-slate-900">
172
+ {truncateText(typeof value === 'boolean' ? (value ? 'Yes' : 'No') : String(value), 50)}
173
+ </span>
174
+ </div>
175
+ ))}
176
+ </div>
177
+ )}
178
+
179
+ {/* Metadata */}
180
+ <div className="flex items-center justify-between text-xs text-slate-500">
181
+ <div className="flex items-center space-x-4">
182
+ <span className="flex items-center">
183
+ <Calendar className="h-3 w-3 mr-1" />
184
+ Created {formatDateTime(item.created_at)}
185
+ </span>
186
+ <span className="flex items-center">
187
+ <User className="h-3 w-3 mr-1" />
188
+ ID: {item.id.slice(0, 8)}...
189
+ </span>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ </div>
194
+
195
+ {showActions && (
196
+ <div className="flex items-center space-x-2 ml-4">
197
+ {onView && (
198
+ <Button
199
+ variant="outline"
200
+ size="sm"
201
+ onClick={() => onView(item)}
202
+ >
203
+ View
204
+ </Button>
205
+ )}
206
+ {onEdit && (
207
+ <Button
208
+ variant="outline"
209
+ size="sm"
210
+ onClick={() => onEdit(item)}
211
+ >
212
+ Edit
213
+ </Button>
214
+ )}
215
+ <Button
216
+ variant="ghost"
217
+ size="sm"
218
+ >
219
+ <MoreVertical className="h-4 w-4" />
220
+ </Button>
221
+ </div>
222
+ )}
223
+ </div>
224
+ </div>
225
+ )
226
+ }
227
+
228
+ /**
229
+ * Props for `ItemGrid`.
230
+ *
231
+ * @prop items - Typed item array with resolved `item_type`
232
+ * @prop loading - Shows spinner while true
233
+ * @prop compact - Passes compact mode to each `ItemCard`
234
+ * @prop emptyMessage - Text shown when `items` is empty
235
+ */
236
+ interface ItemGridProps {
237
+ items: (Item & { item_type: ItemType })[]
238
+ loading?: boolean
239
+ onEdit?: (item: Item) => void
240
+ onDelete?: (item: Item) => void
241
+ onView?: (item: Item) => void
242
+ compact?: boolean
243
+ emptyMessage?: string
244
+ }
245
+
246
+ /**
247
+ * Responsive card grid for items.
248
+ *
249
+ * @param props - `ItemGridProps`
250
+ * @returns Responsive grid, loading spinner, or empty state
251
+ * @sideEffects none (delegates actions to `onEdit` / `onDelete` / `onView`)
252
+ */
253
+ export function ItemGrid({
254
+ items,
255
+ loading = false,
256
+ onEdit,
257
+ onDelete,
258
+ onView,
259
+ compact = false,
260
+ emptyMessage = 'No items found'
261
+ }: ItemGridProps) {
262
+ if (loading) {
263
+ return (
264
+ <div className="flex justify-center py-8">
265
+ <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
266
+ </div>
267
+ )
268
+ }
269
+
270
+ if (items.length === 0) {
271
+ return (
272
+ <div className="text-center py-8">
273
+ <FileText className="mx-auto h-12 w-12 text-slate-400" />
274
+ <h3 className="mt-2 text-sm font-medium text-slate-900">{emptyMessage}</h3>
275
+ </div>
276
+ )
277
+ }
278
+
279
+ return (
280
+ <div className={compact
281
+ ? "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
282
+ : "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"
283
+ }>
284
+ {items.map((item) => (
285
+ <ItemCard
286
+ key={item.id}
287
+ item={item}
288
+ onEdit={onEdit}
289
+ onDelete={onDelete}
290
+ onView={onView}
291
+ compact={compact}
292
+ />
293
+ ))}
294
+ </div>
295
+ )
296
+ }
@@ -0,0 +1,308 @@
1
+ /**
2
+ * @module src/components/ui/ItemListView
3
+ * @audience installer
4
+ * @layer frontend-component
5
+ * @stability stable
6
+ *
7
+ * Switchable item view widget and page shell.
8
+ *
9
+ * **`ItemListView`** — renders items in either a compact `ItemGrid` or a
10
+ * full `DataTable` view, toggled by icon buttons. Derives unique type
11
+ * filter options from the items array and builds a fixed table column
12
+ * set. The primary display field is resolved from the first `text` or
13
+ * `textarea` field in the item type's `design_schema`.
14
+ *
15
+ * **`ItemListPage`** — wraps `ItemListView` with a page-level title and
16
+ * description header. Use as a standalone page component.
17
+ *
18
+ * @seeAlso src/components/ui/ItemCard.tsx
19
+ * @seeAlso src/components/ui/DataTable.tsx
20
+ * @seeAlso src/types/types.ts (Item, ItemType)
21
+ */
22
+
23
+ import React, { useState } from 'react'
24
+ import { Item, ItemType } from '../../types/types'
25
+ import { DataTable } from './DataTable'
26
+ import { ItemCard, ItemGrid } from './ItemCard'
27
+ import { Badge } from './badge'
28
+ import { Button } from './button'
29
+ import { Squares2X2Icon, List, Plus } from 'lucide-react';
30
+ import { formatDateTime } from '../../lib/utils'
31
+
32
+ /**
33
+ * Props for `ItemListView`.
34
+ *
35
+ * @prop items - Typed item array with resolved `item_type`
36
+ * @prop loading - Shows spinner while fetching
37
+ * @prop onEdit / onDelete / onView - Row/card action callbacks
38
+ * @prop onCreate - Create button callback
39
+ * @prop searchable - Enables search in table view (default: `true`)
40
+ * @prop filterable - Enables column filters in table view (default: `true`)
41
+ * @prop emptyMessage - Empty-state label
42
+ * @prop showCreateButton - Shows the create button (default: `true`)
43
+ * @prop createButtonText - Create button label (default: `'Create Item'`)
44
+ */
45
+ interface ItemListViewProps {
46
+ items: (Item & { item_type: ItemType })[]
47
+ loading?: boolean
48
+ onEdit?: (item: Item) => void
49
+ onDelete?: (item: Item) => void
50
+ onView?: (item: Item) => void
51
+ onCreate?: () => void
52
+ searchable?: boolean
53
+ filterable?: boolean
54
+ emptyMessage?: string
55
+ showCreateButton?: boolean
56
+ createButtonText?: string
57
+ }
58
+
59
+ /**
60
+ * Switchable grid/table item view.
61
+ *
62
+ * @param props - `ItemListViewProps`
63
+ * @returns Header with view-mode toggle + `ItemGrid` or `DataTable`
64
+ * @sideEffects none (delegates actions and creation to prop callbacks)
65
+ */
66
+ export function ItemListView({
67
+ items,
68
+ loading = false,
69
+ onEdit,
70
+ onDelete,
71
+ onView,
72
+ onCreate,
73
+ searchable = true,
74
+ filterable = true,
75
+ emptyMessage = 'No items found',
76
+ showCreateButton = true,
77
+ createButtonText = 'Create Item'
78
+ }: ItemListViewProps) {
79
+ const [viewMode, setViewMode] = useState<'grid' | 'table'>('grid')
80
+
81
+ // Get unique types for filtering
82
+ const typesMap = new Map<string, ItemType>()
83
+ items.forEach(item => {
84
+ typesMap.set(item.item_type.id, item.item_type)
85
+ })
86
+ const types = Array.from(typesMap.values()).map(type => ({
87
+ value: type.id,
88
+ label: type.name
89
+ }))
90
+
91
+ // Table columns
92
+ const tableColumns = [
93
+ {
94
+ key: 'data' as const,
95
+ title: 'Item',
96
+ sortable: true,
97
+ render: (value: Record<string, any>, item: Item & { item_type: ItemType }) => {
98
+ const primaryField = item.item_type.design_schema?.fields ? Object.entries(item.item_type.design_schema.fields).find(([_, f]: [string, any]) =>
99
+ f.data_type === 'text' || f.data_type === 'textarea'
100
+ ) : null
101
+ const fieldEntry = primaryField ? primaryField : null
102
+ const fieldName = fieldEntry ? fieldEntry[0] : 'name'
103
+ const displayValue = value[fieldName] || 'Untitled Item'
104
+
105
+ return (
106
+ <div>
107
+ <div className="font-medium text-slate-900">{displayValue}</div>
108
+ <div className="text-sm text-slate-500">
109
+ <Badge variant={item.item_type.is_active ? 'success' : 'default'}>
110
+ {item.item_type.name}
111
+ </Badge>
112
+ </div>
113
+ </div>
114
+ )
115
+ }
116
+ },
117
+ {
118
+ key: 'item_type' as const,
119
+ title: 'Type',
120
+ filterable: true,
121
+ filterOptions: types,
122
+ render: (value: ItemType) => (
123
+ <Badge variant={value.is_active ? 'success' : 'default'}>
124
+ {value.name}
125
+ </Badge>
126
+ )
127
+ },
128
+ {
129
+ key: 'created_at' as const,
130
+ title: 'Created',
131
+ sortable: true,
132
+ render: (value: string) => formatDateTime(value)
133
+ },
134
+ {
135
+ key: 'updated_at' as const,
136
+ title: 'Updated',
137
+ sortable: true,
138
+ render: (value: string) => formatDateTime(value)
139
+ },
140
+ {
141
+ key: 'id' as const,
142
+ title: 'Actions',
143
+ render: (_: any, item: Item & { item_type: ItemType }) => (
144
+ <div className="flex items-center space-x-2">
145
+ {onView && (
146
+ <Button
147
+ variant="outline"
148
+ size="sm"
149
+ onClick={() => onView(item)}
150
+ >
151
+ View
152
+ </Button>
153
+ )}
154
+ {onEdit && (
155
+ <Button
156
+ variant="outline"
157
+ size="sm"
158
+ onClick={() => onEdit(item)}
159
+ >
160
+ Edit
161
+ </Button>
162
+ )}
163
+ </div>
164
+ )
165
+ }
166
+ ]
167
+
168
+ return (
169
+ <div className="space-y-4">
170
+ {/* Header */}
171
+ <div className="flex items-center justify-between">
172
+ <div className="flex items-center space-x-4">
173
+ <h2 className="text-lg font-medium text-slate-900">
174
+ Items ({items.length})
175
+ </h2>
176
+
177
+ {/* View Mode Toggle */}
178
+ <div className="flex items-center bg-slate-100 rounded-lg p-1">
179
+ <button
180
+ onClick={() => setViewMode('grid')}
181
+ className={`
182
+ px-3 py-1.5 rounded-md text-sm font-medium transition-colors
183
+ ${viewMode === 'grid'
184
+ ? 'bg-white text-slate-900 shadow-sm'
185
+ : 'text-slate-600 hover:text-slate-900'
186
+ }
187
+ `}
188
+ >
189
+ <Squares2X2Icon className="h-4 w-4" />
190
+ </button>
191
+ <button
192
+ onClick={() => setViewMode('table')}
193
+ className={`
194
+ px-3 py-1.5 rounded-md text-sm font-medium transition-colors
195
+ ${viewMode === 'table'
196
+ ? 'bg-white text-slate-900 shadow-sm'
197
+ : 'text-slate-600 hover:text-slate-900'
198
+ }
199
+ `}
200
+ >
201
+ <List className="h-4 w-4" />
202
+ </button>
203
+ </div>
204
+ </div>
205
+
206
+ {showCreateButton && onCreate && (
207
+ <Button onClick={onCreate}>
208
+ <Plus className="h-4 w-4 mr-2" />
209
+ {createButtonText}
210
+ </Button>
211
+ )}
212
+ </div>
213
+
214
+ {/* Content */}
215
+ {viewMode === 'grid' ? (
216
+ <ItemGrid
217
+ items={items}
218
+ loading={loading}
219
+ onEdit={onEdit}
220
+ onDelete={onDelete}
221
+ onView={onView}
222
+ compact={true}
223
+ emptyMessage={emptyMessage}
224
+ />
225
+ ) : (
226
+ <DataTable
227
+ data={items}
228
+ columns={tableColumns as any}
229
+ loading={loading}
230
+ searchable={searchable}
231
+ filterable={filterable}
232
+ emptyMessage={emptyMessage}
233
+ />
234
+ )}
235
+ </div>
236
+ )
237
+ }
238
+
239
+ /**
240
+ * Props for `ItemListPage`.
241
+ *
242
+ * @prop title - Page heading (default: `'Items'`)
243
+ * @prop description - Page subtitle (default: `'Manage and organize your items'`)
244
+ * (other props same as `ItemListViewProps`)
245
+ */
246
+ interface ItemListPageProps {
247
+ items: (Item & { item_type: ItemType })[]
248
+ loading?: boolean
249
+ onEdit?: (item: Item) => void
250
+ onDelete?: (item: Item) => void
251
+ onView?: (item: Item) => void
252
+ onCreate?: () => void
253
+ searchable?: boolean
254
+ filterable?: boolean
255
+ emptyMessage?: string
256
+ showCreateButton?: boolean
257
+ createButtonText?: string
258
+ title?: string
259
+ description?: string
260
+ }
261
+
262
+ /**
263
+ * Full item list page with title header and switchable view.
264
+ *
265
+ * @param props - `ItemListPageProps`
266
+ * @returns Page header + `ItemListView`
267
+ * @sideEffects none (pure rendering)
268
+ */
269
+ export function ItemListPage({
270
+ items,
271
+ loading = false,
272
+ onEdit,
273
+ onDelete,
274
+ onView,
275
+ onCreate,
276
+ searchable = true,
277
+ filterable = true,
278
+ emptyMessage = 'No items found',
279
+ showCreateButton = true,
280
+ createButtonText = 'Create Item',
281
+ title = 'Items',
282
+ description = 'Manage and organize your items'
283
+ }: ItemListPageProps) {
284
+ return (
285
+ <div className="space-y-6">
286
+ {/* Page Header */}
287
+ <div>
288
+ <h1 className="text-2xl font-bold text-slate-900">{title}</h1>
289
+ <p className="mt-1 text-sm text-slate-600">{description}</p>
290
+ </div>
291
+
292
+ {/* Item List View */}
293
+ <ItemListView
294
+ items={items}
295
+ loading={loading}
296
+ onEdit={onEdit}
297
+ onDelete={onDelete}
298
+ onView={onView}
299
+ onCreate={onCreate}
300
+ searchable={searchable}
301
+ filterable={filterable}
302
+ emptyMessage={emptyMessage}
303
+ showCreateButton={showCreateButton}
304
+ createButtonText={createButtonText}
305
+ />
306
+ </div>
307
+ )
308
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @module src/components/ui/LoadingSpinner
3
+ * @audience installer
4
+ * @layer frontend-component
5
+ * @stability stable
6
+ *
7
+ * Animated CSS spinner used to indicate loading state inline or as a
8
+ * centred overlay. Uses `border-t-blue-600` as the active segment colour
9
+ * and `border-slate-200` for the track.
10
+ *
11
+ * @seeAlso src/lib/utils.ts (cn)
12
+ */
13
+
14
+ import React from 'react'
15
+ import { Loader2 } from 'lucide-react'
16
+ import { cn } from '../../lib/utils'
17
+
18
+ /**
19
+ * Props for `LoadingSpinner`.
20
+ *
21
+ * @prop size - Diameter: `'sm'` (16px), `'md'` (24px), `'lg'` (32px)
22
+ * @prop className - Additional Tailwind classes
23
+ */
24
+ interface LoadingSpinnerProps {
25
+ className?: string
26
+ size?: 'sm' | 'md' | 'lg'
27
+ }
28
+
29
+ /**
30
+ * Inline animated spinner.
31
+ *
32
+ * @param props - `LoadingSpinnerProps`
33
+ * @returns `<Loader2>` styled as a spinning ring
34
+ * @sideEffects none (pure rendering)
35
+ */
36
+ export function LoadingSpinner({ className, size = 'md' }: LoadingSpinnerProps) {
37
+ const sizeClasses = {
38
+ sm: 'h-4 w-4',
39
+ md: 'h-6 w-6',
40
+ lg: 'h-8 w-8',
41
+ }
42
+
43
+ return (
44
+ <Loader2
45
+ className={cn(
46
+ 'animate-spin',
47
+ sizeClasses[size],
48
+ className
49
+ )}
50
+ />
51
+ )
52
+ }