@friggframework/core 2.0.0-next.1 → 2.0.0-next.100
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/CLAUDE.md +702 -0
- package/README.md +959 -50
- package/admin-scripts/index.js +52 -0
- package/admin-scripts/repositories/admin-script-execution-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/admin-script-execution-repository-factory.js +51 -0
- package/admin-scripts/repositories/admin-script-execution-repository-interface.js +166 -0
- package/admin-scripts/repositories/admin-script-execution-repository-mongo.js +228 -0
- package/admin-scripts/repositories/admin-script-execution-repository-postgres.js +268 -0
- package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/script-schedule-repository-factory.js +51 -0
- package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
- package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
- package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
- package/application/commands/README.md +451 -0
- package/application/commands/admin-script-commands.js +358 -0
- package/application/commands/credential-commands.js +245 -0
- package/application/commands/entity-commands.js +336 -0
- package/application/commands/integration-commands.js +343 -0
- package/application/commands/process-commands.js +135 -0
- package/application/commands/scheduler-commands.js +263 -0
- package/application/commands/user-commands.js +312 -0
- package/application/index.js +82 -0
- package/assertions/index.js +0 -3
- package/core/CLAUDE.md +690 -0
- package/core/Worker.js +60 -24
- package/core/create-handler.js +84 -6
- package/credential/repositories/credential-repository-documentdb.js +304 -0
- package/credential/repositories/credential-repository-factory.js +54 -0
- package/credential/repositories/credential-repository-interface.js +98 -0
- package/credential/repositories/credential-repository-mongo.js +269 -0
- package/credential/repositories/credential-repository-postgres.js +287 -0
- package/credential/repositories/credential-repository.js +300 -0
- package/credential/use-cases/get-credential-for-user.js +25 -0
- package/credential/use-cases/update-authentication-status.js +15 -0
- package/database/MONGODB_TRANSACTION_FIX.md +198 -0
- package/database/adapters/lambda-invoker.js +97 -0
- package/database/config.js +154 -0
- package/database/documentdb-encryption-service.js +330 -0
- package/database/documentdb-utils.js +136 -0
- package/database/encryption/README.md +839 -0
- package/database/encryption/documentdb-encryption-service.md +3575 -0
- package/database/encryption/encryption-schema-registry.js +401 -0
- package/database/encryption/field-encryption-service.js +254 -0
- package/database/encryption/logger.js +79 -0
- package/database/encryption/prisma-encryption-extension.js +230 -0
- package/database/index.js +21 -21
- package/database/prisma.js +182 -0
- package/database/repositories/health-check-repository-documentdb.js +138 -0
- package/database/repositories/health-check-repository-factory.js +48 -0
- package/database/repositories/health-check-repository-interface.js +82 -0
- package/database/repositories/health-check-repository-mongodb.js +89 -0
- package/database/repositories/health-check-repository-postgres.js +82 -0
- package/database/repositories/migration-status-repository-s3.js +137 -0
- package/database/use-cases/check-database-health-use-case.js +29 -0
- package/database/use-cases/check-database-state-use-case.js +81 -0
- package/database/use-cases/check-encryption-health-use-case.js +83 -0
- package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
- package/database/use-cases/get-migration-status-use-case.js +93 -0
- package/database/use-cases/run-database-migration-use-case.js +139 -0
- package/database/use-cases/test-encryption-use-case.js +253 -0
- package/database/use-cases/trigger-database-migration-use-case.js +157 -0
- package/database/utils/mongodb-collection-utils.js +94 -0
- package/database/utils/mongodb-schema-init.js +108 -0
- package/database/utils/prisma-runner.js +477 -0
- package/database/utils/prisma-schema-parser.js +182 -0
- package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
- package/encrypt/Cryptor.js +34 -168
- package/encrypt/index.js +1 -2
- package/errors/client-safe-error.js +26 -0
- package/errors/fetch-error.js +15 -7
- package/errors/index.js +2 -0
- package/generated/prisma-mongodb/client.d.ts +1 -0
- package/generated/prisma-mongodb/client.js +5 -0
- package/generated/prisma-mongodb/default.d.ts +1 -0
- package/generated/prisma-mongodb/default.js +5 -0
- package/generated/prisma-mongodb/edge.d.ts +1 -0
- package/generated/prisma-mongodb/edge.js +374 -0
- package/generated/prisma-mongodb/index-browser.js +356 -0
- package/generated/prisma-mongodb/index.d.ts +25667 -0
- package/generated/prisma-mongodb/index.js +399 -0
- package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-mongodb/package.json +183 -0
- package/generated/prisma-mongodb/runtime/edge-esm.js +35 -0
- package/generated/prisma-mongodb/runtime/edge.js +35 -0
- package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-mongodb/runtime/index-browser.js +17 -0
- package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
- package/generated/prisma-mongodb/runtime/library.js +147 -0
- package/generated/prisma-mongodb/runtime/react-native.js +84 -0
- package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +85 -0
- package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +38 -0
- package/generated/prisma-mongodb/schema.prisma +432 -0
- package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +5 -0
- package/generated/prisma-mongodb/wasm-worker-loader.mjs +5 -0
- package/generated/prisma-mongodb/wasm.d.ts +1 -0
- package/generated/prisma-mongodb/wasm.js +381 -0
- package/generated/prisma-postgresql/client.d.ts +1 -0
- package/generated/prisma-postgresql/client.js +5 -0
- package/generated/prisma-postgresql/default.d.ts +1 -0
- package/generated/prisma-postgresql/default.js +5 -0
- package/generated/prisma-postgresql/edge.d.ts +1 -0
- package/generated/prisma-postgresql/edge.js +395 -0
- package/generated/prisma-postgresql/index-browser.js +377 -0
- package/generated/prisma-postgresql/index.d.ts +28455 -0
- package/generated/prisma-postgresql/index.js +420 -0
- package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-postgresql/package.json +183 -0
- package/generated/prisma-postgresql/query_engine_bg.js +2 -0
- package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
- package/generated/prisma-postgresql/runtime/edge-esm.js +35 -0
- package/generated/prisma-postgresql/runtime/edge.js +35 -0
- package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-postgresql/runtime/index-browser.js +17 -0
- package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
- package/generated/prisma-postgresql/runtime/library.js +147 -0
- package/generated/prisma-postgresql/runtime/react-native.js +84 -0
- package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +85 -0
- package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +38 -0
- package/generated/prisma-postgresql/schema.prisma +414 -0
- package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +5 -0
- package/generated/prisma-postgresql/wasm-worker-loader.mjs +5 -0
- package/generated/prisma-postgresql/wasm.d.ts +1 -0
- package/generated/prisma-postgresql/wasm.js +402 -0
- package/handlers/WEBHOOKS.md +653 -0
- package/handlers/app-definition-loader.js +43 -0
- package/handlers/app-handler-helpers.js +57 -0
- package/handlers/backend-utils.js +316 -0
- package/handlers/database-migration-handler.js +227 -0
- package/handlers/integration-event-dispatcher.js +54 -0
- package/handlers/middleware/admin-auth.js +73 -0
- package/handlers/routers/HEALTHCHECK.md +342 -0
- package/handlers/routers/auth.js +15 -0
- package/handlers/routers/db-migration.handler.js +29 -0
- package/handlers/routers/db-migration.js +311 -0
- package/handlers/routers/health.js +518 -0
- package/handlers/routers/integration-defined-routers.js +117 -0
- package/handlers/routers/integration-webhook-routers.js +67 -0
- package/handlers/routers/reporting.js +9 -0
- package/handlers/routers/user.js +63 -0
- package/handlers/routers/websocket.js +57 -0
- package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
- package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
- package/handlers/workers/db-migration.js +352 -0
- package/handlers/workers/dlq-processor.js +63 -0
- package/handlers/workers/integration-defined-workers.js +30 -0
- package/index.js +111 -50
- package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +184 -0
- package/infrastructure/scheduler/index.js +33 -0
- package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
- package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
- package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
- package/integrations/EXTENSIONS.md +240 -0
- package/integrations/WEBHOOK-QUICKSTART.md +151 -0
- package/integrations/extension.js +254 -0
- package/integrations/index.js +20 -10
- package/integrations/integration-base.js +619 -72
- package/integrations/integration-router.js +460 -218
- package/integrations/options.js +3 -4
- package/integrations/repositories/config-patch-shared.js +43 -0
- package/integrations/repositories/integration-mapping-repository-documentdb.js +280 -0
- package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
- package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
- package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
- package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
- package/integrations/repositories/integration-mapping-repository.js +156 -0
- package/integrations/repositories/integration-repository-documentdb.js +284 -0
- package/integrations/repositories/integration-repository-factory.js +51 -0
- package/integrations/repositories/integration-repository-interface.js +173 -0
- package/integrations/repositories/integration-repository-mongo.js +414 -0
- package/integrations/repositories/integration-repository-postgres.js +452 -0
- package/integrations/repositories/process-repository-documentdb.js +311 -0
- package/integrations/repositories/process-repository-factory.js +53 -0
- package/integrations/repositories/process-repository-interface.js +136 -0
- package/integrations/repositories/process-repository-mongo.js +262 -0
- package/integrations/repositories/process-repository-postgres.js +380 -0
- package/integrations/repositories/process-update-ops-shared.js +112 -0
- package/integrations/tests/doubles/config-capturing-integration.js +81 -0
- package/integrations/tests/doubles/dummy-integration-class.js +113 -0
- package/integrations/tests/doubles/test-integration-repository.js +146 -0
- package/integrations/use-cases/create-integration.js +215 -0
- package/integrations/use-cases/create-process.js +130 -0
- package/integrations/use-cases/delete-integration-for-user.js +119 -0
- package/integrations/use-cases/find-integration-by-entity-external-id.js +74 -0
- package/integrations/use-cases/find-integration-context-by-external-entity-id.js +76 -0
- package/integrations/use-cases/get-integration-for-user.js +78 -0
- package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
- package/integrations/use-cases/get-integration-instance.js +83 -0
- package/integrations/use-cases/get-integrations-for-user.js +88 -0
- package/integrations/use-cases/get-possible-integrations.js +27 -0
- package/integrations/use-cases/get-process.js +89 -0
- package/integrations/use-cases/index.js +19 -0
- package/integrations/use-cases/list-integrations-by-entity-external-id.js +46 -0
- package/integrations/use-cases/load-integration-context.js +71 -0
- package/integrations/use-cases/patch-integration-config.js +39 -0
- package/integrations/use-cases/process-errors.js +28 -0
- package/integrations/use-cases/update-integration-config.js +32 -0
- package/integrations/use-cases/update-integration-messages.js +44 -0
- package/integrations/use-cases/update-integration-status.js +32 -0
- package/integrations/use-cases/update-integration.js +92 -0
- package/integrations/use-cases/update-process-metrics.js +216 -0
- package/integrations/use-cases/update-process-state.js +163 -0
- package/integrations/utils/map-integration-dto.js +37 -0
- package/jest-global-setup-noop.js +3 -0
- package/jest-global-teardown-noop.js +3 -0
- package/logs/logger.js +0 -4
- package/{module-plugin → modules}/index.js +0 -10
- package/modules/module-factory.js +56 -0
- package/modules/module.js +274 -0
- package/modules/repositories/module-repository-documentdb.js +350 -0
- package/modules/repositories/module-repository-factory.js +40 -0
- package/modules/repositories/module-repository-interface.js +145 -0
- package/modules/repositories/module-repository-mongo.js +436 -0
- package/modules/repositories/module-repository-postgres.js +481 -0
- package/modules/repositories/module-repository.js +369 -0
- package/modules/requester/api-key.js +52 -0
- package/modules/requester/oauth-2.js +396 -0
- package/modules/requester/requester.js +285 -0
- package/{module-plugin → modules}/test/mock-api/api.js +8 -3
- package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
- package/modules/tests/doubles/test-module-factory.js +16 -0
- package/modules/tests/doubles/test-module-repository.js +39 -0
- package/modules/use-cases/get-entities-for-user.js +32 -0
- package/modules/use-cases/get-entity-options-by-id.js +71 -0
- package/modules/use-cases/get-entity-options-by-type.js +34 -0
- package/modules/use-cases/get-module-instance-from-type.js +34 -0
- package/modules/use-cases/get-module.js +74 -0
- package/modules/use-cases/process-authorization-callback.js +243 -0
- package/modules/use-cases/refresh-entity-options.js +72 -0
- package/modules/use-cases/test-module-auth.js +72 -0
- package/modules/utils/map-module-dto.js +18 -0
- package/package.json +82 -50
- package/prisma-mongodb/schema.prisma +432 -0
- package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
- package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
- package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
- package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
- package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
- package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
- package/prisma-postgresql/migrations/20260625000000_add_user_organization_id_index/migration.sql +2 -0
- package/prisma-postgresql/migrations/20260703000000_add_integration_status_in_creation_in_deletion/migration.sql +11 -0
- package/prisma-postgresql/migrations/20260703000001_integration_status_default_in_creation/migration.sql +8 -0
- package/prisma-postgresql/migrations/20260706000000_add_admin_script_execution_and_schedule/migration.sql +61 -0
- package/prisma-postgresql/migrations/migration_lock.toml +3 -0
- package/prisma-postgresql/schema.prisma +414 -0
- package/queues/queuer-util.js +103 -21
- package/reporting/README.md +86 -0
- package/reporting/index.js +17 -0
- package/reporting/reporting-router.js +77 -0
- package/reporting/repositories/reporting-repository-documentdb.js +127 -0
- package/reporting/repositories/reporting-repository-factory.js +35 -0
- package/reporting/repositories/reporting-repository-interface.js +16 -0
- package/reporting/repositories/reporting-repository-mongo.js +54 -0
- package/reporting/repositories/reporting-repository-postgres.js +70 -0
- package/reporting/use-cases/index.js +6 -0
- package/reporting/use-cases/list-integrations-report.js +142 -0
- package/syncs/manager.js +468 -443
- package/syncs/repositories/sync-repository-documentdb.js +240 -0
- package/syncs/repositories/sync-repository-factory.js +43 -0
- package/syncs/repositories/sync-repository-interface.js +109 -0
- package/syncs/repositories/sync-repository-mongo.js +239 -0
- package/syncs/repositories/sync-repository-postgres.js +319 -0
- package/syncs/sync.js +0 -1
- package/token/repositories/token-repository-documentdb.js +137 -0
- package/token/repositories/token-repository-factory.js +40 -0
- package/token/repositories/token-repository-interface.js +131 -0
- package/token/repositories/token-repository-mongo.js +219 -0
- package/token/repositories/token-repository-postgres.js +264 -0
- package/token/repositories/token-repository.js +219 -0
- package/types/associations/index.d.ts +0 -17
- package/types/core/index.d.ts +12 -4
- package/types/database/index.d.ts +10 -2
- package/types/encrypt/index.d.ts +5 -3
- package/types/integrations/index.d.ts +3 -8
- package/types/module-plugin/index.d.ts +17 -69
- package/types/syncs/index.d.ts +0 -17
- package/user/repositories/user-repository-documentdb.js +458 -0
- package/user/repositories/user-repository-factory.js +52 -0
- package/user/repositories/user-repository-interface.js +214 -0
- package/user/repositories/user-repository-mongo.js +323 -0
- package/user/repositories/user-repository-postgres.js +377 -0
- package/user/tests/doubles/test-user-repository.js +72 -0
- package/user/use-cases/authenticate-user.js +127 -0
- package/user/use-cases/authenticate-with-shared-secret.js +48 -0
- package/user/use-cases/create-individual-user.js +61 -0
- package/user/use-cases/create-organization-user.js +47 -0
- package/user/use-cases/create-token-for-user-id.js +30 -0
- package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
- package/user/use-cases/get-user-from-bearer-token.js +77 -0
- package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
- package/user/use-cases/login-user.js +122 -0
- package/user/user.js +125 -0
- package/utils/backend-path.js +38 -0
- package/utils/index.js +6 -0
- package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
- package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
- package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
- package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
- package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
- package/websocket/repositories/websocket-connection-repository.js +161 -0
- package/assertions/is-equal.js +0 -17
- package/associations/model.js +0 -54
- package/database/models/IndividualUser.js +0 -76
- package/database/models/OrganizationUser.js +0 -29
- package/database/models/State.js +0 -9
- package/database/models/Token.js +0 -70
- package/database/models/UserModel.js +0 -7
- package/database/models/WebsocketConnection.js +0 -49
- package/database/mongo.js +0 -45
- package/database/mongoose.js +0 -5
- package/encrypt/Cryptor.test.js +0 -32
- package/encrypt/encrypt.js +0 -132
- package/encrypt/encrypt.test.js +0 -1069
- package/encrypt/test-encrypt.js +0 -107
- package/errors/base-error.test.js +0 -32
- package/errors/fetch-error.test.js +0 -79
- package/errors/halt-error.test.js +0 -11
- package/errors/validation-errors.test.js +0 -120
- package/integrations/create-frigg-backend.js +0 -31
- package/integrations/integration-factory.js +0 -251
- package/integrations/integration-mapping.js +0 -43
- package/integrations/integration-model.js +0 -46
- package/integrations/integration-user.js +0 -144
- package/integrations/test/integration-base.test.js +0 -144
- package/lambda/TimeoutCatcher.test.js +0 -68
- package/logs/logger.test.js +0 -76
- package/module-plugin/auther.js +0 -350
- package/module-plugin/credential.js +0 -22
- package/module-plugin/entity-manager.js +0 -70
- package/module-plugin/entity.js +0 -46
- package/module-plugin/manager.js +0 -169
- package/module-plugin/module-factory.js +0 -61
- package/module-plugin/requester/api-key.js +0 -36
- package/module-plugin/requester/oauth-2.js +0 -219
- package/module-plugin/requester/requester.js +0 -165
- package/module-plugin/requester/requester.test.js +0 -28
- package/module-plugin/test/auther.test.js +0 -97
- package/syncs/model.js +0 -62
- /package/{module-plugin → modules}/ModuleConstants.js +0 -0
- /package/{module-plugin → modules}/requester/basic.js +0 -0
- /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Scripts Module
|
|
3
|
+
*
|
|
4
|
+
* Exports repository interfaces and factories for admin script management.
|
|
5
|
+
* Concrete implementations support MongoDB, PostgreSQL, and DocumentDB.
|
|
6
|
+
*
|
|
7
|
+
* Repository interfaces follow the Port pattern in Hexagonal Architecture:
|
|
8
|
+
* - Define contracts for data access
|
|
9
|
+
* - Enable dependency injection
|
|
10
|
+
* - Allow testing with mocks
|
|
11
|
+
* - Support multiple database implementations
|
|
12
|
+
*
|
|
13
|
+
* Authentication:
|
|
14
|
+
* - Uses ENV-based ADMIN_API_KEY (see handlers/middleware/admin-auth.js)
|
|
15
|
+
* - No database-backed API keys (simplified from original design)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Repository Interfaces
|
|
19
|
+
const { AdminScriptExecutionRepositoryInterface } = require('./repositories/admin-script-execution-repository-interface');
|
|
20
|
+
const { ScriptScheduleRepositoryInterface } = require('./repositories/script-schedule-repository-interface');
|
|
21
|
+
|
|
22
|
+
// Repository Factories
|
|
23
|
+
const {
|
|
24
|
+
createAdminScriptExecutionRepository,
|
|
25
|
+
AdminScriptExecutionRepositoryMongo,
|
|
26
|
+
AdminScriptExecutionRepositoryPostgres,
|
|
27
|
+
AdminScriptExecutionRepositoryDocumentDB,
|
|
28
|
+
} = require('./repositories/admin-script-execution-repository-factory');
|
|
29
|
+
const {
|
|
30
|
+
createScriptScheduleRepository,
|
|
31
|
+
ScriptScheduleRepositoryMongo,
|
|
32
|
+
ScriptScheduleRepositoryPostgres,
|
|
33
|
+
ScriptScheduleRepositoryDocumentDB,
|
|
34
|
+
} = require('./repositories/script-schedule-repository-factory');
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
// Repository Interfaces
|
|
38
|
+
AdminScriptExecutionRepositoryInterface,
|
|
39
|
+
ScriptScheduleRepositoryInterface,
|
|
40
|
+
|
|
41
|
+
// Repository Factories (primary exports for use cases)
|
|
42
|
+
createAdminScriptExecutionRepository,
|
|
43
|
+
createScriptScheduleRepository,
|
|
44
|
+
|
|
45
|
+
// Concrete Implementations (for testing)
|
|
46
|
+
AdminScriptExecutionRepositoryMongo,
|
|
47
|
+
AdminScriptExecutionRepositoryPostgres,
|
|
48
|
+
AdminScriptExecutionRepositoryDocumentDB,
|
|
49
|
+
ScriptScheduleRepositoryMongo,
|
|
50
|
+
ScriptScheduleRepositoryPostgres,
|
|
51
|
+
ScriptScheduleRepositoryDocumentDB,
|
|
52
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const {
|
|
2
|
+
AdminScriptExecutionRepositoryMongo,
|
|
3
|
+
} = require('./admin-script-execution-repository-mongo');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* DocumentDB Admin Process Repository Adapter
|
|
7
|
+
* Extends MongoDB implementation since DocumentDB uses the same Prisma client
|
|
8
|
+
*
|
|
9
|
+
* DocumentDB-specific characteristics:
|
|
10
|
+
* - Uses MongoDB-compatible API
|
|
11
|
+
* - Prisma client handles the connection
|
|
12
|
+
* - IDs are strings with ObjectId format
|
|
13
|
+
* - All operations identical to MongoDB implementation
|
|
14
|
+
*/
|
|
15
|
+
class AdminScriptExecutionRepositoryDocumentDB extends AdminScriptExecutionRepositoryMongo {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { AdminScriptExecutionRepositoryDocumentDB };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const { AdminScriptExecutionRepositoryMongo } = require('./admin-script-execution-repository-mongo');
|
|
2
|
+
const { AdminScriptExecutionRepositoryPostgres } = require('./admin-script-execution-repository-postgres');
|
|
3
|
+
const {
|
|
4
|
+
AdminScriptExecutionRepositoryDocumentDB,
|
|
5
|
+
} = require('./admin-script-execution-repository-documentdb');
|
|
6
|
+
const config = require('../../database/config');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Admin Process Repository Factory
|
|
10
|
+
* Creates the appropriate repository adapter based on database type
|
|
11
|
+
*
|
|
12
|
+
* This implements the Factory pattern for Hexagonal Architecture:
|
|
13
|
+
* - Reads database type from app definition (backend/index.js)
|
|
14
|
+
* - Returns correct adapter (MongoDB, DocumentDB, or PostgreSQL)
|
|
15
|
+
* - Provides clear error for unsupported databases
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```javascript
|
|
19
|
+
* const repository = createAdminScriptExecutionRepository();
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @returns {AdminScriptExecutionRepositoryInterface} Configured repository adapter
|
|
23
|
+
* @throws {Error} If database type is not supported
|
|
24
|
+
*/
|
|
25
|
+
function createAdminScriptExecutionRepository() {
|
|
26
|
+
const dbType = config.DB_TYPE;
|
|
27
|
+
|
|
28
|
+
switch (dbType) {
|
|
29
|
+
case 'mongodb':
|
|
30
|
+
return new AdminScriptExecutionRepositoryMongo();
|
|
31
|
+
|
|
32
|
+
case 'postgresql':
|
|
33
|
+
return new AdminScriptExecutionRepositoryPostgres();
|
|
34
|
+
|
|
35
|
+
case 'documentdb':
|
|
36
|
+
return new AdminScriptExecutionRepositoryDocumentDB();
|
|
37
|
+
|
|
38
|
+
default:
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Unsupported database type: ${dbType}. Supported values: 'mongodb', 'documentdb', 'postgresql'`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = {
|
|
46
|
+
createAdminScriptExecutionRepository,
|
|
47
|
+
// Export adapters for direct testing
|
|
48
|
+
AdminScriptExecutionRepositoryMongo,
|
|
49
|
+
AdminScriptExecutionRepositoryPostgres,
|
|
50
|
+
AdminScriptExecutionRepositoryDocumentDB,
|
|
51
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Process Repository Interface
|
|
3
|
+
* Abstract base class defining the contract for admin process persistence adapters
|
|
4
|
+
*
|
|
5
|
+
* This follows the Port in Hexagonal Architecture:
|
|
6
|
+
* - Domain layer depends on this abstraction
|
|
7
|
+
* - Concrete adapters implement this interface
|
|
8
|
+
* - Use cases receive repositories via dependency injection
|
|
9
|
+
*
|
|
10
|
+
* Admin processes track administrative operations including:
|
|
11
|
+
* - Admin script executions
|
|
12
|
+
* - Database migrations
|
|
13
|
+
* - Scheduled maintenance tasks
|
|
14
|
+
*
|
|
15
|
+
* The AdminScriptExecution model uses a flexible JSON storage pattern:
|
|
16
|
+
* - context: Input parameters, trigger info, audit data, script version
|
|
17
|
+
* - results: Output data, logs, metrics, error details
|
|
18
|
+
*
|
|
19
|
+
* @abstract
|
|
20
|
+
*/
|
|
21
|
+
class AdminScriptExecutionRepositoryInterface {
|
|
22
|
+
/**
|
|
23
|
+
* Create a new admin process record
|
|
24
|
+
*
|
|
25
|
+
* @param {Object} params - Process creation parameters
|
|
26
|
+
* @param {string} params.name - Name of the process (e.g., script name, migration name)
|
|
27
|
+
* @param {string} params.type - Type of process (e.g., 'ADMIN_SCRIPT', 'DB_MIGRATION')
|
|
28
|
+
* @param {Object} [params.context] - Context data (input, trigger, audit, script version)
|
|
29
|
+
* @param {string} [params.context.scriptVersion] - Version of the script
|
|
30
|
+
* @param {string} [params.context.trigger] - Trigger type ('MANUAL', 'SCHEDULED', 'QUEUE', 'WEBHOOK')
|
|
31
|
+
* @param {string} [params.context.mode] - Execution mode ('sync' or 'async')
|
|
32
|
+
* @param {Object} [params.context.input] - Input parameters
|
|
33
|
+
* @param {Object} [params.context.audit] - Audit information
|
|
34
|
+
* @param {string} [params.context.audit.apiKeyName] - Name of API key used
|
|
35
|
+
* @param {string} [params.context.audit.apiKeyLast4] - Last 4 chars of API key
|
|
36
|
+
* @param {string} [params.context.audit.ipAddress] - IP address of requester
|
|
37
|
+
* @param {string|number} [params.parentExecutionId] - ID of the execution that queued this one; persisted to the parentExecutionId column (self-FK) for the parent/child hierarchy
|
|
38
|
+
* @returns {Promise<Object>} The created process record
|
|
39
|
+
* @abstract
|
|
40
|
+
*/
|
|
41
|
+
async createExecution({ name, type, context, parentExecutionId }) {
|
|
42
|
+
throw new Error('Method createExecution must be implemented by subclass');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Find a process by its ID
|
|
47
|
+
*
|
|
48
|
+
* @param {string|number} id - The process ID
|
|
49
|
+
* @returns {Promise<Object|null>} The process record or null if not found
|
|
50
|
+
* @abstract
|
|
51
|
+
*/
|
|
52
|
+
async findExecutionById(id) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
'Method findExecutionById must be implemented by subclass'
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Find all processes with a specific name
|
|
60
|
+
*
|
|
61
|
+
* @param {string} name - The process name to filter by
|
|
62
|
+
* @param {Object} [options] - Query options
|
|
63
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
64
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
65
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
66
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
67
|
+
* @param {string} [options.state] - Optional state filter ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
|
|
68
|
+
* @returns {Promise<Array>} Array of process records
|
|
69
|
+
* @abstract
|
|
70
|
+
*/
|
|
71
|
+
async findExecutionsByName(name, options = {}) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
'Method findExecutionsByName must be implemented by subclass'
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Find all processes with a specific state
|
|
79
|
+
*
|
|
80
|
+
* @param {string} state - State to filter by ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
|
|
81
|
+
* @param {Object} [options] - Query options
|
|
82
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
83
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
84
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
85
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
86
|
+
* @returns {Promise<Array>} Array of process records
|
|
87
|
+
* @abstract
|
|
88
|
+
*/
|
|
89
|
+
async findExecutionsByState(state, options = {}) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
'Method findExecutionsByState must be implemented by subclass'
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Update the state of a process
|
|
97
|
+
*
|
|
98
|
+
* @param {string|number} id - The process ID
|
|
99
|
+
* @param {string} state - New state value ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
|
|
100
|
+
* @returns {Promise<Object>} Updated process record
|
|
101
|
+
* @abstract
|
|
102
|
+
*/
|
|
103
|
+
async updateExecutionState(id, state) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
'Method updateExecutionState must be implemented by subclass'
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Update the results of a process
|
|
111
|
+
* Merges new results with existing results in the results JSON field
|
|
112
|
+
*
|
|
113
|
+
* @param {string|number} id - The process ID
|
|
114
|
+
* @param {Object} results - Results data to merge
|
|
115
|
+
* @param {Object} [results.output] - Output data from the process
|
|
116
|
+
* @param {Object} [results.error] - Error information
|
|
117
|
+
* @param {string} [results.error.name] - Error name/type
|
|
118
|
+
* @param {string} [results.error.message] - Error message
|
|
119
|
+
* @param {string} [results.error.stack] - Error stack trace
|
|
120
|
+
* @param {Object} [results.metrics] - Performance metrics
|
|
121
|
+
* @param {Date} [results.metrics.startTime] - Process start time
|
|
122
|
+
* @param {Date} [results.metrics.endTime] - Process end time
|
|
123
|
+
* @param {number} [results.metrics.durationMs] - Duration in milliseconds
|
|
124
|
+
* @returns {Promise<Object>} Updated process record
|
|
125
|
+
* @abstract
|
|
126
|
+
*/
|
|
127
|
+
async updateExecutionResults(id, results) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
'Method updateExecutionResults must be implemented by subclass'
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Append a log entry to a process's log array in results
|
|
135
|
+
*
|
|
136
|
+
* @param {string|number} id - The process ID
|
|
137
|
+
* @param {Object} logEntry - Log entry to append
|
|
138
|
+
* @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
|
|
139
|
+
* @param {string} logEntry.message - Log message
|
|
140
|
+
* @param {Object} [logEntry.data] - Additional log data
|
|
141
|
+
* @param {string} logEntry.timestamp - ISO timestamp
|
|
142
|
+
* @returns {Promise<Object>} Updated process record
|
|
143
|
+
* @abstract
|
|
144
|
+
*/
|
|
145
|
+
async appendExecutionLog(id, logEntry) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
'Method appendExecutionLog must be implemented by subclass'
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Delete all processes older than a specific date
|
|
153
|
+
* Used for cleanup and retention policies
|
|
154
|
+
*
|
|
155
|
+
* @param {Date} date - Delete processes older than this date
|
|
156
|
+
* @returns {Promise<Object>} Deletion result with count
|
|
157
|
+
* @abstract
|
|
158
|
+
*/
|
|
159
|
+
async deleteExecutionsOlderThan(date) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
'Method deleteExecutionsOlderThan must be implemented by subclass'
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = { AdminScriptExecutionRepositoryInterface };
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const {
|
|
3
|
+
AdminScriptExecutionRepositoryInterface,
|
|
4
|
+
} = require('./admin-script-execution-repository-interface');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MongoDB Admin Process Repository Adapter
|
|
8
|
+
* Handles admin process persistence using Prisma with MongoDB
|
|
9
|
+
*
|
|
10
|
+
* MongoDB-specific characteristics:
|
|
11
|
+
* - IDs are strings with @db.ObjectId
|
|
12
|
+
* - context and results are Json objects
|
|
13
|
+
* - Stores logs in results.logs array
|
|
14
|
+
*/
|
|
15
|
+
class AdminScriptExecutionRepositoryMongo extends AdminScriptExecutionRepositoryInterface {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
this.prisma = prisma;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a new admin process record
|
|
23
|
+
*
|
|
24
|
+
* @param {Object} params - Process creation parameters
|
|
25
|
+
* @param {string} params.name - Name of the process
|
|
26
|
+
* @param {string} params.type - Type of process (e.g., 'ADMIN_SCRIPT', 'DB_MIGRATION')
|
|
27
|
+
* @param {Object} [params.context] - Context data
|
|
28
|
+
* @returns {Promise<Object>} The created process record
|
|
29
|
+
*/
|
|
30
|
+
async createExecution({ name, type, context = {}, parentExecutionId }) {
|
|
31
|
+
const data = {
|
|
32
|
+
name,
|
|
33
|
+
type,
|
|
34
|
+
context,
|
|
35
|
+
results: { logs: [] },
|
|
36
|
+
...(parentExecutionId != null && { parentExecutionId }),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const process = await this.prisma.adminScriptExecution.create({
|
|
40
|
+
data,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return process;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Find a process by its ID
|
|
48
|
+
*
|
|
49
|
+
* @param {string} id - The process ID
|
|
50
|
+
* @returns {Promise<Object|null>} The process record or null if not found
|
|
51
|
+
*/
|
|
52
|
+
async findExecutionById(id) {
|
|
53
|
+
const process = await this.prisma.adminScriptExecution.findUnique({
|
|
54
|
+
where: { id },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return process;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Find all processes with a specific name
|
|
62
|
+
*
|
|
63
|
+
* @param {string} name - The process name to filter by
|
|
64
|
+
* @param {Object} [options] - Query options
|
|
65
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
66
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
67
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
68
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
69
|
+
* @returns {Promise<Array>} Array of process records
|
|
70
|
+
*/
|
|
71
|
+
async findExecutionsByName(name, options = {}) {
|
|
72
|
+
const {
|
|
73
|
+
limit,
|
|
74
|
+
offset,
|
|
75
|
+
sortBy = 'createdAt',
|
|
76
|
+
sortOrder = 'desc',
|
|
77
|
+
state,
|
|
78
|
+
} = options;
|
|
79
|
+
|
|
80
|
+
const where = { name };
|
|
81
|
+
if (state) where.state = state;
|
|
82
|
+
|
|
83
|
+
const processes = await this.prisma.adminScriptExecution.findMany({
|
|
84
|
+
where,
|
|
85
|
+
orderBy: { [sortBy]: sortOrder },
|
|
86
|
+
take: limit,
|
|
87
|
+
skip: offset,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return processes;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Find all processes with a specific state
|
|
95
|
+
*
|
|
96
|
+
* @param {string} state - State to filter by
|
|
97
|
+
* @param {Object} [options] - Query options
|
|
98
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
99
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
100
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
101
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
102
|
+
* @returns {Promise<Array>} Array of process records
|
|
103
|
+
*/
|
|
104
|
+
async findExecutionsByState(state, options = {}) {
|
|
105
|
+
const {
|
|
106
|
+
limit,
|
|
107
|
+
offset,
|
|
108
|
+
sortBy = 'createdAt',
|
|
109
|
+
sortOrder = 'desc',
|
|
110
|
+
} = options;
|
|
111
|
+
|
|
112
|
+
const processes = await this.prisma.adminScriptExecution.findMany({
|
|
113
|
+
where: { state },
|
|
114
|
+
orderBy: { [sortBy]: sortOrder },
|
|
115
|
+
take: limit,
|
|
116
|
+
skip: offset,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return processes;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Update the state of a process
|
|
124
|
+
*
|
|
125
|
+
* @param {string} id - The process ID
|
|
126
|
+
* @param {string} state - New state value
|
|
127
|
+
* @returns {Promise<Object>} Updated process record
|
|
128
|
+
*/
|
|
129
|
+
async updateExecutionState(id, state) {
|
|
130
|
+
const process = await this.prisma.adminScriptExecution.update({
|
|
131
|
+
where: { id },
|
|
132
|
+
data: { state },
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return process;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Update the results of a process
|
|
140
|
+
* Merges new results with existing results
|
|
141
|
+
*
|
|
142
|
+
* @param {string} id - The process ID
|
|
143
|
+
* @param {Object} results - Results data to merge
|
|
144
|
+
* @returns {Promise<Object>} Updated process record
|
|
145
|
+
*/
|
|
146
|
+
async updateExecutionResults(id, results) {
|
|
147
|
+
// Get current process to merge results
|
|
148
|
+
const currentProcess = await this.prisma.adminScriptExecution.findUnique({
|
|
149
|
+
where: { id },
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (!currentProcess) {
|
|
153
|
+
throw new Error(`AdminScriptExecution ${id} not found`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Merge new results with existing results
|
|
157
|
+
const mergedResults = {
|
|
158
|
+
...(currentProcess.results || {}),
|
|
159
|
+
...results,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const process = await this.prisma.adminScriptExecution.update({
|
|
163
|
+
where: { id },
|
|
164
|
+
data: { results: mergedResults },
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return process;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Append a log entry to a process's log array in results
|
|
172
|
+
*
|
|
173
|
+
* @param {string} id - The process ID
|
|
174
|
+
* @param {Object} logEntry - Log entry to append
|
|
175
|
+
* @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
|
|
176
|
+
* @param {string} logEntry.message - Log message
|
|
177
|
+
* @param {Object} [logEntry.data] - Additional log data
|
|
178
|
+
* @param {string} logEntry.timestamp - ISO timestamp
|
|
179
|
+
* @returns {Promise<Object>} Updated process record
|
|
180
|
+
*/
|
|
181
|
+
async appendExecutionLog(id, logEntry) {
|
|
182
|
+
// Get current process
|
|
183
|
+
const process = await this.prisma.adminScriptExecution.findUnique({
|
|
184
|
+
where: { id },
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
if (!process) {
|
|
188
|
+
throw new Error(`AdminScriptExecution ${id} not found`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Get current results and logs
|
|
192
|
+
const results = process.results || {};
|
|
193
|
+
const logs = Array.isArray(results.logs) ? [...results.logs] : [];
|
|
194
|
+
logs.push(logEntry);
|
|
195
|
+
|
|
196
|
+
// Update with new logs array in results
|
|
197
|
+
const updated = await this.prisma.adminScriptExecution.update({
|
|
198
|
+
where: { id },
|
|
199
|
+
data: { results: { ...results, logs } },
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
return updated;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Delete all processes older than a specific date
|
|
207
|
+
* Used for cleanup and retention policies
|
|
208
|
+
*
|
|
209
|
+
* @param {Date} date - Delete processes older than this date
|
|
210
|
+
* @returns {Promise<Object>} Deletion result with count
|
|
211
|
+
*/
|
|
212
|
+
async deleteExecutionsOlderThan(date) {
|
|
213
|
+
const result = await this.prisma.adminScriptExecution.deleteMany({
|
|
214
|
+
where: {
|
|
215
|
+
createdAt: {
|
|
216
|
+
lt: date,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
acknowledged: true,
|
|
223
|
+
deletedCount: result.count,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
module.exports = { AdminScriptExecutionRepositoryMongo };
|