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.
- package/.framework/README.md +129 -0
- package/.framework/cli/bin.cjs +14 -0
- package/.framework/cli/commands/agents.ts +153 -0
- package/.framework/cli/commands/auth.ts +94 -0
- package/.framework/cli/commands/create-app.ts +185 -0
- package/.framework/cli/commands/dev.ts +295 -0
- package/.framework/cli/commands/doctor.ts +442 -0
- package/.framework/cli/commands/generate.ts +332 -0
- package/.framework/cli/commands/init.ts +272 -0
- package/.framework/cli/commands/install-app.ts +391 -0
- package/.framework/cli/commands/items.ts +253 -0
- package/.framework/cli/commands/migrations.ts +141 -0
- package/.framework/cli/commands/pipelines.ts +166 -0
- package/.framework/cli/commands/status.ts +197 -0
- package/.framework/cli/commands/system.ts +184 -0
- package/.framework/cli/commands/test.ts +227 -0
- package/.framework/cli/commands/uninstall-app.ts +166 -0
- package/.framework/cli/context.ts +268 -0
- package/.framework/cli/env-loader.ts +36 -0
- package/.framework/cli/index.ts +106 -0
- package/.framework/cli/welcome.cjs +45 -0
- package/.framework/docs/API.md +384 -0
- package/.framework/docs/STABILITY.md +52 -0
- package/.framework/docs/admin-routes.md +76 -0
- package/.framework/docs/api-docs-progress.md +38 -0
- package/.framework/docs/api-governance.md +146 -0
- package/.framework/docs/api-testing-results.md +212 -0
- package/.framework/docs/apis/admin-configs.md +567 -0
- package/.framework/docs/apis/admin-data.md +272 -0
- package/.framework/docs/apis/index.md +231 -0
- package/.framework/docs/apis/internal.md +295 -0
- package/.framework/docs/apis/runtime.md +537 -0
- package/.framework/docs/assembly-launch-guide.md +138 -0
- package/.framework/docs/audit-results.md +590 -0
- package/.framework/docs/authorization-model.md +170 -0
- package/.framework/docs/db-api-inventory.md +95 -0
- package/.framework/docs/examples/custom-app/README.md +77 -0
- package/.framework/docs/examples/custom-function/README.md +27 -0
- package/.framework/docs/examples/custom-function/handler.ts +48 -0
- package/.framework/docs/examples/custom-webhook/README.md +68 -0
- package/.framework/docs/gap-remediation-backlog.md +103 -0
- package/.framework/docs/guides/cli-guide.md +224 -0
- package/.framework/docs/guides/getting-started.md +103 -0
- package/.framework/docs/guides/import-guide.md +193 -0
- package/.framework/docs/guides/testing-guide.md +229 -0
- package/.framework/docs/permission-examples.md +326 -0
- package/.framework/docs/ui-adoption-verification.md +111 -0
- package/.framework/docs/ui-api-coverage.md +84 -0
- package/.framework/docs/v2-compatibility-audit.md +228 -0
- package/.framework/functions/.gitkeep +1 -0
- package/.framework/functions/_shared/agent-runner.ts +1097 -0
- package/.framework/functions/_shared/app-manifest.ts +184 -0
- package/.framework/functions/_shared/audit.ts +150 -0
- package/.framework/functions/_shared/db.ts +174 -0
- package/.framework/functions/_shared/index.ts +382 -0
- package/.framework/functions/_shared/middleware.ts +490 -0
- package/.framework/functions/_shared/permissions.ts +1325 -0
- package/.framework/functions/_shared/pipeline-runner.ts +731 -0
- package/.framework/functions/_shared/principal.ts +760 -0
- package/.framework/functions/_shared/schema-utils.ts +967 -0
- package/.framework/functions/_shared/testing.ts +258 -0
- package/.framework/functions/_shared/trigger-engine.ts +425 -0
- package/.framework/functions/_shared/webhook-registration.ts +168 -0
- package/.framework/functions/_shared/webhook-registry.ts +129 -0
- package/.framework/functions/account-nodes.ts +111 -0
- package/.framework/functions/admin-data.ts +606 -0
- package/.framework/functions/ai-agents.ts +323 -0
- package/.framework/functions/api-keys.ts +376 -0
- package/.framework/functions/apps.ts +483 -0
- package/.framework/functions/auth.ts +196 -0
- package/.framework/functions/debug-auth.ts +107 -0
- package/.framework/functions/embeddings.ts +556 -0
- package/.framework/functions/integration-routes.ts +523 -0
- package/.framework/functions/integrations.ts +319 -0
- package/.framework/functions/item-progress.ts +272 -0
- package/.framework/functions/logs.ts +438 -0
- package/.framework/functions/observability.ts +275 -0
- package/.framework/functions/pipeline-executions.ts +494 -0
- package/.framework/functions/pipelines.ts +485 -0
- package/.framework/functions/prompt-configs.ts +339 -0
- package/.framework/functions/roles.ts +387 -0
- package/.framework/functions/system-cron.ts +742 -0
- package/.framework/functions/system.ts +323 -0
- package/.framework/functions/tests.ts +119 -0
- package/.framework/functions/timers.ts +357 -0
- package/.framework/functions/triggers.ts +563 -0
- package/.framework/functions/types.ts +604 -0
- package/.framework/migrations/000_foundation.sql +1256 -0
- package/.framework/migrations/001_seed.sql +92 -0
- package/.framework/migrations/002_seed_constraints.sql +13 -0
- package/.framework/migrations/003_auth_user_trigger.sql +59 -0
- package/.framework/src/App.tsx +126 -0
- package/.framework/src/apps/admin/index.tsx +173 -0
- package/.framework/src/components/AppWrapper.tsx +56 -0
- package/.framework/src/components/CustomAppLoader.tsx +116 -0
- package/.framework/src/components/admin/AdminListPage.tsx +151 -0
- package/.framework/src/components/admin/AdminSidebar.tsx +166 -0
- package/.framework/src/components/admin/AdminStatsCard.tsx +62 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +42 -0
- package/.framework/src/components/app-shell/GenericAppShell.tsx +181 -0
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +200 -0
- package/.framework/src/components/app-shell/GenericListPage.tsx +116 -0
- package/.framework/src/components/app-sidebar.tsx +228 -0
- package/.framework/src/components/auth/ProtectedRoute.tsx +88 -0
- package/.framework/src/components/layout/AppShell.tsx +91 -0
- package/.framework/src/components/layout/Header.tsx +88 -0
- package/.framework/src/components/layout/Layout.tsx +95 -0
- package/.framework/src/components/layout/Sidebar.tsx +329 -0
- package/.framework/src/components/runtime/DataDetailHeader.tsx +77 -0
- package/.framework/src/components/runtime/DataDetailPage.tsx +171 -0
- package/.framework/src/components/runtime/DataFilters.tsx +91 -0
- package/.framework/src/components/runtime/DataHeader.tsx +68 -0
- package/.framework/src/components/runtime/DataListPage.tsx +124 -0
- package/.framework/src/components/runtime/DataStats.tsx +70 -0
- package/.framework/src/components/runtime/DataTable.tsx +174 -0
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +134 -0
- package/.framework/src/components/runtime/index.ts +18 -0
- package/.framework/src/components/search-form.tsx +29 -0
- package/.framework/src/components/shared/AgentView.tsx +213 -0
- package/.framework/src/components/shared/FieldRenderer.tsx +478 -0
- package/.framework/src/components/shared/SchemaFields.tsx +226 -0
- package/.framework/src/components/ui/DataTable.tsx +343 -0
- package/.framework/src/components/ui/Form.tsx +281 -0
- package/.framework/src/components/ui/ItemCard.tsx +296 -0
- package/.framework/src/components/ui/ItemListView.tsx +308 -0
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -0
- package/.framework/src/components/ui/Modal.tsx +61 -0
- package/.framework/src/components/ui/RichTextEditor.tsx +210 -0
- package/.framework/src/components/ui/accordion.tsx +82 -0
- package/.framework/src/components/ui/alert-dialog.tsx +197 -0
- package/.framework/src/components/ui/alert.tsx +76 -0
- package/.framework/src/components/ui/aspect-ratio.tsx +11 -0
- package/.framework/src/components/ui/avatar.tsx +110 -0
- package/.framework/src/components/ui/badge.tsx +49 -0
- package/.framework/src/components/ui/breadcrumb.tsx +122 -0
- package/.framework/src/components/ui/button-group.tsx +83 -0
- package/.framework/src/components/ui/button.tsx +65 -0
- package/.framework/src/components/ui/calendar.tsx +222 -0
- package/.framework/src/components/ui/card.tsx +100 -0
- package/.framework/src/components/ui/carousel.tsx +240 -0
- package/.framework/src/components/ui/chart.tsx +373 -0
- package/.framework/src/components/ui/checkbox.tsx +31 -0
- package/.framework/src/components/ui/collapsible.tsx +33 -0
- package/.framework/src/components/ui/combobox.tsx +299 -0
- package/.framework/src/components/ui/command.tsx +193 -0
- package/.framework/src/components/ui/context-menu.tsx +261 -0
- package/.framework/src/components/ui/dialog.tsx +165 -0
- package/.framework/src/components/ui/direction.tsx +22 -0
- package/.framework/src/components/ui/drawer.tsx +132 -0
- package/.framework/src/components/ui/dropdown-menu.tsx +269 -0
- package/.framework/src/components/ui/empty.tsx +104 -0
- package/.framework/src/components/ui/field.tsx +238 -0
- package/.framework/src/components/ui/hover-card.tsx +42 -0
- package/.framework/src/components/ui/input-group.tsx +153 -0
- package/.framework/src/components/ui/input-otp.tsx +87 -0
- package/.framework/src/components/ui/input.tsx +19 -0
- package/.framework/src/components/ui/item.tsx +196 -0
- package/.framework/src/components/ui/kbd.tsx +26 -0
- package/.framework/src/components/ui/label.tsx +22 -0
- package/.framework/src/components/ui/menubar.tsx +277 -0
- package/.framework/src/components/ui/native-select.tsx +61 -0
- package/.framework/src/components/ui/navigation-menu.tsx +164 -0
- package/.framework/src/components/ui/pagination.tsx +129 -0
- package/.framework/src/components/ui/popover.tsx +87 -0
- package/.framework/src/components/ui/progress.tsx +31 -0
- package/.framework/src/components/ui/radio-group.tsx +42 -0
- package/.framework/src/components/ui/resizable.tsx +50 -0
- package/.framework/src/components/ui/scroll-area.tsx +53 -0
- package/.framework/src/components/ui/select.tsx +195 -0
- package/.framework/src/components/ui/separator.tsx +26 -0
- package/.framework/src/components/ui/sheet.tsx +145 -0
- package/.framework/src/components/ui/sidebar.tsx +706 -0
- package/.framework/src/components/ui/skeleton.tsx +13 -0
- package/.framework/src/components/ui/slider.tsx +59 -0
- package/.framework/src/components/ui/sonner.tsx +47 -0
- package/.framework/src/components/ui/spinner.tsx +10 -0
- package/.framework/src/components/ui/switch.tsx +33 -0
- package/.framework/src/components/ui/table-primitives.tsx +141 -0
- package/.framework/src/components/ui/table.tsx +114 -0
- package/.framework/src/components/ui/tabs.tsx +90 -0
- package/.framework/src/components/ui/textarea.tsx +18 -0
- package/.framework/src/components/ui/toggle-group.tsx +89 -0
- package/.framework/src/components/ui/toggle.tsx +45 -0
- package/.framework/src/components/ui/tooltip.tsx +57 -0
- package/.framework/src/contexts/AppContext.tsx +133 -0
- package/.framework/src/contexts/AuthContext.tsx +371 -0
- package/.framework/src/hooks/use-mobile.ts +19 -0
- package/.framework/src/hooks/useApi.ts +526 -0
- package/.framework/src/hooks/useApps.ts +114 -0
- package/.framework/src/hooks/useEntityList.ts +190 -0
- package/.framework/src/hooks/useEntityRecord.ts +308 -0
- package/.framework/src/hooks/useForm.ts +307 -0
- package/.framework/src/hooks/useListSchema.ts +264 -0
- package/.framework/src/hooks/useSchemaRecord.ts +223 -0
- package/.framework/src/index.css +128 -0
- package/.framework/src/lib/api.ts +156 -0
- package/.framework/src/lib/supabase.ts +94 -0
- package/.framework/src/lib/utils.ts +317 -0
- package/.framework/src/main.tsx +27 -0
- package/.framework/src/pages/DashboardPage.tsx +181 -0
- package/.framework/src/pages/NotFoundPage.tsx +39 -0
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +161 -0
- package/.framework/src/pages/admin/AIAgentsPage.tsx +318 -0
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +199 -0
- package/.framework/src/pages/admin/APIKeysPage.tsx +303 -0
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +523 -0
- package/.framework/src/pages/admin/AppDetailPage.tsx +493 -0
- package/.framework/src/pages/admin/AppsPage.tsx +355 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +491 -0
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +534 -0
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +424 -0
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +176 -0
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +109 -0
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +402 -0
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +187 -0
- package/.framework/src/pages/admin/IntegrationsPage.tsx +301 -0
- package/.framework/src/pages/admin/LogsPage.tsx +283 -0
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +85 -0
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +470 -0
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +183 -0
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +279 -0
- package/.framework/src/pages/admin/PipelinesPage.tsx +390 -0
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +299 -0
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +292 -0
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +434 -0
- package/.framework/src/pages/admin/RoleDetailPage.tsx +273 -0
- package/.framework/src/pages/admin/RolesPage.tsx +292 -0
- package/.framework/src/pages/admin/SelectTestPage.tsx +61 -0
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +588 -0
- package/.framework/src/pages/admin/SimpleDashboard.tsx +387 -0
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +172 -0
- package/.framework/src/pages/admin/TestingDashboard.tsx +257 -0
- package/.framework/src/pages/admin/TimerDetailPage.tsx +151 -0
- package/.framework/src/pages/admin/TimersPage.tsx +376 -0
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +149 -0
- package/.framework/src/pages/admin/TriggersPage.tsx +381 -0
- package/.framework/src/pages/admin/TypeDetailPage.tsx +694 -0
- package/.framework/src/pages/admin/TypesPage.tsx +295 -0
- package/.framework/src/pages/auth/LoginPage.tsx +188 -0
- package/.framework/src/pages/auth/RegisterPage.tsx +163 -0
- package/.framework/src/pages/spine-framework/APIPage.tsx +17 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +25 -0
- package/.framework/src/types/auth.ts +125 -0
- package/.framework/src/types/types.ts +407 -0
- package/STRUCTURE.md +150 -0
- package/config/components.json +25 -0
- package/config/deno.lock +108 -0
- package/config/package-lock.json +17183 -0
- package/config/postcss.config.cjs +10 -0
- package/config/tailwind.config.cjs +78 -0
- package/config/tsconfig.build.json +32 -0
- package/config/tsconfig.cli.json +18 -0
- package/config/tsconfig.json +41 -0
- package/config/tsconfig.node.json +17 -0
- package/config/tsconfig.node.tsbuildinfo +1 -0
- package/config/tsconfig.tsbuildinfo +1 -0
- package/config/typedoc.json +16 -0
- package/config/vite.config.d.ts +2 -0
- package/config/vite.config.ts +72 -0
- package/dist/cli/commands/agents.d.ts +39 -0
- package/dist/cli/commands/agents.d.ts.map +1 -0
- package/dist/cli/commands/auth.d.ts +36 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/create-app.d.ts +23 -0
- package/dist/cli/commands/create-app.d.ts.map +1 -0
- package/dist/cli/commands/dev.d.ts +39 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/doctor.d.ts +42 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/generate.d.ts +36 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/init.d.ts +30 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/install-app.d.ts +30 -0
- package/dist/cli/commands/install-app.d.ts.map +1 -0
- package/dist/cli/commands/items.d.ts +45 -0
- package/dist/cli/commands/items.d.ts.map +1 -0
- package/dist/cli/commands/migrations.d.ts +41 -0
- package/dist/cli/commands/migrations.d.ts.map +1 -0
- package/dist/cli/commands/pipelines.d.ts +40 -0
- package/dist/cli/commands/pipelines.d.ts.map +1 -0
- package/dist/cli/commands/status.d.ts +23 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/system.d.ts +29 -0
- package/dist/cli/commands/system.d.ts.map +1 -0
- package/dist/cli/commands/test.d.ts +46 -0
- package/dist/cli/commands/test.d.ts.map +1 -0
- package/dist/cli/commands/uninstall-app.d.ts +23 -0
- package/dist/cli/commands/uninstall-app.d.ts.map +1 -0
- package/dist/cli/context.d.ts +88 -0
- package/dist/cli/context.d.ts.map +1 -0
- package/dist/cli/env-loader.d.ts +14 -0
- package/dist/cli/env-loader.d.ts.map +1 -0
- package/dist/cli/index.d.ts +41 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/functions/_shared/agent-runner.d.ts +156 -0
- package/dist/functions/_shared/agent-runner.d.ts.map +1 -0
- package/dist/functions/_shared/app-manifest.d.ts +68 -0
- package/dist/functions/_shared/app-manifest.d.ts.map +1 -0
- package/dist/functions/_shared/audit.d.ts +91 -0
- package/dist/functions/_shared/audit.d.ts.map +1 -0
- package/dist/functions/_shared/db.d.ts +125 -0
- package/dist/functions/_shared/db.d.ts.map +1 -0
- package/dist/functions/_shared/index.d.ts +298 -0
- package/dist/functions/_shared/index.d.ts.map +1 -0
- package/dist/functions/_shared/middleware.d.ts +315 -0
- package/dist/functions/_shared/middleware.d.ts.map +1 -0
- package/dist/functions/_shared/permissions.d.ts +626 -0
- package/dist/functions/_shared/permissions.d.ts.map +1 -0
- package/dist/functions/_shared/pipeline-runner.d.ts +124 -0
- package/dist/functions/_shared/pipeline-runner.d.ts.map +1 -0
- package/dist/functions/_shared/principal.d.ts +284 -0
- package/dist/functions/_shared/principal.d.ts.map +1 -0
- package/dist/functions/_shared/schema-utils.d.ts +181 -0
- package/dist/functions/_shared/schema-utils.d.ts.map +1 -0
- package/dist/functions/_shared/testing.d.ts +172 -0
- package/dist/functions/_shared/testing.d.ts.map +1 -0
- package/dist/functions/_shared/trigger-engine.d.ts +140 -0
- package/dist/functions/_shared/trigger-engine.d.ts.map +1 -0
- package/dist/functions/_shared/webhook-registration.d.ts +81 -0
- package/dist/functions/_shared/webhook-registration.d.ts.map +1 -0
- package/dist/functions/_shared/webhook-registry.d.ts +57 -0
- package/dist/functions/_shared/webhook-registry.d.ts.map +1 -0
- package/dist/functions/account-nodes.d.ts +48 -0
- package/dist/functions/account-nodes.d.ts.map +1 -0
- package/dist/functions/admin-data.d.ts +178 -0
- package/dist/functions/admin-data.d.ts.map +1 -0
- package/dist/functions/ai-agents.d.ts +125 -0
- package/dist/functions/ai-agents.d.ts.map +1 -0
- package/dist/functions/api-keys.d.ts +140 -0
- package/dist/functions/api-keys.d.ts.map +1 -0
- package/dist/functions/apps.d.ts +163 -0
- package/dist/functions/apps.d.ts.map +1 -0
- package/dist/functions/auth.d.ts +74 -0
- package/dist/functions/auth.d.ts.map +1 -0
- package/dist/functions/debug-auth.d.ts +33 -0
- package/dist/functions/debug-auth.d.ts.map +1 -0
- package/dist/functions/embeddings.d.ts +205 -0
- package/dist/functions/embeddings.d.ts.map +1 -0
- package/dist/functions/integration-routes.d.ts +45 -0
- package/dist/functions/integration-routes.d.ts.map +1 -0
- package/dist/functions/integrations.d.ts +124 -0
- package/dist/functions/integrations.d.ts.map +1 -0
- package/dist/functions/item-progress.d.ts +41 -0
- package/dist/functions/item-progress.d.ts.map +1 -0
- package/dist/functions/logs.d.ts +162 -0
- package/dist/functions/logs.d.ts.map +1 -0
- package/dist/functions/observability.d.ts +123 -0
- package/dist/functions/observability.d.ts.map +1 -0
- package/dist/functions/pipeline-executions.d.ts +190 -0
- package/dist/functions/pipeline-executions.d.ts.map +1 -0
- package/dist/functions/pipelines.d.ts +171 -0
- package/dist/functions/pipelines.d.ts.map +1 -0
- package/dist/functions/prompt-configs.d.ts +125 -0
- package/dist/functions/prompt-configs.d.ts.map +1 -0
- package/dist/functions/roles.d.ts +118 -0
- package/dist/functions/roles.d.ts.map +1 -0
- package/dist/functions/system-cron.d.ts +65 -0
- package/dist/functions/system-cron.d.ts.map +1 -0
- package/dist/functions/system.d.ts +29 -0
- package/dist/functions/system.d.ts.map +1 -0
- package/dist/functions/tests.d.ts +28 -0
- package/dist/functions/tests.d.ts.map +1 -0
- package/dist/functions/timers.d.ts +139 -0
- package/dist/functions/timers.d.ts.map +1 -0
- package/dist/functions/triggers.d.ts +203 -0
- package/dist/functions/triggers.d.ts.map +1 -0
- package/dist/functions/types.d.ts +151 -0
- package/dist/functions/types.d.ts.map +1 -0
- package/dist/src/types/types.d.ts +364 -0
- package/dist/src/types/types.d.ts.map +1 -0
- package/package.json +192 -0
- package/scripts/app-install-cli.ts +286 -0
- package/scripts/assemble-frontend.sh +79 -0
- package/scripts/assemble-functions.sh +62 -0
- package/scripts/assemble.sh +35 -0
- package/scripts/boundary-check.sh +106 -0
- package/scripts/build-manifest.sh +80 -0
- package/scripts/check-core-integrity.sh +82 -0
- package/scripts/ingest-chunks.cjs +202 -0
- package/scripts/kb-chunk-parser.cjs +312 -0
- package/scripts/kb-chunk-parser.ts +330 -0
- package/scripts/load-test-app-install.ts +484 -0
- package/scripts/netlify-dev-wrapper.sh +22 -0
- package/scripts/verify-integrity.sh +69 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module src/hooks/useEntityList
|
|
3
|
+
* @audience installer
|
|
4
|
+
* @layer frontend-hook
|
|
5
|
+
* @stability stable
|
|
6
|
+
*
|
|
7
|
+
* Schema-driven list data hook. Given an entity name and a minimal
|
|
8
|
+
* `MinimalEntityListConfig`, fetches a paginated, filtered, and sorted list
|
|
9
|
+
* from the API and exposes controls for filters, sort, and pagination.
|
|
10
|
+
*
|
|
11
|
+
* **How it works:**
|
|
12
|
+
* 1. Builds query params from `entity`, `config.api`, filters, sort, and pagination
|
|
13
|
+
* 2. Calls `apiFetch('/api/<endpoint>?action=list&...')` via `useApi`
|
|
14
|
+
* 3. Re-fetches when `config` arrives (async schema load), or when filters change
|
|
15
|
+
* (which also resets page to 1)
|
|
16
|
+
*
|
|
17
|
+
* **Auth retry:** `useApi` re-executes on route navigation, which naturally
|
|
18
|
+
* retries after the auth session hydrates on the next tick.
|
|
19
|
+
*
|
|
20
|
+
* @seeAlso src/hooks/useApi.ts (useApi — underlying fetch + abort primitive)
|
|
21
|
+
* @seeAlso src/lib/api.ts (apiFetch)
|
|
22
|
+
* @seeAlso src/components/runtime/DataListPage.tsx (primary consumer)
|
|
23
|
+
* @seeAlso functions/admin-data.ts (API endpoint for list action)
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { useState, useEffect, useCallback } from 'react'
|
|
27
|
+
import { useApi } from './useApi'
|
|
28
|
+
import { apiFetch } from '../lib/api'
|
|
29
|
+
|
|
30
|
+
// ─── TYPES ───────────────────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Minimal configuration shape consumed by `useEntityList`.
|
|
34
|
+
*
|
|
35
|
+
* @prop entity - Entity name (used as fallback endpoint, filter param)
|
|
36
|
+
* @prop typeSlug - Optional type slug; appended as `type_slug` param if present
|
|
37
|
+
* @prop api.endpoint - Netlify function base path (e.g. `'admin-data'`)
|
|
38
|
+
* @prop api.listAction - Action string; defaults to `'list'`
|
|
39
|
+
* @prop list.defaultSort - Initial sort field and direction
|
|
40
|
+
*/
|
|
41
|
+
interface MinimalEntityListConfig {
|
|
42
|
+
entity: string
|
|
43
|
+
typeSlug?: string
|
|
44
|
+
api: {
|
|
45
|
+
endpoint: string
|
|
46
|
+
listAction?: string
|
|
47
|
+
}
|
|
48
|
+
list: {
|
|
49
|
+
defaultSort: { field: string; direction: 'asc' | 'desc' }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Return value of `useEntityList`.
|
|
55
|
+
*
|
|
56
|
+
* @prop data - Fetched records array (empty while loading or on error)
|
|
57
|
+
* @prop loading - True while fetching
|
|
58
|
+
* @prop error - Error message or null
|
|
59
|
+
* @prop refetch - Re-execute the current query
|
|
60
|
+
* @prop filters - Active filter values keyed by param name
|
|
61
|
+
* @prop setFilters - Replace the active filters (resets page to 1)
|
|
62
|
+
* @prop sort - Current sort field and direction
|
|
63
|
+
* @prop setSort - Update sort (does not auto-reset page)
|
|
64
|
+
* @prop pagination - page/setPage/pageSize/setPageSize/total controls
|
|
65
|
+
*/
|
|
66
|
+
interface UseEntityListReturn {
|
|
67
|
+
data: any[]
|
|
68
|
+
loading: boolean
|
|
69
|
+
error: string | null
|
|
70
|
+
refetch: () => void
|
|
71
|
+
filters: Record<string, any>
|
|
72
|
+
setFilters: (filters: Record<string, any>) => void
|
|
73
|
+
sort: { field: string; direction: 'asc' | 'desc' }
|
|
74
|
+
setSort: (sort: { field: string; direction: 'asc' | 'desc' }) => void
|
|
75
|
+
pagination: {
|
|
76
|
+
page: number
|
|
77
|
+
setPage: (page: number) => void
|
|
78
|
+
pageSize: number
|
|
79
|
+
setPageSize: (size: number) => void
|
|
80
|
+
total: number
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ─── HOOK ────────────────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Fetches and manages a filtered, sorted, paginated entity list.
|
|
88
|
+
*
|
|
89
|
+
* @param entity - Entity name (e.g. `'accounts'`, `'items'`)
|
|
90
|
+
* @param config - Schema-derived config; pass `null` while schema is loading
|
|
91
|
+
* (hook is a no-op until config is non-null)
|
|
92
|
+
* @returns `UseEntityListReturn` — see type for full details
|
|
93
|
+
*
|
|
94
|
+
* @inputSpec config.api.endpoint: string — function name, e.g. `'admin-data'`
|
|
95
|
+
* @inputSpec filters: values of `''`, `undefined`, or `'all'` are omitted from params
|
|
96
|
+
* @outputSpec data: any[] — raw API response; shape depends on entity type
|
|
97
|
+
* @sideEffects Network request via apiFetch; React state mutations
|
|
98
|
+
* @calledBy DataListPage.tsx
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```tsx
|
|
102
|
+
* const { data, loading, setFilters } = useEntityList('accounts', config)
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export function useEntityList(
|
|
106
|
+
entity: string,
|
|
107
|
+
config: MinimalEntityListConfig | null
|
|
108
|
+
): UseEntityListReturn {
|
|
109
|
+
const [filters, setFilters] = useState<Record<string, any>>({})
|
|
110
|
+
const [sort, setSort] = useState<{ field: string; direction: 'asc' | 'desc' }>(config?.list?.defaultSort || { field: 'created_at', direction: 'desc' })
|
|
111
|
+
const [page, setPage] = useState(1)
|
|
112
|
+
const [pageSize, setPageSize] = useState(50)
|
|
113
|
+
|
|
114
|
+
const fetchData = useCallback(async () => {
|
|
115
|
+
if (!config) return
|
|
116
|
+
|
|
117
|
+
const params = new URLSearchParams()
|
|
118
|
+
|
|
119
|
+
// Support new endpoint-based API pattern
|
|
120
|
+
const endpoint = config.api.endpoint || entity
|
|
121
|
+
const action = config.api.listAction || 'list'
|
|
122
|
+
params.append('action', action)
|
|
123
|
+
|
|
124
|
+
// Add entity parameter for unified admin-data endpoint
|
|
125
|
+
if (config.api.endpoint) {
|
|
126
|
+
params.append('entity', entity)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Add type_slug for schema-driven filtering if available
|
|
130
|
+
if (config.typeSlug) {
|
|
131
|
+
params.append('type_slug', config.typeSlug)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Add filters
|
|
135
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
136
|
+
if (value !== undefined && value !== '' && value !== 'all') {
|
|
137
|
+
params.append(key, value.toString())
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// Add sort
|
|
142
|
+
params.append('sort_field', sort.field)
|
|
143
|
+
params.append('sort_direction', sort.direction)
|
|
144
|
+
|
|
145
|
+
// Add pagination
|
|
146
|
+
params.append('limit', pageSize.toString())
|
|
147
|
+
params.append('offset', ((page - 1) * pageSize).toString())
|
|
148
|
+
|
|
149
|
+
const response = await apiFetch(`/api/${endpoint}?${params.toString()}`)
|
|
150
|
+
|
|
151
|
+
if (!response.ok) {
|
|
152
|
+
throw new Error(`Failed to fetch ${entity}: ${response.statusText}`)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const result = await response.json()
|
|
156
|
+
return result.data || []
|
|
157
|
+
}, [entity, config?.api.endpoint, config?.api.listAction, config?.typeSlug, filters, sort, page, pageSize])
|
|
158
|
+
|
|
159
|
+
const { data, loading, error, execute, refetch } = useApi<any[]>(fetchData, {
|
|
160
|
+
immediate: true
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
// Re-fetch when config arrives (schema was not ready on initial mount)
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
if (config) execute()
|
|
166
|
+
}, [config?.api.endpoint, config?.api.listAction, config?.typeSlug])
|
|
167
|
+
|
|
168
|
+
// Reset page when filters change
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
setPage(1)
|
|
171
|
+
}, [filters])
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
data: data || [],
|
|
175
|
+
loading,
|
|
176
|
+
error,
|
|
177
|
+
refetch,
|
|
178
|
+
filters,
|
|
179
|
+
setFilters,
|
|
180
|
+
sort,
|
|
181
|
+
setSort,
|
|
182
|
+
pagination: {
|
|
183
|
+
page,
|
|
184
|
+
setPage,
|
|
185
|
+
pageSize,
|
|
186
|
+
setPageSize,
|
|
187
|
+
total: data?.length || 0
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module src/hooks/useEntityRecord
|
|
3
|
+
* @audience installer
|
|
4
|
+
* @layer frontend-hook
|
|
5
|
+
* @stability stable
|
|
6
|
+
*
|
|
7
|
+
* Schema-driven single-record hook. Fetches a record by ID, exposes its
|
|
8
|
+
* design schema, computes field-level read/write permissions for the
|
|
9
|
+
* current principal, and provides save and delete mutations.
|
|
10
|
+
*
|
|
11
|
+
* **Field permission model:**
|
|
12
|
+
* - `system_admin` role always gets `{ read: true, write: true }` on all fields
|
|
13
|
+
* - Other principals: permissions are read from `design_schema.fields[n].permissions`
|
|
14
|
+
* as role arrays; defaults to `true` if absent
|
|
15
|
+
*
|
|
16
|
+
* **Save routing:**
|
|
17
|
+
* - Fields marked `fieldDef.system = true` go to top-level record columns
|
|
18
|
+
* - All other fields are nested under the `data` JSONB column
|
|
19
|
+
*
|
|
20
|
+
* **Delete:** sends a `DELETE` request with the configured `deleteAction`;
|
|
21
|
+
* hard vs. soft delete is determined by the API handler (`config.softDelete`
|
|
22
|
+
* signals intent to the handler).
|
|
23
|
+
*
|
|
24
|
+
* @seeAlso src/hooks/useApi.ts (useApi + useMutation primitives)
|
|
25
|
+
* @seeAlso src/hooks/useSchemaRecord.ts (companion for schema-driven form data)
|
|
26
|
+
* @seeAlso src/components/runtime/DataDetailPage.tsx (primary consumer)
|
|
27
|
+
* @seeAlso functions/admin-data.ts (API endpoint handling get/update/delete)
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { useCallback } from 'react'
|
|
31
|
+
import { useApi, useMutation } from './useApi'
|
|
32
|
+
import { apiFetch } from '../lib/api'
|
|
33
|
+
import { useAuth } from '../contexts/AuthContext'
|
|
34
|
+
|
|
35
|
+
// ─── TYPES ───────────────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Per-field read/write permission map keyed by field name.
|
|
39
|
+
* Computed from `design_schema.fields[n].permissions` and the current user's roles.
|
|
40
|
+
*/
|
|
41
|
+
interface FieldPermissions {
|
|
42
|
+
[key: string]: { read: boolean; write: boolean }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Minimal entity configuration consumed by `useEntityRecord`.
|
|
47
|
+
*
|
|
48
|
+
* @prop entity - Entity table name
|
|
49
|
+
* @prop typeSlug - Optional type slug for schema resolution
|
|
50
|
+
* @prop icon - Icon identifier (used by detail page header)
|
|
51
|
+
* @prop displayField - Field name used as the record title
|
|
52
|
+
* @prop api.endpoint - Netlify function base path
|
|
53
|
+
* @prop api.*Action - Action strings for get/create/update/delete
|
|
54
|
+
* @prop softDelete - Hint for the API handler (true = set is_active=false)
|
|
55
|
+
*/
|
|
56
|
+
interface MinimalEntityConfig {
|
|
57
|
+
entity: string
|
|
58
|
+
typeSlug?: string
|
|
59
|
+
icon: string
|
|
60
|
+
displayField: string
|
|
61
|
+
api: {
|
|
62
|
+
endpoint: string
|
|
63
|
+
getAction?: string
|
|
64
|
+
createAction?: string
|
|
65
|
+
updateAction?: string
|
|
66
|
+
deleteAction?: string
|
|
67
|
+
}
|
|
68
|
+
softDelete?: boolean
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Return value of `useEntityRecord`.
|
|
73
|
+
*
|
|
74
|
+
* @prop record - Fetched record or null
|
|
75
|
+
* @prop schema - `design_schema` extracted from the record (or nested type)
|
|
76
|
+
* @prop fieldPermissions - Per-field `{ read, write }` map for the current user
|
|
77
|
+
* @prop loading - True while fetching
|
|
78
|
+
* @prop error - Error message or null
|
|
79
|
+
* @prop refetch - Re-fetch the record
|
|
80
|
+
* @prop save - Trigger the save mutation (create or update based on `id`)
|
|
81
|
+
* @prop delete - Trigger the delete mutation
|
|
82
|
+
* @prop saving / deleting - Mutation loading flags
|
|
83
|
+
*/
|
|
84
|
+
interface UseEntityRecordReturn {
|
|
85
|
+
record: any
|
|
86
|
+
schema: any
|
|
87
|
+
fieldPermissions: FieldPermissions
|
|
88
|
+
loading: boolean
|
|
89
|
+
error: string | null
|
|
90
|
+
refetch: () => void
|
|
91
|
+
save: (data: any) => Promise<void>
|
|
92
|
+
delete: () => Promise<void>
|
|
93
|
+
saving: boolean
|
|
94
|
+
deleting: boolean
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─── HOOK ────────────────────────────────────────────────────────────────────
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Fetches, saves, and deletes a single entity record with schema and
|
|
101
|
+
* field-permission awareness.
|
|
102
|
+
*
|
|
103
|
+
* @param entity - Entity table name (e.g. `'accounts'`)
|
|
104
|
+
* @param id - Record UUID; pass `undefined` to enter create mode
|
|
105
|
+
* @param config - Schema-derived config; pass `null` while loading
|
|
106
|
+
* @returns `UseEntityRecordReturn` — see type for full details
|
|
107
|
+
*
|
|
108
|
+
* @inputSpec id: string | undefined — undefined triggers create mode (no GET)
|
|
109
|
+
* @outputSpec schema: DesignSchema | {} — empty object if no design_schema found
|
|
110
|
+
* @outputSpec fieldPermissions: FieldPermissions — computed per-render
|
|
111
|
+
* @sideEffects Network requests via apiFetch; React state mutations
|
|
112
|
+
* @calledBy DataDetailPage.tsx
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```tsx
|
|
116
|
+
* const { record, save, saving, fieldPermissions } =
|
|
117
|
+
* useEntityRecord('accounts', id, config)
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export function useEntityRecord(
|
|
121
|
+
entity: string,
|
|
122
|
+
id: string | undefined,
|
|
123
|
+
config: MinimalEntityConfig | null
|
|
124
|
+
): UseEntityRecordReturn {
|
|
125
|
+
const { user } = useAuth()
|
|
126
|
+
|
|
127
|
+
// Get API configuration with safe defaults
|
|
128
|
+
const endpoint = config?.api?.endpoint || entity
|
|
129
|
+
const getAction = config?.api?.getAction || 'get'
|
|
130
|
+
const createAction = config?.api?.createAction || 'create'
|
|
131
|
+
const updateAction = config?.api?.updateAction || 'update'
|
|
132
|
+
const deleteAction = config?.api?.deleteAction || 'delete'
|
|
133
|
+
|
|
134
|
+
// Fetch record - always call useCallback to maintain hook order
|
|
135
|
+
const fetchRecord = useCallback(async () => {
|
|
136
|
+
if (!id) return null
|
|
137
|
+
|
|
138
|
+
const params = new URLSearchParams()
|
|
139
|
+
params.append('action', getAction)
|
|
140
|
+
params.append('entity', entity)
|
|
141
|
+
params.append('id', id)
|
|
142
|
+
|
|
143
|
+
const response = await apiFetch(`/api/${endpoint}?${params.toString()}`)
|
|
144
|
+
|
|
145
|
+
if (!response.ok) {
|
|
146
|
+
throw new Error(`Failed to fetch ${entity}: ${response.statusText}`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const result = await response.json()
|
|
150
|
+
return result.data || result
|
|
151
|
+
}, [entity, id, endpoint, getAction])
|
|
152
|
+
|
|
153
|
+
const { data: record, loading, error, refetch } = useApi<any>(fetchRecord, {
|
|
154
|
+
immediate: !!id
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// Extract schema from record (accounts have it at root level, items/types have it nested)
|
|
158
|
+
const schema = record?.design_schema || record?.type?.design_schema || {}
|
|
159
|
+
|
|
160
|
+
// Calculate field permissions from record's schema
|
|
161
|
+
const calculatePermissions = (): FieldPermissions => {
|
|
162
|
+
const permissions: FieldPermissions = {}
|
|
163
|
+
|
|
164
|
+
// System admin gets full access
|
|
165
|
+
const isSystemAdmin = user?.roles?.includes('system_admin')
|
|
166
|
+
|
|
167
|
+
// Get all fields from record's schema
|
|
168
|
+
const recordSchema = record?.design_schema?.fields
|
|
169
|
+
if (!recordSchema) return permissions
|
|
170
|
+
|
|
171
|
+
Object.entries(recordSchema).forEach(([fieldName, fieldSchema]: [string, any]) => {
|
|
172
|
+
if (isSystemAdmin) {
|
|
173
|
+
permissions[fieldName] = { read: true, write: true }
|
|
174
|
+
} else {
|
|
175
|
+
// Check field-level permissions from schema
|
|
176
|
+
const fieldPerms = fieldSchema?.permissions || {}
|
|
177
|
+
|
|
178
|
+
const canRead = fieldPerms.read?.some((role: string) =>
|
|
179
|
+
user?.roles?.includes(role)
|
|
180
|
+
) ?? true
|
|
181
|
+
|
|
182
|
+
const canWrite = fieldPerms.write?.some((role: string) =>
|
|
183
|
+
user?.roles?.includes(role)
|
|
184
|
+
) ?? true
|
|
185
|
+
|
|
186
|
+
permissions[fieldName] = { read: canRead, write: canWrite }
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
return permissions
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const fieldPermissions = calculatePermissions()
|
|
194
|
+
|
|
195
|
+
// Save mutation
|
|
196
|
+
const saveMutation = useMutation(
|
|
197
|
+
async (data: any) => {
|
|
198
|
+
// Separate system fields from custom fields
|
|
199
|
+
const systemData: Record<string, any> = {}
|
|
200
|
+
const customData: Record<string, any> = {}
|
|
201
|
+
|
|
202
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
203
|
+
const fieldDef = record?.design_schema?.fields?.[key]
|
|
204
|
+
if (fieldDef?.system) {
|
|
205
|
+
systemData[key] = value
|
|
206
|
+
} else {
|
|
207
|
+
customData[key] = value
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
// Combine system fields with custom data in data field
|
|
212
|
+
const saveData = {
|
|
213
|
+
...systemData,
|
|
214
|
+
data: Object.keys(customData).length > 0 ? customData : undefined
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (id) {
|
|
218
|
+
// Update
|
|
219
|
+
const params = new URLSearchParams()
|
|
220
|
+
params.append('action', updateAction)
|
|
221
|
+
params.append('entity', entity)
|
|
222
|
+
params.append('id', id)
|
|
223
|
+
|
|
224
|
+
const response = await apiFetch(
|
|
225
|
+
`/api/${endpoint}?${params.toString()}`,
|
|
226
|
+
{
|
|
227
|
+
method: 'PATCH',
|
|
228
|
+
headers: { 'Content-Type': 'application/json' },
|
|
229
|
+
body: JSON.stringify(saveData)
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
if (!response.ok) {
|
|
234
|
+
throw new Error(`Failed to update ${entity}: ${response.statusText}`)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return response.json()
|
|
238
|
+
} else {
|
|
239
|
+
// Create
|
|
240
|
+
const createData = { entity, ...saveData }
|
|
241
|
+
|
|
242
|
+
const params = new URLSearchParams()
|
|
243
|
+
params.append('action', createAction)
|
|
244
|
+
params.append('entity', entity)
|
|
245
|
+
|
|
246
|
+
const response = await apiFetch(
|
|
247
|
+
`/api/${endpoint}?${params.toString()}`,
|
|
248
|
+
{
|
|
249
|
+
method: 'POST',
|
|
250
|
+
headers: { 'Content-Type': 'application/json' },
|
|
251
|
+
body: JSON.stringify(createData)
|
|
252
|
+
}
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
if (!response.ok) {
|
|
256
|
+
throw new Error(`Failed to create ${entity}: ${response.statusText}`)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return response.json()
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
onSuccess: () => {
|
|
264
|
+
if (id) {
|
|
265
|
+
refetch()
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
// Delete mutation
|
|
272
|
+
const deleteMutation = useMutation(
|
|
273
|
+
async () => {
|
|
274
|
+
if (!id) throw new Error('Cannot delete: no ID provided')
|
|
275
|
+
|
|
276
|
+
const params = new URLSearchParams()
|
|
277
|
+
params.append('action', deleteAction)
|
|
278
|
+
params.append('entity', entity)
|
|
279
|
+
params.append('id', id)
|
|
280
|
+
|
|
281
|
+
const response = await apiFetch(
|
|
282
|
+
`/api/${endpoint}?${params.toString()}`,
|
|
283
|
+
{
|
|
284
|
+
method: 'DELETE'
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
if (!response.ok) {
|
|
289
|
+
throw new Error(`Failed to delete ${entity}: ${response.statusText}`)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return response.json()
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
record,
|
|
298
|
+
schema,
|
|
299
|
+
fieldPermissions,
|
|
300
|
+
loading,
|
|
301
|
+
error,
|
|
302
|
+
refetch,
|
|
303
|
+
save: saveMutation.mutate,
|
|
304
|
+
delete: deleteMutation.mutate,
|
|
305
|
+
saving: saveMutation.loading,
|
|
306
|
+
deleting: deleteMutation.loading
|
|
307
|
+
}
|
|
308
|
+
}
|