@jini-ai/admin 0.4.1 → 0.4.3
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/CHANGELOG.md +20 -0
- package/README.md +7 -0
- package/dist/agent-plugins/react/components/AgentPluginFileTree.js +1 -1
- package/dist/agent-plugins/react/components/AgentPluginListPanel.d.ts +1 -1
- package/dist/agent-plugins/react/hooks/AgentPluginInspector.hooks.d.ts +0 -1
- package/dist/agent-plugins/react/hooks/AgentPluginInspector.hooks.js +7 -6
- package/dist/agent-plugins/react/hooks/AgentPluginPanel.hooks.d.ts +1 -1
- package/dist/agent-plugins/react/hooks/AgentPluginPanel.hooks.js +3 -2
- package/dist/agent-plugins/react/hooks/AgentPluginsPage.hooks.d.ts +1 -1
- package/dist/agent-plugins/react/hooks/AgentPluginsPage.hooks.js +1 -1
- package/dist/agent-plugins/react/hooks/MarketplaceTab.hooks.d.ts +1 -1
- package/dist/agent-plugins/react/index.js +1 -1
- package/dist/agent-plugins/react/pages/AgentPluginsPage.d.ts +1 -1
- package/dist/agent-plugins/react/tabs/DownloadedTab.d.ts +1 -1
- package/dist/agent-plugins/react/tabs/InstalledTab.d.ts +1 -1
- package/dist/agent-plugins/react/tabs/MarketplaceTab.d.ts +1 -1
- package/dist/comments/adapters/http.d.ts +29 -0
- package/dist/comments/adapters/http.js +50 -0
- package/dist/comments/adapters/memory.d.ts +17 -0
- package/dist/comments/adapters/memory.js +61 -0
- package/dist/comments/comments.module.d.ts +73 -0
- package/dist/comments/comments.module.js +16 -0
- package/dist/comments/conformance/comments-api.conformance.d.ts +9 -0
- package/dist/comments/conformance/comments-api.conformance.js +63 -0
- package/dist/comments/controllers/comment-queue.controller.d.ts +48 -0
- package/dist/comments/controllers/comment-queue.controller.js +164 -0
- package/dist/comments/controllers/comment-settings.controller.d.ts +32 -0
- package/dist/comments/controllers/comment-settings.controller.js +77 -0
- package/dist/comments/controllers/comments.controller.d.ts +16 -0
- package/dist/comments/controllers/comments.controller.js +16 -0
- package/dist/comments/index.d.ts +13 -0
- package/dist/comments/index.js +8 -0
- package/dist/comments/messages.en.d.ts +54 -0
- package/dist/comments/messages.en.js +56 -0
- package/dist/comments/models.d.ts +22 -0
- package/dist/comments/models.js +2 -0
- package/dist/comments/ports.d.ts +14 -0
- package/dist/comments/ports.js +5 -0
- package/dist/comments/react/components/QueueSection.d.ts +30 -0
- package/dist/comments/react/components/QueueSection.js +57 -0
- package/dist/comments/react/components/SettingsSection.d.ts +14 -0
- package/dist/comments/react/components/SettingsSection.js +23 -0
- package/dist/comments/react/hooks/CommentsPage.hooks.d.ts +9 -0
- package/dist/comments/react/hooks/CommentsPage.hooks.js +10 -0
- package/dist/comments/react/hooks/CommentsPorts.hooks.d.ts +13 -0
- package/dist/comments/react/hooks/CommentsPorts.hooks.js +15 -0
- package/dist/comments/react/hooks/QueueSection.hooks.d.ts +62 -0
- package/dist/comments/react/hooks/QueueSection.hooks.js +57 -0
- package/dist/comments/react/hooks/SettingsSection.hooks.d.ts +12 -0
- package/dist/comments/react/hooks/SettingsSection.hooks.js +21 -0
- package/dist/comments/react/hooks/use-comment-queue.hooks.d.ts +34 -0
- package/dist/comments/react/hooks/use-comment-queue.hooks.js +47 -0
- package/dist/comments/react/hooks/use-comment-settings.hooks.d.ts +22 -0
- package/dist/comments/react/hooks/use-comment-settings.hooks.js +30 -0
- package/dist/comments/react/hooks/use-comments.hooks.d.ts +15 -0
- package/dist/comments/react/hooks/use-comments.hooks.js +20 -0
- package/dist/comments/react/index.d.ts +316 -0
- package/dist/comments/react/index.js +35 -0
- package/dist/comments/react/pages/CommentsPage.d.ts +12 -0
- package/dist/comments/react/pages/CommentsPage.js +15 -0
- package/dist/comments/rules.d.ts +140 -0
- package/dist/comments/rules.js +199 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.js +1 -0
- package/dist/core/ledger-slice.d.ts +90 -0
- package/dist/core/ledger-slice.js +81 -0
- package/dist/core/ports/comments.d.ts +2 -0
- package/dist/core/ports/forms.d.ts +19 -7
- package/dist/core/ports/forms.js +4 -4
- package/dist/core/ports/index.d.ts +1 -1
- package/dist/core/ports/seo.d.ts +33 -6
- package/dist/core/react/bind-react.d.ts +46 -0
- package/dist/core/react/bind-react.js +28 -0
- package/dist/core/react/index.d.ts +3 -0
- package/dist/core/react/index.js +3 -0
- package/dist/core/react/use-controller.d.ts +16 -0
- package/dist/core/react/use-controller.js +18 -0
- package/dist/forms/adapters/http.d.ts +26 -0
- package/dist/forms/adapters/http.js +43 -0
- package/dist/forms/adapters/memory.d.ts +14 -0
- package/dist/forms/adapters/memory.js +77 -0
- package/dist/forms/conformance/forms-api.conformance.d.ts +17 -0
- package/dist/forms/conformance/forms-api.conformance.js +71 -0
- package/dist/forms/controllers/draft-store.d.ts +18 -0
- package/dist/forms/controllers/draft-store.js +17 -0
- package/dist/forms/controllers/field-attributes-dialog.controller.d.ts +37 -0
- package/dist/forms/controllers/field-attributes-dialog.controller.js +27 -0
- package/dist/forms/controllers/form-editor.controller.d.ts +36 -0
- package/dist/forms/controllers/form-editor.controller.js +22 -0
- package/dist/forms/controllers/form-fields-editor.controller.d.ts +20 -0
- package/dist/forms/controllers/form-fields-editor.controller.js +10 -0
- package/dist/forms/controllers/form-submission-detail.controller.d.ts +20 -0
- package/dist/forms/controllers/form-submission-detail.controller.js +10 -0
- package/dist/forms/controllers/form-submissions.controller.d.ts +25 -0
- package/dist/forms/controllers/form-submissions.controller.js +10 -0
- package/dist/forms/controllers/forms-list.controller.d.ts +22 -0
- package/dist/forms/controllers/forms-list.controller.js +10 -0
- package/dist/forms/forms.module.d.ts +137 -0
- package/dist/forms/forms.module.js +17 -0
- package/dist/forms/html-rules.d.ts +20 -0
- package/dist/forms/html-rules.js +24 -0
- package/dist/forms/index.d.ts +14 -0
- package/dist/forms/index.js +12 -0
- package/dist/forms/messages.en.d.ts +100 -0
- package/dist/forms/messages.en.js +104 -0
- package/dist/forms/models.d.ts +29 -0
- package/dist/forms/models.js +8 -0
- package/dist/forms/ports.d.ts +26 -0
- package/dist/forms/ports.js +6 -0
- package/dist/forms/react/components/FieldAttributesDialog.d.ts +14 -0
- package/dist/forms/react/components/FieldAttributesDialog.js +47 -0
- package/dist/forms/react/components/FormEditorFieldsBody.d.ts +28 -0
- package/dist/forms/react/components/FormEditorFieldsBody.js +24 -0
- package/dist/forms/react/components/FormEditorHeaderText.d.ts +7 -0
- package/dist/forms/react/components/FormEditorHeaderText.js +8 -0
- package/dist/forms/react/components/FormEditorMainPanel.d.ts +12 -0
- package/dist/forms/react/components/FormEditorMainPanel.js +13 -0
- package/dist/forms/react/components/FormEditorTabStrip.d.ts +13 -0
- package/dist/forms/react/components/FormEditorTabStrip.js +14 -0
- package/dist/forms/react/components/FormFieldsEditor.d.ts +13 -0
- package/dist/forms/react/components/FormFieldsEditor.js +39 -0
- package/dist/forms/react/components/FormSubmissionDate.d.ts +8 -0
- package/dist/forms/react/components/FormSubmissionDate.js +5 -0
- package/dist/forms/react/components/FormSubmissionDetail.d.ts +13 -0
- package/dist/forms/react/components/FormSubmissionDetail.js +29 -0
- package/dist/forms/react/components/FormSubmissions.d.ts +12 -0
- package/dist/forms/react/components/FormSubmissions.js +46 -0
- package/dist/forms/react/hooks/FormsPorts.hooks.d.ts +41 -0
- package/dist/forms/react/hooks/FormsPorts.hooks.js +16 -0
- package/dist/forms/react/hooks/forms-view.hooks.d.ts +122 -0
- package/dist/forms/react/hooks/forms-view.hooks.js +79 -0
- package/dist/forms/react/hooks/use-field-attributes-dialog.hooks.d.ts +31 -0
- package/dist/forms/react/hooks/use-field-attributes-dialog.hooks.js +22 -0
- package/dist/forms/react/hooks/use-form-editor.hooks.d.ts +118 -0
- package/dist/forms/react/hooks/use-form-editor.hooks.js +208 -0
- package/dist/forms/react/hooks/use-form-fields-editor.hooks.d.ts +34 -0
- package/dist/forms/react/hooks/use-form-fields-editor.hooks.js +36 -0
- package/dist/forms/react/hooks/use-form-submission-date.hooks.d.ts +12 -0
- package/dist/forms/react/hooks/use-form-submission-date.hooks.js +9 -0
- package/dist/forms/react/hooks/use-form-submission-detail.hooks.d.ts +68 -0
- package/dist/forms/react/hooks/use-form-submission-detail.hooks.js +81 -0
- package/dist/forms/react/hooks/use-form-submissions.hooks.d.ts +67 -0
- package/dist/forms/react/hooks/use-form-submissions.hooks.js +110 -0
- package/dist/forms/react/hooks/use-forms-list.hooks.d.ts +78 -0
- package/dist/forms/react/hooks/use-forms-list.hooks.js +103 -0
- package/dist/forms/react/index.d.ts +449 -0
- package/dist/forms/react/index.js +35 -0
- package/dist/forms/react/pages/FormEditor.d.ts +19 -0
- package/dist/forms/react/pages/FormEditor.js +40 -0
- package/dist/forms/react/pages/FormsList.d.ts +39 -0
- package/dist/forms/react/pages/FormsList.js +55 -0
- package/dist/forms/rules.d.ts +291 -0
- package/dist/forms/rules.js +338 -0
- package/dist/media/react/hooks/EditMediaPanel.hooks.js +1 -1
- package/dist/media/react/hooks/LibraryTab.hooks.d.ts +1 -3
- package/dist/media/react/hooks/LibraryTab.hooks.js +8 -17
- package/dist/media/react/hooks/MediaCard.hooks.js +6 -20
- package/dist/media/react/hooks/MediaGrid.hooks.d.ts +2 -2
- package/dist/media/react/hooks/MediaPage.hooks.d.ts +1 -1
- package/dist/media/react/hooks/MediaPage.hooks.js +1 -1
- package/dist/media/react/hooks/MediaPicker.hooks.js +1 -1
- package/dist/media/react/hooks/ProvidersTab.hooks.js +5 -1
- package/dist/media/react/hooks/UploadButton.hooks.d.ts +9 -2
- package/dist/media/react/hooks/UploadButton.hooks.js +12 -10
- package/dist/media/react/index.js +1 -1
- package/dist/media/react/tabs/LibraryTab.d.ts +1 -1
- package/dist/media/react/tabs/ProvidersTab.d.ts +1 -1
- package/dist/playground/react/components/Canvas.d.ts +1 -1
- package/dist/playground/react/hooks/Canvas.hooks.d.ts +1 -1
- package/dist/playground/react/hooks/Canvas.hooks.js +1 -1
- package/dist/playground/react/hooks/PlaygroundPage.hooks.d.ts +1 -1
- package/dist/playground/react/index.js +1 -1
- package/dist/playground/react/pages/PlaygroundPage.d.ts +1 -1
- package/dist/playground/react/tabs/CanvasTab.d.ts +1 -1
- package/dist/react/bind-react.d.ts +1 -45
- package/dist/react/bind-react.js +2 -27
- package/dist/react/components/ConfirmDialog/ConfirmDialog.d.ts +22 -5
- package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts +2 -2
- package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js +17 -55
- package/dist/react/components/ConfirmDialog/ConfirmDialog.js +33 -70
- package/dist/react/components/RowMenu/RowMenu.hooks.d.ts +23 -16
- package/dist/react/components/RowMenu/RowMenu.hooks.js +74 -54
- package/dist/react/entities/EntityField.d.ts +1 -1
- package/dist/react/entities/EntityField.js +4 -2
- package/dist/react/entities/types.d.ts +9 -0
- package/dist/react/entities/types.js +9 -0
- package/dist/react/use-controller.d.ts +1 -15
- package/dist/react/use-controller.js +2 -17
- package/dist/redirects/adapters/http.d.ts +20 -0
- package/dist/redirects/adapters/http.js +31 -0
- package/dist/redirects/adapters/memory.d.ts +13 -0
- package/dist/redirects/adapters/memory.js +83 -0
- package/dist/redirects/conformance/redirects-api.conformance.d.ts +12 -0
- package/dist/redirects/conformance/redirects-api.conformance.js +66 -0
- package/dist/redirects/controllers/hit-count.controller.d.ts +14 -0
- package/dist/redirects/controllers/hit-count.controller.js +10 -0
- package/dist/redirects/controllers/import-redirects.controller.d.ts +28 -0
- package/dist/redirects/controllers/import-redirects.controller.js +29 -0
- package/dist/redirects/controllers/redirects.controller.d.ts +37 -0
- package/dist/redirects/controllers/redirects.controller.js +38 -0
- package/dist/redirects/index.d.ts +11 -0
- package/dist/redirects/index.js +10 -0
- package/dist/redirects/messages.en.d.ts +56 -0
- package/dist/redirects/messages.en.js +55 -0
- package/dist/redirects/models.d.ts +14 -0
- package/dist/redirects/models.js +2 -0
- package/dist/redirects/ports.d.ts +9 -0
- package/dist/redirects/ports.js +4 -0
- package/dist/redirects/react/components/HitCountCell.d.ts +19 -0
- package/dist/redirects/react/components/HitCountCell.js +19 -0
- package/dist/redirects/react/components/ImportRedirectsForm.d.ts +17 -0
- package/dist/redirects/react/components/ImportRedirectsForm.js +12 -0
- package/dist/redirects/react/hooks/RedirectsOptions.hooks.d.ts +27 -0
- package/dist/redirects/react/hooks/RedirectsOptions.hooks.js +15 -0
- package/dist/redirects/react/hooks/RedirectsPage.hooks.d.ts +50 -0
- package/dist/redirects/react/hooks/RedirectsPage.hooks.js +30 -0
- package/dist/redirects/react/hooks/RedirectsPorts.hooks.d.ts +10 -0
- package/dist/redirects/react/hooks/RedirectsPorts.hooks.js +11 -0
- package/dist/redirects/react/hooks/use-hit-count-cell.hooks.d.ts +19 -0
- package/dist/redirects/react/hooks/use-hit-count-cell.hooks.js +15 -0
- package/dist/redirects/react/hooks/use-import-redirects-form.hooks.d.ts +21 -0
- package/dist/redirects/react/hooks/use-import-redirects-form.hooks.js +25 -0
- package/dist/redirects/react/hooks/use-redirects.hooks.d.ts +34 -0
- package/dist/redirects/react/hooks/use-redirects.hooks.js +63 -0
- package/dist/redirects/react/hooks/wired.hooks.d.ts +55 -0
- package/dist/redirects/react/hooks/wired.hooks.js +31 -0
- package/dist/redirects/react/index.d.ts +316 -0
- package/dist/redirects/react/index.js +28 -0
- package/dist/redirects/react/pages/RedirectsPage.d.ts +15 -0
- package/dist/redirects/react/pages/RedirectsPage.js +20 -0
- package/dist/redirects/redirects.module.d.ts +75 -0
- package/dist/redirects/redirects.module.js +13 -0
- package/dist/redirects/rules.d.ts +131 -0
- package/dist/redirects/rules.js +134 -0
- package/dist/security/react/hooks/AccessTokensTab.hooks.d.ts +1 -1
- package/dist/security/react/hooks/AccessTokensTab.hooks.js +3 -3
- package/dist/security/react/hooks/RootKeyTab.hooks.d.ts +1 -1
- package/dist/security/react/hooks/RootKeyTab.hooks.js +3 -4
- package/dist/security/react/hooks/SecurityPage.hooks.d.ts +1 -1
- package/dist/security/react/hooks/SecurityPorts.hooks.d.ts +4 -0
- package/dist/security/react/hooks/SecurityPorts.hooks.js +5 -0
- package/dist/security/react/index.js +1 -1
- package/dist/security/react/pages/SecurityPage.d.ts +1 -1
- package/dist/security/react/tabs/AccessTokensTab.d.ts +1 -1
- package/dist/security/react/tabs/RootKeyTab.d.ts +1 -1
- package/dist/seo/adapters/http.d.ts +31 -0
- package/dist/seo/adapters/http.js +37 -0
- package/dist/seo/adapters/memory.d.ts +28 -0
- package/dist/seo/adapters/memory.js +129 -0
- package/dist/seo/conformance/seo-api.conformance.d.ts +8 -0
- package/dist/seo/conformance/seo-api.conformance.js +44 -0
- package/dist/seo/controllers/entry-picker.controller.d.ts +21 -0
- package/dist/seo/controllers/entry-picker.controller.js +17 -0
- package/dist/seo/controllers/entry-section.controller.d.ts +20 -0
- package/dist/seo/controllers/entry-section.controller.js +7 -0
- package/dist/seo/controllers/media-ref.controller.d.ts +26 -0
- package/dist/seo/controllers/media-ref.controller.js +14 -0
- package/dist/seo/controllers/seo-entry.controller.d.ts +31 -0
- package/dist/seo/controllers/seo-entry.controller.js +52 -0
- package/dist/seo/controllers/seo.controller.d.ts +29 -0
- package/dist/seo/controllers/seo.controller.js +50 -0
- package/dist/seo/controllers/sitemap.controller.d.ts +25 -0
- package/dist/seo/controllers/sitemap.controller.js +27 -0
- package/dist/seo/index.d.ts +14 -0
- package/dist/seo/index.js +12 -0
- package/dist/seo/messages.en.d.ts +78 -0
- package/dist/seo/messages.en.js +78 -0
- package/dist/seo/models.d.ts +179 -0
- package/dist/seo/models.js +8 -0
- package/dist/seo/ports.d.ts +11 -0
- package/dist/seo/ports.js +4 -0
- package/dist/seo/react/components/MediaPickerBridge.d.ts +4 -0
- package/dist/seo/react/components/MediaPickerBridge.js +8 -0
- package/dist/seo/react/components/MediaRefField.d.ts +36 -0
- package/dist/seo/react/components/MediaRefField.js +12 -0
- package/dist/seo/react/components/SeoIcons.d.ts +13 -0
- package/dist/seo/react/components/SeoIcons.js +32 -0
- package/dist/seo/react/components/SitemapModal.d.ts +48 -0
- package/dist/seo/react/components/SitemapModal.js +70 -0
- package/dist/seo/react/hooks/MediaPickerBridge.hooks.d.ts +6 -0
- package/dist/seo/react/hooks/MediaPickerBridge.hooks.js +27 -0
- package/dist/seo/react/hooks/MediaRefField.hooks.d.ts +22 -0
- package/dist/seo/react/hooks/MediaRefField.hooks.js +30 -0
- package/dist/seo/react/hooks/SeoModuleTabs.d.ts +14 -0
- package/dist/seo/react/hooks/SeoModuleTabs.js +18 -0
- package/dist/seo/react/hooks/SeoPage.hooks.d.ts +69 -0
- package/dist/seo/react/hooks/SeoPage.hooks.js +37 -0
- package/dist/seo/react/hooks/SeoPorts.hooks.d.ts +19 -0
- package/dist/seo/react/hooks/SeoPorts.hooks.js +22 -0
- package/dist/seo/react/hooks/SitemapModal.hooks.d.ts +26 -0
- package/dist/seo/react/hooks/SitemapModal.hooks.js +20 -0
- package/dist/seo/react/hooks/use-entry-picker.hooks.d.ts +11 -0
- package/dist/seo/react/hooks/use-entry-picker.hooks.js +20 -0
- package/dist/seo/react/hooks/use-seo-entry-panel.hooks.d.ts +14 -0
- package/dist/seo/react/hooks/use-seo-entry-panel.hooks.js +26 -0
- package/dist/seo/react/hooks/use-seo-entry-section.hooks.d.ts +4 -0
- package/dist/seo/react/hooks/use-seo-entry-section.hooks.js +7 -0
- package/dist/seo/react/hooks/use-seo.hooks.d.ts +11 -0
- package/dist/seo/react/hooks/use-seo.hooks.js +29 -0
- package/dist/seo/react/hooks/use-sitemap-modal.hooks.d.ts +10 -0
- package/dist/seo/react/hooks/use-sitemap-modal.hooks.js +18 -0
- package/dist/seo/react/index.d.ts +366 -0
- package/dist/seo/react/index.js +30 -0
- package/dist/seo/react/options.d.ts +19 -0
- package/dist/seo/react/options.js +2 -0
- package/dist/seo/react/pages/SeoPage.d.ts +161 -0
- package/dist/seo/react/pages/SeoPage.js +215 -0
- package/dist/seo/rules.d.ts +136 -0
- package/dist/seo/rules.js +212 -0
- package/dist/seo/seo.module.d.ts +114 -0
- package/dist/seo/seo.module.js +14 -0
- package/dist/source-control/react/hooks/ProvidersTab.hooks.d.ts +1 -1
- package/dist/source-control/react/hooks/ProvidersTab.hooks.js +4 -4
- package/dist/source-control/react/hooks/SourceControlPage.hooks.d.ts +1 -1
- package/dist/source-control/react/index.js +1 -1
- package/dist/source-control/react/pages/SourceControlPage.d.ts +1 -1
- package/dist/source-control/react/tabs/ProvidersTab.d.ts +1 -1
- package/dist/widgets/adapters/http.d.ts +19 -0
- package/dist/widgets/adapters/http.js +33 -0
- package/dist/widgets/adapters/memory.d.ts +22 -0
- package/dist/widgets/adapters/memory.js +93 -0
- package/dist/widgets/conformance/widgets-api.conformance.d.ts +6 -0
- package/dist/widgets/conformance/widgets-api.conformance.js +55 -0
- package/dist/widgets/controllers/instance-editor.controller.d.ts +49 -0
- package/dist/widgets/controllers/instance-editor.controller.js +87 -0
- package/dist/widgets/controllers/library.controller.d.ts +33 -0
- package/dist/widgets/controllers/library.controller.js +53 -0
- package/dist/widgets/controllers/region-editor.controller.d.ts +42 -0
- package/dist/widgets/controllers/region-editor.controller.js +69 -0
- package/dist/widgets/controllers/regions.controller.d.ts +27 -0
- package/dist/widgets/controllers/regions.controller.js +44 -0
- package/dist/widgets/index.d.ts +11 -0
- package/dist/widgets/index.js +9 -0
- package/dist/widgets/messages.en.d.ts +78 -0
- package/dist/widgets/messages.en.js +83 -0
- package/dist/widgets/models.d.ts +62 -0
- package/dist/widgets/models.js +2 -0
- package/dist/widgets/ports.d.ts +79 -0
- package/dist/widgets/ports.js +5 -0
- package/dist/widgets/react/components/WidgetInstanceNotices.d.ts +14 -0
- package/dist/widgets/react/components/WidgetInstanceNotices.js +25 -0
- package/dist/widgets/react/components/WidgetRegionEditorHeaderActions.d.ts +22 -0
- package/dist/widgets/react/components/WidgetRegionEditorHeaderActions.js +18 -0
- package/dist/widgets/react/components/WidgetsLibraryNotices.d.ts +13 -0
- package/dist/widgets/react/components/WidgetsLibraryNotices.js +10 -0
- package/dist/widgets/react/hooks/WidgetsPorts.hooks.d.ts +270 -0
- package/dist/widgets/react/hooks/WidgetsPorts.hooks.js +17 -0
- package/dist/widgets/react/hooks/navigation.hooks.d.ts +9 -0
- package/dist/widgets/react/hooks/navigation.hooks.js +6 -0
- package/dist/widgets/react/hooks/page-views.hooks.d.ts +87 -0
- package/dist/widgets/react/hooks/page-views.hooks.js +30 -0
- package/dist/widgets/react/hooks/use-widget-instance-editor.hooks.d.ts +56 -0
- package/dist/widgets/react/hooks/use-widget-instance-editor.hooks.js +38 -0
- package/dist/widgets/react/hooks/use-widget-region-editor.hooks.d.ts +32 -0
- package/dist/widgets/react/hooks/use-widget-region-editor.hooks.js +22 -0
- package/dist/widgets/react/hooks/use-widget-regions.hooks.d.ts +23 -0
- package/dist/widgets/react/hooks/use-widget-regions.hooks.js +22 -0
- package/dist/widgets/react/hooks/use-widgets-library.hooks.d.ts +37 -0
- package/dist/widgets/react/hooks/use-widgets-library.hooks.js +23 -0
- package/dist/widgets/react/index.d.ts +391 -0
- package/dist/widgets/react/index.js +31 -0
- package/dist/widgets/react/pages/WidgetInstanceEditor.d.ts +23 -0
- package/dist/widgets/react/pages/WidgetInstanceEditor.js +37 -0
- package/dist/widgets/react/pages/WidgetRegionEditor.d.ts +22 -0
- package/dist/widgets/react/pages/WidgetRegionEditor.js +25 -0
- package/dist/widgets/react/pages/WidgetRegions.d.ts +21 -0
- package/dist/widgets/react/pages/WidgetRegions.js +31 -0
- package/dist/widgets/react/pages/WidgetsLibrary.d.ts +24 -0
- package/dist/widgets/react/pages/WidgetsLibrary.js +61 -0
- package/dist/widgets/rules.d.ts +94 -0
- package/dist/widgets/rules.js +83 -0
- package/dist/widgets/widgets.module.d.ts +122 -0
- package/dist/widgets/widgets.module.js +21 -0
- package/package.json +206 -9
|
@@ -1,6 +1,56 @@
|
|
|
1
|
-
import { useEffect,
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
/** 8px clearance kept between the menu and the viewport edge on every side it's tested against. */
|
|
3
3
|
const VIEWPORT_MARGIN = 8;
|
|
4
|
+
/**
|
|
5
|
+
* Starts the listeners one open menu needs and returns the matching stop. Called from the menu's
|
|
6
|
+
* callback ref, so both elements are in hand: `trigger` is the button the menu opened from and
|
|
7
|
+
* `menu` is the just-attached popup — neither is ever null here.
|
|
8
|
+
*
|
|
9
|
+
* Positioning runs immediately, at ref-attach time in the commit, i.e. after the (initially
|
|
10
|
+
* off-screen, `visibility: hidden`) menu has actually laid out, so its real dimensions are known
|
|
11
|
+
* before deciding above-vs-below — a plain `useEffect` would run one paint too late and produce a
|
|
12
|
+
* visible jump. Recomputed on scroll and resize too: a portaled menu is a DOM sibling of its anchor,
|
|
13
|
+
* not a child, so it does not track the anchor's position on its own the way an in-flow popup would.
|
|
14
|
+
*
|
|
15
|
+
* Click-outside closes. Scoped to the open window only, same lifecycle discipline as
|
|
16
|
+
* `ConfirmButton`'s armed-only document listeners — a closed, idle `RowMenu` costs nothing beyond
|
|
17
|
+
* its trigger button even with many mounted per table.
|
|
18
|
+
*
|
|
19
|
+
* @complexity O(1) per call and per scroll/resize/mousedown event.
|
|
20
|
+
*/
|
|
21
|
+
function trackOpenMenu({ trigger, menu }, { window, document, onPosition, onDismiss }) {
|
|
22
|
+
function reposition() {
|
|
23
|
+
const rect = trigger.getBoundingClientRect();
|
|
24
|
+
const menuHeight = menu.offsetHeight;
|
|
25
|
+
const menuWidth = menu.offsetWidth;
|
|
26
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
27
|
+
const fitsBelow = spaceBelow >= menuHeight + VIEWPORT_MARGIN;
|
|
28
|
+
const placement = fitsBelow || rect.top < menuHeight + VIEWPORT_MARGIN ? 'below' : 'above';
|
|
29
|
+
// Right-aligned to the trigger by default (the trigger is the table's last column), clamped
|
|
30
|
+
// so it never overflows the viewport's left or right edge.
|
|
31
|
+
const left = Math.min(Math.max(VIEWPORT_MARGIN, rect.right - menuWidth), window.innerWidth - menuWidth - VIEWPORT_MARGIN);
|
|
32
|
+
onPosition({
|
|
33
|
+
top: placement === 'below' ? rect.bottom + 4 : rect.top - 4,
|
|
34
|
+
left,
|
|
35
|
+
placement,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function onDocMouseDown(e) {
|
|
39
|
+
const target = e.target;
|
|
40
|
+
if (menu.contains(target) || trigger.contains(target))
|
|
41
|
+
return;
|
|
42
|
+
onDismiss();
|
|
43
|
+
}
|
|
44
|
+
reposition();
|
|
45
|
+
window.addEventListener('scroll', reposition, true);
|
|
46
|
+
window.addEventListener('resize', reposition);
|
|
47
|
+
document.addEventListener('mousedown', onDocMouseDown);
|
|
48
|
+
return () => {
|
|
49
|
+
window.removeEventListener('scroll', reposition, true);
|
|
50
|
+
window.removeEventListener('resize', reposition);
|
|
51
|
+
document.removeEventListener('mousedown', onDocMouseDown);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
4
54
|
/**
|
|
5
55
|
* Owns `RowMenu`'s open/close state, positioning, and keyboard/focus behavior.
|
|
6
56
|
*
|
|
@@ -8,74 +58,44 @@ const VIEWPORT_MARGIN = 8;
|
|
|
8
58
|
* needs, for `ArrowUp`-to-last-item and wraparound navigation.
|
|
9
59
|
*/
|
|
10
60
|
export function useRowMenu({ itemCount, window, document }) {
|
|
11
|
-
|
|
61
|
+
// The trigger the menu is open against; `null` while closed. Held as state (not just a boolean)
|
|
62
|
+
// so the menu's callback ref below is built with the element already in hand. Read from
|
|
63
|
+
// `triggerRef` at open time: an unattached trigger leaves this `null`, so a menu with nothing to
|
|
64
|
+
// anchor to never opens.
|
|
65
|
+
const [anchor, setAnchor] = useState(null);
|
|
66
|
+
const open = anchor !== null;
|
|
12
67
|
const [position, setPosition] = useState(null);
|
|
13
68
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
14
69
|
const triggerRef = useRef(null);
|
|
15
|
-
const menuRef = useRef(null);
|
|
16
70
|
const itemRefs = useRef([]);
|
|
17
71
|
itemRefs.current = itemRefs.current.slice(0, itemCount);
|
|
18
72
|
function close(returnFocus) {
|
|
19
|
-
|
|
73
|
+
setAnchor(null);
|
|
20
74
|
setPosition(null);
|
|
21
75
|
if (returnFocus)
|
|
22
76
|
triggerRef.current?.focus();
|
|
23
77
|
}
|
|
24
78
|
function openAt(index) {
|
|
25
79
|
setActiveIndex(index);
|
|
26
|
-
|
|
80
|
+
setAnchor(triggerRef.current);
|
|
27
81
|
}
|
|
28
|
-
//
|
|
29
|
-
// `
|
|
30
|
-
// `
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const menuHeight = menuRef.current?.offsetHeight ?? 0;
|
|
42
|
-
const menuWidth = menuRef.current?.offsetWidth ?? 0;
|
|
43
|
-
const spaceBelow = window.innerHeight - rect.bottom;
|
|
44
|
-
const fitsBelow = spaceBelow >= menuHeight + VIEWPORT_MARGIN;
|
|
45
|
-
const placement = fitsBelow || rect.top < menuHeight + VIEWPORT_MARGIN ? 'below' : 'above';
|
|
46
|
-
// Right-aligned to the trigger by default (the trigger is the table's last column), clamped
|
|
47
|
-
// so it never overflows the viewport's left or right edge.
|
|
48
|
-
const left = Math.min(Math.max(VIEWPORT_MARGIN, rect.right - menuWidth), window.innerWidth - menuWidth - VIEWPORT_MARGIN);
|
|
49
|
-
setPosition({
|
|
50
|
-
top: placement === 'below' ? rect.bottom + 4 : rect.top - 4,
|
|
51
|
-
left,
|
|
52
|
-
placement,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
reposition();
|
|
56
|
-
window.addEventListener('scroll', reposition, true);
|
|
57
|
-
window.addEventListener('resize', reposition);
|
|
58
|
-
return () => {
|
|
59
|
-
window.removeEventListener('scroll', reposition, true);
|
|
60
|
-
window.removeEventListener('resize', reposition);
|
|
82
|
+
// Only the open menu renders this ref, so it only exists once there is an anchor. React calls it
|
|
83
|
+
// with the menu element on attach and `null` on detach (React 18 and 19 alike; attach always comes
|
|
84
|
+
// first, so `stop` is set by then). A new anchor or new `window`/`document` ports make a new ref,
|
|
85
|
+
// which React detaches and re-attaches — the same re-subscribe an effect's deps would give.
|
|
86
|
+
const menuRef = useMemo(() => {
|
|
87
|
+
if (!anchor)
|
|
88
|
+
return null;
|
|
89
|
+
let stop;
|
|
90
|
+
return (menu) => {
|
|
91
|
+
if (menu)
|
|
92
|
+
stop = trackOpenMenu({ trigger: anchor, menu }, { window, document, onPosition: setPosition, onDismiss: () => close(false) });
|
|
93
|
+
else
|
|
94
|
+
stop();
|
|
61
95
|
};
|
|
62
|
-
|
|
63
|
-
// Click-outside closes. Scoped to the open window only, same lifecycle discipline as
|
|
64
|
-
// `ConfirmButton`'s armed-only document listeners — a closed, idle `RowMenu` costs nothing beyond
|
|
65
|
-
// its trigger button even with many mounted per table.
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
if (!open)
|
|
68
|
-
return;
|
|
69
|
-
function onDocMouseDown(e) {
|
|
70
|
-
const target = e.target;
|
|
71
|
-
if (menuRef.current?.contains(target) || triggerRef.current?.contains(target))
|
|
72
|
-
return;
|
|
73
|
-
close(false);
|
|
74
|
-
}
|
|
75
|
-
document.addEventListener('mousedown', onDocMouseDown);
|
|
76
|
-
return () => document.removeEventListener('mousedown', onDocMouseDown);
|
|
96
|
+
// `close` only touches state setters and `triggerRef`, all stable across renders.
|
|
77
97
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
|
-
}, [
|
|
98
|
+
}, [anchor, window, document]);
|
|
79
99
|
// Keeps real DOM focus on the active item (roving focus via `tabIndex={-1}` on every item except
|
|
80
100
|
// the active one) rather than only tracking `activeIndex` in state — arrow-key navigation needs
|
|
81
101
|
// to move the browser's actual focus for a screen reader to announce it.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AdminEntityField } from '../../core/ports/entities.js';
|
|
2
|
-
import type
|
|
2
|
+
import { type EntityTranslate } from './types.js';
|
|
3
3
|
import { type RelationIndex } from './rules.js';
|
|
4
4
|
export declare function EntityField(props: {
|
|
5
5
|
readonly inputId: string;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Select } from '@jini-ai/ui/admin-widgets';
|
|
3
|
+
import { selectTranslate } from './types.js';
|
|
3
4
|
import { fromDatetimeLocalValue, toDatetimeLocalValue } from './rules.js';
|
|
4
5
|
export function EntityField(props) {
|
|
5
6
|
const { inputId, field, value, translate, disabled, invalid, onChange } = props;
|
|
6
7
|
const common = { id: inputId, disabled, 'aria-invalid': invalid };
|
|
8
|
+
const selectT = selectTranslate({ translate });
|
|
7
9
|
switch (field.kind) {
|
|
8
10
|
case 'json': return _jsx("textarea", { ...common, value: props.text, onChange: (e) => props.onTextChange({ text: e.target.value }) });
|
|
9
11
|
case 'relation': {
|
|
10
12
|
const options = props.relations[field.target]?.options ?? [];
|
|
11
13
|
const selectedId = typeof value === 'string' ? value : '';
|
|
12
14
|
const missing = selectedId !== '' && !options.some((option) => option.id === selectedId);
|
|
13
|
-
return _jsx(Select, { id: inputId, disabled: disabled, value: selectedId, translate:
|
|
15
|
+
return _jsx(Select, { id: inputId, disabled: disabled, value: selectedId, translate: selectT, "aria-label": translate({ key: field.label ?? field.name }), options: [
|
|
14
16
|
{ value: '', label: translate({ key: 'No value' }) },
|
|
15
17
|
...(missing ? [{ value: selectedId, label: `${selectedId} (${translate({ key: 'Unresolved' })})` }] : []),
|
|
16
18
|
...options.map((option) => ({ value: option.id, label: option.title })),
|
|
@@ -19,7 +21,7 @@ export function EntityField(props) {
|
|
|
19
21
|
case 'boolean':
|
|
20
22
|
if (field.required)
|
|
21
23
|
return _jsx("input", { ...common, type: "checkbox", checked: value === true, onChange: (e) => onChange({ value: e.target.checked }) });
|
|
22
|
-
return _jsx(Select, { id: inputId, disabled: disabled, value: value === undefined ? '' : value === true ? 'true' : 'false', translate:
|
|
24
|
+
return _jsx(Select, { id: inputId, disabled: disabled, value: value === undefined ? '' : value === true ? 'true' : 'false', translate: selectT, "aria-label": translate({ key: field.label ?? field.name }), options: [
|
|
23
25
|
{ value: '', label: translate({ key: 'No value' }) }, { value: 'true', label: translate({ key: 'Yes' }) }, { value: 'false', label: translate({ key: 'No' }) },
|
|
24
26
|
], onChange: (selected) => onChange({ value: selected === '' ? undefined : selected === 'true' }) });
|
|
25
27
|
case 'datetime': return _jsx("input", { ...common, type: "datetime-local", step: "0.001", value: toDatetimeLocalValue({ value }), onChange: (e) => onChange({ value: fromDatetimeLocalValue({ raw: e.target.value }) }) });
|
|
@@ -42,4 +42,13 @@ export declare function entityText({ translate, key, values }: {
|
|
|
42
42
|
readonly key: string;
|
|
43
43
|
readonly values: Readonly<Record<string, string | number>>;
|
|
44
44
|
}): string;
|
|
45
|
+
/**
|
|
46
|
+
* Adapts the host's object-arg {@link EntityTranslate} to the positional `(key) => string` form the
|
|
47
|
+
* shared `Select` widget takes. One adapter for every `Select` an entity form renders, so each one
|
|
48
|
+
* routes its own copy (search box, empty state) through the host dictionary — even the short boolean
|
|
49
|
+
* select, which never shows that copy today.
|
|
50
|
+
*/
|
|
51
|
+
export declare function selectTranslate({ translate }: {
|
|
52
|
+
readonly translate: EntityTranslate;
|
|
53
|
+
}): (key: string) => string;
|
|
45
54
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -2,4 +2,13 @@
|
|
|
2
2
|
export function entityText({ translate, key, values }) {
|
|
3
3
|
return translate({ key: key }).replace(/\{([\w]+)\}/g, (match, name) => Object.hasOwn(values, name) ? String(values[name]) : match);
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Adapts the host's object-arg {@link EntityTranslate} to the positional `(key) => string` form the
|
|
7
|
+
* shared `Select` widget takes. One adapter for every `Select` an entity form renders, so each one
|
|
8
|
+
* routes its own copy (search box, empty state) through the host dictionary — even the short boolean
|
|
9
|
+
* select, which never shows that copy today.
|
|
10
|
+
*/
|
|
11
|
+
export function selectTranslate({ translate }) {
|
|
12
|
+
return (key) => translate({ key });
|
|
13
|
+
}
|
|
5
14
|
//# sourceMappingURL=types.js.map
|
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { ControllerStore } from '../core/module/controller-store.js';
|
|
3
|
-
/** Factory runs after commit, never during render. Each effect attachment owns a fresh
|
|
4
|
-
* controller, so StrictMode's cleanup/replay cannot revive a disposed controller. */
|
|
5
|
-
export declare function useController<C extends ControllerStore<unknown>>({ create, dependencies }: {
|
|
6
|
-
create: () => C;
|
|
7
|
-
dependencies: DependencyList;
|
|
8
|
-
}, { start, }?: {
|
|
9
|
-
start?: (required: {
|
|
10
|
-
controller: C;
|
|
11
|
-
}, optional?: Record<string, never>) => void;
|
|
12
|
-
}): {
|
|
13
|
-
controller: C | null;
|
|
14
|
-
snapshot: ReturnType<C["getSnapshot"]> | null;
|
|
15
|
-
};
|
|
1
|
+
export * from '../core/react/use-controller.js';
|
|
16
2
|
//# sourceMappingURL=use-controller.d.ts.map
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* controller, so StrictMode's cleanup/replay cannot revive a disposed controller. */
|
|
4
|
-
export function useController({ create, dependencies }, { start, } = {}) {
|
|
5
|
-
const [controller, setController] = useState(null);
|
|
6
|
-
useEffect(() => {
|
|
7
|
-
const current = create();
|
|
8
|
-
setController(current);
|
|
9
|
-
start?.({ controller: current });
|
|
10
|
-
return () => current.dispose();
|
|
11
|
-
// Dependencies are explicitly supplied by the owning hook, like useMemo's contract.
|
|
12
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
13
|
-
}, dependencies);
|
|
14
|
-
const subscribe = useCallback((listener) => controller?.subscribe({ listener }) ?? (() => { }), [controller]);
|
|
15
|
-
const snapshot = useSyncExternalStore(subscribe, () => (controller?.getSnapshot() ?? null), () => null);
|
|
16
|
-
return { controller, snapshot };
|
|
17
|
-
}
|
|
1
|
+
// Compatibility path; the shared implementation lives in core.
|
|
2
|
+
export * from '../core/react/use-controller.js';
|
|
18
3
|
//# sourceMappingURL=use-controller.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AdminRedirectsPort } from '../../core/ports/redirects.js';
|
|
2
|
+
/** Host owns authentication, addressing, retries and error decoding, as in media's adapter. */
|
|
3
|
+
export interface RedirectsTransportPort {
|
|
4
|
+
request<T>(required: {
|
|
5
|
+
path: string;
|
|
6
|
+
method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
|
|
7
|
+
body?: unknown;
|
|
8
|
+
}, optional?: Record<string, never>): Promise<T>;
|
|
9
|
+
url(required: {
|
|
10
|
+
path: string;
|
|
11
|
+
}, optional?: Record<string, never>): string;
|
|
12
|
+
}
|
|
13
|
+
/** Map existing HTTP envelopes to the core API without validating or rewriting operator inputs.
|
|
14
|
+
* @example createHttpRedirectsApi({ transport, basePath: workspacePath + '/redirects' }, {});
|
|
15
|
+
*/
|
|
16
|
+
export declare function createHttpRedirectsApi({ transport, basePath }: {
|
|
17
|
+
transport: RedirectsTransportPort;
|
|
18
|
+
basePath: string;
|
|
19
|
+
}, _optional?: Record<string, never>): AdminRedirectsPort;
|
|
20
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Map existing HTTP envelopes to the core API without validating or rewriting operator inputs.
|
|
2
|
+
* @example createHttpRedirectsApi({ transport, basePath: workspacePath + '/redirects' }, {});
|
|
3
|
+
*/
|
|
4
|
+
export function createHttpRedirectsApi({ transport, basePath }, _optional = {}) {
|
|
5
|
+
const base = basePath.replace(/\/$/, '');
|
|
6
|
+
const path = (id) => `${base}/${encodeURIComponent(id)}`;
|
|
7
|
+
async function record(method, target, body) {
|
|
8
|
+
const response = await transport.request({ path: target, method, ...(body === undefined ? {} : { body }) });
|
|
9
|
+
return response.data;
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
async listRedirects(_required, filter = {}) {
|
|
13
|
+
const query = new URLSearchParams();
|
|
14
|
+
for (const key of ['status', 'source', 'matchType']) {
|
|
15
|
+
if (filter[key] !== undefined)
|
|
16
|
+
query.set(key, filter[key]);
|
|
17
|
+
}
|
|
18
|
+
const suffix = query.size ? `?${query.toString()}` : '';
|
|
19
|
+
return (await transport.request({ path: `${base}${suffix}`, method: 'GET' })).data;
|
|
20
|
+
},
|
|
21
|
+
getRedirect: ({ id }) => record('GET', path(id)),
|
|
22
|
+
createRedirect: (input, options = {}) => record('POST', base, { ...input, ...options }),
|
|
23
|
+
updateRedirect: ({ id }, patch = {}) => record('PATCH', path(id), patch),
|
|
24
|
+
tombstoneRedirect: ({ id }) => record('DELETE', path(id)),
|
|
25
|
+
async getRedirectHitStats({ id }) {
|
|
26
|
+
return (await transport.request({ path: `${path(id)}/hits`, method: 'GET' })).data;
|
|
27
|
+
},
|
|
28
|
+
importRedirects: ({ rules }) => transport.request({ path: `${base}/import`, method: 'POST', body: { rules } }),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AdminRedirect, AdminRedirectCreateInput, AdminRedirectHitStats, AdminRedirectImportResult, AdminRedirectsPort } from '../../core/ports/redirects.js';
|
|
2
|
+
/** Presentation backend, not a routing engine: host validators/origin policy remain server owned.
|
|
3
|
+
* Optional validation lets a host model its own open match vocabulary without a second schema.
|
|
4
|
+
* @example createMemoryRedirectsApi({ redirects: [] }, {});
|
|
5
|
+
*/
|
|
6
|
+
export declare function createMemoryRedirectsApi({ redirects, hits }: {
|
|
7
|
+
redirects?: readonly AdminRedirect[];
|
|
8
|
+
hits?: Readonly<Record<string, AdminRedirectHitStats>>;
|
|
9
|
+
}, { validate, onImport }?: {
|
|
10
|
+
validate?: (input: AdminRedirectCreateInput) => void;
|
|
11
|
+
onImport?: (rules: readonly AdminRedirectCreateInput[]) => AdminRedirectImportResult | undefined;
|
|
12
|
+
}): AdminRedirectsPort;
|
|
13
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { AdminApiError } from '../../core/transport/errors.js';
|
|
2
|
+
/** Presentation backend, not a routing engine: host validators/origin policy remain server owned.
|
|
3
|
+
* Optional validation lets a host model its own open match vocabulary without a second schema.
|
|
4
|
+
* @example createMemoryRedirectsApi({ redirects: [] }, {});
|
|
5
|
+
*/
|
|
6
|
+
export function createMemoryRedirectsApi({ redirects = [], hits = {} }, { validate, onImport } = {}) {
|
|
7
|
+
const rows = new Map(redirects.map(row => [row.id, Object.freeze({ ...row })]));
|
|
8
|
+
const stats = new Map(Object.entries(hits).map(([id, value]) => [id, Object.freeze({ ...value })]));
|
|
9
|
+
let nextId = 1;
|
|
10
|
+
function get(id) {
|
|
11
|
+
const row = rows.get(id);
|
|
12
|
+
if (!row)
|
|
13
|
+
throw new AdminApiError({ message: `redirect '${id}' was not found`, status: 404 }, { code: 'REDIRECT_NOT_FOUND' });
|
|
14
|
+
return row;
|
|
15
|
+
}
|
|
16
|
+
function create(input, source) {
|
|
17
|
+
// The core port documents reference-host rejection. A supplied validator owns alternate hosts.
|
|
18
|
+
if (validate)
|
|
19
|
+
validate(input);
|
|
20
|
+
else if (input.matchType === 'regex')
|
|
21
|
+
throw new AdminApiError({ message: 'regex match type is not supported', status: 400 }, { code: 'REDIRECT_VALIDATION_ERROR' });
|
|
22
|
+
let id;
|
|
23
|
+
do {
|
|
24
|
+
id = `memory-redirect-${nextId++}`;
|
|
25
|
+
} while (rows.has(id));
|
|
26
|
+
const row = Object.freeze({ ...input, id, status: 'active', override: input.override ?? false,
|
|
27
|
+
priority: input.priority ?? 0, source, sourceEntryId: null, fromPathAtCapture: null, toPathAtCapture: null,
|
|
28
|
+
createdByPrincipal: 'memory-principal', createdByPluginId: null,
|
|
29
|
+
createdAt: new Date(0).toISOString(), updatedAt: new Date(0).toISOString(), version: 1 });
|
|
30
|
+
rows.set(id, row);
|
|
31
|
+
return row;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
async listRedirects(_required, filter = {}) {
|
|
35
|
+
return Object.freeze([...rows.values()].filter(row => (filter.status === undefined || row.status === filter.status) &&
|
|
36
|
+
(filter.source === undefined || row.source === filter.source) &&
|
|
37
|
+
(filter.matchType === undefined || row.matchType === filter.matchType)));
|
|
38
|
+
},
|
|
39
|
+
async getRedirect({ id }) { return get(id); },
|
|
40
|
+
async createRedirect(input, options = {}) { return create({ ...input, ...options }, 'manual'); },
|
|
41
|
+
async updateRedirect({ id }, patch = {}) {
|
|
42
|
+
const before = get(id);
|
|
43
|
+
const next = { ...before, ...patch };
|
|
44
|
+
if (validate)
|
|
45
|
+
validate(next);
|
|
46
|
+
else if (patch.matchType === 'regex')
|
|
47
|
+
throw new AdminApiError({ message: 'regex match type is not supported', status: 400 }, { code: 'REDIRECT_VALIDATION_ERROR' });
|
|
48
|
+
const row = Object.freeze({ ...next, version: before.version + 1 });
|
|
49
|
+
rows.set(id, row);
|
|
50
|
+
return row;
|
|
51
|
+
},
|
|
52
|
+
async tombstoneRedirect({ id }) {
|
|
53
|
+
const row = get(id);
|
|
54
|
+
if (row.status === 'disabled')
|
|
55
|
+
return row;
|
|
56
|
+
const disabled = Object.freeze({ ...row, status: 'disabled', version: row.version + 1 });
|
|
57
|
+
rows.set(id, disabled);
|
|
58
|
+
return disabled;
|
|
59
|
+
},
|
|
60
|
+
async getRedirectHitStats({ id }) {
|
|
61
|
+
get(id);
|
|
62
|
+
return stats.get(id) ?? Object.freeze({ redirectId: id, hitCount: 0, lastHitAt: null });
|
|
63
|
+
},
|
|
64
|
+
async importRedirects({ rules }) {
|
|
65
|
+
const overridden = onImport?.(rules);
|
|
66
|
+
if (overridden)
|
|
67
|
+
return overridden;
|
|
68
|
+
const created = [], failed = [];
|
|
69
|
+
// One failed item never discards successful siblings; no per-item network I/O.
|
|
70
|
+
for (const [index, input] of rules.entries()) {
|
|
71
|
+
try {
|
|
72
|
+
created.push(create(input, 'import'));
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
failed.push({ index, code: error instanceof AdminApiError ? error.code ?? 'INTERNAL_ERROR' : 'INTERNAL_ERROR',
|
|
76
|
+
message: error instanceof AdminApiError ? error.message : 'an internal error occurred' });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { created: Object.freeze(created), failed: Object.freeze(failed) };
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AdminRedirectsPort } from '../../core/ports/redirects.js';
|
|
2
|
+
/** Destructive framework-free checklist: use an isolated backend with no production data.
|
|
3
|
+
* Validates core soft-delete, snapshots, lazy-read data and per-item partial import contracts.
|
|
4
|
+
* Reference regex rejection probes can be disabled for a host implementing the port's open vocabulary.
|
|
5
|
+
* @example await runRedirectsApiConformance({ api: createMemoryRedirectsApi({}, {}) }, {});
|
|
6
|
+
*/
|
|
7
|
+
export declare function runRedirectsApiConformance({ api }: {
|
|
8
|
+
api: AdminRedirectsPort;
|
|
9
|
+
}, { referenceRegexRejection }?: {
|
|
10
|
+
referenceRegexRejection?: boolean;
|
|
11
|
+
}): Promise<readonly string[]>;
|
|
12
|
+
//# sourceMappingURL=redirects-api.conformance.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { AdminApiError } from '../../core/transport/errors.js';
|
|
2
|
+
/** Destructive framework-free checklist: use an isolated backend with no production data.
|
|
3
|
+
* Validates core soft-delete, snapshots, lazy-read data and per-item partial import contracts.
|
|
4
|
+
* Reference regex rejection probes can be disabled for a host implementing the port's open vocabulary.
|
|
5
|
+
* @example await runRedirectsApiConformance({ api: createMemoryRedirectsApi({}, {}) }, {});
|
|
6
|
+
*/
|
|
7
|
+
export async function runRedirectsApiConformance({ api }, { referenceRegexRejection = true } = {}) {
|
|
8
|
+
const checks = [];
|
|
9
|
+
function assert(ok, name) {
|
|
10
|
+
if (!ok)
|
|
11
|
+
throw new AdminApiError({ message: `Redirects API conformance: ${name}`, status: 0 }, { code: 'CONFORMANCE_FAILED' });
|
|
12
|
+
checks.push(name);
|
|
13
|
+
}
|
|
14
|
+
async function rejects(run, name) {
|
|
15
|
+
let rejected = false;
|
|
16
|
+
try {
|
|
17
|
+
await run();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
rejected = true;
|
|
21
|
+
}
|
|
22
|
+
assert(rejected, name);
|
|
23
|
+
}
|
|
24
|
+
const input = { matchType: 'exact', fromPattern: '/redirects-conformance-a', toTarget: '/redirects-conformance-b', statusCode: 301 };
|
|
25
|
+
const created = await api.createRedirect(input, { override: true, priority: 7 });
|
|
26
|
+
assert(created.status === 'active' && created.override && created.priority === 7, 'create preserves fields and options');
|
|
27
|
+
const before = await api.listRedirects({});
|
|
28
|
+
assert(before.some(row => row.id === created.id), 'list contains the created rule');
|
|
29
|
+
assert((await api.getRedirect({ id: created.id })).id === created.id, 'get reads by id');
|
|
30
|
+
const hits = await api.getRedirectHitStats({ id: created.id });
|
|
31
|
+
assert(hits.redirectId === created.id && hits.hitCount === 0 && hits.lastHitAt === null, 'new rule has zero hits');
|
|
32
|
+
const updated = await api.updateRedirect({ id: created.id }, { status: 'disabled' });
|
|
33
|
+
assert(updated.status === 'disabled' && updated.toTarget === created.toTarget, 'partial update preserves other fields');
|
|
34
|
+
assert(created.status === 'active' && before.find(row => row.id === created.id)?.status === 'active', 'prior snapshots stay unchanged');
|
|
35
|
+
assert((await api.listRedirects({}, { status: 'disabled' })).every(row => row.status === 'disabled'), 'status filter');
|
|
36
|
+
await api.updateRedirect({ id: created.id }, { status: 'active' });
|
|
37
|
+
const disabled = await api.tombstoneRedirect({ id: created.id });
|
|
38
|
+
assert(disabled.status === 'disabled', 'tombstone returns the disabled rule');
|
|
39
|
+
assert((await api.listRedirects({})).some(row => row.id === created.id), 'soft deletion retains the rule');
|
|
40
|
+
assert((await api.getRedirect({ id: created.id })).status === 'disabled', 'tombstoned rule remains readable');
|
|
41
|
+
await rejects(() => api.getRedirect({ id: 'missing-conformance-rule' }), 'missing rule rejects');
|
|
42
|
+
await rejects(() => api.getRedirectHitStats({ id: 'missing-conformance-rule' }), 'missing hits differs from zero hits');
|
|
43
|
+
await rejects(() => api.updateRedirect({ id: 'missing-conformance-rule' }, { status: 'disabled' }), 'missing update rejects');
|
|
44
|
+
await rejects(() => api.tombstoneRedirect({ id: 'missing-conformance-rule' }), 'missing tombstone rejects');
|
|
45
|
+
if (referenceRegexRejection) {
|
|
46
|
+
await rejects(() => api.createRedirect({ ...input, fromPattern: '/regex-conformance', matchType: 'regex' }), 'reference regex create is loudly rejected');
|
|
47
|
+
await rejects(() => api.updateRedirect({ id: created.id }, { matchType: 'regex' }), 'reference regex update is loudly rejected');
|
|
48
|
+
}
|
|
49
|
+
const batch = await api.importRedirects({ rules: [
|
|
50
|
+
{ ...input, fromPattern: '/import-conformance-a' },
|
|
51
|
+
...(referenceRegexRejection ? [{ ...input, fromPattern: '/import-conformance-regex', matchType: 'regex' }] : []),
|
|
52
|
+
{ ...input, fromPattern: '/import-conformance-c' },
|
|
53
|
+
] });
|
|
54
|
+
if (referenceRegexRejection) {
|
|
55
|
+
assert(batch.created.length === 2 && batch.failed.length === 1 && batch.failed[0]?.index === 1, 'middle failure preserves both successful siblings');
|
|
56
|
+
assert(batch.created.every(row => row.fromPattern !== '/import-conformance-regex'), 'invalid item is never reported created');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
assert(batch.created.length === 2 && batch.failed.length === 0, 'valid import batch succeeds');
|
|
60
|
+
}
|
|
61
|
+
assert(batch.created.every(row => row.source === 'import'), 'import provenance is stamped by the backend');
|
|
62
|
+
for (const row of batch.created)
|
|
63
|
+
await api.tombstoneRedirect({ id: row.id });
|
|
64
|
+
return Object.freeze(checks);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=redirects-api.conformance.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Button-controlled query gate: many mounted rows never cause a burst of hit requests.
|
|
2
|
+
* @example createHitCountController({}, {});
|
|
3
|
+
*/
|
|
4
|
+
export declare function createHitCountController(_required: Record<string, never>, _optional?: {}): {
|
|
5
|
+
getSnapshot: () => Readonly<{
|
|
6
|
+
requested: boolean;
|
|
7
|
+
}>;
|
|
8
|
+
subscribe: ({ listener }: {
|
|
9
|
+
listener: () => void;
|
|
10
|
+
}) => () => void;
|
|
11
|
+
dispose: () => void;
|
|
12
|
+
request(_input?: Record<string, never>, _options?: {}): void;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=hit-count.controller.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createControllerStore } from '../../core/module/controller-store.js';
|
|
2
|
+
/** Button-controlled query gate: many mounted rows never cause a burst of hit requests.
|
|
3
|
+
* @example createHitCountController({}, {});
|
|
4
|
+
*/
|
|
5
|
+
export function createHitCountController(_required, _optional = {}) {
|
|
6
|
+
const store = createControllerStore({ initial: { requested: false } });
|
|
7
|
+
return { getSnapshot: store.getSnapshot, subscribe: store.subscribe, dispose: store.dispose,
|
|
8
|
+
request(_input = {}, _options = {}) { store.set({ patch: { requested: true } }); } };
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=hit-count.controller.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AdminRedirectCreateInput, AdminRedirectImportResult } from '../../core/ports/redirects.js';
|
|
2
|
+
import type { RedirectsTranslate } from '../models.js';
|
|
3
|
+
export interface ImportRedirectsActions {
|
|
4
|
+
reset(): void;
|
|
5
|
+
run(rules: readonly AdminRedirectCreateInput[]): Promise<AdminRedirectImportResult>;
|
|
6
|
+
}
|
|
7
|
+
/** Parse errors are local; the existing query mutation owns request errors and pending state.
|
|
8
|
+
* @example createImportRedirectsController({ actions: () => currentMutation, t }, {});
|
|
9
|
+
*/
|
|
10
|
+
export declare function createImportRedirectsController({ actions, t }: {
|
|
11
|
+
actions: () => ImportRedirectsActions;
|
|
12
|
+
t: () => RedirectsTranslate;
|
|
13
|
+
}, _optional?: {}): {
|
|
14
|
+
getSnapshot: () => Readonly<{
|
|
15
|
+
raw: string;
|
|
16
|
+
parseError: string | null;
|
|
17
|
+
result: AdminRedirectImportResult | null;
|
|
18
|
+
}>;
|
|
19
|
+
subscribe: ({ listener }: {
|
|
20
|
+
listener: () => void;
|
|
21
|
+
}) => () => void;
|
|
22
|
+
dispose: () => void;
|
|
23
|
+
setRaw({ raw }: {
|
|
24
|
+
raw: string;
|
|
25
|
+
}, _options?: {}): void;
|
|
26
|
+
submit(_required?: Record<string, never>, _options?: {}): Promise<void>;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=import-redirects.controller.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createControllerStore } from '../../core/module/controller-store.js';
|
|
2
|
+
import { parseImportPayload } from '../rules.js';
|
|
3
|
+
/** Parse errors are local; the existing query mutation owns request errors and pending state.
|
|
4
|
+
* @example createImportRedirectsController({ actions: () => currentMutation, t }, {});
|
|
5
|
+
*/
|
|
6
|
+
export function createImportRedirectsController({ actions, t }, _optional = {}) {
|
|
7
|
+
const store = createControllerStore({
|
|
8
|
+
initial: { raw: '', parseError: null, result: null },
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
getSnapshot: store.getSnapshot, subscribe: store.subscribe, dispose: store.dispose,
|
|
12
|
+
setRaw({ raw }, _options = {}) { store.set({ patch: { raw } }); },
|
|
13
|
+
async submit(_required = {}, _options = {}) {
|
|
14
|
+
store.set({ patch: { parseError: null, result: null } });
|
|
15
|
+
actions().reset();
|
|
16
|
+
// Check JSON + array only: the server remains the validator and returns each item's 207 outcome.
|
|
17
|
+
const parsed = parseImportPayload({ raw: store.getSnapshot().raw, translate: t() });
|
|
18
|
+
if (!parsed.ok) {
|
|
19
|
+
store.set({ patch: { parseError: parsed.error } });
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
store.set({ patch: { result: await actions().run(parsed.rules) } });
|
|
24
|
+
}
|
|
25
|
+
catch { /* already surfaced by the mutation's request-error channel */ }
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=import-redirects.controller.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AdminRedirect } from '../../core/ports/redirects.js';
|
|
2
|
+
/** Fetch-query owns request/cache states; this controller owns confirmation and write sequencing. */
|
|
3
|
+
export interface RedirectsActions {
|
|
4
|
+
saving: boolean;
|
|
5
|
+
create(form: FormData): Promise<unknown>;
|
|
6
|
+
toggle(rule: AdminRedirect): Promise<unknown>;
|
|
7
|
+
remove(rule: AdminRedirect): Promise<unknown>;
|
|
8
|
+
resetOthers(active: 'create' | 'toggle' | 'remove'): void;
|
|
9
|
+
}
|
|
10
|
+
/** The action getter reads the current query mutations, preserving independent errors and guards.
|
|
11
|
+
* @example createRedirectsController({ actions: () => currentActions }, {});
|
|
12
|
+
*/
|
|
13
|
+
export declare function createRedirectsController({ actions }: {
|
|
14
|
+
actions: () => RedirectsActions;
|
|
15
|
+
}, _optional?: {}): {
|
|
16
|
+
getSnapshot: () => Readonly<{
|
|
17
|
+
pendingDelete: AdminRedirect | null;
|
|
18
|
+
}>;
|
|
19
|
+
subscribe: ({ listener }: {
|
|
20
|
+
listener: () => void;
|
|
21
|
+
}) => () => void;
|
|
22
|
+
dispose: () => void;
|
|
23
|
+
setPendingDelete({ rule }: {
|
|
24
|
+
rule: AdminRedirect | null;
|
|
25
|
+
}, _options?: {}): void;
|
|
26
|
+
createRedirect({ form }: {
|
|
27
|
+
form: FormData;
|
|
28
|
+
}, _options?: {}): Promise<boolean>;
|
|
29
|
+
onToggleStatus({ rule }: {
|
|
30
|
+
rule: AdminRedirect;
|
|
31
|
+
}, _options?: {}): void;
|
|
32
|
+
onRequestDelete({ rule }: {
|
|
33
|
+
rule: AdminRedirect;
|
|
34
|
+
}, _options?: {}): void;
|
|
35
|
+
confirmDelete(_required?: Record<string, never>, _options?: {}): void;
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=redirects.controller.d.ts.map
|