@jagilber-org/index-server 1.22.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/CHANGELOG.md +1354 -0
- package/CODE_OF_CONDUCT.md +49 -0
- package/CONTRIBUTING.md +99 -0
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/SECURITY.md +50 -0
- package/dist/config/configUtils.d.ts +11 -0
- package/dist/config/configUtils.js +87 -0
- package/dist/config/dashboardConfig.d.ts +46 -0
- package/dist/config/dashboardConfig.js +67 -0
- package/dist/config/defaultValues.d.ts +63 -0
- package/dist/config/defaultValues.js +72 -0
- package/dist/config/dirConstants.d.ts +18 -0
- package/dist/config/dirConstants.js +29 -0
- package/dist/config/featureConfig.d.ts +61 -0
- package/dist/config/featureConfig.js +121 -0
- package/dist/config/runtimeConfig.d.ts +151 -0
- package/dist/config/runtimeConfig.js +380 -0
- package/dist/config/serverConfig.d.ts +90 -0
- package/dist/config/serverConfig.js +167 -0
- package/dist/dashboard/analytics/AnalyticsEngine.d.ts +142 -0
- package/dist/dashboard/analytics/AnalyticsEngine.js +373 -0
- package/dist/dashboard/analytics/BusinessIntelligence.d.ts +187 -0
- package/dist/dashboard/analytics/BusinessIntelligence.js +594 -0
- package/dist/dashboard/client/admin.html +2175 -0
- package/dist/dashboard/client/chunks/mermaid-layout-elk.esm.min/chunk-SP2CHFBE.mjs +1 -0
- package/dist/dashboard/client/chunks/mermaid-layout-elk.esm.min/render-T6MDALS3.mjs +27 -0
- package/dist/dashboard/client/css/admin.css +1587 -0
- package/dist/dashboard/client/js/admin.auth.js +179 -0
- package/dist/dashboard/client/js/admin.boot.js +359 -0
- package/dist/dashboard/client/js/admin.config.js +196 -0
- package/dist/dashboard/client/js/admin.embeddings.js +426 -0
- package/dist/dashboard/client/js/admin.graph.js +615 -0
- package/dist/dashboard/client/js/admin.instances.js +120 -0
- package/dist/dashboard/client/js/admin.instructions.js +579 -0
- package/dist/dashboard/client/js/admin.logs.js +113 -0
- package/dist/dashboard/client/js/admin.maintenance.js +393 -0
- package/dist/dashboard/client/js/admin.messaging.js +636 -0
- package/dist/dashboard/client/js/admin.monitor.js +184 -0
- package/dist/dashboard/client/js/admin.overview.js +221 -0
- package/dist/dashboard/client/js/admin.performance.js +61 -0
- package/dist/dashboard/client/js/admin.sessions.js +292 -0
- package/dist/dashboard/client/js/admin.sqlite.js +373 -0
- package/dist/dashboard/client/js/admin.utils.js +49 -0
- package/dist/dashboard/client/js/chart.umd.js +14 -0
- package/dist/dashboard/client/js/elk.bundled.js +6696 -0
- package/dist/dashboard/client/js/marked.umd.js +74 -0
- package/dist/dashboard/client/js/mermaid.min.js +3022 -0
- package/dist/dashboard/client/mermaid-layout-elk.esm.min.mjs +1 -0
- package/dist/dashboard/export/DataExporter.d.ts +169 -0
- package/dist/dashboard/export/DataExporter.js +737 -0
- package/dist/dashboard/export/exporters/csvExporter.d.ts +11 -0
- package/dist/dashboard/export/exporters/csvExporter.js +47 -0
- package/dist/dashboard/export/exporters/exportTypes.d.ts +89 -0
- package/dist/dashboard/export/exporters/exportTypes.js +5 -0
- package/dist/dashboard/export/exporters/jsonExporter.d.ts +7 -0
- package/dist/dashboard/export/exporters/jsonExporter.js +23 -0
- package/dist/dashboard/export/exporters/xmlExporter.d.ts +17 -0
- package/dist/dashboard/export/exporters/xmlExporter.js +176 -0
- package/dist/dashboard/integration/APIIntegration.d.ts +41 -0
- package/dist/dashboard/integration/APIIntegration.js +95 -0
- package/dist/dashboard/security/SecurityMonitor.d.ts +167 -0
- package/dist/dashboard/security/SecurityMonitor.js +560 -0
- package/dist/dashboard/server/AdminPanel.d.ts +195 -0
- package/dist/dashboard/server/AdminPanel.js +861 -0
- package/dist/dashboard/server/AdminPanelConfig.d.ts +42 -0
- package/dist/dashboard/server/AdminPanelConfig.js +80 -0
- package/dist/dashboard/server/AdminPanelState.d.ts +47 -0
- package/dist/dashboard/server/AdminPanelState.js +215 -0
- package/dist/dashboard/server/ApiRoutes.d.ts +17 -0
- package/dist/dashboard/server/ApiRoutes.js +184 -0
- package/dist/dashboard/server/DashboardServer.d.ts +49 -0
- package/dist/dashboard/server/DashboardServer.js +160 -0
- package/dist/dashboard/server/FileMetricsStorage.d.ts +49 -0
- package/dist/dashboard/server/FileMetricsStorage.js +196 -0
- package/dist/dashboard/server/HttpTransport.d.ts +23 -0
- package/dist/dashboard/server/HttpTransport.js +116 -0
- package/dist/dashboard/server/InstanceManager.d.ts +53 -0
- package/dist/dashboard/server/InstanceManager.js +295 -0
- package/dist/dashboard/server/KnowledgeStore.d.ts +35 -0
- package/dist/dashboard/server/KnowledgeStore.js +105 -0
- package/dist/dashboard/server/LeaderElection.d.ts +81 -0
- package/dist/dashboard/server/LeaderElection.js +268 -0
- package/dist/dashboard/server/MetricsCollector.d.ts +200 -0
- package/dist/dashboard/server/MetricsCollector.js +810 -0
- package/dist/dashboard/server/SessionPersistenceManager.d.ts +88 -0
- package/dist/dashboard/server/SessionPersistenceManager.js +458 -0
- package/dist/dashboard/server/ThinClient.d.ts +64 -0
- package/dist/dashboard/server/ThinClient.js +237 -0
- package/dist/dashboard/server/WebSocketManager.d.ts +161 -0
- package/dist/dashboard/server/WebSocketManager.js +448 -0
- package/dist/dashboard/server/httpLifecycle.d.ts +17 -0
- package/dist/dashboard/server/httpLifecycle.js +35 -0
- package/dist/dashboard/server/legacyDashboardHtml.d.ts +9 -0
- package/dist/dashboard/server/legacyDashboardHtml.js +618 -0
- package/dist/dashboard/server/legacyDashboardStyles.d.ts +5 -0
- package/dist/dashboard/server/legacyDashboardStyles.js +490 -0
- package/dist/dashboard/server/metricsAggregation.d.ts +252 -0
- package/dist/dashboard/server/metricsAggregation.js +210 -0
- package/dist/dashboard/server/metricsSerializer.d.ts +25 -0
- package/dist/dashboard/server/metricsSerializer.js +195 -0
- package/dist/dashboard/server/middleware/ensureLoadedMiddleware.d.ts +25 -0
- package/dist/dashboard/server/middleware/ensureLoadedMiddleware.js +24 -0
- package/dist/dashboard/server/routes/admin.routes.d.ts +16 -0
- package/dist/dashboard/server/routes/admin.routes.js +574 -0
- package/dist/dashboard/server/routes/adminAuth.d.ts +4 -0
- package/dist/dashboard/server/routes/adminAuth.js +46 -0
- package/dist/dashboard/server/routes/alerts.routes.d.ts +7 -0
- package/dist/dashboard/server/routes/alerts.routes.js +91 -0
- package/dist/dashboard/server/routes/api.feedback.routes.d.ts +73 -0
- package/dist/dashboard/server/routes/api.feedback.routes.js +171 -0
- package/dist/dashboard/server/routes/api.instructions.routes.d.ts +101 -0
- package/dist/dashboard/server/routes/api.instructions.routes.js +213 -0
- package/dist/dashboard/server/routes/api.usage.routes.d.ts +57 -0
- package/dist/dashboard/server/routes/api.usage.routes.js +374 -0
- package/dist/dashboard/server/routes/embeddings.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/embeddings.routes.js +246 -0
- package/dist/dashboard/server/routes/graph.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/graph.routes.js +279 -0
- package/dist/dashboard/server/routes/index.d.ts +39 -0
- package/dist/dashboard/server/routes/index.js +229 -0
- package/dist/dashboard/server/routes/instances.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/instances.routes.js +35 -0
- package/dist/dashboard/server/routes/instructions.routes.d.ts +8 -0
- package/dist/dashboard/server/routes/instructions.routes.js +268 -0
- package/dist/dashboard/server/routes/knowledge.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/knowledge.routes.js +80 -0
- package/dist/dashboard/server/routes/logs.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/logs.routes.js +166 -0
- package/dist/dashboard/server/routes/messaging.routes.d.ts +16 -0
- package/dist/dashboard/server/routes/messaging.routes.js +307 -0
- package/dist/dashboard/server/routes/metrics.routes.d.ts +10 -0
- package/dist/dashboard/server/routes/metrics.routes.js +335 -0
- package/dist/dashboard/server/routes/scripts.routes.d.ts +9 -0
- package/dist/dashboard/server/routes/scripts.routes.js +84 -0
- package/dist/dashboard/server/routes/sqlite.routes.d.ts +9 -0
- package/dist/dashboard/server/routes/sqlite.routes.js +570 -0
- package/dist/dashboard/server/routes/status.routes.d.ts +7 -0
- package/dist/dashboard/server/routes/status.routes.js +179 -0
- package/dist/dashboard/server/routes/synthetic.routes.d.ts +7 -0
- package/dist/dashboard/server/routes/synthetic.routes.js +197 -0
- package/dist/dashboard/server/routes/tools.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/tools.routes.js +47 -0
- package/dist/dashboard/server/routes/usage.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/usage.routes.js +26 -0
- package/dist/dashboard/server/wsInit.d.ts +16 -0
- package/dist/dashboard/server/wsInit.js +35 -0
- package/dist/externalClientLib.d.ts +1 -0
- package/dist/externalClientLib.js +2 -0
- package/dist/minimal/index.d.ts +1 -0
- package/dist/minimal/index.js +140 -0
- package/dist/models/SessionPersistence.d.ts +115 -0
- package/dist/models/SessionPersistence.js +66 -0
- package/dist/models/instruction.d.ts +46 -0
- package/dist/models/instruction.js +2 -0
- package/dist/perf/benchmark.d.ts +1 -0
- package/dist/perf/benchmark.js +50 -0
- package/dist/portableClientWrapper.d.ts +1 -0
- package/dist/portableClientWrapper.js +2 -0
- package/dist/schemas/index.d.ts +132 -0
- package/dist/schemas/index.js +372 -0
- package/dist/scripts/runPerformanceBaseline.d.ts +1 -0
- package/dist/scripts/runPerformanceBaseline.js +17 -0
- package/dist/server/backgroundServicesStartup.d.ts +3 -0
- package/dist/server/backgroundServicesStartup.js +51 -0
- package/dist/server/handshakeManager.d.ts +25 -0
- package/dist/server/handshakeManager.js +470 -0
- package/dist/server/index-server.d.ts +38 -0
- package/dist/server/index-server.js +620 -0
- package/dist/server/multiInstanceStartup.d.ts +6 -0
- package/dist/server/multiInstanceStartup.js +132 -0
- package/dist/server/registry.d.ts +44 -0
- package/dist/server/registry.js +236 -0
- package/dist/server/sdkServer.d.ts +8 -0
- package/dist/server/sdkServer.js +299 -0
- package/dist/server/shutdownGuard.d.ts +41 -0
- package/dist/server/shutdownGuard.js +52 -0
- package/dist/server/startupDiagnostics.d.ts +2 -0
- package/dist/server/startupDiagnostics.js +33 -0
- package/dist/server/thin-client.d.ts +22 -0
- package/dist/server/thin-client.js +111 -0
- package/dist/server/transport.d.ts +41 -0
- package/dist/server/transport.js +312 -0
- package/dist/server/transportFactory.d.ts +21 -0
- package/dist/server/transportFactory.js +429 -0
- package/dist/services/atomicFs.d.ts +22 -0
- package/dist/services/atomicFs.js +103 -0
- package/dist/services/auditLog.d.ts +38 -0
- package/dist/services/auditLog.js +142 -0
- package/dist/services/autoBackup.d.ts +14 -0
- package/dist/services/autoBackup.js +171 -0
- package/dist/services/autoSplit.d.ts +32 -0
- package/dist/services/autoSplit.js +113 -0
- package/dist/services/backupZip.d.ts +25 -0
- package/dist/services/backupZip.js +112 -0
- package/dist/services/bootstrapGating.d.ts +123 -0
- package/dist/services/bootstrapGating.js +221 -0
- package/dist/services/canonical.d.ts +23 -0
- package/dist/services/canonical.js +65 -0
- package/dist/services/categoryRules.d.ts +7 -0
- package/dist/services/categoryRules.js +37 -0
- package/dist/services/classificationService.d.ts +42 -0
- package/dist/services/classificationService.js +168 -0
- package/dist/services/embeddingService.d.ts +62 -0
- package/dist/services/embeddingService.js +264 -0
- package/dist/services/errors.d.ts +22 -0
- package/dist/services/errors.js +31 -0
- package/dist/services/featureFlags.d.ts +25 -0
- package/dist/services/featureFlags.js +89 -0
- package/dist/services/features.d.ts +13 -0
- package/dist/services/features.js +35 -0
- package/dist/services/handlers/instructions.add.d.ts +1 -0
- package/dist/services/handlers/instructions.add.js +510 -0
- package/dist/services/handlers/instructions.groom.d.ts +1 -0
- package/dist/services/handlers/instructions.groom.js +575 -0
- package/dist/services/handlers/instructions.import.d.ts +1 -0
- package/dist/services/handlers/instructions.import.js +205 -0
- package/dist/services/handlers/instructions.patch.d.ts +1 -0
- package/dist/services/handlers/instructions.patch.js +121 -0
- package/dist/services/handlers/instructions.query.d.ts +159 -0
- package/dist/services/handlers/instructions.query.js +469 -0
- package/dist/services/handlers/instructions.reload.d.ts +1 -0
- package/dist/services/handlers/instructions.reload.js +13 -0
- package/dist/services/handlers/instructions.remove.d.ts +1 -0
- package/dist/services/handlers/instructions.remove.js +122 -0
- package/dist/services/handlers/instructions.shared.d.ts +32 -0
- package/dist/services/handlers/instructions.shared.js +91 -0
- package/dist/services/handlers.activation.d.ts +1 -0
- package/dist/services/handlers.activation.js +203 -0
- package/dist/services/handlers.bootstrap.d.ts +1 -0
- package/dist/services/handlers.bootstrap.js +38 -0
- package/dist/services/handlers.dashboardConfig.d.ts +34 -0
- package/dist/services/handlers.dashboardConfig.js +110 -0
- package/dist/services/handlers.diagnostics.d.ts +1 -0
- package/dist/services/handlers.diagnostics.js +64 -0
- package/dist/services/handlers.feedback.d.ts +15 -0
- package/dist/services/handlers.feedback.js +389 -0
- package/dist/services/handlers.gates.d.ts +1 -0
- package/dist/services/handlers.gates.js +47 -0
- package/dist/services/handlers.graph.d.ts +53 -0
- package/dist/services/handlers.graph.js +231 -0
- package/dist/services/handlers.help.d.ts +1 -0
- package/dist/services/handlers.help.js +119 -0
- package/dist/services/handlers.instructionSchema.d.ts +1 -0
- package/dist/services/handlers.instructionSchema.js +227 -0
- package/dist/services/handlers.instructions.d.ts +8 -0
- package/dist/services/handlers.instructions.js +14 -0
- package/dist/services/handlers.instructionsDiagnostics.d.ts +1 -0
- package/dist/services/handlers.instructionsDiagnostics.js +14 -0
- package/dist/services/handlers.integrity.d.ts +1 -0
- package/dist/services/handlers.integrity.js +35 -0
- package/dist/services/handlers.manifest.d.ts +1 -0
- package/dist/services/handlers.manifest.js +24 -0
- package/dist/services/handlers.messaging.d.ts +12 -0
- package/dist/services/handlers.messaging.js +203 -0
- package/dist/services/handlers.metrics.d.ts +1 -0
- package/dist/services/handlers.metrics.js +43 -0
- package/dist/services/handlers.promote.d.ts +1 -0
- package/dist/services/handlers.promote.js +326 -0
- package/dist/services/handlers.prompt.d.ts +1 -0
- package/dist/services/handlers.prompt.js +7 -0
- package/dist/services/handlers.search.d.ts +69 -0
- package/dist/services/handlers.search.js +669 -0
- package/dist/services/handlers.testPrimitive.d.ts +1 -0
- package/dist/services/handlers.testPrimitive.js +5 -0
- package/dist/services/handlers.trace.d.ts +1 -0
- package/dist/services/handlers.trace.js +35 -0
- package/dist/services/handlers.usage.d.ts +1 -0
- package/dist/services/handlers.usage.js +11 -0
- package/dist/services/hotScore.d.ts +137 -0
- package/dist/services/hotScore.js +244 -0
- package/dist/services/indexContext.d.ts +117 -0
- package/dist/services/indexContext.js +989 -0
- package/dist/services/indexLoader.d.ts +44 -0
- package/dist/services/indexLoader.js +920 -0
- package/dist/services/indexRepository.d.ts +32 -0
- package/dist/services/indexRepository.js +71 -0
- package/dist/services/indexingService.d.ts +1 -0
- package/dist/services/indexingService.js +2 -0
- package/dist/services/instructions.dispatcher.d.ts +1 -0
- package/dist/services/instructions.dispatcher.js +231 -0
- package/dist/services/logPrefix.d.ts +1 -0
- package/dist/services/logPrefix.js +30 -0
- package/dist/services/logger.d.ts +52 -0
- package/dist/services/logger.js +268 -0
- package/dist/services/manifestManager.d.ts +82 -0
- package/dist/services/manifestManager.js +200 -0
- package/dist/services/messaging/agentMailbox.d.ts +60 -0
- package/dist/services/messaging/agentMailbox.js +353 -0
- package/dist/services/messaging/messagingPersistence.d.ts +20 -0
- package/dist/services/messaging/messagingPersistence.js +111 -0
- package/dist/services/messaging/messagingTypes.d.ts +150 -0
- package/dist/services/messaging/messagingTypes.js +66 -0
- package/dist/services/ownershipService.d.ts +1 -0
- package/dist/services/ownershipService.js +36 -0
- package/dist/services/performanceBaseline.d.ts +19 -0
- package/dist/services/performanceBaseline.js +210 -0
- package/dist/services/preflight.d.ts +12 -0
- package/dist/services/preflight.js +79 -0
- package/dist/services/promptReviewService.d.ts +44 -0
- package/dist/services/promptReviewService.js +101 -0
- package/dist/services/responseEnvelope.d.ts +6 -0
- package/dist/services/responseEnvelope.js +25 -0
- package/dist/services/seedBootstrap.d.ts +34 -0
- package/dist/services/seedBootstrap.js +259 -0
- package/dist/services/storage/factory.d.ts +17 -0
- package/dist/services/storage/factory.js +35 -0
- package/dist/services/storage/hashUtils.d.ts +11 -0
- package/dist/services/storage/hashUtils.js +35 -0
- package/dist/services/storage/index.d.ts +12 -0
- package/dist/services/storage/index.js +18 -0
- package/dist/services/storage/jsonFileStore.d.ts +32 -0
- package/dist/services/storage/jsonFileStore.js +241 -0
- package/dist/services/storage/migrationEngine.d.ts +35 -0
- package/dist/services/storage/migrationEngine.js +93 -0
- package/dist/services/storage/sqliteMessageStore.d.ts +53 -0
- package/dist/services/storage/sqliteMessageStore.js +146 -0
- package/dist/services/storage/sqliteSchema.d.ts +12 -0
- package/dist/services/storage/sqliteSchema.js +123 -0
- package/dist/services/storage/sqliteStore.d.ts +42 -0
- package/dist/services/storage/sqliteStore.js +361 -0
- package/dist/services/storage/sqliteUsageStore.d.ts +35 -0
- package/dist/services/storage/sqliteUsageStore.js +94 -0
- package/dist/services/storage/types.d.ts +171 -0
- package/dist/services/storage/types.js +12 -0
- package/dist/services/toolHandlers.d.ts +23 -0
- package/dist/services/toolHandlers.js +50 -0
- package/dist/services/toolRegistry.d.ts +20 -0
- package/dist/services/toolRegistry.js +490 -0
- package/dist/services/toolRegistry.zod.d.ts +10 -0
- package/dist/services/toolRegistry.zod.js +325 -0
- package/dist/services/tracing.d.ts +26 -0
- package/dist/services/tracing.js +260 -0
- package/dist/services/usageBuckets.d.ts +161 -0
- package/dist/services/usageBuckets.js +364 -0
- package/dist/services/validationService.d.ts +38 -0
- package/dist/services/validationService.js +125 -0
- package/dist/utils/BufferRing.d.ts +203 -0
- package/dist/utils/BufferRing.js +551 -0
- package/dist/utils/BufferRingExamples.d.ts +55 -0
- package/dist/utils/BufferRingExamples.js +188 -0
- package/dist/utils/envUtils.d.ts +42 -0
- package/dist/utils/envUtils.js +80 -0
- package/dist/utils/memoryMonitor.d.ts +83 -0
- package/dist/utils/memoryMonitor.js +275 -0
- package/dist/versioning/schemaVersion.d.ts +6 -0
- package/dist/versioning/schemaVersion.js +94 -0
- package/package.json +139 -0
- package/schemas/README.md +13 -0
- package/schemas/feedback-entry.schema.json +27 -0
- package/schemas/graph-export-v2.schema.json +60 -0
- package/schemas/index-server.code-schema.json +40670 -0
- package/schemas/instruction.schema.json +262 -0
- package/schemas/json-schema/SessionPersistence-persisted-admin-session.schema.json +54 -0
- package/schemas/json-schema/SessionPersistence-persisted-session-history-entry.schema.json +51 -0
- package/schemas/json-schema/SessionPersistence-persisted-web-socket-connection.schema.json +54 -0
- package/schemas/json-schema/SessionPersistence-session-persistence-config.schema.json +110 -0
- package/schemas/json-schema/SessionPersistence-session-persistence-data.schema.json +229 -0
- package/schemas/json-schema/SessionPersistence-session-persistence-manifest.schema.json +109 -0
- package/schemas/json-schema/SessionPersistence-session-persistence-metadata.schema.json +55 -0
- package/schemas/json-schema/instruction-audience-scope.schema.json +14 -0
- package/schemas/json-schema/instruction-content-type.schema.json +17 -0
- package/schemas/json-schema/instruction-instruction-entry.schema.json +210 -0
- package/schemas/json-schema/instruction-requirement-level.schema.json +16 -0
- package/schemas/manifest.json +78 -0
- package/schemas/manifest.schema.json +33 -0
- package/schemas/usage-batch.schema.json +16 -0
- package/schemas/usage-buckets.schema.json +30 -0
- package/schemas/usage-event.schema.json +17 -0
- package/scripts/copy-dashboard-assets.mjs +170 -0
- package/scripts/dist/README.md +15 -0
- package/scripts/setup-hooks.cjs +28 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express middleware that calls ensureLoaded() once per request and attaches
|
|
3
|
+
* the IndexState to res.locals.indexState. This eliminates redundant filesystem
|
|
4
|
+
* I/O from repeated ensureLoaded() calls within a single request cycle.
|
|
5
|
+
*
|
|
6
|
+
* Route handlers that only need a read-consistent snapshot should use
|
|
7
|
+
* res.locals.indexState instead of calling ensureLoaded() directly.
|
|
8
|
+
* Mutation handlers that call invalidate() must still call ensureLoaded()
|
|
9
|
+
* explicitly after invalidation to pick up their own changes.
|
|
10
|
+
*
|
|
11
|
+
* See: https://github.com/jagilber-dev/index-server/issues/45
|
|
12
|
+
*/
|
|
13
|
+
import { Request, Response, NextFunction } from 'express';
|
|
14
|
+
import { IndexState } from '../../../services/indexContext.js';
|
|
15
|
+
/**
|
|
16
|
+
* Augment Express res.locals with the pre-loaded index state.
|
|
17
|
+
*/
|
|
18
|
+
export interface IndexLocals {
|
|
19
|
+
indexState: IndexState;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Middleware that eagerly loads the instruction index once per request.
|
|
23
|
+
* Attach to any router whose handlers need index state.
|
|
24
|
+
*/
|
|
25
|
+
export declare function ensureLoadedMiddleware(_req: Request, res: Response, next: NextFunction): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Express middleware that calls ensureLoaded() once per request and attaches
|
|
4
|
+
* the IndexState to res.locals.indexState. This eliminates redundant filesystem
|
|
5
|
+
* I/O from repeated ensureLoaded() calls within a single request cycle.
|
|
6
|
+
*
|
|
7
|
+
* Route handlers that only need a read-consistent snapshot should use
|
|
8
|
+
* res.locals.indexState instead of calling ensureLoaded() directly.
|
|
9
|
+
* Mutation handlers that call invalidate() must still call ensureLoaded()
|
|
10
|
+
* explicitly after invalidation to pick up their own changes.
|
|
11
|
+
*
|
|
12
|
+
* See: https://github.com/jagilber-dev/index-server/issues/45
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ensureLoadedMiddleware = ensureLoadedMiddleware;
|
|
16
|
+
const indexContext_js_1 = require("../../../services/indexContext.js");
|
|
17
|
+
/**
|
|
18
|
+
* Middleware that eagerly loads the instruction index once per request.
|
|
19
|
+
* Attach to any router whose handlers need index state.
|
|
20
|
+
*/
|
|
21
|
+
function ensureLoadedMiddleware(_req, res, next) {
|
|
22
|
+
res.locals.indexState = (0, indexContext_js_1.ensureLoaded)();
|
|
23
|
+
next();
|
|
24
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Panel Routes
|
|
3
|
+
* Routes: GET /admin/config, GET /admin/flags, POST /admin/config,
|
|
4
|
+
* GET /admin/sessions, POST /admin/sessions, DELETE /admin/sessions/:sessionId,
|
|
5
|
+
* GET /admin/connections, GET /admin/sessions/history,
|
|
6
|
+
* GET /admin/maintenance, POST /admin/maintenance/mode,
|
|
7
|
+
* POST /admin/maintenance/normalize, POST /admin/maintenance/backup,
|
|
8
|
+
* GET /admin/maintenance/backups, POST /admin/maintenance/restore,
|
|
9
|
+
* DELETE /admin/maintenance/backup/:id, POST /admin/maintenance/backups/prune,
|
|
10
|
+
* GET /admin/maintenance/backup/:id/export, POST /admin/maintenance/backup/import,
|
|
11
|
+
* GET /admin/stats, POST /admin/restart, POST /admin/cache/clear,
|
|
12
|
+
* POST /admin/clear-metrics
|
|
13
|
+
*/
|
|
14
|
+
import { Router } from 'express';
|
|
15
|
+
import { MetricsCollector } from '../MetricsCollector.js';
|
|
16
|
+
export declare function createAdminRoutes(metricsCollector: MetricsCollector): Router;
|
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Admin Panel Routes
|
|
4
|
+
* Routes: GET /admin/config, GET /admin/flags, POST /admin/config,
|
|
5
|
+
* GET /admin/sessions, POST /admin/sessions, DELETE /admin/sessions/:sessionId,
|
|
6
|
+
* GET /admin/connections, GET /admin/sessions/history,
|
|
7
|
+
* GET /admin/maintenance, POST /admin/maintenance/mode,
|
|
8
|
+
* POST /admin/maintenance/normalize, POST /admin/maintenance/backup,
|
|
9
|
+
* GET /admin/maintenance/backups, POST /admin/maintenance/restore,
|
|
10
|
+
* DELETE /admin/maintenance/backup/:id, POST /admin/maintenance/backups/prune,
|
|
11
|
+
* GET /admin/maintenance/backup/:id/export, POST /admin/maintenance/backup/import,
|
|
12
|
+
* GET /admin/stats, POST /admin/restart, POST /admin/cache/clear,
|
|
13
|
+
* POST /admin/clear-metrics
|
|
14
|
+
*/
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.createAdminRoutes = createAdminRoutes;
|
|
20
|
+
const fs_1 = __importDefault(require("fs"));
|
|
21
|
+
const express_1 = require("express");
|
|
22
|
+
const AdminPanel_js_1 = require("../AdminPanel.js");
|
|
23
|
+
const WebSocketManager_js_1 = require("../WebSocketManager.js");
|
|
24
|
+
const featureFlags_js_1 = require("../../../services/featureFlags.js");
|
|
25
|
+
const handlers_dashboardConfig_js_1 = require("../../../services/handlers.dashboardConfig.js");
|
|
26
|
+
const registry_js_1 = require("../../../server/registry.js");
|
|
27
|
+
const adminAuth_js_1 = require("./adminAuth.js");
|
|
28
|
+
function createAdminRoutes(metricsCollector) {
|
|
29
|
+
const router = (0, express_1.Router)();
|
|
30
|
+
const adminPanel = (0, AdminPanel_js_1.getAdminPanel)();
|
|
31
|
+
router.use(adminAuth_js_1.dashboardAdminAuth);
|
|
32
|
+
/**
|
|
33
|
+
* GET /api/admin/config - Get admin configuration
|
|
34
|
+
*/
|
|
35
|
+
router.get('/admin/config', (_req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const config = adminPanel.getAdminConfig();
|
|
38
|
+
// Surface feature flags (environment + file) for visibility
|
|
39
|
+
let featureFlags = {};
|
|
40
|
+
try {
|
|
41
|
+
featureFlags = (0, featureFlags_js_1.dumpFlags)();
|
|
42
|
+
}
|
|
43
|
+
catch { /* ignore */ }
|
|
44
|
+
// Include full registry snapshot for UI (so dashboard shows ALL flags, not just active)
|
|
45
|
+
let allFlags = [];
|
|
46
|
+
try {
|
|
47
|
+
allFlags = (0, handlers_dashboardConfig_js_1.getFlagRegistrySnapshot)();
|
|
48
|
+
}
|
|
49
|
+
catch { /* ignore */ }
|
|
50
|
+
res.json({
|
|
51
|
+
success: true,
|
|
52
|
+
config,
|
|
53
|
+
featureFlags, // currently configured / resolved flags
|
|
54
|
+
allFlags, // full registry with metadata + parsed values
|
|
55
|
+
timestamp: Date.now()
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error('[API] Get admin config error:', error);
|
|
60
|
+
res.status(500).json({
|
|
61
|
+
success: false,
|
|
62
|
+
error: 'Failed to get admin configuration',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Lightweight flags-only endpoint so the UI can retry if /admin/config was served from an older cache.
|
|
67
|
+
router.get('/admin/flags', (_req, res) => {
|
|
68
|
+
try {
|
|
69
|
+
let featureFlags = {};
|
|
70
|
+
try {
|
|
71
|
+
featureFlags = (0, featureFlags_js_1.dumpFlags)();
|
|
72
|
+
}
|
|
73
|
+
catch { /* ignore */ }
|
|
74
|
+
let allFlags = [];
|
|
75
|
+
try {
|
|
76
|
+
allFlags = (0, handlers_dashboardConfig_js_1.getFlagRegistrySnapshot)();
|
|
77
|
+
}
|
|
78
|
+
catch { /* ignore */ }
|
|
79
|
+
res.json({ success: true, featureFlags, allFlags, total: allFlags.length, timestamp: Date.now() });
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error('[Admin] Failed to get flags snapshot:', error);
|
|
83
|
+
res.status(500).json({ success: false, error: 'Failed to get flags snapshot' });
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* POST /api/admin/config - Update admin configuration
|
|
88
|
+
*/
|
|
89
|
+
router.post('/admin/config', (req, res) => {
|
|
90
|
+
try {
|
|
91
|
+
const updates = req.body;
|
|
92
|
+
const result = adminPanel.updateAdminConfig(updates);
|
|
93
|
+
// Feature flag persistence (optional field featureFlags { name:boolean })
|
|
94
|
+
if (updates.featureFlags && typeof updates.featureFlags === 'object') {
|
|
95
|
+
try {
|
|
96
|
+
(0, featureFlags_js_1.updateFlags)(updates.featureFlags);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
console.warn('[API] feature flag update failed:', e instanceof Error ? e.message : e);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (result.success) {
|
|
103
|
+
res.json({
|
|
104
|
+
success: true,
|
|
105
|
+
message: result.message,
|
|
106
|
+
timestamp: Date.now()
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
res.status(400).json({
|
|
111
|
+
success: false,
|
|
112
|
+
error: result.message,
|
|
113
|
+
timestamp: Date.now()
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
console.error('[API] Update admin config error:', error);
|
|
119
|
+
res.status(500).json({
|
|
120
|
+
success: false,
|
|
121
|
+
error: 'Failed to update admin configuration',
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
/**
|
|
126
|
+
* GET /api/admin/sessions - Get active admin sessions
|
|
127
|
+
*/
|
|
128
|
+
router.get('/admin/sessions', (_req, res) => {
|
|
129
|
+
try {
|
|
130
|
+
const sessions = adminPanel.getActiveSessions();
|
|
131
|
+
res.json({
|
|
132
|
+
success: true,
|
|
133
|
+
sessions,
|
|
134
|
+
count: sessions.length,
|
|
135
|
+
timestamp: Date.now()
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
console.error('[API] Get admin sessions error:', error);
|
|
140
|
+
res.status(500).json({
|
|
141
|
+
success: false,
|
|
142
|
+
error: 'Failed to get admin sessions',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
/**
|
|
147
|
+
* GET /api/admin/connections - Get active websocket connections (Phase 4.1 enhancement)
|
|
148
|
+
*/
|
|
149
|
+
router.get('/admin/connections', (_req, res) => {
|
|
150
|
+
try {
|
|
151
|
+
const wsMgr = (0, WebSocketManager_js_1.getWebSocketManager)();
|
|
152
|
+
const connections = wsMgr.getActiveConnectionSummaries();
|
|
153
|
+
res.json({
|
|
154
|
+
success: true,
|
|
155
|
+
connections: connections.sort((a, b) => a.connectedAt - b.connectedAt),
|
|
156
|
+
count: connections.length,
|
|
157
|
+
timestamp: Date.now()
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
console.error('[API] Get active connections error:', error);
|
|
162
|
+
res.status(500).json({ success: false, error: 'Failed to get active connections' });
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
/**
|
|
166
|
+
* POST /api/admin/sessions - Create new admin session
|
|
167
|
+
*/
|
|
168
|
+
router.post('/admin/sessions', (req, res) => {
|
|
169
|
+
try {
|
|
170
|
+
const { userId } = req.body;
|
|
171
|
+
const ipAddress = req.ip || req.connection.remoteAddress || 'unknown';
|
|
172
|
+
const userAgent = req.get('User-Agent') || 'unknown';
|
|
173
|
+
const session = adminPanel.createAdminSession(userId, ipAddress, userAgent);
|
|
174
|
+
res.json({
|
|
175
|
+
success: true,
|
|
176
|
+
session,
|
|
177
|
+
message: 'Admin session created successfully',
|
|
178
|
+
timestamp: Date.now()
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
console.error('[API] Create admin session error:', error);
|
|
183
|
+
res.status(500).json({
|
|
184
|
+
success: false,
|
|
185
|
+
error: 'Failed to create admin session',
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
/**
|
|
190
|
+
* DELETE /api/admin/sessions/:sessionId - Terminate admin session
|
|
191
|
+
*/
|
|
192
|
+
router.delete('/admin/sessions/:sessionId', (req, res) => {
|
|
193
|
+
try {
|
|
194
|
+
const { sessionId } = req.params;
|
|
195
|
+
const terminated = adminPanel.terminateSession(sessionId);
|
|
196
|
+
if (terminated) {
|
|
197
|
+
res.json({
|
|
198
|
+
success: true,
|
|
199
|
+
message: 'Admin session terminated successfully',
|
|
200
|
+
timestamp: Date.now()
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
res.status(404).json({
|
|
205
|
+
success: false,
|
|
206
|
+
error: 'Session not found',
|
|
207
|
+
timestamp: Date.now()
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.error('[API] Terminate admin session error:', error);
|
|
213
|
+
res.status(500).json({
|
|
214
|
+
success: false,
|
|
215
|
+
error: 'Failed to terminate admin session',
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
/**
|
|
220
|
+
* GET /api/admin/maintenance - Get maintenance information
|
|
221
|
+
*/
|
|
222
|
+
router.get('/admin/maintenance', (_req, res) => {
|
|
223
|
+
try {
|
|
224
|
+
const maintenance = adminPanel.getMaintenanceInfo();
|
|
225
|
+
res.json({
|
|
226
|
+
success: true,
|
|
227
|
+
maintenance,
|
|
228
|
+
timestamp: Date.now()
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
console.error('[API] Get maintenance info error:', error);
|
|
233
|
+
res.status(500).json({
|
|
234
|
+
success: false,
|
|
235
|
+
error: 'Failed to get maintenance information',
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
/**
|
|
240
|
+
* POST /api/admin/maintenance/mode - Set maintenance mode
|
|
241
|
+
*/
|
|
242
|
+
router.post('/admin/maintenance/mode', (req, res) => {
|
|
243
|
+
try {
|
|
244
|
+
const { enabled, message } = req.body;
|
|
245
|
+
const result = adminPanel.setMaintenanceMode(enabled, message);
|
|
246
|
+
if (result.success) {
|
|
247
|
+
res.json({
|
|
248
|
+
success: true,
|
|
249
|
+
message: result.message,
|
|
250
|
+
timestamp: Date.now()
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
res.status(400).json({
|
|
255
|
+
success: false,
|
|
256
|
+
error: result.message,
|
|
257
|
+
timestamp: Date.now()
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
console.error('[API] Set maintenance mode error:', error);
|
|
263
|
+
res.status(500).json({
|
|
264
|
+
success: false,
|
|
265
|
+
error: 'Failed to set maintenance mode',
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
/**
|
|
270
|
+
* POST /api/admin/maintenance/normalize - Normalize instruction index
|
|
271
|
+
* (FIX: extracted from /status handler where it was accidentally nested)
|
|
272
|
+
*/
|
|
273
|
+
router.post('/admin/maintenance/normalize', async (req, res) => {
|
|
274
|
+
try {
|
|
275
|
+
const { dryRun, forceCanonical } = req.body || {};
|
|
276
|
+
// We call the handler directly (registered via handlers.instructions) ensuring mutation flag is respected.
|
|
277
|
+
const handler = (0, registry_js_1.getLocalHandler)('index_normalize');
|
|
278
|
+
if (!handler) {
|
|
279
|
+
return res.status(503).json({ success: false, error: 'normalize_tool_unavailable' });
|
|
280
|
+
}
|
|
281
|
+
const started = Date.now();
|
|
282
|
+
const summary = await Promise.resolve(handler({ dryRun: !!dryRun, forceCanonical: !!forceCanonical }));
|
|
283
|
+
const durationMs = Date.now() - started;
|
|
284
|
+
res.json({ success: true, durationMs, dryRun: !!dryRun, forceCanonical: !!forceCanonical, summary });
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
console.error('[Admin] Normalize failed:', err);
|
|
288
|
+
res.status(500).json({ success: false, error: 'normalize_failed' });
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
/**
|
|
292
|
+
* POST /api/admin/maintenance/backup - Perform system backup
|
|
293
|
+
*/
|
|
294
|
+
router.post('/admin/maintenance/backup', async (_req, res) => {
|
|
295
|
+
try {
|
|
296
|
+
const result = await adminPanel.performBackup();
|
|
297
|
+
if (result.success) {
|
|
298
|
+
res.json({
|
|
299
|
+
success: true,
|
|
300
|
+
message: result.message,
|
|
301
|
+
backupId: result.backupId,
|
|
302
|
+
timestamp: Date.now()
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
res.status(500).json({
|
|
307
|
+
success: false,
|
|
308
|
+
error: result.message,
|
|
309
|
+
timestamp: Date.now()
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
console.error('[API] Perform backup error:', error);
|
|
315
|
+
res.status(500).json({
|
|
316
|
+
success: false,
|
|
317
|
+
error: 'Failed to perform backup',
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
/**
|
|
322
|
+
* GET /api/admin/maintenance/backups - List available backups
|
|
323
|
+
*/
|
|
324
|
+
router.get('/admin/maintenance/backups', (_req, res) => {
|
|
325
|
+
try {
|
|
326
|
+
const backups = adminPanel.listBackups();
|
|
327
|
+
res.json({ success: true, backups, count: backups.length, timestamp: Date.now() });
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
console.error('[API] List backups error:', error);
|
|
331
|
+
res.status(500).json({ success: false, error: 'Failed to list backups' });
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
/**
|
|
335
|
+
* POST /api/admin/maintenance/restore - Restore a backup
|
|
336
|
+
* body: { backupId: string }
|
|
337
|
+
*/
|
|
338
|
+
router.post('/admin/maintenance/restore', (req, res) => {
|
|
339
|
+
try {
|
|
340
|
+
const { backupId } = req.body || {};
|
|
341
|
+
const result = adminPanel.restoreBackup(backupId);
|
|
342
|
+
if (result.success) {
|
|
343
|
+
res.json({ success: true, message: result.message, restored: result.restored, timestamp: Date.now() });
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
res.status(400).json({ success: false, error: result.message, timestamp: Date.now() });
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
console.error('[API] Restore backup error:', error);
|
|
351
|
+
res.status(500).json({ success: false, error: 'Failed to restore backup' });
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
/**
|
|
355
|
+
* DELETE /api/admin/maintenance/backup/:id - Delete a specific backup directory
|
|
356
|
+
*/
|
|
357
|
+
router.delete('/admin/maintenance/backup/:id', (req, res) => {
|
|
358
|
+
try {
|
|
359
|
+
const { id } = req.params;
|
|
360
|
+
const result = adminPanel.deleteBackup(id);
|
|
361
|
+
if (result.success) {
|
|
362
|
+
res.json({ success: true, message: result.message, removed: result.removed, timestamp: Date.now() });
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
res.status(400).json({ success: false, error: result.message, timestamp: Date.now() });
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
console.error('[API] Delete backup error:', error);
|
|
370
|
+
res.status(500).json({ success: false, error: 'Failed to delete backup' });
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
/**
|
|
374
|
+
* POST /api/admin/maintenance/backups/prune { retain:number } - retain newest N (0 = delete all)
|
|
375
|
+
*/
|
|
376
|
+
router.post('/admin/maintenance/backups/prune', (req, res) => {
|
|
377
|
+
try {
|
|
378
|
+
const retain = typeof req.body?.retain === 'number' ? req.body.retain : 10;
|
|
379
|
+
const result = adminPanel.pruneBackups(retain);
|
|
380
|
+
if (result.success) {
|
|
381
|
+
res.json({ success: true, message: result.message, pruned: result.pruned, timestamp: Date.now() });
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
res.status(400).json({ success: false, error: result.message, timestamp: Date.now() });
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
console.error('[API] Prune backups error:', error);
|
|
389
|
+
res.status(500).json({ success: false, error: 'Failed to prune backups' });
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
/**
|
|
393
|
+
* GET /api/admin/maintenance/backup/:id/export - Export backup as downloadable zip or JSON bundle
|
|
394
|
+
*/
|
|
395
|
+
router.get('/admin/maintenance/backup/:id/export', (req, res) => {
|
|
396
|
+
try {
|
|
397
|
+
const { id } = req.params;
|
|
398
|
+
const result = adminPanel.exportBackup(id);
|
|
399
|
+
if (result.success && result.zipPath) {
|
|
400
|
+
res.setHeader('Content-Type', 'application/zip');
|
|
401
|
+
res.setHeader('Content-Disposition', `attachment; filename="${id}.zip"`);
|
|
402
|
+
const stream = fs_1.default.createReadStream(result.zipPath);
|
|
403
|
+
stream.pipe(res);
|
|
404
|
+
}
|
|
405
|
+
else if (result.success && result.bundle) {
|
|
406
|
+
// Legacy directory backup — serve as JSON
|
|
407
|
+
res.setHeader('Content-Type', 'application/json');
|
|
408
|
+
res.setHeader('Content-Disposition', `attachment; filename="${id}.json"`);
|
|
409
|
+
res.json(result.bundle);
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
res.status(400).json({ success: false, error: result.message, timestamp: Date.now() });
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
catch (error) {
|
|
416
|
+
console.error('[API] Export backup error:', error);
|
|
417
|
+
res.status(500).json({ success: false, error: 'Failed to export backup' });
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
/**
|
|
421
|
+
* POST /api/admin/maintenance/backup/import - Import backup from uploaded JSON bundle or zip archive
|
|
422
|
+
* body: { manifest?: object, files: { [filename]: content } } or raw zip bytes
|
|
423
|
+
*/
|
|
424
|
+
router.post('/admin/maintenance/backup/import', (0, express_1.raw)({ type: ['application/zip', 'application/octet-stream'], limit: '100mb' }), (req, res) => {
|
|
425
|
+
try {
|
|
426
|
+
if (Buffer.isBuffer(req.body) && req.body.length > 0) {
|
|
427
|
+
const sourceName = req.header('x-backup-filename') || req.header('x-file-name') || undefined;
|
|
428
|
+
const result = adminPanel.importZipBackup(req.body, sourceName);
|
|
429
|
+
if (result.success) {
|
|
430
|
+
return res.json({ success: true, message: result.message, backupId: result.backupId, files: result.files, timestamp: Date.now() });
|
|
431
|
+
}
|
|
432
|
+
return res.status(400).json({ success: false, error: result.message, timestamp: Date.now() });
|
|
433
|
+
}
|
|
434
|
+
const bundle = req.body;
|
|
435
|
+
if (!bundle || typeof bundle !== 'object' || !bundle.files) {
|
|
436
|
+
return res.status(400).json({ success: false, error: 'Request body must contain a "files" object', timestamp: Date.now() });
|
|
437
|
+
}
|
|
438
|
+
const result = adminPanel.importBackup(bundle);
|
|
439
|
+
if (result.success) {
|
|
440
|
+
res.json({ success: true, message: result.message, backupId: result.backupId, files: result.files, timestamp: Date.now() });
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
res.status(400).json({ success: false, error: result.message, timestamp: Date.now() });
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
catch (error) {
|
|
447
|
+
console.error('[API] Import backup error:', error);
|
|
448
|
+
res.status(500).json({ success: false, error: 'Failed to import backup' });
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
/**
|
|
452
|
+
* GET /api/admin/stats - Get comprehensive admin statistics
|
|
453
|
+
*/
|
|
454
|
+
router.get('/admin/stats', (_req, res) => {
|
|
455
|
+
try {
|
|
456
|
+
const stats = adminPanel.getAdminStats();
|
|
457
|
+
res.json({
|
|
458
|
+
success: true,
|
|
459
|
+
stats,
|
|
460
|
+
timestamp: Date.now()
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
console.error('[API] Get admin stats error:', error);
|
|
465
|
+
res.status(500).json({
|
|
466
|
+
success: false,
|
|
467
|
+
error: 'Failed to get admin statistics',
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
/**
|
|
472
|
+
* GET /api/admin/sessions/history - Historical admin sessions (bounded)
|
|
473
|
+
*/
|
|
474
|
+
router.get('/admin/sessions/history', (req, res) => {
|
|
475
|
+
try {
|
|
476
|
+
const limitParam = req.query.limit;
|
|
477
|
+
const limit = limitParam ? parseInt(limitParam, 10) : undefined;
|
|
478
|
+
const history = adminPanel.getSessionHistory(limit);
|
|
479
|
+
res.json({
|
|
480
|
+
success: true,
|
|
481
|
+
history,
|
|
482
|
+
count: history.length,
|
|
483
|
+
timestamp: Date.now()
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
catch (error) {
|
|
487
|
+
console.error('[API] Get session history error:', error);
|
|
488
|
+
res.status(500).json({
|
|
489
|
+
success: false,
|
|
490
|
+
error: 'Failed to get session history',
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
/**
|
|
495
|
+
* POST /api/admin/restart - Restart server components
|
|
496
|
+
*/
|
|
497
|
+
router.post('/admin/restart', async (req, res) => {
|
|
498
|
+
try {
|
|
499
|
+
const { component = 'all' } = req.body;
|
|
500
|
+
const result = await adminPanel.restartServer(component);
|
|
501
|
+
if (result.success) {
|
|
502
|
+
res.json({
|
|
503
|
+
success: true,
|
|
504
|
+
message: result.message,
|
|
505
|
+
timestamp: Date.now()
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
res.status(500).json({
|
|
510
|
+
success: false,
|
|
511
|
+
error: result.message,
|
|
512
|
+
timestamp: Date.now()
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
console.error('[API] Restart server error:', error);
|
|
518
|
+
res.status(500).json({
|
|
519
|
+
success: false,
|
|
520
|
+
error: 'Failed to restart server',
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
/**
|
|
525
|
+
* POST /api/admin/cache/clear - Clear server caches
|
|
526
|
+
*/
|
|
527
|
+
router.post('/admin/cache/clear', (_req, res) => {
|
|
528
|
+
try {
|
|
529
|
+
const result = adminPanel.clearCaches();
|
|
530
|
+
if (result.success) {
|
|
531
|
+
res.json({
|
|
532
|
+
success: true,
|
|
533
|
+
message: result.message,
|
|
534
|
+
cleared: result.cleared,
|
|
535
|
+
timestamp: Date.now()
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
res.status(500).json({
|
|
540
|
+
success: false,
|
|
541
|
+
error: result.message,
|
|
542
|
+
timestamp: Date.now()
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
catch (error) {
|
|
547
|
+
console.error('[API] Clear caches error:', error);
|
|
548
|
+
res.status(500).json({
|
|
549
|
+
success: false,
|
|
550
|
+
error: 'Failed to clear caches',
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
/**
|
|
555
|
+
* POST /api/admin/clear-metrics - Clear all metrics data (admin only)
|
|
556
|
+
*/
|
|
557
|
+
router.post('/admin/clear-metrics', (_req, res) => {
|
|
558
|
+
try {
|
|
559
|
+
metricsCollector.clearMetrics();
|
|
560
|
+
res.json({
|
|
561
|
+
success: true,
|
|
562
|
+
message: 'Metrics cleared successfully',
|
|
563
|
+
timestamp: Date.now(),
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
catch (error) {
|
|
567
|
+
console.error('[API] Clear metrics error:', error);
|
|
568
|
+
res.status(500).json({
|
|
569
|
+
error: 'Failed to clear metrics',
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
return router;
|
|
574
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
|
+
export declare function isLoopbackHost(value: string | undefined): boolean;
|
|
3
|
+
export declare function constantTimeKeyMatch(provided: string | undefined, expected: string): boolean;
|
|
4
|
+
export declare function dashboardAdminAuth(req: Request, res: Response, next: NextFunction): void;
|