spine-framework 0.2.1 → 1.0.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/LICENSE.md +213 -8
- package/README.md +327 -0
- package/package.json +107 -217
- package/src/cli/commands/init.ts +192 -0
- package/src/cli/commands/install.ts +25 -0
- package/src/cli/commands/list.ts +33 -0
- package/src/cli/commands/migrate.ts +24 -0
- package/src/cli/index.ts +46 -0
- package/src/components/AppLayout.tsx +21 -0
- package/src/components/AuthGuard.tsx +21 -0
- package/src/components/RoleGuard.tsx +23 -0
- package/src/components/index.ts +3 -0
- package/src/contexts/AppContext.tsx +122 -0
- package/src/contexts/AuthContext.tsx +87 -0
- package/src/contexts/SpineContext.tsx +46 -0
- package/src/contexts/index.ts +3 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useItems.ts +78 -0
- package/src/hooks/useThreads.ts +73 -0
- package/src/hooks/useWebSocket.ts +97 -0
- package/src/index.ts +22 -0
- package/src/types/index.ts +163 -0
- package/src/utils/api.ts +88 -0
- package/src/utils/client.ts +146 -0
- package/src/utils/config.ts +20 -0
- package/src/utils/index.ts +3 -0
- package/.framework/README.md +0 -129
- package/.framework/cli/bin.cjs +0 -14
- package/.framework/cli/commands/agents.ts +0 -153
- package/.framework/cli/commands/auth.ts +0 -94
- package/.framework/cli/commands/create-app.ts +0 -185
- package/.framework/cli/commands/dev.ts +0 -113
- package/.framework/cli/commands/doctor.ts +0 -442
- package/.framework/cli/commands/generate.ts +0 -332
- package/.framework/cli/commands/init.ts +0 -186
- package/.framework/cli/commands/install-app.ts +0 -565
- package/.framework/cli/commands/items.ts +0 -253
- package/.framework/cli/commands/migrate.ts +0 -139
- package/.framework/cli/commands/migrations.ts +0 -141
- package/.framework/cli/commands/pipelines.ts +0 -166
- package/.framework/cli/commands/status.ts +0 -197
- package/.framework/cli/commands/system.ts +0 -184
- package/.framework/cli/commands/test.ts +0 -227
- package/.framework/cli/commands/uninstall-app.ts +0 -166
- package/.framework/cli/context.ts +0 -268
- package/.framework/cli/env-loader.ts +0 -36
- package/.framework/cli/index.ts +0 -116
- package/.framework/cli/welcome.cjs +0 -45
- package/.framework/docs/API.md +0 -384
- package/.framework/docs/STABILITY.md +0 -52
- package/.framework/docs/admin-routes.md +0 -76
- package/.framework/docs/api-docs-progress.md +0 -38
- package/.framework/docs/api-governance.md +0 -146
- package/.framework/docs/api-testing-results.md +0 -212
- package/.framework/docs/apis/admin-configs.md +0 -567
- package/.framework/docs/apis/admin-data.md +0 -272
- package/.framework/docs/apis/index.md +0 -231
- package/.framework/docs/apis/internal.md +0 -295
- package/.framework/docs/apis/runtime.md +0 -537
- package/.framework/docs/assembly-launch-guide.md +0 -138
- package/.framework/docs/audit-results.md +0 -590
- package/.framework/docs/authorization-model.md +0 -170
- package/.framework/docs/db-api-inventory.md +0 -95
- package/.framework/docs/examples/custom-app/README.md +0 -77
- package/.framework/docs/examples/custom-function/README.md +0 -27
- package/.framework/docs/examples/custom-function/handler.ts +0 -48
- package/.framework/docs/examples/custom-webhook/README.md +0 -68
- package/.framework/docs/gap-remediation-backlog.md +0 -103
- package/.framework/docs/guides/cli-guide.md +0 -224
- package/.framework/docs/guides/getting-started.md +0 -103
- package/.framework/docs/guides/import-guide.md +0 -193
- package/.framework/docs/guides/testing-guide.md +0 -229
- package/.framework/docs/permission-examples.md +0 -326
- package/.framework/docs/ui-adoption-verification.md +0 -111
- package/.framework/docs/ui-api-coverage.md +0 -84
- package/.framework/docs/v2-compatibility-audit.md +0 -228
- package/.framework/functions/.gitkeep +0 -1
- package/.framework/functions/_shared/agent-runner.ts +0 -1097
- package/.framework/functions/_shared/app-manifest.ts +0 -184
- package/.framework/functions/_shared/audit.ts +0 -150
- package/.framework/functions/_shared/db.ts +0 -178
- package/.framework/functions/_shared/index.ts +0 -391
- package/.framework/functions/_shared/middleware.ts +0 -490
- package/.framework/functions/_shared/permissions.ts +0 -1325
- package/.framework/functions/_shared/pipeline-runner.ts +0 -731
- package/.framework/functions/_shared/principal.ts +0 -818
- package/.framework/functions/_shared/resolve-ids.ts +0 -106
- package/.framework/functions/_shared/schema-utils.ts +0 -967
- package/.framework/functions/_shared/testing.ts +0 -258
- package/.framework/functions/_shared/trigger-engine.ts +0 -425
- package/.framework/functions/_shared/webhook-registration.ts +0 -168
- package/.framework/functions/_shared/webhook-registry.ts +0 -129
- package/.framework/functions/account-nodes.ts +0 -111
- package/.framework/functions/admin-data.ts +0 -606
- package/.framework/functions/ai-agents.ts +0 -323
- package/.framework/functions/api-keys.ts +0 -376
- package/.framework/functions/apps.ts +0 -483
- package/.framework/functions/auth.ts +0 -196
- package/.framework/functions/debug-auth.ts +0 -107
- package/.framework/functions/embeddings.ts +0 -556
- package/.framework/functions/integration-routes.ts +0 -523
- package/.framework/functions/integrations.ts +0 -319
- package/.framework/functions/item-progress.ts +0 -272
- package/.framework/functions/logs.ts +0 -438
- package/.framework/functions/observability.ts +0 -275
- package/.framework/functions/pipeline-executions.ts +0 -494
- package/.framework/functions/pipelines.ts +0 -485
- package/.framework/functions/prompt-configs.ts +0 -339
- package/.framework/functions/roles.ts +0 -387
- package/.framework/functions/system-cron.ts +0 -742
- package/.framework/functions/system.ts +0 -323
- package/.framework/functions/tests.ts +0 -119
- package/.framework/functions/timers.ts +0 -357
- package/.framework/functions/triggers.ts +0 -563
- package/.framework/functions/types.ts +0 -604
- package/.framework/index.html +0 -16
- package/.framework/migrations/000_foundation.sql +0 -1266
- package/.framework/migrations/001_seed.sql +0 -163
- package/.framework/migrations/002_seed_constraints.sql +0 -19
- package/.framework/migrations/003_auth_user_trigger.sql +0 -67
- package/.framework/src/App.tsx +0 -133
- package/.framework/src/apps/admin/index.tsx +0 -173
- package/.framework/src/components/AppWrapper.tsx +0 -56
- package/.framework/src/components/CustomAppLoader.tsx +0 -116
- package/.framework/src/components/admin/AdminListPage.tsx +0 -151
- package/.framework/src/components/admin/AdminSidebar.tsx +0 -166
- package/.framework/src/components/admin/AdminStatsCard.tsx +0 -62
- package/.framework/src/components/admin/SortableTableHeader.tsx +0 -42
- package/.framework/src/components/app-shell/GenericAppShell.tsx +0 -181
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +0 -200
- package/.framework/src/components/app-shell/GenericListPage.tsx +0 -116
- package/.framework/src/components/app-sidebar.tsx +0 -228
- package/.framework/src/components/auth/ProtectedRoute.tsx +0 -88
- package/.framework/src/components/layout/AppShell.tsx +0 -91
- package/.framework/src/components/layout/Header.tsx +0 -88
- package/.framework/src/components/layout/Layout.tsx +0 -95
- package/.framework/src/components/layout/Sidebar.tsx +0 -329
- package/.framework/src/components/runtime/DataDetailHeader.tsx +0 -77
- package/.framework/src/components/runtime/DataDetailPage.tsx +0 -171
- package/.framework/src/components/runtime/DataFilters.tsx +0 -91
- package/.framework/src/components/runtime/DataHeader.tsx +0 -68
- package/.framework/src/components/runtime/DataListPage.tsx +0 -124
- package/.framework/src/components/runtime/DataStats.tsx +0 -70
- package/.framework/src/components/runtime/DataTable.tsx +0 -174
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +0 -134
- package/.framework/src/components/runtime/index.ts +0 -18
- package/.framework/src/components/search-form.tsx +0 -29
- package/.framework/src/components/shared/AgentView.tsx +0 -213
- package/.framework/src/components/shared/FieldRenderer.tsx +0 -478
- package/.framework/src/components/shared/SchemaFields.tsx +0 -226
- package/.framework/src/components/ui/DataTable.tsx +0 -343
- package/.framework/src/components/ui/Form.tsx +0 -281
- package/.framework/src/components/ui/ItemCard.tsx +0 -296
- package/.framework/src/components/ui/ItemListView.tsx +0 -308
- package/.framework/src/components/ui/LoadingSpinner.tsx +0 -52
- package/.framework/src/components/ui/Modal.tsx +0 -61
- package/.framework/src/components/ui/RichTextEditor.tsx +0 -210
- package/.framework/src/components/ui/accordion.tsx +0 -82
- package/.framework/src/components/ui/alert-dialog.tsx +0 -197
- package/.framework/src/components/ui/alert.tsx +0 -76
- package/.framework/src/components/ui/aspect-ratio.tsx +0 -11
- package/.framework/src/components/ui/avatar.tsx +0 -110
- package/.framework/src/components/ui/badge.tsx +0 -49
- package/.framework/src/components/ui/breadcrumb.tsx +0 -122
- package/.framework/src/components/ui/button-group.tsx +0 -83
- package/.framework/src/components/ui/button.tsx +0 -65
- package/.framework/src/components/ui/calendar.tsx +0 -222
- package/.framework/src/components/ui/card.tsx +0 -100
- package/.framework/src/components/ui/carousel.tsx +0 -240
- package/.framework/src/components/ui/chart.tsx +0 -368
- package/.framework/src/components/ui/checkbox.tsx +0 -31
- package/.framework/src/components/ui/collapsible.tsx +0 -33
- package/.framework/src/components/ui/combobox.tsx +0 -299
- package/.framework/src/components/ui/command.tsx +0 -193
- package/.framework/src/components/ui/context-menu.tsx +0 -261
- package/.framework/src/components/ui/dialog.tsx +0 -165
- package/.framework/src/components/ui/direction.tsx +0 -6
- package/.framework/src/components/ui/drawer.tsx +0 -132
- package/.framework/src/components/ui/dropdown-menu.tsx +0 -269
- package/.framework/src/components/ui/empty.tsx +0 -104
- package/.framework/src/components/ui/field.tsx +0 -238
- package/.framework/src/components/ui/hover-card.tsx +0 -42
- package/.framework/src/components/ui/input-group.tsx +0 -153
- package/.framework/src/components/ui/input-otp.tsx +0 -87
- package/.framework/src/components/ui/input.tsx +0 -19
- package/.framework/src/components/ui/item.tsx +0 -196
- package/.framework/src/components/ui/kbd.tsx +0 -26
- package/.framework/src/components/ui/label.tsx +0 -22
- package/.framework/src/components/ui/menubar.tsx +0 -277
- package/.framework/src/components/ui/native-select.tsx +0 -61
- package/.framework/src/components/ui/navigation-menu.tsx +0 -164
- package/.framework/src/components/ui/pagination.tsx +0 -129
- package/.framework/src/components/ui/popover.tsx +0 -87
- package/.framework/src/components/ui/progress.tsx +0 -31
- package/.framework/src/components/ui/radio-group.tsx +0 -42
- package/.framework/src/components/ui/resizable.tsx +0 -50
- package/.framework/src/components/ui/scroll-area.tsx +0 -53
- package/.framework/src/components/ui/select.tsx +0 -195
- package/.framework/src/components/ui/separator.tsx +0 -26
- package/.framework/src/components/ui/sheet.tsx +0 -145
- package/.framework/src/components/ui/sidebar.tsx +0 -706
- package/.framework/src/components/ui/skeleton.tsx +0 -13
- package/.framework/src/components/ui/slider.tsx +0 -59
- package/.framework/src/components/ui/sonner.tsx +0 -47
- package/.framework/src/components/ui/spinner.tsx +0 -10
- package/.framework/src/components/ui/switch.tsx +0 -33
- package/.framework/src/components/ui/table-primitives.tsx +0 -141
- package/.framework/src/components/ui/table.tsx +0 -114
- package/.framework/src/components/ui/tabs.tsx +0 -90
- package/.framework/src/components/ui/textarea.tsx +0 -18
- package/.framework/src/components/ui/toggle-group.tsx +0 -89
- package/.framework/src/components/ui/toggle.tsx +0 -45
- package/.framework/src/components/ui/tooltip.tsx +0 -57
- package/.framework/src/contexts/AppContext.tsx +0 -133
- package/.framework/src/contexts/AuthContext.tsx +0 -371
- package/.framework/src/hooks/use-mobile.ts +0 -19
- package/.framework/src/hooks/useApi.ts +0 -526
- package/.framework/src/hooks/useApps.ts +0 -114
- package/.framework/src/hooks/useEntityList.ts +0 -190
- package/.framework/src/hooks/useEntityRecord.ts +0 -308
- package/.framework/src/hooks/useForm.ts +0 -307
- package/.framework/src/hooks/useListSchema.ts +0 -264
- package/.framework/src/hooks/useSchemaRecord.ts +0 -223
- package/.framework/src/index.css +0 -128
- package/.framework/src/lib/api.ts +0 -156
- package/.framework/src/lib/supabase.ts +0 -94
- package/.framework/src/lib/utils.ts +0 -317
- package/.framework/src/main.tsx +0 -27
- package/.framework/src/pages/DashboardPage.tsx +0 -181
- package/.framework/src/pages/NotFoundPage.tsx +0 -39
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +0 -161
- package/.framework/src/pages/admin/AIAgentsPage.tsx +0 -318
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +0 -199
- package/.framework/src/pages/admin/APIKeysPage.tsx +0 -303
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +0 -523
- package/.framework/src/pages/admin/AppDetailPage.tsx +0 -493
- package/.framework/src/pages/admin/AppsPage.tsx +0 -355
- package/.framework/src/pages/admin/DesignedPage.tsx +0 -491
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +0 -534
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +0 -424
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +0 -176
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +0 -109
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +0 -402
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +0 -187
- package/.framework/src/pages/admin/IntegrationsPage.tsx +0 -301
- package/.framework/src/pages/admin/LogsPage.tsx +0 -283
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +0 -85
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +0 -470
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +0 -183
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +0 -279
- package/.framework/src/pages/admin/PipelinesPage.tsx +0 -390
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +0 -299
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +0 -292
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +0 -434
- package/.framework/src/pages/admin/RoleDetailPage.tsx +0 -273
- package/.framework/src/pages/admin/RolesPage.tsx +0 -292
- package/.framework/src/pages/admin/SelectTestPage.tsx +0 -61
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +0 -588
- package/.framework/src/pages/admin/SimpleDashboard.tsx +0 -387
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +0 -172
- package/.framework/src/pages/admin/TestingDashboard.tsx +0 -257
- package/.framework/src/pages/admin/TimerDetailPage.tsx +0 -151
- package/.framework/src/pages/admin/TimersPage.tsx +0 -376
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +0 -149
- package/.framework/src/pages/admin/TriggersPage.tsx +0 -381
- package/.framework/src/pages/admin/TypeDetailPage.tsx +0 -694
- package/.framework/src/pages/admin/TypesPage.tsx +0 -295
- package/.framework/src/pages/auth/LoginPage.tsx +0 -187
- package/.framework/src/pages/auth/RegisterPage.tsx +0 -163
- package/.framework/src/pages/spine-framework/APIPage.tsx +0 -17
- package/.framework/src/pages/spine-framework/CLIPage.tsx +0 -25
- package/.framework/src/types/auth.ts +0 -125
- package/.framework/src/types/types.ts +0 -407
- package/STRUCTURE.md +0 -150
- package/bin/spine-framework.cjs +0 -62
- package/bin/welcome.cjs +0 -45
- package/bin/ws-shim.cjs +0 -8
- package/bin/ws-shim.ts +0 -10
- package/config/components.json +0 -25
- package/config/deno.lock +0 -108
- package/config/package-lock.json +0 -17183
- package/config/postcss.config.cjs +0 -10
- package/config/tailwind.config.cjs +0 -78
- package/config/tsconfig.build.json +0 -32
- package/config/tsconfig.cli.json +0 -18
- package/config/tsconfig.json +0 -41
- package/config/tsconfig.node.json +0 -17
- package/config/tsconfig.node.tsbuildinfo +0 -1
- package/config/tsconfig.tsbuildinfo +0 -1
- package/config/typedoc.json +0 -16
- package/config/vite.config.d.ts +0 -2
- package/config/vite.config.ts +0 -71
- package/dist/cli/commands/agents.d.ts +0 -39
- package/dist/cli/commands/agents.d.ts.map +0 -1
- package/dist/cli/commands/auth.d.ts +0 -36
- package/dist/cli/commands/auth.d.ts.map +0 -1
- package/dist/cli/commands/create-app.d.ts +0 -23
- package/dist/cli/commands/create-app.d.ts.map +0 -1
- package/dist/cli/commands/dev.d.ts +0 -24
- package/dist/cli/commands/dev.d.ts.map +0 -1
- package/dist/cli/commands/doctor.d.ts +0 -42
- package/dist/cli/commands/doctor.d.ts.map +0 -1
- package/dist/cli/commands/generate.d.ts +0 -36
- package/dist/cli/commands/generate.d.ts.map +0 -1
- package/dist/cli/commands/init.d.ts +0 -20
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/install-app.d.ts +0 -30
- package/dist/cli/commands/install-app.d.ts.map +0 -1
- package/dist/cli/commands/items.d.ts +0 -45
- package/dist/cli/commands/items.d.ts.map +0 -1
- package/dist/cli/commands/migrate.d.ts +0 -21
- package/dist/cli/commands/migrate.d.ts.map +0 -1
- package/dist/cli/commands/migrations.d.ts +0 -41
- package/dist/cli/commands/migrations.d.ts.map +0 -1
- package/dist/cli/commands/pipelines.d.ts +0 -40
- package/dist/cli/commands/pipelines.d.ts.map +0 -1
- package/dist/cli/commands/status.d.ts +0 -23
- package/dist/cli/commands/status.d.ts.map +0 -1
- package/dist/cli/commands/system.d.ts +0 -29
- package/dist/cli/commands/system.d.ts.map +0 -1
- package/dist/cli/commands/test.d.ts +0 -46
- package/dist/cli/commands/test.d.ts.map +0 -1
- package/dist/cli/commands/uninstall-app.d.ts +0 -23
- package/dist/cli/commands/uninstall-app.d.ts.map +0 -1
- package/dist/cli/context.d.ts +0 -88
- package/dist/cli/context.d.ts.map +0 -1
- package/dist/cli/env-loader.d.ts +0 -14
- package/dist/cli/env-loader.d.ts.map +0 -1
- package/dist/cli/index.d.ts +0 -41
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/functions/_shared/agent-runner.d.ts +0 -156
- package/dist/functions/_shared/agent-runner.d.ts.map +0 -1
- package/dist/functions/_shared/app-manifest.d.ts +0 -68
- package/dist/functions/_shared/app-manifest.d.ts.map +0 -1
- package/dist/functions/_shared/audit.d.ts +0 -91
- package/dist/functions/_shared/audit.d.ts.map +0 -1
- package/dist/functions/_shared/db.d.ts +0 -125
- package/dist/functions/_shared/db.d.ts.map +0 -1
- package/dist/functions/_shared/index.d.ts +0 -299
- package/dist/functions/_shared/index.d.ts.map +0 -1
- package/dist/functions/_shared/middleware.d.ts +0 -315
- package/dist/functions/_shared/middleware.d.ts.map +0 -1
- package/dist/functions/_shared/permissions.d.ts +0 -626
- package/dist/functions/_shared/permissions.d.ts.map +0 -1
- package/dist/functions/_shared/pipeline-runner.d.ts +0 -124
- package/dist/functions/_shared/pipeline-runner.d.ts.map +0 -1
- package/dist/functions/_shared/principal.d.ts +0 -284
- package/dist/functions/_shared/principal.d.ts.map +0 -1
- package/dist/functions/_shared/resolve-ids.d.ts +0 -10
- package/dist/functions/_shared/resolve-ids.d.ts.map +0 -1
- package/dist/functions/_shared/schema-utils.d.ts +0 -181
- package/dist/functions/_shared/schema-utils.d.ts.map +0 -1
- package/dist/functions/_shared/testing.d.ts +0 -172
- package/dist/functions/_shared/testing.d.ts.map +0 -1
- package/dist/functions/_shared/trigger-engine.d.ts +0 -140
- package/dist/functions/_shared/trigger-engine.d.ts.map +0 -1
- package/dist/functions/_shared/webhook-registration.d.ts +0 -81
- package/dist/functions/_shared/webhook-registration.d.ts.map +0 -1
- package/dist/functions/_shared/webhook-registry.d.ts +0 -57
- package/dist/functions/_shared/webhook-registry.d.ts.map +0 -1
- package/dist/functions/account-nodes.d.ts +0 -48
- package/dist/functions/account-nodes.d.ts.map +0 -1
- package/dist/functions/admin-data.d.ts +0 -178
- package/dist/functions/admin-data.d.ts.map +0 -1
- package/dist/functions/ai-agents.d.ts +0 -125
- package/dist/functions/ai-agents.d.ts.map +0 -1
- package/dist/functions/api-keys.d.ts +0 -140
- package/dist/functions/api-keys.d.ts.map +0 -1
- package/dist/functions/apps.d.ts +0 -163
- package/dist/functions/apps.d.ts.map +0 -1
- package/dist/functions/auth.d.ts +0 -74
- package/dist/functions/auth.d.ts.map +0 -1
- package/dist/functions/debug-auth.d.ts +0 -33
- package/dist/functions/debug-auth.d.ts.map +0 -1
- package/dist/functions/embeddings.d.ts +0 -205
- package/dist/functions/embeddings.d.ts.map +0 -1
- package/dist/functions/integration-routes.d.ts +0 -45
- package/dist/functions/integration-routes.d.ts.map +0 -1
- package/dist/functions/integrations.d.ts +0 -124
- package/dist/functions/integrations.d.ts.map +0 -1
- package/dist/functions/item-progress.d.ts +0 -41
- package/dist/functions/item-progress.d.ts.map +0 -1
- package/dist/functions/logs.d.ts +0 -162
- package/dist/functions/logs.d.ts.map +0 -1
- package/dist/functions/observability.d.ts +0 -123
- package/dist/functions/observability.d.ts.map +0 -1
- package/dist/functions/pipeline-executions.d.ts +0 -190
- package/dist/functions/pipeline-executions.d.ts.map +0 -1
- package/dist/functions/pipelines.d.ts +0 -171
- package/dist/functions/pipelines.d.ts.map +0 -1
- package/dist/functions/prompt-configs.d.ts +0 -125
- package/dist/functions/prompt-configs.d.ts.map +0 -1
- package/dist/functions/roles.d.ts +0 -118
- package/dist/functions/roles.d.ts.map +0 -1
- package/dist/functions/system-cron.d.ts +0 -65
- package/dist/functions/system-cron.d.ts.map +0 -1
- package/dist/functions/system.d.ts +0 -29
- package/dist/functions/system.d.ts.map +0 -1
- package/dist/functions/tests.d.ts +0 -28
- package/dist/functions/tests.d.ts.map +0 -1
- package/dist/functions/timers.d.ts +0 -139
- package/dist/functions/timers.d.ts.map +0 -1
- package/dist/functions/triggers.d.ts +0 -203
- package/dist/functions/triggers.d.ts.map +0 -1
- package/dist/functions/types.d.ts +0 -151
- package/dist/functions/types.d.ts.map +0 -1
- package/dist/src/types/types.d.ts +0 -364
- package/dist/src/types/types.d.ts.map +0 -1
- package/index.html +0 -13
- package/netlify.toml +0 -36
- package/package-project.json +0 -71
- package/scripts/app-install-cli.ts +0 -286
- package/scripts/assemble-frontend.sh +0 -76
- package/scripts/assemble-functions.sh +0 -62
- package/scripts/assemble.sh +0 -41
- package/scripts/boundary-check.sh +0 -106
- package/scripts/build-manifest.sh +0 -80
- package/scripts/check-core-integrity.sh +0 -82
- package/scripts/ingest-chunks.cjs +0 -202
- package/scripts/kb-chunk-parser.cjs +0 -312
- package/scripts/kb-chunk-parser.ts +0 -330
- package/scripts/load-test-app-install.ts +0 -484
- package/scripts/netlify-dev-wrapper.sh +0 -22
- package/scripts/verify-integrity.sh +0 -69
- package/vitest.config.ts +0 -45
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @component AgentView
|
|
3
|
-
* @audience installer
|
|
4
|
-
* @layer component
|
|
5
|
-
* @stability stable
|
|
6
|
-
*
|
|
7
|
-
* Agent View toggle component for exposing raw API data and code examples.
|
|
8
|
-
* Provides agents (and developers) with:
|
|
9
|
-
* - Raw JSON of current record/page data
|
|
10
|
-
* - Copy-pasteable API calls (curl/fetch)
|
|
11
|
-
* - Equivalent CLI commands
|
|
12
|
-
*
|
|
13
|
-
* **Usage:**
|
|
14
|
-
* ```tsx
|
|
15
|
-
* <AgentView
|
|
16
|
-
* data={recordData}
|
|
17
|
-
* endpoint="/.netlify/functions/items"
|
|
18
|
-
* method="GET"
|
|
19
|
-
* query={{ id: recordId }}
|
|
20
|
-
* />
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* **Features:**
|
|
24
|
-
* - Collapsible panel (closed by default)
|
|
25
|
-
* - Copy to clipboard buttons
|
|
26
|
-
* - Syntax highlighting for JSON
|
|
27
|
-
* - Responsive layout
|
|
28
|
-
*
|
|
29
|
-
* @seeAlso hooks/useApi.ts (API call logging)
|
|
30
|
-
* @seeAlso pages/admin/* (admin pages using this component)
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
import React, { useState, useEffect } from 'react'
|
|
34
|
-
import { Code, Terminal, Copy, Check, ChevronDown, ChevronUp } from 'lucide-react'
|
|
35
|
-
|
|
36
|
-
interface AgentViewProps {
|
|
37
|
-
/** The raw data object to display */
|
|
38
|
-
data: any
|
|
39
|
-
/** API endpoint path */
|
|
40
|
-
endpoint: string
|
|
41
|
-
/** HTTP method */
|
|
42
|
-
method?: 'GET' | 'POST' | 'PATCH' | 'DELETE'
|
|
43
|
-
/** Query parameters used */
|
|
44
|
-
query?: Record<string, any>
|
|
45
|
-
/** Request body (for POST/PATCH) */
|
|
46
|
-
body?: any
|
|
47
|
-
/** Optional title override */
|
|
48
|
-
title?: string
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function AgentView({
|
|
52
|
-
data,
|
|
53
|
-
endpoint,
|
|
54
|
-
method = 'GET',
|
|
55
|
-
query,
|
|
56
|
-
body,
|
|
57
|
-
title = 'Agent View'
|
|
58
|
-
}: AgentViewProps) {
|
|
59
|
-
const [isOpen, setIsOpen] = useState(false)
|
|
60
|
-
const [copied, setCopied] = useState<string | null>(null)
|
|
61
|
-
|
|
62
|
-
// Build API URL
|
|
63
|
-
const baseUrl = window.location.origin
|
|
64
|
-
const fullUrl = `${baseUrl}${endpoint}${query ? '?' + new URLSearchParams(query).toString() : ''}`
|
|
65
|
-
|
|
66
|
-
// Generate curl command
|
|
67
|
-
const curlCmd = `curl -X ${method} \\
|
|
68
|
-
${method !== 'GET' ? `-H "Content-Type: application/json" \\
|
|
69
|
-
` : ''}${baseUrl}${endpoint}${query ? '?' + new URLSearchParams(query).toString() : ''}${method !== 'GET' && body ? ` \\
|
|
70
|
-
-d '${JSON.stringify(body, null, 2)}'` : ''}`
|
|
71
|
-
|
|
72
|
-
// Generate fetch code
|
|
73
|
-
const fetchCode = `fetch('${baseUrl}${endpoint}${query ? '?' + new URLSearchParams(query).toString() : ''}', {
|
|
74
|
-
method: '${method}',${method !== 'GET' ? `
|
|
75
|
-
headers: { 'Content-Type': 'application/json' },` : ''}${method !== 'GET' && body ? `
|
|
76
|
-
body: JSON.stringify(${JSON.stringify(body, null, 2).replace(/\n/g, '\n ')})` : ''}
|
|
77
|
-
})
|
|
78
|
-
.then(r => r.json())
|
|
79
|
-
.then(data => console.log(data))`
|
|
80
|
-
|
|
81
|
-
// Generate CLI command
|
|
82
|
-
const cliCmd = `spine ${endpoint.replace('/.netlify/functions/', '').replace(/\//g, ' ')} ${query?.id || query?.slug || ''}${method === 'POST' && body ? ` --data '${JSON.stringify(body)}'` : ''}${method === 'PATCH' && body ? ` --update '${JSON.stringify(body)}'` : ''}${method === 'DELETE' ? ' --delete' : ''}`
|
|
83
|
-
|
|
84
|
-
const handleCopy = (text: string, key: string) => {
|
|
85
|
-
navigator.clipboard.writeText(text)
|
|
86
|
-
setCopied(key)
|
|
87
|
-
setTimeout(() => setCopied(null), 2000)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<div className="mt-6 border border-gray-200 rounded-lg bg-gray-50">
|
|
92
|
-
{/* Header */}
|
|
93
|
-
<button
|
|
94
|
-
onClick={() => setIsOpen(!isOpen)}
|
|
95
|
-
className="w-full flex items-center justify-between px-4 py-3 text-left hover:bg-gray-100 transition-colors"
|
|
96
|
-
>
|
|
97
|
-
<div className="flex items-center gap-2">
|
|
98
|
-
<Terminal className="w-4 h-4 text-gray-600" />
|
|
99
|
-
<span className="font-medium text-gray-700">{title}</span>
|
|
100
|
-
<span className="text-xs text-gray-500">(for agents & developers)</span>
|
|
101
|
-
</div>
|
|
102
|
-
{isOpen ? (
|
|
103
|
-
<ChevronUp className="w-4 h-4 text-gray-500" />
|
|
104
|
-
) : (
|
|
105
|
-
<ChevronDown className="w-4 h-4 text-gray-500" />
|
|
106
|
-
)}
|
|
107
|
-
</button>
|
|
108
|
-
|
|
109
|
-
{/* Content */}
|
|
110
|
-
{isOpen && (
|
|
111
|
-
<div className="border-t border-gray-200">
|
|
112
|
-
{/* API Info */}
|
|
113
|
-
<div className="px-4 py-3 bg-blue-50 border-b border-blue-100">
|
|
114
|
-
<div className="flex items-center gap-2 text-sm text-blue-800">
|
|
115
|
-
<span className="font-mono font-bold">{method}</span>
|
|
116
|
-
<span className="font-mono">{endpoint}</span>
|
|
117
|
-
{query && (
|
|
118
|
-
<span className="text-blue-600">
|
|
119
|
-
with query: {JSON.stringify(query)}
|
|
120
|
-
</span>
|
|
121
|
-
)}
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
|
|
125
|
-
<div className="p-4 space-y-4">
|
|
126
|
-
{/* Raw JSON */}
|
|
127
|
-
<div>
|
|
128
|
-
<div className="flex items-center justify-between mb-2">
|
|
129
|
-
<div className="flex items-center gap-2 text-sm font-medium text-gray-700">
|
|
130
|
-
<Code className="w-4 h-4" />
|
|
131
|
-
Response JSON
|
|
132
|
-
</div>
|
|
133
|
-
<button
|
|
134
|
-
onClick={() => handleCopy(JSON.stringify(data, null, 2), 'json')}
|
|
135
|
-
className="flex items-center gap-1 text-xs text-gray-500 hover:text-gray-700"
|
|
136
|
-
>
|
|
137
|
-
{copied === 'json' ? (
|
|
138
|
-
<Check className="w-3 h-3" />
|
|
139
|
-
) : (
|
|
140
|
-
<Copy className="w-3 h-3" />
|
|
141
|
-
)}
|
|
142
|
-
{copied === 'json' ? 'Copied!' : 'Copy'}
|
|
143
|
-
</button>
|
|
144
|
-
</div>
|
|
145
|
-
<pre className="bg-gray-900 text-gray-100 p-3 rounded text-xs overflow-auto max-h-64 font-mono">
|
|
146
|
-
{JSON.stringify(data, null, 2)}
|
|
147
|
-
</pre>
|
|
148
|
-
</div>
|
|
149
|
-
|
|
150
|
-
{/* Code Examples */}
|
|
151
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
152
|
-
{/* cURL */}
|
|
153
|
-
<div>
|
|
154
|
-
<div className="flex items-center justify-between mb-2">
|
|
155
|
-
<div className="text-sm font-medium text-gray-700">cURL</div>
|
|
156
|
-
<button
|
|
157
|
-
onClick={() => handleCopy(curlCmd, 'curl')}
|
|
158
|
-
className="flex items-center gap-1 text-xs text-gray-500 hover:text-gray-700"
|
|
159
|
-
>
|
|
160
|
-
{copied === 'curl' ? <Check className="w-3 h-3" /> : <Copy className="w-3 h-3" />}
|
|
161
|
-
{copied === 'curl' ? 'Copied!' : 'Copy'}
|
|
162
|
-
</button>
|
|
163
|
-
</div>
|
|
164
|
-
<pre className="bg-gray-800 text-gray-100 p-3 rounded text-xs overflow-auto max-h-32 font-mono">
|
|
165
|
-
{curlCmd}
|
|
166
|
-
</pre>
|
|
167
|
-
</div>
|
|
168
|
-
|
|
169
|
-
{/* Fetch */}
|
|
170
|
-
<div>
|
|
171
|
-
<div className="flex items-center justify-between mb-2">
|
|
172
|
-
<div className="text-sm font-medium text-gray-700">JavaScript Fetch</div>
|
|
173
|
-
<button
|
|
174
|
-
onClick={() => handleCopy(fetchCode, 'fetch')}
|
|
175
|
-
className="flex items-center gap-1 text-xs text-gray-500 hover:text-gray-700"
|
|
176
|
-
>
|
|
177
|
-
{copied === 'fetch' ? <Check className="w-3 h-3" /> : <Copy className="w-3 h-3" />}
|
|
178
|
-
{copied === 'fetch' ? 'Copied!' : 'Copy'}
|
|
179
|
-
</button>
|
|
180
|
-
</div>
|
|
181
|
-
<pre className="bg-gray-800 text-gray-100 p-3 rounded text-xs overflow-auto max-h-32 font-mono">
|
|
182
|
-
{fetchCode}
|
|
183
|
-
</pre>
|
|
184
|
-
</div>
|
|
185
|
-
</div>
|
|
186
|
-
|
|
187
|
-
{/* CLI Command */}
|
|
188
|
-
<div>
|
|
189
|
-
<div className="flex items-center justify-between mb-2">
|
|
190
|
-
<div className="flex items-center gap-2 text-sm font-medium text-gray-700">
|
|
191
|
-
<Terminal className="w-4 h-4" />
|
|
192
|
-
Spine CLI
|
|
193
|
-
</div>
|
|
194
|
-
<button
|
|
195
|
-
onClick={() => handleCopy(cliCmd, 'cli')}
|
|
196
|
-
className="flex items-center gap-1 text-xs text-gray-500 hover:text-gray-700"
|
|
197
|
-
>
|
|
198
|
-
{copied === 'cli' ? <Check className="w-3 h-3" /> : <Copy className="w-3 h-3" />}
|
|
199
|
-
{copied === 'cli' ? 'Copied!' : 'Copy'}
|
|
200
|
-
</button>
|
|
201
|
-
</div>
|
|
202
|
-
<pre className="bg-green-900 text-green-100 p-3 rounded text-xs overflow-auto font-mono">
|
|
203
|
-
{cliCmd}
|
|
204
|
-
</pre>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
208
|
-
)}
|
|
209
|
-
</div>
|
|
210
|
-
)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export default AgentView
|
|
@@ -1,478 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module src/components/shared/FieldRenderer
|
|
3
|
-
* @audience installer
|
|
4
|
-
* @layer frontend-component
|
|
5
|
-
* @stability stable
|
|
6
|
-
*
|
|
7
|
-
* Low-level field rendering primitive. Given a `FieldDefinition` and a
|
|
8
|
-
* current value, renders the appropriate input widget (edit mode) or
|
|
9
|
-
* display element (read-only mode).
|
|
10
|
-
*
|
|
11
|
-
* **Render type resolution** (`resolveRenderType`):
|
|
12
|
-
* 1. If `displayType` is set (from the view config), it maps to a canonical
|
|
13
|
-
* render type first — this lets a view override how a field looks without
|
|
14
|
-
* changing the underlying `FieldDefinition`.
|
|
15
|
-
* 2. Falls back to `field.data_type`.
|
|
16
|
-
*
|
|
17
|
-
* **Supported render types:**
|
|
18
|
-
* `text`, `textarea`, `email`, `phone`, `url`, `number`, `date`,
|
|
19
|
-
* `datetime`, `select`, `multiselect`, `radio`, `checkbox`, `json`,
|
|
20
|
-
* `file`, `color`, `range`
|
|
21
|
-
*
|
|
22
|
-
* **Error display:** when `error` is set, a red helper text is shown below
|
|
23
|
-
* the field and `border-red-500` is applied where applicable.
|
|
24
|
-
*
|
|
25
|
-
* **Label + description:** rendered above / below the input respectively,
|
|
26
|
-
* with a red `*` suffix when `field.required` is true.
|
|
27
|
-
*
|
|
28
|
-
* @seeAlso src/components/shared/SchemaFields.tsx (mounts this component)
|
|
29
|
-
* @seeAlso src/types/types.ts (FieldDefinition)
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
import React from 'react'
|
|
33
|
-
import { FieldDefinition } from '../../types/types'
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Props for `FieldRenderer`.
|
|
37
|
-
*
|
|
38
|
-
* @prop field - Full field definition including data_type, options, validation
|
|
39
|
-
* @prop value - Current controlled value
|
|
40
|
-
* @prop onChange - Value change callback (omit or pass `undefined` for read-only)
|
|
41
|
-
* @prop onBlur - Optional blur callback for validation triggers
|
|
42
|
-
* @prop readonly - If true, renders a display element instead of an input
|
|
43
|
-
* @prop error - Validation error message to display below the field
|
|
44
|
-
* @prop displayType - View-config widget override (e.g. `'textarea'`, `'select'`)
|
|
45
|
-
*/
|
|
46
|
-
interface FieldRendererProps {
|
|
47
|
-
field: FieldDefinition
|
|
48
|
-
value: any
|
|
49
|
-
onChange?: (value: any) => void
|
|
50
|
-
onBlur?: () => void
|
|
51
|
-
readonly?: boolean
|
|
52
|
-
error?: string
|
|
53
|
-
displayType?: string // From view config — controls rendering without polluting field data contract
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Resolves the canonical render type for a field.
|
|
58
|
-
*
|
|
59
|
-
* `displayType` (from view config) takes precedence over `field.data_type`
|
|
60
|
-
* so view authors can choose a different widget without changing the
|
|
61
|
-
* underlying schema.
|
|
62
|
-
*
|
|
63
|
-
* @param field - Field definition
|
|
64
|
-
* @param displayType - Optional view-config widget override
|
|
65
|
-
* @returns Canonical render type string (e.g. `'text'`, `'select'`, `'checkbox'`)
|
|
66
|
-
*/
|
|
67
|
-
function resolveRenderType(field: FieldDefinition, displayType?: string): string {
|
|
68
|
-
// displayType from view config overrides data_type for rendering decisions
|
|
69
|
-
if (displayType) {
|
|
70
|
-
switch (displayType) {
|
|
71
|
-
case 'textarea':
|
|
72
|
-
case 'rich_text':
|
|
73
|
-
return 'textarea'
|
|
74
|
-
case 'select':
|
|
75
|
-
return 'select'
|
|
76
|
-
case 'multiselect':
|
|
77
|
-
return 'multiselect'
|
|
78
|
-
case 'radio':
|
|
79
|
-
return 'radio'
|
|
80
|
-
case 'checkbox':
|
|
81
|
-
case 'switch':
|
|
82
|
-
return 'checkbox'
|
|
83
|
-
case 'date_picker':
|
|
84
|
-
return 'date'
|
|
85
|
-
case 'datetime_picker':
|
|
86
|
-
return 'datetime'
|
|
87
|
-
case 'color_picker':
|
|
88
|
-
return 'color'
|
|
89
|
-
case 'range_slider':
|
|
90
|
-
return 'range'
|
|
91
|
-
case 'file_upload':
|
|
92
|
-
case 'image_upload':
|
|
93
|
-
return 'file'
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// Fall back to data_type
|
|
97
|
-
switch (field.data_type) {
|
|
98
|
-
case 'textarea':
|
|
99
|
-
case 'rich_text':
|
|
100
|
-
return 'textarea'
|
|
101
|
-
case 'email':
|
|
102
|
-
return 'email'
|
|
103
|
-
case 'phone':
|
|
104
|
-
return 'phone'
|
|
105
|
-
case 'url':
|
|
106
|
-
return 'url'
|
|
107
|
-
case 'number':
|
|
108
|
-
case 'currency':
|
|
109
|
-
case 'range':
|
|
110
|
-
return 'number'
|
|
111
|
-
case 'date':
|
|
112
|
-
return 'date'
|
|
113
|
-
case 'datetime':
|
|
114
|
-
return 'datetime'
|
|
115
|
-
case 'boolean':
|
|
116
|
-
case 'checkbox':
|
|
117
|
-
return 'checkbox'
|
|
118
|
-
case 'select':
|
|
119
|
-
return 'select'
|
|
120
|
-
case 'multiselect':
|
|
121
|
-
return 'multiselect'
|
|
122
|
-
case 'radio':
|
|
123
|
-
return 'radio'
|
|
124
|
-
case 'color':
|
|
125
|
-
return 'color'
|
|
126
|
-
case 'file':
|
|
127
|
-
case 'image':
|
|
128
|
-
return 'file'
|
|
129
|
-
case 'json':
|
|
130
|
-
return 'json'
|
|
131
|
-
default:
|
|
132
|
-
return 'text'
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Renders a single schema field as an input widget or read-only display.
|
|
138
|
-
*
|
|
139
|
-
* @param props - `FieldRendererProps`
|
|
140
|
-
* @returns Label + field widget + description + error message
|
|
141
|
-
* @sideEffects none (delegates changes to `onChange`)
|
|
142
|
-
*/
|
|
143
|
-
export function FieldRenderer({ field, value, onChange, readonly = false, error, displayType }: FieldRendererProps) {
|
|
144
|
-
const renderType = resolveRenderType(field, displayType)
|
|
145
|
-
|
|
146
|
-
const renderField = () => {
|
|
147
|
-
switch (renderType) {
|
|
148
|
-
case 'text':
|
|
149
|
-
return readonly ? (
|
|
150
|
-
<div className={`text-slate-900 ${error ? 'border-red-500' : ''}`}>
|
|
151
|
-
{value || <span className="text-slate-400 italic">—</span>}
|
|
152
|
-
</div>
|
|
153
|
-
) : (
|
|
154
|
-
<input
|
|
155
|
-
type="text"
|
|
156
|
-
value={value || ''}
|
|
157
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
158
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
159
|
-
placeholder={field.placeholder}
|
|
160
|
-
/>
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
case 'textarea':
|
|
164
|
-
return readonly ? (
|
|
165
|
-
<div className={`text-slate-900 whitespace-pre-wrap ${error ? 'border-red-500' : ''}`}>
|
|
166
|
-
{value || <span className="text-slate-400 italic">—</span>}
|
|
167
|
-
</div>
|
|
168
|
-
) : (
|
|
169
|
-
<textarea
|
|
170
|
-
value={value || ''}
|
|
171
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
172
|
-
className={`textarea ${error ? 'border-red-500' : ''}`}
|
|
173
|
-
placeholder={field.placeholder}
|
|
174
|
-
rows={field.rows || 3}
|
|
175
|
-
/>
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
case 'email':
|
|
179
|
-
return readonly ? (
|
|
180
|
-
<div className={`text-slate-900 ${error ? 'border-red-500' : ''}`}>
|
|
181
|
-
{value ? <a href={`mailto:${value}`} className="text-blue-600 hover:text-blue-800">{value}</a> : <span className="text-slate-400 italic">—</span>}
|
|
182
|
-
</div>
|
|
183
|
-
) : (
|
|
184
|
-
<input
|
|
185
|
-
type="email"
|
|
186
|
-
value={value || ''}
|
|
187
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
188
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
189
|
-
placeholder={field.placeholder}
|
|
190
|
-
/>
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
case 'phone':
|
|
194
|
-
return readonly ? (
|
|
195
|
-
<div className={`text-slate-900 ${error ? 'border-red-500' : ''}`}>
|
|
196
|
-
{value || <span className="text-slate-400 italic">—</span>}
|
|
197
|
-
</div>
|
|
198
|
-
) : (
|
|
199
|
-
<input
|
|
200
|
-
type="tel"
|
|
201
|
-
value={value || ''}
|
|
202
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
203
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
204
|
-
placeholder={field.placeholder}
|
|
205
|
-
/>
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
case 'number':
|
|
209
|
-
return (
|
|
210
|
-
<input
|
|
211
|
-
type="number"
|
|
212
|
-
value={value ?? ''}
|
|
213
|
-
onChange={(e) => onChange?.(e.target.value ? Number(e.target.value) : null)}
|
|
214
|
-
readOnly={readonly}
|
|
215
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
216
|
-
placeholder={field.placeholder}
|
|
217
|
-
min={field.min ?? field.validation?.min}
|
|
218
|
-
max={field.max ?? field.validation?.max}
|
|
219
|
-
step={field.step ?? field.validation?.step}
|
|
220
|
-
/>
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
case 'date':
|
|
224
|
-
return (
|
|
225
|
-
<input
|
|
226
|
-
type="date"
|
|
227
|
-
value={value ? new Date(value).toISOString().split('T')[0] : ''}
|
|
228
|
-
onChange={(e) => onChange?.(e.target.value || null)}
|
|
229
|
-
readOnly={readonly}
|
|
230
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
231
|
-
/>
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
case 'datetime':
|
|
235
|
-
return (
|
|
236
|
-
<input
|
|
237
|
-
type="datetime-local"
|
|
238
|
-
value={value ? new Date(value).toISOString().slice(0, 16) : ''}
|
|
239
|
-
onChange={(e) => onChange?.(e.target.value || null)}
|
|
240
|
-
readOnly={readonly}
|
|
241
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
242
|
-
/>
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
case 'select':
|
|
246
|
-
return readonly ? (
|
|
247
|
-
<div className={`text-slate-900 ${error ? 'border-red-500' : ''}`}>
|
|
248
|
-
{(() => {
|
|
249
|
-
if (!value) return <span className="text-slate-400 italic">—</span>
|
|
250
|
-
const option = field.options?.find((opt) => {
|
|
251
|
-
const optVal = typeof opt === 'string' ? opt : opt.value
|
|
252
|
-
return optVal === value
|
|
253
|
-
})
|
|
254
|
-
return typeof option === 'string' ? option : option?.label || value
|
|
255
|
-
})()}
|
|
256
|
-
</div>
|
|
257
|
-
) : (
|
|
258
|
-
<select
|
|
259
|
-
value={value || ''}
|
|
260
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
261
|
-
className={`select ${error ? 'border-red-500' : ''}`}
|
|
262
|
-
>
|
|
263
|
-
<option value="">Select...</option>
|
|
264
|
-
{field.options?.map((option) => {
|
|
265
|
-
const optVal = typeof option === 'string' ? option : option.value
|
|
266
|
-
const optLabel = typeof option === 'string' ? option : option.label
|
|
267
|
-
return (
|
|
268
|
-
<option key={optVal} value={optVal}>
|
|
269
|
-
{optLabel}
|
|
270
|
-
</option>
|
|
271
|
-
)
|
|
272
|
-
})}
|
|
273
|
-
</select>
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
case 'multiselect':
|
|
277
|
-
return (
|
|
278
|
-
<div className="space-y-2">
|
|
279
|
-
{field.options?.map((option) => {
|
|
280
|
-
const optionValue = typeof option === 'string' ? option : option.value
|
|
281
|
-
const optionLabel = typeof option === 'string' ? option : option.label
|
|
282
|
-
return (
|
|
283
|
-
<label key={optionValue} className="flex items-center">
|
|
284
|
-
<input
|
|
285
|
-
type="checkbox"
|
|
286
|
-
checked={Array.isArray(value) && value.includes(optionValue)}
|
|
287
|
-
onChange={(e) => {
|
|
288
|
-
const currentValue = Array.isArray(value) ? value : []
|
|
289
|
-
if (e.target.checked) {
|
|
290
|
-
onChange?.([...currentValue, optionValue])
|
|
291
|
-
} else {
|
|
292
|
-
onChange?.(currentValue.filter((v: string) => v !== optionValue))
|
|
293
|
-
}
|
|
294
|
-
}}
|
|
295
|
-
disabled={readonly}
|
|
296
|
-
className="mr-2"
|
|
297
|
-
/>
|
|
298
|
-
<span>{optionLabel}</span>
|
|
299
|
-
</label>
|
|
300
|
-
)
|
|
301
|
-
})}
|
|
302
|
-
</div>
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
case 'radio':
|
|
306
|
-
return (
|
|
307
|
-
<div className="space-y-2">
|
|
308
|
-
{field.options?.map((option) => {
|
|
309
|
-
const optionValue = typeof option === 'string' ? option : option.value
|
|
310
|
-
const optionLabel = typeof option === 'string' ? option : option.label
|
|
311
|
-
return (
|
|
312
|
-
<label key={optionValue} className="flex items-center">
|
|
313
|
-
<input
|
|
314
|
-
type="radio"
|
|
315
|
-
name={field.name}
|
|
316
|
-
value={optionValue}
|
|
317
|
-
checked={value === optionValue}
|
|
318
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
319
|
-
disabled={readonly}
|
|
320
|
-
className="mr-2"
|
|
321
|
-
/>
|
|
322
|
-
<span>{optionLabel}</span>
|
|
323
|
-
</label>
|
|
324
|
-
)
|
|
325
|
-
})}
|
|
326
|
-
</div>
|
|
327
|
-
)
|
|
328
|
-
|
|
329
|
-
case 'checkbox':
|
|
330
|
-
return readonly ? (
|
|
331
|
-
<div className={`text-slate-900 ${error ? 'border-red-500' : ''}`}>
|
|
332
|
-
{Boolean(value) ? 'Yes' : 'No'}
|
|
333
|
-
</div>
|
|
334
|
-
) : (
|
|
335
|
-
<label className="flex items-center">
|
|
336
|
-
<input
|
|
337
|
-
type="checkbox"
|
|
338
|
-
checked={Boolean(value)}
|
|
339
|
-
onChange={(e) => onChange?.(e.target.checked)}
|
|
340
|
-
className="mr-2"
|
|
341
|
-
/>
|
|
342
|
-
<span>{field.label}</span>
|
|
343
|
-
</label>
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
case 'json':
|
|
347
|
-
return readonly ? (
|
|
348
|
-
<pre className="bg-slate-100 p-3 rounded-md text-sm overflow-x-auto">
|
|
349
|
-
{JSON.stringify(value, null, 2)}
|
|
350
|
-
</pre>
|
|
351
|
-
) : (
|
|
352
|
-
<textarea
|
|
353
|
-
value={typeof value === 'string' ? value : JSON.stringify(value, null, 2)}
|
|
354
|
-
onChange={(e) => {
|
|
355
|
-
try {
|
|
356
|
-
onChange?.(JSON.parse(e.target.value))
|
|
357
|
-
} catch {
|
|
358
|
-
// Invalid JSON, don't update
|
|
359
|
-
}
|
|
360
|
-
}}
|
|
361
|
-
className={`textarea font-mono text-sm ${error ? 'border-red-500' : ''}`}
|
|
362
|
-
rows={field.rows || 6}
|
|
363
|
-
placeholder="Enter valid JSON"
|
|
364
|
-
/>
|
|
365
|
-
)
|
|
366
|
-
|
|
367
|
-
case 'url':
|
|
368
|
-
return readonly ? (
|
|
369
|
-
<div className={`text-slate-900 ${error ? 'border-red-500' : ''}`}>
|
|
370
|
-
{value ? <a href={value} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-800">{value}</a> : <span className="text-slate-400 italic">—</span>}
|
|
371
|
-
</div>
|
|
372
|
-
) : (
|
|
373
|
-
<input
|
|
374
|
-
type="url"
|
|
375
|
-
value={value || ''}
|
|
376
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
377
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
378
|
-
placeholder={field.placeholder || 'https://example.com'}
|
|
379
|
-
/>
|
|
380
|
-
)
|
|
381
|
-
|
|
382
|
-
case 'file':
|
|
383
|
-
return readonly ? (
|
|
384
|
-
value ? (
|
|
385
|
-
<div className="text-sm">
|
|
386
|
-
<a href={value} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-800">
|
|
387
|
-
View File
|
|
388
|
-
</a>
|
|
389
|
-
</div>
|
|
390
|
-
) : (
|
|
391
|
-
<span className="text-slate-500">No file</span>
|
|
392
|
-
)
|
|
393
|
-
) : (
|
|
394
|
-
<input
|
|
395
|
-
type="file"
|
|
396
|
-
onChange={(e) => {
|
|
397
|
-
const file = e.target.files?.[0]
|
|
398
|
-
if (file) onChange?.(file.name)
|
|
399
|
-
}}
|
|
400
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
401
|
-
/>
|
|
402
|
-
)
|
|
403
|
-
|
|
404
|
-
case 'color':
|
|
405
|
-
return (
|
|
406
|
-
<div className="flex items-center space-x-2">
|
|
407
|
-
<input
|
|
408
|
-
type="color"
|
|
409
|
-
value={value || '#000000'}
|
|
410
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
411
|
-
disabled={readonly}
|
|
412
|
-
className="h-10 w-20"
|
|
413
|
-
/>
|
|
414
|
-
<input
|
|
415
|
-
type="text"
|
|
416
|
-
value={value || ''}
|
|
417
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
418
|
-
readOnly={readonly}
|
|
419
|
-
className={`input flex-1 ${error ? 'border-red-500' : ''}`}
|
|
420
|
-
placeholder="#000000"
|
|
421
|
-
/>
|
|
422
|
-
</div>
|
|
423
|
-
)
|
|
424
|
-
|
|
425
|
-
case 'range':
|
|
426
|
-
return (
|
|
427
|
-
<div className="space-y-2">
|
|
428
|
-
<input
|
|
429
|
-
type="range"
|
|
430
|
-
value={value ?? field.min ?? field.validation?.min ?? 0}
|
|
431
|
-
onChange={(e) => onChange?.(Number(e.target.value))}
|
|
432
|
-
disabled={readonly}
|
|
433
|
-
className="w-full"
|
|
434
|
-
min={field.min ?? field.validation?.min}
|
|
435
|
-
max={field.max ?? field.validation?.max}
|
|
436
|
-
step={field.step ?? field.validation?.step}
|
|
437
|
-
/>
|
|
438
|
-
<div className="text-sm text-slate-600">
|
|
439
|
-
Value: {value ?? field.min ?? 0}
|
|
440
|
-
</div>
|
|
441
|
-
</div>
|
|
442
|
-
)
|
|
443
|
-
|
|
444
|
-
default:
|
|
445
|
-
return (
|
|
446
|
-
<input
|
|
447
|
-
type="text"
|
|
448
|
-
value={value || ''}
|
|
449
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
450
|
-
readOnly={readonly}
|
|
451
|
-
className={`input ${error ? 'border-red-500' : ''}`}
|
|
452
|
-
placeholder={field.placeholder}
|
|
453
|
-
/>
|
|
454
|
-
)
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
return (
|
|
459
|
-
<div className="space-y-1">
|
|
460
|
-
{field.label && (
|
|
461
|
-
<label className="label">
|
|
462
|
-
{field.label}
|
|
463
|
-
{field.required && <span className="text-red-500 ml-1">*</span>}
|
|
464
|
-
</label>
|
|
465
|
-
)}
|
|
466
|
-
|
|
467
|
-
{renderField()}
|
|
468
|
-
|
|
469
|
-
{field.description && (
|
|
470
|
-
<p className="text-xs text-slate-500">{field.description}</p>
|
|
471
|
-
)}
|
|
472
|
-
|
|
473
|
-
{error && (
|
|
474
|
-
<p className="text-xs text-red-600">{error}</p>
|
|
475
|
-
)}
|
|
476
|
-
</div>
|
|
477
|
-
)
|
|
478
|
-
}
|