@memberjunction/ng-dashboards 5.30.1 → 5.32.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/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +4 -4
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.d.ts +2 -1
- package/dist/AI/components/agents/agent-editor.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +8 -6
- package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.d.ts +2 -1
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js +6 -5
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +2 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +6 -5
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.d.ts +2 -1
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.js +6 -5
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts +2 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +7 -4
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +3 -2
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.js +10 -6
- package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +2 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +6 -5
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +2 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +6 -5
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +55 -52
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +15 -15
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +4 -3
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +2 -2
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +2 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +10 -8
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +2 -2
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.d.ts +2 -1
- package/dist/AI/components/prompts/prompt-version-control.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js +13 -10
- package/dist/AI/components/prompts/prompt-version-control.component.js.map +1 -1
- package/dist/AI/components/requests/agent-requests-resource.component.js +1 -1
- package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +1181 -0
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -0
- package/dist/AI/components/tags/tags-resource.component.js +7487 -0
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +25 -21
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/index.d.ts +1 -0
- package/dist/AI/index.d.ts.map +1 -1
- package/dist/AI/index.js +5 -0
- package/dist/AI/index.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js +12 -4
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.d.ts +3 -2
- package/dist/APIKeys/api-applications-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +5 -4
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.d.ts +2 -1
- package/dist/APIKeys/api-key-create-dialog.component.d.ts.map +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.js +5 -5
- package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.d.ts +3 -2
- package/dist/APIKeys/api-key-edit-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js +11 -10
- package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-list.component.d.ts +2 -1
- package/dist/APIKeys/api-key-list.component.d.ts.map +1 -1
- package/dist/APIKeys/api-key-list.component.js +6 -5
- package/dist/APIKeys/api-key-list.component.js.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.d.ts.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +4 -4
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.d.ts +3 -2
- package/dist/APIKeys/api-scopes-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +8 -6
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
- package/dist/APIKeys/api-usage-panel.component.d.ts +3 -2
- package/dist/APIKeys/api-usage-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-usage-panel.component.js +10 -8
- package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
- package/dist/Actions/components/actions-list-view.component.d.ts +2 -1
- package/dist/Actions/components/actions-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/actions-list-view.component.js +6 -5
- package/dist/Actions/components/actions-list-view.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +2 -2
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts +2 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +6 -5
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +1 -1
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.d.ts +2 -1
- package/dist/Actions/components/explorer/action-card.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.js +6 -4
- package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.d.ts +2 -1
- package/dist/Actions/components/explorer/new-action-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js +7 -5
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.d.ts +2 -1
- package/dist/Actions/components/explorer/new-category-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +7 -5
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/ApplicationRoles/application-roles-resource.component.js +4 -4
- package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +1 -1
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +1 -1
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +3 -3
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +1 -1
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +3 -3
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +5 -4
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts +2 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +6 -4
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +11 -2
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +61 -27
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +4 -2
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +19 -11
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.d.ts +4 -2
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +11 -3
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/workspace/component-preview.component.d.ts +10 -1
- package/dist/ComponentStudio/components/workspace/component-preview.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/workspace/component-preview.component.js +18 -9
- package/dist/ComponentStudio/components/workspace/component-preview.component.js.map +1 -1
- package/dist/ComponentStudio/services/component-studio-state.service.d.ts +11 -1
- package/dist/ComponentStudio/services/component-studio-state.service.d.ts.map +1 -1
- package/dist/ComponentStudio/services/component-studio-state.service.js +23 -3
- package/dist/ComponentStudio/services/component-studio-state.service.js.map +1 -1
- package/dist/ComponentStudio/services/component-version.service.d.ts +6 -1
- package/dist/ComponentStudio/services/component-version.service.d.ts.map +1 -1
- package/dist/ComponentStudio/services/component-version.service.js +16 -6
- package/dist/ComponentStudio/services/component-version.service.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +3 -3
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +3 -3
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +3 -3
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +3 -3
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/Credentials/credentials-dashboard.component.js +1 -1
- package/dist/Credentials/credentials-dashboard.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +13 -13
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-adapter.d.ts +4 -0
- package/dist/DashboardBrowser/dashboard-share-adapter.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-adapter.js +5 -2
- package/dist/DashboardBrowser/dashboard-share-adapter.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts +3 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +9 -4
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +3 -2
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +7 -6
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +3 -2
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +6 -5
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +10 -9
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts +6 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js +15 -5
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/DatabaseDesigner/components/create-wizard/database-create-wizard.component.d.ts +64 -0
- package/dist/DatabaseDesigner/components/create-wizard/database-create-wizard.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/database-create-wizard.component.js +400 -0
- package/dist/DatabaseDesigner/components/create-wizard/database-create-wizard.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-basics.component.d.ts +42 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-basics.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-basics.component.js +232 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-basics.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-fields.component.d.ts +14 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-fields.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-fields.component.js +38 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-fields.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-pipeline.component.d.ts +24 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-pipeline.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-pipeline.component.js +77 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-pipeline.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-relationships.component.d.ts +88 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-relationships.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-relationships.component.js +404 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-relationships.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-review.component.d.ts +12 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-review.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-review.component.js +116 -0
- package/dist/DatabaseDesigner/components/create-wizard/steps/step-review.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.d.ts +55 -0
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +204 -0
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/entity-list.component.d.ts +61 -0
- package/dist/DatabaseDesigner/components/entity-list.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/entity-list.component.js +485 -0
- package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/modify/database-modify.component.d.ts +52 -0
- package/dist/DatabaseDesigner/components/modify/database-modify.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/modify/database-modify.component.js +320 -0
- package/dist/DatabaseDesigner/components/modify/database-modify.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/shared/database-preview-pane.component.d.ts +79 -0
- package/dist/DatabaseDesigner/components/shared/database-preview-pane.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/shared/database-preview-pane.component.js +378 -0
- package/dist/DatabaseDesigner/components/shared/database-preview-pane.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/shared/entity-fields-grid.component.d.ts +85 -0
- package/dist/DatabaseDesigner/components/shared/entity-fields-grid.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/shared/entity-fields-grid.component.js +429 -0
- package/dist/DatabaseDesigner/components/shared/entity-fields-grid.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/shared/entity-pipeline-panel.component.d.ts +58 -0
- package/dist/DatabaseDesigner/components/shared/entity-pipeline-panel.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/shared/entity-pipeline-panel.component.js +333 -0
- package/dist/DatabaseDesigner/components/shared/entity-pipeline-panel.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/shared/entity-review-panel.component.d.ts +36 -0
- package/dist/DatabaseDesigner/components/shared/entity-review-panel.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/shared/entity-review-panel.component.js +345 -0
- package/dist/DatabaseDesigner/components/shared/entity-review-panel.component.js.map +1 -0
- package/dist/DatabaseDesigner/components/shared/wizard-step-indicator.component.d.ts +13 -0
- package/dist/DatabaseDesigner/components/shared/wizard-step-indicator.component.d.ts.map +1 -0
- package/dist/DatabaseDesigner/components/shared/wizard-step-indicator.component.js +81 -0
- package/dist/DatabaseDesigner/components/shared/wizard-step-indicator.component.js.map +1 -0
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +30 -0
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -0
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js +131 -0
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -0
- package/dist/DatabaseDesigner/database-designer-erd.d.ts +19 -0
- package/dist/DatabaseDesigner/database-designer-erd.d.ts.map +1 -0
- package/dist/DatabaseDesigner/database-designer-erd.js +84 -0
- package/dist/DatabaseDesigner/database-designer-erd.js.map +1 -0
- package/dist/DatabaseDesigner/database-designer.types.d.ts +167 -0
- package/dist/DatabaseDesigner/database-designer.types.d.ts.map +1 -0
- package/dist/DatabaseDesigner/database-designer.types.js +26 -0
- package/dist/DatabaseDesigner/database-designer.types.js.map +1 -0
- package/dist/DatabaseDesigner/services/database-designer.engine.d.ts +94 -0
- package/dist/DatabaseDesigner/services/database-designer.engine.d.ts.map +1 -0
- package/dist/DatabaseDesigner/services/database-designer.engine.js +392 -0
- package/dist/DatabaseDesigner/services/database-designer.engine.js.map +1 -0
- package/dist/DatabaseDesigner/services/database-designer.service.d.ts +78 -0
- package/dist/DatabaseDesigner/services/database-designer.service.d.ts.map +1 -0
- package/dist/DatabaseDesigner/services/database-designer.service.js +273 -0
- package/dist/DatabaseDesigner/services/database-designer.service.js.map +1 -0
- package/dist/DatabaseDesigner/services/entity-wizard-state.service.d.ts +79 -0
- package/dist/DatabaseDesigner/services/entity-wizard-state.service.d.ts.map +1 -0
- package/dist/DatabaseDesigner/services/entity-wizard-state.service.js +204 -0
- package/dist/DatabaseDesigner/services/entity-wizard-state.service.js.map +1 -0
- package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +2 -2
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/action-pin-config-dialog.component.d.ts +2 -1
- package/dist/Home/action-pin-config-dialog.component.d.ts.map +1 -1
- package/dist/Home/action-pin-config-dialog.component.js +6 -4
- package/dist/Home/action-pin-config-dialog.component.js.map +1 -1
- package/dist/Home/action-pin-runner-dialog.component.d.ts +2 -1
- package/dist/Home/action-pin-runner-dialog.component.d.ts.map +1 -1
- package/dist/Home/action-pin-runner-dialog.component.js +5 -4
- package/dist/Home/action-pin-runner-dialog.component.js.map +1 -1
- package/dist/Home/home-application.d.ts.map +1 -1
- package/dist/Home/home-application.js +10 -12
- package/dist/Home/home-application.js.map +1 -1
- package/dist/Home/home-dashboard.component.d.ts.map +1 -1
- package/dist/Home/home-dashboard.component.js +3 -3
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +1 -0
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +11 -10
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.d.ts.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +2 -2
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.d.ts.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +1 -0
- package/dist/Integration/components/overview/overview.component.js.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.d.ts.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.js +1 -0
- package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.d.ts.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.js +5 -4
- package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
- package/dist/Integration/services/integration-data.service.d.ts +5 -1
- package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
- package/dist/Integration/services/integration-data.service.js +27 -19
- package/dist/Integration/services/integration-data.service.js.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +6 -6
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +8 -6
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +6 -6
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +3 -3
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +6 -6
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +4 -4
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +6 -6
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +11 -10
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/Lists/services/list-set-operations.service.d.ts +5 -0
- package/dist/Lists/services/list-set-operations.service.d.ts.map +1 -1
- package/dist/Lists/services/list-set-operations.service.js +11 -3
- package/dist/Lists/services/list-set-operations.service.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.d.ts +2 -1
- package/dist/MCP/components/mcp-connection-dialog.component.d.ts.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +8 -6
- package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.d.ts +2 -1
- package/dist/MCP/components/mcp-server-dialog.component.d.ts.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +7 -5
- package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +12 -12
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/Permissions/permissions-shared.d.ts +3 -3
- package/dist/Permissions/permissions-shared.d.ts.map +1 -1
- package/dist/Permissions/permissions-shared.js +5 -5
- package/dist/Permissions/permissions-shared.js.map +1 -1
- package/dist/Permissions/resource-access-resource.component.js +1 -1
- package/dist/Permissions/resource-access-resource.component.js.map +1 -1
- package/dist/Permissions/user-access-resource.component.js +1 -2
- package/dist/Permissions/user-access-resource.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +2 -2
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.d.ts.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +1 -0
- package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +5 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js +21 -13
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.js +2 -2
- package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +2 -1
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +9 -7
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/services/testing-instrumentation.service.d.ts +6 -1
- package/dist/Testing/services/testing-instrumentation.service.d.ts.map +1 -1
- package/dist/Testing/services/testing-instrumentation.service.js +21 -11
- package/dist/Testing/services/testing-instrumentation.service.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.d.ts +3 -1
- package/dist/Testing/testing-dashboard.component.d.ts.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +15 -11
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js +5 -5
- package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/graph-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/graph-resource.component.js +1 -2
- package/dist/VersionHistory/components/graph-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +3 -3
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +35 -34
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +6 -0
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/module.d.ts +13 -12
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +7 -0
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +3 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -1
- package/dist/public-api.js.map +1 -1
- package/dist/shared/entity-field-display.d.ts +4 -3
- package/dist/shared/entity-field-display.d.ts.map +1 -1
- package/dist/shared/entity-field-display.js +9 -9
- package/dist/shared/entity-field-display.js.map +1 -1
- package/package.json +52 -51
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module database-designer.service
|
|
3
|
+
* @description Angular service that wraps `GraphQLActionClient.RunAction()` for all
|
|
4
|
+
* five Database Designer server-side actions.
|
|
5
|
+
*
|
|
6
|
+
* ### Responsibilities
|
|
7
|
+
* - Lazy-resolve action UUIDs by name on first use and cache them
|
|
8
|
+
* - Build strongly-typed `ActionParam[]` arrays from typed Angular inputs
|
|
9
|
+
* - Parse output params and map them to typed Angular response objects
|
|
10
|
+
* - Surface error messages in a consistent format
|
|
11
|
+
*
|
|
12
|
+
* ### Why @Injectable({ providedIn: 'root' })?
|
|
13
|
+
* The action ID cache (`_actionIdCache`) must outlive individual component
|
|
14
|
+
* lifecycles. A root-level singleton ensures the first action lookup per
|
|
15
|
+
* action name is shared across the entire session.
|
|
16
|
+
*
|
|
17
|
+
* ### Action ID caching
|
|
18
|
+
* Action IDs are cached as `Promise<string>` (not `string`) so that concurrent
|
|
19
|
+
* callers waiting on the same lookup share a single in-flight request rather
|
|
20
|
+
* than triggering N parallel `MJ: Actions` queries.
|
|
21
|
+
*
|
|
22
|
+
* @see DatabaseDesignerEngine — for read-only data access (no action invocations)
|
|
23
|
+
*/
|
|
24
|
+
import { Injectable } from '@angular/core';
|
|
25
|
+
import { RunView } from '@memberjunction/core';
|
|
26
|
+
import { GraphQLDataProvider, GraphQLActionClient } from '@memberjunction/graphql-dataprovider';
|
|
27
|
+
import * as i0 from "@angular/core";
|
|
28
|
+
// ─── Action name constants ────────────────────────────────────────────────────
|
|
29
|
+
// Must stay in sync with @RegisterClass registrations in database-designer-actions package.
|
|
30
|
+
const ACTION_NAMES = {
|
|
31
|
+
CREATE_ENTITY: 'Create Entity',
|
|
32
|
+
MODIFY_ENTITY: 'Modify Entity',
|
|
33
|
+
VALIDATE_ENTITY_SCHEMA: 'Validate Entity Schema',
|
|
34
|
+
DESCRIBE_ENTITY: 'Describe Entity',
|
|
35
|
+
LIST_MY_ENTITIES: 'List My Entities',
|
|
36
|
+
};
|
|
37
|
+
// ─── Service ─────────────────────────────────────────────────────────────────
|
|
38
|
+
export class DatabaseDesignerService {
|
|
39
|
+
// ─── Action client ────────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Lazily-created action client. Re-uses `GraphQLDataProvider.Instance` so the
|
|
42
|
+
* singleton provider (and its auth headers) are shared across all invocations.
|
|
43
|
+
*/
|
|
44
|
+
_actionClient = null;
|
|
45
|
+
getActionClient() {
|
|
46
|
+
if (!this._actionClient) {
|
|
47
|
+
this._actionClient = new GraphQLActionClient(GraphQLDataProvider.Instance);
|
|
48
|
+
}
|
|
49
|
+
return this._actionClient;
|
|
50
|
+
}
|
|
51
|
+
// ─── Action ID resolution ─────────────────────────────────────────────
|
|
52
|
+
/**
|
|
53
|
+
* Cache maps action name → Promise<ID>. Storing a Promise (not a resolved ID)
|
|
54
|
+
* prevents duplicate in-flight lookups when two callers await the same name
|
|
55
|
+
* before the first resolves.
|
|
56
|
+
*/
|
|
57
|
+
_actionIdCache = new Map();
|
|
58
|
+
resolveActionId(actionName) {
|
|
59
|
+
let pending = this._actionIdCache.get(actionName);
|
|
60
|
+
if (!pending) {
|
|
61
|
+
pending = this.fetchActionId(actionName);
|
|
62
|
+
this._actionIdCache.set(actionName, pending);
|
|
63
|
+
}
|
|
64
|
+
return pending;
|
|
65
|
+
}
|
|
66
|
+
async fetchActionId(actionName) {
|
|
67
|
+
const rv = new RunView();
|
|
68
|
+
const result = await rv.RunView({
|
|
69
|
+
EntityName: 'MJ: Actions',
|
|
70
|
+
ExtraFilter: `Name = '${actionName.replace(/'/g, "''")}'`,
|
|
71
|
+
Fields: ['ID'],
|
|
72
|
+
ResultType: 'simple',
|
|
73
|
+
});
|
|
74
|
+
if (!result.Success || result.Results.length === 0) {
|
|
75
|
+
throw new Error(`Database Designer action '${actionName}' not found in MJ. ` +
|
|
76
|
+
`Ensure database-designer-actions metadata has been pushed via mj sync push.`);
|
|
77
|
+
}
|
|
78
|
+
return result.Results[0].ID;
|
|
79
|
+
}
|
|
80
|
+
// ─── Public action methods ────────────────────────────────────────────
|
|
81
|
+
/**
|
|
82
|
+
* Create a new MemberJunction entity from a `EntityTableSpec`.
|
|
83
|
+
* Calls the `Create Entity` action on the server which runs the full RSU pipeline.
|
|
84
|
+
*/
|
|
85
|
+
async createEntity(tableSpec, options = {}) {
|
|
86
|
+
try {
|
|
87
|
+
const actionId = await this.resolveActionId(ACTION_NAMES.CREATE_ENTITY);
|
|
88
|
+
const params = this.buildPipelineParams(tableSpec, options);
|
|
89
|
+
const result = await this.getActionClient().RunAction(actionId, params);
|
|
90
|
+
return this.extractPipelineResult(result);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
return { Success: false, ErrorMessage: this.errorMessage(err) };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Modify an existing MemberJunction entity.
|
|
98
|
+
* Calls the `Modify Entity` action on the server.
|
|
99
|
+
*/
|
|
100
|
+
async modifyEntity(tableSpec, options) {
|
|
101
|
+
try {
|
|
102
|
+
const actionId = await this.resolveActionId(ACTION_NAMES.MODIFY_ENTITY);
|
|
103
|
+
const params = [
|
|
104
|
+
...this.buildPipelineParams(tableSpec, options),
|
|
105
|
+
{ Name: 'ExistingEntityID', Type: 'Input', Value: options.existingEntityId },
|
|
106
|
+
];
|
|
107
|
+
const result = await this.getActionClient().RunAction(actionId, params);
|
|
108
|
+
return this.extractPipelineResult(result);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
return { Success: false, ErrorMessage: this.errorMessage(err) };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Validate a `EntityTableSpec` without executing the pipeline.
|
|
116
|
+
* Used by Step 4 (Review) of the wizard to surface errors before the user submits.
|
|
117
|
+
*
|
|
118
|
+
* Note: `ActionResult.Success` is `true` even when `ValidationResult.Valid` is `false`
|
|
119
|
+
* because the action itself succeeded — validation failure is a business outcome, not
|
|
120
|
+
* an infrastructure error.
|
|
121
|
+
*/
|
|
122
|
+
async validateEntitySchema(tableSpec, modificationType = 'create') {
|
|
123
|
+
try {
|
|
124
|
+
const actionId = await this.resolveActionId(ACTION_NAMES.VALIDATE_ENTITY_SCHEMA);
|
|
125
|
+
const params = [
|
|
126
|
+
{ Name: 'TableDefinition', Type: 'Input', Value: tableSpec },
|
|
127
|
+
{ Name: 'ModificationType', Type: 'Input', Value: modificationType },
|
|
128
|
+
];
|
|
129
|
+
const result = await this.getActionClient().RunAction(actionId, params);
|
|
130
|
+
const outputParams = this.extractOutputParams(result);
|
|
131
|
+
const outputParam = outputParams.find(p => p.Name === 'ValidationResult');
|
|
132
|
+
if (outputParam?.Value) {
|
|
133
|
+
const raw = typeof outputParam.Value === 'string'
|
|
134
|
+
? JSON.parse(outputParam.Value)
|
|
135
|
+
: outputParam.Value;
|
|
136
|
+
return { Valid: !!raw.Valid, Errors: raw.Errors ?? [], Warnings: raw.Warnings ?? [] };
|
|
137
|
+
}
|
|
138
|
+
// Fallback: treat action-level failure as a validation failure
|
|
139
|
+
return { Valid: false, Errors: [result.Message ?? 'Validation failed'], Warnings: [] };
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
return { Valid: false, Errors: [this.errorMessage(err)], Warnings: [] };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Load detailed metadata for an existing entity.
|
|
147
|
+
* Used by the entity list slide panel and the modify wizard entry point.
|
|
148
|
+
*/
|
|
149
|
+
async describeEntity(entityId) {
|
|
150
|
+
try {
|
|
151
|
+
const actionId = await this.resolveActionId(ACTION_NAMES.DESCRIBE_ENTITY);
|
|
152
|
+
const params = [
|
|
153
|
+
{ Name: 'EntityID', Type: 'Input', Value: entityId },
|
|
154
|
+
];
|
|
155
|
+
const result = await this.getActionClient().RunAction(actionId, params);
|
|
156
|
+
if (!result.Success) {
|
|
157
|
+
return { Success: false, ErrorMessage: result.Message };
|
|
158
|
+
}
|
|
159
|
+
const outputParams = this.extractOutputParams(result);
|
|
160
|
+
const outputParam = outputParams.find(p => p.Name === 'EntityDetails');
|
|
161
|
+
const raw = outputParam?.Value
|
|
162
|
+
? (typeof outputParam.Value === 'string' ? JSON.parse(outputParam.Value) : outputParam.Value)
|
|
163
|
+
: {};
|
|
164
|
+
return {
|
|
165
|
+
Success: true,
|
|
166
|
+
EntityName: raw.EntityName,
|
|
167
|
+
SchemaName: raw.SchemaName,
|
|
168
|
+
TableName: raw.TableName,
|
|
169
|
+
Description: raw.Description,
|
|
170
|
+
Fields: raw.Fields ?? [],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
return { Success: false, ErrorMessage: this.errorMessage(err) };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ─── Private helpers ──────────────────────────────────────────────────
|
|
178
|
+
buildPipelineParams(tableSpec, options) {
|
|
179
|
+
const params = [
|
|
180
|
+
{ Name: 'TableDefinition', Type: 'Input', Value: tableSpec },
|
|
181
|
+
];
|
|
182
|
+
if (options.skipGitCommit) {
|
|
183
|
+
params.push({ Name: 'SkipGitCommit', Type: 'Input', Value: 'true' });
|
|
184
|
+
}
|
|
185
|
+
if (options.skipRestart) {
|
|
186
|
+
params.push({ Name: 'SkipRestart', Type: 'Input', Value: 'true' });
|
|
187
|
+
}
|
|
188
|
+
return params;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Extract server output params from a `RunAction` result.
|
|
192
|
+
*
|
|
193
|
+
* ### Why `result.Result`, not `result.Params`?
|
|
194
|
+
* `ActionResolver.createActionResult` on the server serializes all Output/Both typed
|
|
195
|
+
* params into a JSON string stored in `ResultData`. `GraphQLActionClient` parses that
|
|
196
|
+
* JSON and stores the resulting array in `result.Result`. The `result.Params` field
|
|
197
|
+
* contains only the *input* params passed by the caller — the server's output params
|
|
198
|
+
* are never included there.
|
|
199
|
+
*
|
|
200
|
+
* This helper centralizes the cast so no caller ever needs to understand this transport
|
|
201
|
+
* contract directly.
|
|
202
|
+
*/
|
|
203
|
+
extractOutputParams(result) {
|
|
204
|
+
// result.Result is typed as MJActionResultCodeEntity | undefined in the ActionResult
|
|
205
|
+
// class, but GraphQLActionClient repurposes it to carry the parsed ResultData payload
|
|
206
|
+
// (an ActionParam[]). We cast through unknown to acknowledge this intentional mismatch.
|
|
207
|
+
const raw = result.Result;
|
|
208
|
+
if (Array.isArray(raw))
|
|
209
|
+
return raw;
|
|
210
|
+
// CopyScalarsAndArrays (used server-side to serialize ResultData) converts arrays to
|
|
211
|
+
// numeric-keyed plain objects — e.g. [p0, p1] → {"0": p0, "1": p1}.
|
|
212
|
+
// Detect and restore that pattern so callers can find their output params.
|
|
213
|
+
if (raw && typeof raw === 'object') {
|
|
214
|
+
const keys = Object.keys(raw);
|
|
215
|
+
if (keys.length > 0 && keys.every(k => /^\d+$/.test(k))) {
|
|
216
|
+
const obj = raw;
|
|
217
|
+
return keys.sort((a, b) => +a - +b).map(k => obj[k]);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return [];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Map a completed `ActionResult` to an `EntityPipelineResult`.
|
|
224
|
+
*
|
|
225
|
+
* Two failure modes are distinguished:
|
|
226
|
+
* - `result.Success === false`: infrastructure failure (auth, pipeline exception) → hard error
|
|
227
|
+
* - `result.Success === true` but `EntityID` missing: pipeline ran but ID unconfirmed →
|
|
228
|
+
* soft warning so the UI can surface guidance without blocking the user
|
|
229
|
+
*/
|
|
230
|
+
extractPipelineResult(result) {
|
|
231
|
+
const outputParams = this.extractOutputParams(result);
|
|
232
|
+
const find = (name) => outputParams.find(p => p.Name === name)?.Value;
|
|
233
|
+
const stepsRaw = find('PipelineSteps');
|
|
234
|
+
const steps = stepsRaw
|
|
235
|
+
? (typeof stepsRaw === 'string' ? JSON.parse(stepsRaw) : stepsRaw)
|
|
236
|
+
: [];
|
|
237
|
+
if (!result.Success) {
|
|
238
|
+
return {
|
|
239
|
+
Success: false,
|
|
240
|
+
PipelineSteps: steps,
|
|
241
|
+
ErrorMessage: result.Message ?? 'Action execution failed.',
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
const entityId = find('EntityID');
|
|
245
|
+
const warnings = [];
|
|
246
|
+
if (entityId == null) {
|
|
247
|
+
// Pipeline ran but EntityID was not echoed back — this can happen when the server
|
|
248
|
+
// completes the RSU pipeline but the metadata refresh hasn't propagated the new
|
|
249
|
+
// entity ID yet. Treat as a soft warning, not a hard failure.
|
|
250
|
+
warnings.push('Entity was saved successfully but the EntityID could not be confirmed. ' +
|
|
251
|
+
'Refresh the list to verify.');
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
Success: true,
|
|
255
|
+
EntityID: entityId != null ? String(entityId) : undefined,
|
|
256
|
+
EntityName: String(find('EntityName') ?? ''),
|
|
257
|
+
SchemaName: String(find('SchemaName') ?? ''),
|
|
258
|
+
TableName: String(find('TableName') ?? ''),
|
|
259
|
+
PipelineSteps: steps,
|
|
260
|
+
Warnings: warnings.length > 0 ? warnings : undefined,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
errorMessage(err) {
|
|
264
|
+
return err instanceof Error ? err.message : String(err);
|
|
265
|
+
}
|
|
266
|
+
static ɵfac = function DatabaseDesignerService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DatabaseDesignerService)(); };
|
|
267
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DatabaseDesignerService, factory: DatabaseDesignerService.ɵfac, providedIn: 'root' });
|
|
268
|
+
}
|
|
269
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DatabaseDesignerService, [{
|
|
270
|
+
type: Injectable,
|
|
271
|
+
args: [{ providedIn: 'root' }]
|
|
272
|
+
}], null, null); })();
|
|
273
|
+
//# sourceMappingURL=database-designer.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-designer.service.js","sourceRoot":"","sources":["../../../src/DatabaseDesigner/services/database-designer.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @module database-designer.service\n * @description Angular service that wraps `GraphQLActionClient.RunAction()` for all\n * five Database Designer server-side actions.\n *\n * ### Responsibilities\n * - Lazy-resolve action UUIDs by name on first use and cache them\n * - Build strongly-typed `ActionParam[]` arrays from typed Angular inputs\n * - Parse output params and map them to typed Angular response objects\n * - Surface error messages in a consistent format\n *\n * ### Why @Injectable({ providedIn: 'root' })?\n * The action ID cache (`_actionIdCache`) must outlive individual component\n * lifecycles. A root-level singleton ensures the first action lookup per\n * action name is shared across the entire session.\n *\n * ### Action ID caching\n * Action IDs are cached as `Promise<string>` (not `string`) so that concurrent\n * callers waiting on the same lookup share a single in-flight request rather\n * than triggering N parallel `MJ: Actions` queries.\n *\n * @see DatabaseDesignerEngine — for read-only data access (no action invocations)\n */\n\nimport { Injectable } from '@angular/core';\nimport { RunView } from '@memberjunction/core';\nimport { GraphQLDataProvider, GraphQLActionClient } from '@memberjunction/graphql-dataprovider';\nimport type { ActionParam, ActionResult } from '@memberjunction/actions-base';\n\nimport type {\n EntityTableSpec,\n ClientValidationResult,\n EntityPipelineResult,\n EntityDescribeResult,\n PipelineStepSummary,\n} from '../database-designer.types.js';\n\n// ─── Action name constants ────────────────────────────────────────────────────\n// Must stay in sync with @RegisterClass registrations in database-designer-actions package.\n\nconst ACTION_NAMES = {\n CREATE_ENTITY: 'Create Entity',\n MODIFY_ENTITY: 'Modify Entity',\n VALIDATE_ENTITY_SCHEMA: 'Validate Entity Schema',\n DESCRIBE_ENTITY: 'Describe Entity',\n LIST_MY_ENTITIES: 'List My Entities',\n} as const;\n\n// ─── Options ──────────────────────────────────────────────────────────────────\n\nexport interface CreateEntityOptions {\n skipGitCommit?: boolean;\n skipRestart?: boolean;\n}\n\nexport interface ModifyEntityOptions extends CreateEntityOptions {\n /** ID of the existing entity being modified. */\n existingEntityId: string;\n}\n\n// ─── Service ─────────────────────────────────────────────────────────────────\n\n@Injectable({ providedIn: 'root' })\nexport class DatabaseDesignerService {\n\n // ─── Action client ────────────────────────────────────────────────────\n\n /**\n * Lazily-created action client. Re-uses `GraphQLDataProvider.Instance` so the\n * singleton provider (and its auth headers) are shared across all invocations.\n */\n private _actionClient: GraphQLActionClient | null = null;\n\n private getActionClient(): GraphQLActionClient {\n if (!this._actionClient) {\n this._actionClient = new GraphQLActionClient(GraphQLDataProvider.Instance);\n }\n return this._actionClient;\n }\n\n // ─── Action ID resolution ─────────────────────────────────────────────\n\n /**\n * Cache maps action name → Promise<ID>. Storing a Promise (not a resolved ID)\n * prevents duplicate in-flight lookups when two callers await the same name\n * before the first resolves.\n */\n private readonly _actionIdCache = new Map<string, Promise<string>>();\n\n private resolveActionId(actionName: string): Promise<string> {\n let pending = this._actionIdCache.get(actionName);\n if (!pending) {\n pending = this.fetchActionId(actionName);\n this._actionIdCache.set(actionName, pending);\n }\n return pending;\n }\n\n private async fetchActionId(actionName: string): Promise<string> {\n const rv = new RunView();\n const result = await rv.RunView<{ ID: string }>({\n EntityName: 'MJ: Actions',\n ExtraFilter: `Name = '${actionName.replace(/'/g, \"''\")}'`,\n Fields: ['ID'],\n ResultType: 'simple',\n });\n\n if (!result.Success || result.Results.length === 0) {\n throw new Error(\n `Database Designer action '${actionName}' not found in MJ. ` +\n `Ensure database-designer-actions metadata has been pushed via mj sync push.`\n );\n }\n return result.Results[0].ID;\n }\n\n // ─── Public action methods ────────────────────────────────────────────\n\n /**\n * Create a new MemberJunction entity from a `EntityTableSpec`.\n * Calls the `Create Entity` action on the server which runs the full RSU pipeline.\n */\n public async createEntity(\n tableSpec: EntityTableSpec,\n options: CreateEntityOptions = {}\n ): Promise<EntityPipelineResult> {\n try {\n const actionId = await this.resolveActionId(ACTION_NAMES.CREATE_ENTITY);\n const params = this.buildPipelineParams(tableSpec, options);\n const result = await this.getActionClient().RunAction(actionId, params);\n return this.extractPipelineResult(result);\n } catch (err) {\n return { Success: false, ErrorMessage: this.errorMessage(err) };\n }\n }\n\n /**\n * Modify an existing MemberJunction entity.\n * Calls the `Modify Entity` action on the server.\n */\n public async modifyEntity(\n tableSpec: EntityTableSpec,\n options: ModifyEntityOptions\n ): Promise<EntityPipelineResult> {\n try {\n const actionId = await this.resolveActionId(ACTION_NAMES.MODIFY_ENTITY);\n const params: ActionParam[] = [\n ...this.buildPipelineParams(tableSpec, options),\n { Name: 'ExistingEntityID', Type: 'Input', Value: options.existingEntityId },\n ];\n const result = await this.getActionClient().RunAction(actionId, params);\n return this.extractPipelineResult(result);\n } catch (err) {\n return { Success: false, ErrorMessage: this.errorMessage(err) };\n }\n }\n\n /**\n * Validate a `EntityTableSpec` without executing the pipeline.\n * Used by Step 4 (Review) of the wizard to surface errors before the user submits.\n *\n * Note: `ActionResult.Success` is `true` even when `ValidationResult.Valid` is `false`\n * because the action itself succeeded — validation failure is a business outcome, not\n * an infrastructure error.\n */\n public async validateEntitySchema(\n tableSpec: EntityTableSpec,\n modificationType: 'create' | 'alter' = 'create'\n ): Promise<ClientValidationResult> {\n try {\n const actionId = await this.resolveActionId(ACTION_NAMES.VALIDATE_ENTITY_SCHEMA);\n const params: ActionParam[] = [\n { Name: 'TableDefinition', Type: 'Input', Value: tableSpec },\n { Name: 'ModificationType', Type: 'Input', Value: modificationType },\n ];\n const result = await this.getActionClient().RunAction(actionId, params);\n const outputParams = this.extractOutputParams(result);\n const outputParam = outputParams.find(p => p.Name === 'ValidationResult');\n if (outputParam?.Value) {\n const raw = typeof outputParam.Value === 'string'\n ? JSON.parse(outputParam.Value)\n : outputParam.Value;\n return { Valid: !!raw.Valid, Errors: raw.Errors ?? [], Warnings: raw.Warnings ?? [] };\n }\n // Fallback: treat action-level failure as a validation failure\n return { Valid: false, Errors: [result.Message ?? 'Validation failed'], Warnings: [] };\n } catch (err) {\n return { Valid: false, Errors: [this.errorMessage(err)], Warnings: [] };\n }\n }\n\n /**\n * Load detailed metadata for an existing entity.\n * Used by the entity list slide panel and the modify wizard entry point.\n */\n public async describeEntity(entityId: string): Promise<EntityDescribeResult> {\n try {\n const actionId = await this.resolveActionId(ACTION_NAMES.DESCRIBE_ENTITY);\n const params: ActionParam[] = [\n { Name: 'EntityID', Type: 'Input', Value: entityId },\n ];\n const result = await this.getActionClient().RunAction(actionId, params);\n if (!result.Success) {\n return { Success: false, ErrorMessage: result.Message };\n }\n\n const outputParams = this.extractOutputParams(result);\n const outputParam = outputParams.find(p => p.Name === 'EntityDetails');\n const raw = outputParam?.Value\n ? (typeof outputParam.Value === 'string' ? JSON.parse(outputParam.Value) : outputParam.Value)\n : {};\n\n return {\n Success: true,\n EntityName: raw.EntityName,\n SchemaName: raw.SchemaName,\n TableName: raw.TableName,\n Description: raw.Description,\n Fields: raw.Fields ?? [],\n };\n } catch (err) {\n return { Success: false, ErrorMessage: this.errorMessage(err) };\n }\n }\n\n // ─── Private helpers ──────────────────────────────────────────────────\n\n private buildPipelineParams(tableSpec: EntityTableSpec, options: CreateEntityOptions): ActionParam[] {\n const params: ActionParam[] = [\n { Name: 'TableDefinition', Type: 'Input', Value: tableSpec },\n ];\n if (options.skipGitCommit) {\n params.push({ Name: 'SkipGitCommit', Type: 'Input', Value: 'true' });\n }\n if (options.skipRestart) {\n params.push({ Name: 'SkipRestart', Type: 'Input', Value: 'true' });\n }\n return params;\n }\n\n /**\n * Extract server output params from a `RunAction` result.\n *\n * ### Why `result.Result`, not `result.Params`?\n * `ActionResolver.createActionResult` on the server serializes all Output/Both typed\n * params into a JSON string stored in `ResultData`. `GraphQLActionClient` parses that\n * JSON and stores the resulting array in `result.Result`. The `result.Params` field\n * contains only the *input* params passed by the caller — the server's output params\n * are never included there.\n *\n * This helper centralizes the cast so no caller ever needs to understand this transport\n * contract directly.\n */\n private extractOutputParams(result: ActionResult): ActionParam[] {\n // result.Result is typed as MJActionResultCodeEntity | undefined in the ActionResult\n // class, but GraphQLActionClient repurposes it to carry the parsed ResultData payload\n // (an ActionParam[]). We cast through unknown to acknowledge this intentional mismatch.\n const raw: unknown = result.Result;\n if (Array.isArray(raw)) return raw as ActionParam[];\n\n // CopyScalarsAndArrays (used server-side to serialize ResultData) converts arrays to\n // numeric-keyed plain objects — e.g. [p0, p1] → {\"0\": p0, \"1\": p1}.\n // Detect and restore that pattern so callers can find their output params.\n if (raw && typeof raw === 'object') {\n const keys = Object.keys(raw as object);\n if (keys.length > 0 && keys.every(k => /^\\d+$/.test(k))) {\n const obj = raw as Record<string, ActionParam>;\n return keys.sort((a, b) => +a - +b).map(k => obj[k]);\n }\n }\n return [];\n }\n\n /**\n * Map a completed `ActionResult` to an `EntityPipelineResult`.\n *\n * Two failure modes are distinguished:\n * - `result.Success === false`: infrastructure failure (auth, pipeline exception) → hard error\n * - `result.Success === true` but `EntityID` missing: pipeline ran but ID unconfirmed →\n * soft warning so the UI can surface guidance without blocking the user\n */\n private extractPipelineResult(result: ActionResult): EntityPipelineResult {\n const outputParams = this.extractOutputParams(result);\n const find = (name: string) => outputParams.find(p => p.Name === name)?.Value;\n\n const stepsRaw = find('PipelineSteps');\n const steps: PipelineStepSummary[] = stepsRaw\n ? (typeof stepsRaw === 'string' ? JSON.parse(stepsRaw) : stepsRaw)\n : [];\n\n if (!result.Success) {\n return {\n Success: false,\n PipelineSteps: steps,\n ErrorMessage: result.Message ?? 'Action execution failed.',\n };\n }\n\n const entityId = find('EntityID');\n const warnings: string[] = [];\n\n if (entityId == null) {\n // Pipeline ran but EntityID was not echoed back — this can happen when the server\n // completes the RSU pipeline but the metadata refresh hasn't propagated the new\n // entity ID yet. Treat as a soft warning, not a hard failure.\n warnings.push(\n 'Entity was saved successfully but the EntityID could not be confirmed. ' +\n 'Refresh the list to verify.'\n );\n }\n\n return {\n Success: true,\n EntityID: entityId != null ? String(entityId) : undefined,\n EntityName: String(find('EntityName') ?? ''),\n SchemaName: String(find('SchemaName') ?? ''),\n TableName: String(find('TableName') ?? ''),\n PipelineSteps: steps,\n Warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n\n private errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n }\n}\n"]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module entity-wizard-state.service
|
|
3
|
+
* @description Per-wizard state management for the Database Designer create/modify flow.
|
|
4
|
+
*
|
|
5
|
+
* ### Lifecycle
|
|
6
|
+
* NOT an Angular injectable — manually instantiated by the wizard host component so
|
|
7
|
+
* each open panel has its own isolated state. The host must call `destroy()` from
|
|
8
|
+
* `ngOnDestroy()` to complete all observables and prevent leaks.
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // In the wizard component:
|
|
12
|
+
* private readonly designerService = inject(DatabaseDesignerService);
|
|
13
|
+
* private readonly wizardState = new EntityWizardStateService(this.designerService);
|
|
14
|
+
*
|
|
15
|
+
* ngOnDestroy(): void { this.wizardState.destroy(); }
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* ### Responsibility boundary
|
|
19
|
+
* - Step navigation (currentStep$ BehaviorSubject)
|
|
20
|
+
* - Draft TableDefinition assembly from step values
|
|
21
|
+
* - Synchronous step validation (empty required fields, reserved column names)
|
|
22
|
+
* - Server round-trips (validateSchema, submit) delegated to DatabaseDesignerService
|
|
23
|
+
*
|
|
24
|
+
* No component layout, no templates, no Angular DI lifecycle.
|
|
25
|
+
*/
|
|
26
|
+
import { Observable } from 'rxjs';
|
|
27
|
+
import { DatabaseDesignerService } from './database-designer.service.js';
|
|
28
|
+
import type { EntityTableSpec, BasicsStepValue, ColumnSpec, ForeignKeySpec, ClientValidationResult, EntityPipelineResult, WizardStep } from '../database-designer.types.js';
|
|
29
|
+
export declare class EntityWizardStateService {
|
|
30
|
+
private readonly designerService;
|
|
31
|
+
constructor(designerService: DatabaseDesignerService);
|
|
32
|
+
private readonly _currentStep;
|
|
33
|
+
private readonly _tableDefinition;
|
|
34
|
+
private readonly _stepErrors;
|
|
35
|
+
private readonly _validationResult;
|
|
36
|
+
private readonly _pipelineResult;
|
|
37
|
+
private readonly _isValidating;
|
|
38
|
+
private readonly _isSubmitting;
|
|
39
|
+
readonly currentStep$: Observable<WizardStep>;
|
|
40
|
+
readonly tableDefinition$: Observable<Partial<EntityTableSpec>>;
|
|
41
|
+
readonly stepErrors$: Observable<Record<string, string>>;
|
|
42
|
+
readonly validationResult$: Observable<ClientValidationResult | null>;
|
|
43
|
+
readonly pipelineResult$: Observable<EntityPipelineResult | null>;
|
|
44
|
+
readonly isValidating$: Observable<boolean>;
|
|
45
|
+
readonly isSubmitting$: Observable<boolean>;
|
|
46
|
+
get CurrentStep(): WizardStep;
|
|
47
|
+
get TableDefinition(): Partial<EntityTableSpec>;
|
|
48
|
+
GoToStep(step: WizardStep): void;
|
|
49
|
+
/** Returns true if the current step passes synchronous validation. */
|
|
50
|
+
ValidateStep(step: WizardStep): boolean;
|
|
51
|
+
UpdateBasics(basics: BasicsStepValue): void;
|
|
52
|
+
UpdateFields(columns: ColumnSpec[]): void;
|
|
53
|
+
UpdateRelationships(fks: ForeignKeySpec[]): void;
|
|
54
|
+
/**
|
|
55
|
+
* Update relationships and auto-create UUID source columns for any FK whose
|
|
56
|
+
* `ColumnName` does not yet exist in `Columns`. Fixes the "Step 3 dead-end"
|
|
57
|
+
* where a user can add a relationship but has no valid UUID column to back it.
|
|
58
|
+
*
|
|
59
|
+
* An auto-created column is marked with `Description: 'Auto-generated FK to {Table}'`
|
|
60
|
+
* so the user can tell what the wizard added for them. The column can still
|
|
61
|
+
* be renamed or deleted from Step 2.
|
|
62
|
+
*/
|
|
63
|
+
UpdateRelationshipsAndAutoColumns(fks: ForeignKeySpec[]): void;
|
|
64
|
+
/**
|
|
65
|
+
* Validate the current TableDefinition via `Validate Entity Schema` action.
|
|
66
|
+
* Updates `validationResult$` and `stepErrors$`.
|
|
67
|
+
*/
|
|
68
|
+
ValidateSchema(): Promise<ClientValidationResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Run the entity creation or modification pipeline via the appropriate action.
|
|
71
|
+
* Updates `pipelineResult$` on completion.
|
|
72
|
+
*/
|
|
73
|
+
Submit(modificationType: 'create' | 'alter', existingEntityId?: string): Promise<EntityPipelineResult>;
|
|
74
|
+
/** Complete all subjects — call from the host component's ngOnDestroy. */
|
|
75
|
+
Destroy(): void;
|
|
76
|
+
/** Build a complete EntityTableSpec from the draft, or null if required fields missing. */
|
|
77
|
+
private buildCompleteSpec;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=entity-wizard-state.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-wizard-state.service.d.ts","sourceRoot":"","sources":["../../../src/DatabaseDesigner/services/entity-wizard-state.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAmB,UAAU,EAAE,MAAM,MAAM,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,KAAK,EACR,eAAe,EACf,eAAe,EACf,UAAU,EACV,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,UAAU,EACb,MAAM,+BAA+B,CAAC;AAEvC,qBAAa,wBAAwB;IAErB,OAAO,CAAC,QAAQ,CAAC,eAAe;gBAAf,eAAe,EAAE,uBAAuB;IAIrE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6C;IAC1E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqD;IACtF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmD;IAC/E,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA4D;IAC9F,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0D;IAC1F,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;IACrE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;IAErE,SAAgB,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,CAAgD;IACpG,SAAgB,gBAAgB,EAAE,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAwC;IAC9G,SAAgB,WAAW,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAoC;IACnG,SAAgB,iBAAiB,EAAE,UAAU,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAyC;IACrH,SAAgB,eAAe,EAAE,UAAU,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAwC;IAChH,SAAgB,aAAa,EAAE,UAAU,CAAC,OAAO,CAAC,CAAmD;IACrG,SAAgB,aAAa,EAAE,UAAU,CAAC,OAAO,CAAC,CAAmD;IAIrG,IAAW,WAAW,IAAI,UAAU,CAAoC;IACxE,IAAW,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CAAwC;IAIvF,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAIvC,sEAAsE;IAC/D,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO;IAyBvC,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAU3C,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI;IAIzC,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,IAAI;IAIvD;;;;;;;;OAQG;IACI,iCAAiC,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,IAAI;IA0BrE;;;OAGG;IACU,cAAc,IAAI,OAAO,CAAC,sBAAsB,CAAC;IAuB9D;;;OAGG;IACU,MAAM,CACf,gBAAgB,EAAE,QAAQ,GAAG,OAAO,EACpC,gBAAgB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,oBAAoB,CAAC;IAsBhC,0EAA0E;IACnE,OAAO,IAAI,IAAI;IAYtB,2FAA2F;IAC3F,OAAO,CAAC,iBAAiB;CAY5B"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module entity-wizard-state.service
|
|
3
|
+
* @description Per-wizard state management for the Database Designer create/modify flow.
|
|
4
|
+
*
|
|
5
|
+
* ### Lifecycle
|
|
6
|
+
* NOT an Angular injectable — manually instantiated by the wizard host component so
|
|
7
|
+
* each open panel has its own isolated state. The host must call `destroy()` from
|
|
8
|
+
* `ngOnDestroy()` to complete all observables and prevent leaks.
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // In the wizard component:
|
|
12
|
+
* private readonly designerService = inject(DatabaseDesignerService);
|
|
13
|
+
* private readonly wizardState = new EntityWizardStateService(this.designerService);
|
|
14
|
+
*
|
|
15
|
+
* ngOnDestroy(): void { this.wizardState.destroy(); }
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* ### Responsibility boundary
|
|
19
|
+
* - Step navigation (currentStep$ BehaviorSubject)
|
|
20
|
+
* - Draft TableDefinition assembly from step values
|
|
21
|
+
* - Synchronous step validation (empty required fields, reserved column names)
|
|
22
|
+
* - Server round-trips (validateSchema, submit) delegated to DatabaseDesignerService
|
|
23
|
+
*
|
|
24
|
+
* No component layout, no templates, no Angular DI lifecycle.
|
|
25
|
+
*/
|
|
26
|
+
import { BehaviorSubject } from 'rxjs';
|
|
27
|
+
export class EntityWizardStateService {
|
|
28
|
+
designerService;
|
|
29
|
+
constructor(designerService) {
|
|
30
|
+
this.designerService = designerService;
|
|
31
|
+
}
|
|
32
|
+
// ─── Observables ───────────────────────────────────────────────────────
|
|
33
|
+
_currentStep = new BehaviorSubject('basics');
|
|
34
|
+
_tableDefinition = new BehaviorSubject({});
|
|
35
|
+
_stepErrors = new BehaviorSubject({});
|
|
36
|
+
_validationResult = new BehaviorSubject(null);
|
|
37
|
+
_pipelineResult = new BehaviorSubject(null);
|
|
38
|
+
_isValidating = new BehaviorSubject(false);
|
|
39
|
+
_isSubmitting = new BehaviorSubject(false);
|
|
40
|
+
currentStep$ = this._currentStep.asObservable();
|
|
41
|
+
tableDefinition$ = this._tableDefinition.asObservable();
|
|
42
|
+
stepErrors$ = this._stepErrors.asObservable();
|
|
43
|
+
validationResult$ = this._validationResult.asObservable();
|
|
44
|
+
pipelineResult$ = this._pipelineResult.asObservable();
|
|
45
|
+
isValidating$ = this._isValidating.asObservable();
|
|
46
|
+
isSubmitting$ = this._isSubmitting.asObservable();
|
|
47
|
+
// ─── Convenience snapshot getters ─────────────────────────────────────
|
|
48
|
+
get CurrentStep() { return this._currentStep.value; }
|
|
49
|
+
get TableDefinition() { return this._tableDefinition.value; }
|
|
50
|
+
// ─── Step navigation ───────────────────────────────────────────────────
|
|
51
|
+
GoToStep(step) {
|
|
52
|
+
this._currentStep.next(step);
|
|
53
|
+
}
|
|
54
|
+
/** Returns true if the current step passes synchronous validation. */
|
|
55
|
+
ValidateStep(step) {
|
|
56
|
+
const errors = {};
|
|
57
|
+
if (step === 'basics') {
|
|
58
|
+
const td = this._tableDefinition.value;
|
|
59
|
+
if (!td.EntityName?.trim())
|
|
60
|
+
errors['entityName'] = 'Entity name is required.';
|
|
61
|
+
if (!td.TableName?.trim())
|
|
62
|
+
errors['tableName'] = 'Table name is required.';
|
|
63
|
+
if (!td.SchemaName?.trim())
|
|
64
|
+
errors['schemaName'] = 'Schema is required.';
|
|
65
|
+
}
|
|
66
|
+
if (step === 'fields') {
|
|
67
|
+
const reserved = (this._tableDefinition.value.Columns ?? [])
|
|
68
|
+
.filter(c => /^(id|__mj_createdat|__mj_updatedat)$/i.test(c.Name));
|
|
69
|
+
if (reserved.length > 0) {
|
|
70
|
+
errors['reservedNames'] =
|
|
71
|
+
`Remove reserved column names: ${reserved.map(c => c.Name).join(', ')}.`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
this._stepErrors.next(errors);
|
|
75
|
+
return Object.keys(errors).length === 0;
|
|
76
|
+
}
|
|
77
|
+
// ─── Mutation helpers ──────────────────────────────────────────────────
|
|
78
|
+
UpdateBasics(basics) {
|
|
79
|
+
this._tableDefinition.next({
|
|
80
|
+
...this._tableDefinition.value,
|
|
81
|
+
EntityName: basics.entityName,
|
|
82
|
+
TableName: basics.tableName,
|
|
83
|
+
SchemaName: basics.schemaName,
|
|
84
|
+
Description: basics.description || undefined,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
UpdateFields(columns) {
|
|
88
|
+
this._tableDefinition.next({ ...this._tableDefinition.value, Columns: columns });
|
|
89
|
+
}
|
|
90
|
+
UpdateRelationships(fks) {
|
|
91
|
+
this._tableDefinition.next({ ...this._tableDefinition.value, ForeignKeys: fks });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Update relationships and auto-create UUID source columns for any FK whose
|
|
95
|
+
* `ColumnName` does not yet exist in `Columns`. Fixes the "Step 3 dead-end"
|
|
96
|
+
* where a user can add a relationship but has no valid UUID column to back it.
|
|
97
|
+
*
|
|
98
|
+
* An auto-created column is marked with `Description: 'Auto-generated FK to {Table}'`
|
|
99
|
+
* so the user can tell what the wizard added for them. The column can still
|
|
100
|
+
* be renamed or deleted from Step 2.
|
|
101
|
+
*/
|
|
102
|
+
UpdateRelationshipsAndAutoColumns(fks) {
|
|
103
|
+
const existing = this._tableDefinition.value.Columns ?? [];
|
|
104
|
+
const existingNames = new Set(existing.map(c => c.Name.toLowerCase()));
|
|
105
|
+
const newColumns = [];
|
|
106
|
+
for (const fk of fks) {
|
|
107
|
+
if (!fk.ColumnName)
|
|
108
|
+
continue;
|
|
109
|
+
if (existingNames.has(fk.ColumnName.toLowerCase()))
|
|
110
|
+
continue;
|
|
111
|
+
existingNames.add(fk.ColumnName.toLowerCase());
|
|
112
|
+
newColumns.push({
|
|
113
|
+
Name: fk.ColumnName,
|
|
114
|
+
Type: 'uuid',
|
|
115
|
+
IsNullable: true,
|
|
116
|
+
Description: `Auto-generated FK to ${fk.ReferencedSchema}.${fk.ReferencedTable}`,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
this._tableDefinition.next({
|
|
120
|
+
...this._tableDefinition.value,
|
|
121
|
+
Columns: newColumns.length ? [...existing, ...newColumns] : existing,
|
|
122
|
+
ForeignKeys: fks,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// ─── Server round-trips ────────────────────────────────────────────────
|
|
126
|
+
/**
|
|
127
|
+
* Validate the current TableDefinition via `Validate Entity Schema` action.
|
|
128
|
+
* Updates `validationResult$` and `stepErrors$`.
|
|
129
|
+
*/
|
|
130
|
+
async ValidateSchema() {
|
|
131
|
+
const td = this.buildCompleteSpec();
|
|
132
|
+
if (!td) {
|
|
133
|
+
const err = { Valid: false, Errors: ['Schema is incomplete.'], Warnings: [] };
|
|
134
|
+
this._validationResult.next(err);
|
|
135
|
+
return err;
|
|
136
|
+
}
|
|
137
|
+
this._isValidating.next(true);
|
|
138
|
+
try {
|
|
139
|
+
const result = await this.designerService.validateEntitySchema(td);
|
|
140
|
+
this._validationResult.next(result);
|
|
141
|
+
if (!result.Valid) {
|
|
142
|
+
this._stepErrors.next({ serverValidation: result.Errors.join('; ') });
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
this._stepErrors.next({});
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
this._isValidating.next(false);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Run the entity creation or modification pipeline via the appropriate action.
|
|
155
|
+
* Updates `pipelineResult$` on completion.
|
|
156
|
+
*/
|
|
157
|
+
async Submit(modificationType, existingEntityId) {
|
|
158
|
+
const td = this.buildCompleteSpec();
|
|
159
|
+
if (!td) {
|
|
160
|
+
const err = { Success: false, ErrorMessage: 'Schema is incomplete.' };
|
|
161
|
+
this._pipelineResult.next(err);
|
|
162
|
+
return err;
|
|
163
|
+
}
|
|
164
|
+
this._isSubmitting.next(true);
|
|
165
|
+
try {
|
|
166
|
+
const result = modificationType === 'create'
|
|
167
|
+
? await this.designerService.createEntity(td)
|
|
168
|
+
: await this.designerService.modifyEntity(td, {
|
|
169
|
+
existingEntityId: existingEntityId ?? '',
|
|
170
|
+
});
|
|
171
|
+
this._pipelineResult.next(result);
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
this._isSubmitting.next(false);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/** Complete all subjects — call from the host component's ngOnDestroy. */
|
|
179
|
+
Destroy() {
|
|
180
|
+
this._currentStep.complete();
|
|
181
|
+
this._tableDefinition.complete();
|
|
182
|
+
this._stepErrors.complete();
|
|
183
|
+
this._validationResult.complete();
|
|
184
|
+
this._pipelineResult.complete();
|
|
185
|
+
this._isValidating.complete();
|
|
186
|
+
this._isSubmitting.complete();
|
|
187
|
+
}
|
|
188
|
+
// ─── Private helpers ───────────────────────────────────────────────────
|
|
189
|
+
/** Build a complete EntityTableSpec from the draft, or null if required fields missing. */
|
|
190
|
+
buildCompleteSpec() {
|
|
191
|
+
const draft = this._tableDefinition.value;
|
|
192
|
+
if (!draft.EntityName || !draft.TableName || !draft.SchemaName)
|
|
193
|
+
return null;
|
|
194
|
+
return {
|
|
195
|
+
EntityName: draft.EntityName,
|
|
196
|
+
TableName: draft.TableName,
|
|
197
|
+
SchemaName: draft.SchemaName,
|
|
198
|
+
Description: draft.Description,
|
|
199
|
+
Columns: draft.Columns ?? [],
|
|
200
|
+
ForeignKeys: draft.ForeignKeys ?? [],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=entity-wizard-state.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-wizard-state.service.js","sourceRoot":"","sources":["../../../src/DatabaseDesigner/services/entity-wizard-state.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @module entity-wizard-state.service\n * @description Per-wizard state management for the Database Designer create/modify flow.\n *\n * ### Lifecycle\n * NOT an Angular injectable — manually instantiated by the wizard host component so\n * each open panel has its own isolated state. The host must call `destroy()` from\n * `ngOnDestroy()` to complete all observables and prevent leaks.\n *\n * ```typescript\n * // In the wizard component:\n * private readonly designerService = inject(DatabaseDesignerService);\n * private readonly wizardState = new EntityWizardStateService(this.designerService);\n *\n * ngOnDestroy(): void { this.wizardState.destroy(); }\n * ```\n *\n * ### Responsibility boundary\n * - Step navigation (currentStep$ BehaviorSubject)\n * - Draft TableDefinition assembly from step values\n * - Synchronous step validation (empty required fields, reserved column names)\n * - Server round-trips (validateSchema, submit) delegated to DatabaseDesignerService\n *\n * No component layout, no templates, no Angular DI lifecycle.\n */\n\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { DatabaseDesignerService } from './database-designer.service.js';\nimport type {\n EntityTableSpec,\n BasicsStepValue,\n ColumnSpec,\n ForeignKeySpec,\n ClientValidationResult,\n EntityPipelineResult,\n WizardStep,\n} from '../database-designer.types.js';\n\nexport class EntityWizardStateService {\n\n constructor(private readonly designerService: DatabaseDesignerService) {}\n\n // ─── Observables ───────────────────────────────────────────────────────\n\n private readonly _currentStep = new BehaviorSubject<WizardStep>('basics');\n private readonly _tableDefinition = new BehaviorSubject<Partial<EntityTableSpec>>({});\n private readonly _stepErrors = new BehaviorSubject<Record<string, string>>({});\n private readonly _validationResult = new BehaviorSubject<ClientValidationResult | null>(null);\n private readonly _pipelineResult = new BehaviorSubject<EntityPipelineResult | null>(null);\n private readonly _isValidating = new BehaviorSubject<boolean>(false);\n private readonly _isSubmitting = new BehaviorSubject<boolean>(false);\n\n public readonly currentStep$: Observable<WizardStep> = this._currentStep.asObservable();\n public readonly tableDefinition$: Observable<Partial<EntityTableSpec>> = this._tableDefinition.asObservable();\n public readonly stepErrors$: Observable<Record<string, string>> = this._stepErrors.asObservable();\n public readonly validationResult$: Observable<ClientValidationResult | null> = this._validationResult.asObservable();\n public readonly pipelineResult$: Observable<EntityPipelineResult | null> = this._pipelineResult.asObservable();\n public readonly isValidating$: Observable<boolean> = this._isValidating.asObservable();\n public readonly isSubmitting$: Observable<boolean> = this._isSubmitting.asObservable();\n\n // ─── Convenience snapshot getters ─────────────────────────────────────\n\n public get CurrentStep(): WizardStep { return this._currentStep.value; }\n public get TableDefinition(): Partial<EntityTableSpec> { return this._tableDefinition.value; }\n\n // ─── Step navigation ───────────────────────────────────────────────────\n\n public GoToStep(step: WizardStep): void {\n this._currentStep.next(step);\n }\n\n /** Returns true if the current step passes synchronous validation. */\n public ValidateStep(step: WizardStep): boolean {\n const errors: Record<string, string> = {};\n\n if (step === 'basics') {\n const td = this._tableDefinition.value;\n if (!td.EntityName?.trim()) errors['entityName'] = 'Entity name is required.';\n if (!td.TableName?.trim()) errors['tableName'] = 'Table name is required.';\n if (!td.SchemaName?.trim()) errors['schemaName'] = 'Schema is required.';\n }\n\n if (step === 'fields') {\n const reserved = (this._tableDefinition.value.Columns ?? [])\n .filter(c => /^(id|__mj_createdat|__mj_updatedat)$/i.test(c.Name));\n if (reserved.length > 0) {\n errors['reservedNames'] =\n `Remove reserved column names: ${reserved.map(c => c.Name).join(', ')}.`;\n }\n }\n\n this._stepErrors.next(errors);\n return Object.keys(errors).length === 0;\n }\n\n // ─── Mutation helpers ──────────────────────────────────────────────────\n\n public UpdateBasics(basics: BasicsStepValue): void {\n this._tableDefinition.next({\n ...this._tableDefinition.value,\n EntityName: basics.entityName,\n TableName: basics.tableName,\n SchemaName: basics.schemaName,\n Description: basics.description || undefined,\n });\n }\n\n public UpdateFields(columns: ColumnSpec[]): void {\n this._tableDefinition.next({ ...this._tableDefinition.value, Columns: columns });\n }\n\n public UpdateRelationships(fks: ForeignKeySpec[]): void {\n this._tableDefinition.next({ ...this._tableDefinition.value, ForeignKeys: fks });\n }\n\n /**\n * Update relationships and auto-create UUID source columns for any FK whose\n * `ColumnName` does not yet exist in `Columns`. Fixes the \"Step 3 dead-end\"\n * where a user can add a relationship but has no valid UUID column to back it.\n *\n * An auto-created column is marked with `Description: 'Auto-generated FK to {Table}'`\n * so the user can tell what the wizard added for them. The column can still\n * be renamed or deleted from Step 2.\n */\n public UpdateRelationshipsAndAutoColumns(fks: ForeignKeySpec[]): void {\n const existing = this._tableDefinition.value.Columns ?? [];\n const existingNames = new Set(existing.map(c => c.Name.toLowerCase()));\n\n const newColumns: ColumnSpec[] = [];\n for (const fk of fks) {\n if (!fk.ColumnName) continue;\n if (existingNames.has(fk.ColumnName.toLowerCase())) continue;\n existingNames.add(fk.ColumnName.toLowerCase());\n newColumns.push({\n Name: fk.ColumnName,\n Type: 'uuid',\n IsNullable: true,\n Description: `Auto-generated FK to ${fk.ReferencedSchema}.${fk.ReferencedTable}`,\n });\n }\n\n this._tableDefinition.next({\n ...this._tableDefinition.value,\n Columns: newColumns.length ? [...existing, ...newColumns] : existing,\n ForeignKeys: fks,\n });\n }\n\n // ─── Server round-trips ────────────────────────────────────────────────\n\n /**\n * Validate the current TableDefinition via `Validate Entity Schema` action.\n * Updates `validationResult$` and `stepErrors$`.\n */\n public async ValidateSchema(): Promise<ClientValidationResult> {\n const td = this.buildCompleteSpec();\n if (!td) {\n const err: ClientValidationResult = { Valid: false, Errors: ['Schema is incomplete.'], Warnings: [] };\n this._validationResult.next(err);\n return err;\n }\n\n this._isValidating.next(true);\n try {\n const result = await this.designerService.validateEntitySchema(td);\n this._validationResult.next(result);\n if (!result.Valid) {\n this._stepErrors.next({ serverValidation: result.Errors.join('; ') });\n } else {\n this._stepErrors.next({});\n }\n return result;\n } finally {\n this._isValidating.next(false);\n }\n }\n\n /**\n * Run the entity creation or modification pipeline via the appropriate action.\n * Updates `pipelineResult$` on completion.\n */\n public async Submit(\n modificationType: 'create' | 'alter',\n existingEntityId?: string,\n ): Promise<EntityPipelineResult> {\n const td = this.buildCompleteSpec();\n if (!td) {\n const err: EntityPipelineResult = { Success: false, ErrorMessage: 'Schema is incomplete.' };\n this._pipelineResult.next(err);\n return err;\n }\n\n this._isSubmitting.next(true);\n try {\n const result = modificationType === 'create'\n ? await this.designerService.createEntity(td)\n : await this.designerService.modifyEntity(td, {\n existingEntityId: existingEntityId ?? '',\n });\n this._pipelineResult.next(result);\n return result;\n } finally {\n this._isSubmitting.next(false);\n }\n }\n\n /** Complete all subjects — call from the host component's ngOnDestroy. */\n public Destroy(): void {\n this._currentStep.complete();\n this._tableDefinition.complete();\n this._stepErrors.complete();\n this._validationResult.complete();\n this._pipelineResult.complete();\n this._isValidating.complete();\n this._isSubmitting.complete();\n }\n\n // ─── Private helpers ───────────────────────────────────────────────────\n\n /** Build a complete EntityTableSpec from the draft, or null if required fields missing. */\n private buildCompleteSpec(): EntityTableSpec | null {\n const draft = this._tableDefinition.value;\n if (!draft.EntityName || !draft.TableName || !draft.SchemaName) return null;\n return {\n EntityName: draft.EntityName,\n TableName: draft.TableName,\n SchemaName: draft.SchemaName,\n Description: draft.Description,\n Columns: draft.Columns ?? [],\n ForeignKeys: draft.ForeignKeys ?? [],\n };\n }\n}\n"]}
|