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,187 @@
1
+ /**
2
+ * @module src/pages/admin/IntegrationDetailPage
3
+ */
4
+ import { useState, useEffect } from 'react'
5
+ import { useParams, useNavigate } from 'react-router-dom'
6
+ import { apiFetch } from '../../lib/api'
7
+ import { Button } from '../../components/ui/button'
8
+ import { Input } from '../../components/ui/input'
9
+ import { Textarea } from '../../components/ui/textarea'
10
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../components/ui/select'
11
+ import { Checkbox } from '../../components/ui/checkbox'
12
+ import { Label } from '../../components/ui/label'
13
+ import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/card'
14
+ import { Skeleton } from '../../components/ui/skeleton'
15
+ import { Alert, AlertDescription, AlertTitle } from '../../components/ui/alert'
16
+ import { Modal } from '../../components/ui/Modal'
17
+ import { Badge } from '../../components/ui/badge'
18
+ import { ArrowLeft, Pencil, Trash2, CheckCircle, XCircle, AlertTriangle, AlertCircle } from 'lucide-react'
19
+ import { formatDateTime } from '../../lib/utils'
20
+
21
+ interface Integration {
22
+ id: string
23
+ name: string
24
+ provider: string
25
+ integration_type: 'webhook' | 'api' | 'database' | 'file' | 'custom'
26
+ description?: string
27
+ config: Record<string, any>
28
+ is_active: boolean
29
+ is_system?: boolean
30
+ created_at: string
31
+ updated_at: string
32
+ account_id: string
33
+ last_sync?: string
34
+ sync_status?: 'success' | 'failed' | 'pending'
35
+ error_message?: string
36
+ }
37
+
38
+ const INTEGRATION_TYPES = [
39
+ { value: 'webhook', label: 'Webhook' },
40
+ { value: 'api', label: 'API' },
41
+ { value: 'database', label: 'Database' },
42
+ { value: 'file', label: 'File' },
43
+ { value: 'custom', label: 'Custom' }
44
+ ]
45
+
46
+ export function IntegrationDetailPage() {
47
+ const { id } = useParams<{ id: string }>()
48
+ const navigate = useNavigate()
49
+ const isCreateMode = !id || id === 'new'
50
+ const [integration, setIntegration] = useState<Integration | null>(null)
51
+ const [loading, setLoading] = useState(true)
52
+ const [error, setError] = useState<string | null>(null)
53
+ const [isEditing, setIsEditing] = useState(isCreateMode)
54
+ const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false)
55
+ const [formData, setFormData] = useState({
56
+ name: '', provider: '', integration_type: 'api' as const, description: '', config: '{}', is_active: true
57
+ })
58
+
59
+ useEffect(() => {
60
+ if (isCreateMode) {
61
+ setLoading(false)
62
+ return
63
+ }
64
+ setLoading(true)
65
+ const fetchIntegration = async () => {
66
+ try {
67
+ 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
68
+ if (!uuidRegex.test(id!)) throw new Error('Invalid ID format')
69
+ const response = await apiFetch(`/api/integrations?action=get&id=${id}`)
70
+ if (!response.ok) throw new Error(response.status === 500 ? 'Integration not found' : 'Failed to fetch integration')
71
+ const result = await response.json()
72
+ const data = result.data
73
+ setIntegration(data)
74
+ setFormData({
75
+ name: data.name, provider: data.provider, integration_type: data.integration_type,
76
+ description: data.description || '', config: JSON.stringify(data.config, null, 2), is_active: data.is_active
77
+ })
78
+ } catch (err) {
79
+ setError(err instanceof Error ? err.message : 'Failed to load integration')
80
+ } finally {
81
+ setLoading(false)
82
+ }
83
+ }
84
+ fetchIntegration()
85
+ }, [id, isCreateMode])
86
+
87
+ const handleSave = async () => {
88
+ try {
89
+ let parsedConfig = {}
90
+ try { parsedConfig = JSON.parse(formData.config) } catch { throw new Error('Invalid JSON in config') }
91
+ const url = isCreateMode ? '/api/integrations?action=create' : `/api/integrations?action=update&id=${id}`
92
+ const method = isCreateMode ? 'POST' : 'PATCH'
93
+ const response = await apiFetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...formData, config: parsedConfig }) })
94
+ if (!response.ok) throw new Error('Failed to save integration')
95
+ if (isCreateMode) {
96
+ const result = await response.json()
97
+ navigate(`/spine-framework/admin/configs/integrations/${result.data?.id || result.id}`)
98
+ } else {
99
+ setIsEditing(false)
100
+ const result = await response.json()
101
+ setIntegration(result.data)
102
+ }
103
+ } catch (err) {
104
+ setError(err instanceof Error ? err.message : 'Failed to save')
105
+ }
106
+ }
107
+
108
+ const handleDelete = async () => {
109
+ try {
110
+ const response = await apiFetch(`/api/integrations?action=delete&id=${id}`, { method: 'DELETE' })
111
+ if (!response.ok) throw new Error('Failed to delete')
112
+ navigate('/spine-framework/admin/configs/integrations')
113
+ } catch (err) {
114
+ setError(err instanceof Error ? err.message : 'Failed to delete')
115
+ }
116
+ }
117
+
118
+ if (loading) return (
119
+ <div className="space-y-6">
120
+ <Skeleton className="h-8 w-48" />
121
+ <Card><CardHeader><Skeleton className="h-6 w-32" /></CardHeader><CardContent className="space-y-4"><Skeleton className="h-4 w-full" /><Skeleton className="h-4 w-2/3" /></CardContent></Card>
122
+ </div>
123
+ )
124
+
125
+ if (error && !isCreateMode) return (
126
+ <Alert variant="destructive"><AlertCircle className="h-4 w-4" /><AlertTitle>Error</AlertTitle><AlertDescription>{error}</AlertDescription></Alert>
127
+ )
128
+
129
+ const getStatusIcon = (status?: string) => {
130
+ switch (status) {
131
+ case 'success': return <CheckCircle className="h-4 w-4 text-green-500" />
132
+ case 'failed': return <XCircle className="h-4 w-4 text-red-500" />
133
+ case 'pending': return <AlertTriangle className="h-4 w-4 text-yellow-500" />
134
+ default: return null
135
+ }
136
+ }
137
+
138
+ return (
139
+ <div className="space-y-6">
140
+ <div className="flex items-center justify-between">
141
+ <div className="flex items-center gap-4">
142
+ <Button variant="ghost" onClick={() => isCreateMode ? navigate('/spine-framework/admin/configs/integrations') : navigate(-1)}><ArrowLeft className="h-5 w-5" /></Button>
143
+ <h1 className="text-2xl font-bold">{isCreateMode ? 'Create Integration' : integration?.name}</h1>
144
+ </div>
145
+ {!isCreateMode && !isEditing && (
146
+ <div className="flex gap-2">
147
+ <Button variant="outline" onClick={() => setIsEditing(true)}><Pencil className="h-4 w-4 mr-2" />Edit</Button>
148
+ {!integration?.is_system && <Button variant="destructive" onClick={() => setIsDeleteModalOpen(true)}><Trash2 className="h-4 w-4 mr-2" />Delete</Button>}
149
+ </div>
150
+ )}
151
+ {isEditing && (
152
+ <div className="flex gap-2">
153
+ <Button variant="outline" onClick={() => isCreateMode ? navigate(-1) : setIsEditing(false)}>Cancel</Button>
154
+ <Button onClick={handleSave}>{isCreateMode ? 'Create' : 'Save'}</Button>
155
+ </div>
156
+ )}
157
+ </div>
158
+
159
+ <Card><CardContent className="p-6">
160
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
161
+ <div className="space-y-4">
162
+ <h3 className="text-sm font-medium text-muted-foreground">Basic Info</h3>
163
+ <div className="space-y-2"><Label>Name</Label>{isEditing ? <Input value={formData.name} onChange={e => setFormData({...formData, name: e.target.value})} /> : <div className="text-sm">{integration?.name}</div>}</div>
164
+ <div className="space-y-2"><Label>Provider</Label>{isEditing ? <Input value={formData.provider} onChange={e => setFormData({...formData, provider: e.target.value})} /> : <div className="text-sm">{integration?.provider}</div>}</div>
165
+ <div className="space-y-2"><Label>Type</Label>{isEditing ? <Select value={formData.integration_type} onValueChange={v => setFormData({...formData, integration_type: v as any})}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent>{INTEGRATION_TYPES.map(t => <SelectItem key={t.value} value={t.value}>{t.label}</SelectItem>)}</SelectContent></Select> : <Badge>{integration?.integration_type}</Badge>}</div>
166
+ <div className="space-y-2"><Label>Active</Label>{isEditing ? <div className="flex items-center gap-2"><Checkbox id="active" checked={formData.is_active} onCheckedChange={c => setFormData({...formData, is_active: c === true})} /><Label htmlFor="active">Enabled</Label></div> : <div className="text-sm">{integration?.is_active ? 'Yes' : 'No'}</div>}</div>
167
+ </div>
168
+ <div className="space-y-4">
169
+ <h3 className="text-sm font-medium text-muted-foreground">Sync Status</h3>
170
+ {!isCreateMode && (
171
+ <>
172
+ <div className="flex justify-between items-center"><span className="text-sm text-muted-foreground">Status</span><div className="flex items-center gap-2">{getStatusIcon(integration?.sync_status)}<span className="text-sm capitalize">{integration?.sync_status || '—'}</span></div></div>
173
+ <div className="flex justify-between items-center"><span className="text-sm text-muted-foreground">Last Sync</span><span className="text-sm">{integration?.last_sync ? formatDateTime(integration.last_sync) : '—'}</span></div>
174
+ </>
175
+ )}
176
+ <div className="space-y-2"><Label>Description</Label>{isEditing ? <Textarea value={formData.description} onChange={e => setFormData({...formData, description: e.target.value})} rows={3} /> : <div className="text-sm">{integration?.description || '—'}</div>}</div>
177
+ </div>
178
+ </div>
179
+ <div className="mt-6 space-y-2"><Label>Configuration (JSON)</Label>{isEditing ? <Textarea value={formData.config} onChange={e => setFormData({...formData, config: e.target.value})} rows={8} className="font-mono text-sm" /> : <pre className="text-sm bg-muted p-3 rounded overflow-auto">{JSON.stringify(integration?.config || {}, null, 2)}</pre>}</div>
180
+ </CardContent></Card>
181
+
182
+ <Modal isOpen={isDeleteModalOpen} onClose={() => setIsDeleteModalOpen(false)} title="Delete Integration" description="Are you sure you want to delete this integration?" size="sm">
183
+ <div className="flex justify-end gap-3"><Button variant="outline" onClick={() => setIsDeleteModalOpen(false)}>Cancel</Button><Button variant="destructive" onClick={handleDelete}>Delete</Button></div>
184
+ </Modal>
185
+ </div>
186
+ )
187
+ }
@@ -0,0 +1,301 @@
1
+ /**
2
+ * @module src/pages/admin/IntegrationsPage
3
+ * @audience installer
4
+ * @layer frontend-page
5
+ * @stability stable
6
+ *
7
+ * Admin list page for third-party integrations (integration instances).
8
+ * Fetches all integration instances via `/api/integrations?action=list`,
9
+ * applies client-side search, status filter, and sort. Renders inside
10
+ * `AdminListPage`. Row clicks navigate to
11
+ * `/spine-framework/admin/configs/integrations/:id`.
12
+ *
13
+ * @seeAlso src/pages/admin/IntegrationDetailPage.tsx
14
+ */
15
+
16
+ import { useState } from 'react'
17
+ import { Link, CheckCircle, AlertTriangle, Settings, Cog } from 'lucide-react';
18
+ import { formatDateTime } from '../../lib/utils'
19
+ import { apiFetch } from '../../lib/api'
20
+ import { AdminListPage } from '../../components/admin/AdminListPage'
21
+ import { SortableTableHeader } from '../../components/admin/SortableTableHeader'
22
+ import { useApi } from '../../hooks/useApi'
23
+
24
+ interface Integration {
25
+ id: string
26
+ name: string
27
+ description: string
28
+ integration_type: string
29
+ provider: string
30
+ version?: string
31
+ is_active: boolean
32
+ is_configured: boolean
33
+ last_sync_at?: string
34
+ sync_status?: string
35
+ sync_error?: string
36
+ created_at: string
37
+ updated_at: string
38
+ app?: {
39
+ id: string
40
+ slug: string
41
+ name: string
42
+ }
43
+ created_by_person?: {
44
+ id: string
45
+ full_name: string
46
+ email: string
47
+ }
48
+ }
49
+
50
+ export function IntegrationsPage() {
51
+ const [searchTerm, setSearchTerm] = useState('')
52
+ const [selectedStatus, setSelectedStatus] = useState('all')
53
+ const [selectedType, setSelectedType] = useState('all')
54
+ const [sortKey, setSortKey] = useState('name')
55
+ const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc')
56
+
57
+ // Fetch integrations from API
58
+ const { data: integrations, loading, error } = useApi<Integration[]>(
59
+ async ({ signal }: { signal?: AbortSignal }) => {
60
+ const response = await apiFetch('/api/integrations?action=list', { signal })
61
+ if (!response.ok) throw new Error('Failed to fetch integrations')
62
+ const result = await response.json()
63
+ return result.data || []
64
+ },
65
+ { immediate: true }
66
+ )
67
+
68
+ const filteredIntegrations = (integrations || []).filter(integration => {
69
+ const matchesSearch = integration.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
70
+ integration.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
71
+ integration.provider.toLowerCase().includes(searchTerm.toLowerCase())
72
+ const matchesStatus = selectedStatus === 'all' ||
73
+ (selectedStatus === 'active' && integration.is_active) ||
74
+ (selectedStatus === 'inactive' && !integration.is_active)
75
+ const matchesType = selectedType === 'all' || integration.integration_type === selectedType
76
+ return matchesSearch && matchesStatus && matchesType
77
+ })
78
+
79
+ const types = Array.from(new Set((integrations || []).map(i => i.integration_type)))
80
+
81
+ // Helper functions
82
+ const getStatusBadge = (integration: Integration) => {
83
+ if (!integration.is_active) {
84
+ return <span className="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-slate-100 text-slate-800">Inactive</span>
85
+ }
86
+ if (integration.sync_status === 'error') {
87
+ return <span className="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-red-100 text-red-800">Error</span>
88
+ }
89
+ if (integration.is_configured) {
90
+ return <span className="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">Configured</span>
91
+ }
92
+ return <span className="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-yellow-100 text-yellow-800">Pending</span>
93
+ }
94
+
95
+ const handleSort = (key: string) => {
96
+ if (sortKey === key) {
97
+ setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc')
98
+ } else {
99
+ setSortKey(key)
100
+ setSortDirection('asc')
101
+ }
102
+ }
103
+
104
+ const handleRowClick = (integration: Integration) => {
105
+ window.location.href = `/spine-framework/admin/configs/integrations/${integration.id}`
106
+ }
107
+
108
+ // Sort integrations
109
+ const sortedIntegrations = [...(filteredIntegrations || [])].sort((a, b) => {
110
+ let aValue: any = a[sortKey as keyof Integration]
111
+ let bValue: any = b[sortKey as keyof Integration]
112
+
113
+ if (typeof aValue === 'string') {
114
+ return sortDirection === 'asc'
115
+ ? aValue.localeCompare(bValue)
116
+ : bValue.localeCompare(aValue)
117
+ }
118
+
119
+ if (typeof aValue === 'boolean') {
120
+ return sortDirection === 'asc' ? (aValue ? 1 : 0) : (bValue ? 1 : 0)
121
+ }
122
+
123
+ return 0
124
+ })
125
+
126
+ const statsCards = [
127
+ {
128
+ title: 'Total Integrations',
129
+ value: (integrations || []).length,
130
+ icon: Link,
131
+ iconColor: 'text-blue-500'
132
+ },
133
+ {
134
+ title: 'Active',
135
+ value: (integrations || []).filter(i => i.is_active).length,
136
+ icon: CheckCircle,
137
+ iconColor: 'text-green-500'
138
+ },
139
+ {
140
+ title: 'Configured',
141
+ value: (integrations || []).filter(i => i.is_configured).length,
142
+ icon: Cog,
143
+ iconColor: 'text-purple-500'
144
+ },
145
+ {
146
+ title: 'Errors',
147
+ value: (integrations || []).filter(i => i.sync_status === 'error').length,
148
+ icon: AlertTriangle,
149
+ iconColor: 'text-red-500'
150
+ }
151
+ ]
152
+
153
+ const statusOptions = [
154
+ { value: 'all', label: 'All Status' },
155
+ { value: 'active', label: 'Active' },
156
+ { value: 'inactive', label: 'Inactive' }
157
+ ]
158
+
159
+ const typeOptions = [
160
+ { value: 'all', label: 'All Types' },
161
+ ...types.map(type => ({ value: type, label: type }))
162
+ ]
163
+
164
+ const filters = [
165
+ {
166
+ label: 'Status',
167
+ value: selectedStatus,
168
+ options: statusOptions,
169
+ onChange: setSelectedStatus
170
+ },
171
+ {
172
+ label: 'Type',
173
+ value: selectedType,
174
+ options: typeOptions,
175
+ onChange: setSelectedType
176
+ }
177
+ ]
178
+
179
+ return (
180
+ <AdminListPage
181
+ title="Integrations"
182
+ description="Configure external service integrations and connections"
183
+ newButtonText="Add Integration"
184
+ newButtonHref="/spine-framework/admin/configs/integrations/new"
185
+ statsCards={statsCards}
186
+ searchPlaceholder="Search integrations..."
187
+ searchValue={searchTerm}
188
+ onSearchChange={setSearchTerm}
189
+ filters={filters}
190
+ loading={loading}
191
+ error={error}
192
+ emptyMessage="No integrations found"
193
+ emptyIcon={Link}
194
+ >
195
+ {sortedIntegrations.length === 0 ? (
196
+ <div className="p-8 text-center">
197
+ <Link className="mx-auto h-12 w-12 text-slate-400" />
198
+ <h3 className="mt-2 text-sm font-medium text-slate-900">No integrations found</h3>
199
+ <p className="mt-1 text-sm text-slate-500">
200
+ Try adjusting your search or filters
201
+ </p>
202
+ </div>
203
+ ) : (
204
+ <table className="min-w-full divide-y divide-slate-200">
205
+ <thead className="bg-slate-50">
206
+ <tr>
207
+ <SortableTableHeader
208
+ title="Integration"
209
+ sortKey="name"
210
+ currentSortKey={sortKey}
211
+ currentSortDirection={sortDirection}
212
+ onSort={handleSort}
213
+ />
214
+ <SortableTableHeader
215
+ title="Provider"
216
+ sortKey="provider"
217
+ currentSortKey={sortKey}
218
+ currentSortDirection={sortDirection}
219
+ onSort={handleSort}
220
+ />
221
+ <SortableTableHeader
222
+ title="Type"
223
+ sortKey="integration_type"
224
+ currentSortKey={sortKey}
225
+ currentSortDirection={sortDirection}
226
+ onSort={handleSort}
227
+ />
228
+ <SortableTableHeader
229
+ title="Status"
230
+ sortKey="is_active"
231
+ currentSortKey={sortKey}
232
+ currentSortDirection={sortDirection}
233
+ onSort={handleSort}
234
+ />
235
+ <SortableTableHeader
236
+ title="Last Sync"
237
+ sortKey="last_sync_at"
238
+ currentSortKey={sortKey}
239
+ currentSortDirection={sortDirection}
240
+ onSort={handleSort}
241
+ />
242
+ <SortableTableHeader
243
+ title="Created"
244
+ sortKey="created_at"
245
+ currentSortKey={sortKey}
246
+ currentSortDirection={sortDirection}
247
+ onSort={handleSort}
248
+ />
249
+ <th className="relative px-6 py-3">
250
+ <span className="sr-only">Actions</span>
251
+ </th>
252
+ </tr>
253
+ </thead>
254
+ <tbody className="bg-white divide-y divide-slate-200">
255
+ {sortedIntegrations.map((integration) => (
256
+ <tr
257
+ key={integration.id}
258
+ className="hover:bg-slate-50 cursor-pointer transition-colors"
259
+ onClick={() => handleRowClick(integration)}
260
+ >
261
+ <td className="px-6 py-4 whitespace-nowrap">
262
+ <div>
263
+ <div className="font-medium text-slate-900">
264
+ <span className="text-accent-blue hover:text-navy">
265
+ {integration.name}
266
+ </span>
267
+ </div>
268
+ <div className="text-sm text-slate-500">
269
+ {integration.description}
270
+ </div>
271
+ </div>
272
+ </td>
273
+ <td className="px-6 py-4 whitespace-nowrap">
274
+ <span className="text-sm text-slate-900 font-medium">{integration.provider}</span>
275
+ {integration.version && (
276
+ <span className="text-xs text-slate-500 ml-1">v{integration.version}</span>
277
+ )}
278
+ </td>
279
+ <td className="px-6 py-4 whitespace-nowrap">
280
+ <span className="text-sm text-slate-900">{integration.integration_type}</span>
281
+ </td>
282
+ <td className="px-6 py-4 whitespace-nowrap">
283
+ {getStatusBadge(integration)}
284
+ </td>
285
+ <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-500">
286
+ {integration.last_sync_at ? formatDateTime(integration.last_sync_at) : 'Never'}
287
+ </td>
288
+ <td className="px-6 py-4 whitespace-nowrap text-sm text-slate-500">
289
+ {formatDateTime(integration.created_at)}
290
+ </td>
291
+ <td className="px-6 py-4 whitespace-nowrap text-right">
292
+ <span className="text-slate-400">→</span>
293
+ </td>
294
+ </tr>
295
+ ))}
296
+ </tbody>
297
+ </table>
298
+ )}
299
+ </AdminListPage>
300
+ )
301
+ }