@owox/backend 0.37.0 → 0.39.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/src/common/helpers/read-bounded-body.helper.d.ts +1 -0
- package/dist/src/common/helpers/read-bounded-body.helper.js +28 -0
- package/dist/src/common/scheduler/system-tasks/system-trigger-type.d.ts +3 -1
- package/dist/src/common/scheduler/system-tasks/system-trigger-type.js +2 -0
- package/dist/src/common/search/search.facade.d.ts +1 -0
- package/dist/src/config/data-source-options.config.d.ts +4 -3
- package/dist/src/config/data-source-options.config.js +10 -3
- package/dist/src/config/plugin-collections-body-parser.config.js +3 -0
- package/dist/src/data-marts/credentials/credential.types.d.ts +26 -2
- package/dist/src/data-marts/credentials/credential.types.js +18 -6
- package/dist/src/data-marts/credentials/dto/credential-api.dto.d.ts +5 -1
- package/dist/src/data-marts/credentials/dto/credential-api.dto.js +21 -0
- package/dist/src/data-marts/credentials/dto/credential.dto.d.ts +2 -1
- package/dist/src/data-marts/credentials/entities/credential.entity.d.ts +2 -1
- package/dist/src/data-marts/credentials/entities/credential.entity.js +5 -0
- package/dist/src/data-marts/credentials/facades/credential-consumer-binding.facade.impl.js +6 -1
- package/dist/src/data-marts/credentials/mappers/credential.mapper.js +2 -0
- package/dist/src/data-marts/credentials/services/builtin-credential-definitions.js +8 -0
- package/dist/src/data-marts/credentials/services/credential-external-definition-registry.service.d.ts +4 -0
- package/dist/src/data-marts/credentials/services/credential-external-definition-registry.service.js +36 -17
- package/dist/src/data-marts/credentials/services/credential-fetch.service.d.ts +8 -0
- package/dist/src/data-marts/credentials/services/credential-fetch.service.js +115 -46
- package/dist/src/data-marts/credentials/services/credential-validation-probe.service.d.ts +3 -1
- package/dist/src/data-marts/credentials/services/credential-validation-probe.service.js +10 -2
- package/dist/src/data-marts/credentials/services/credential.service.d.ts +4 -0
- package/dist/src/data-marts/credentials/services/credential.service.js +36 -0
- package/dist/src/data-marts/credentials/services/google-service-account-key.d.ts +6 -0
- package/dist/src/data-marts/credentials/services/google-service-account-key.js +46 -0
- package/dist/src/data-marts/credentials/services/google-service-account-token.service.d.ts +25 -0
- package/dist/src/data-marts/credentials/services/google-service-account-token.service.js +177 -0
- package/dist/src/data-marts/credentials/use-cases/create-credential.service.d.ts +1 -0
- package/dist/src/data-marts/credentials/use-cases/create-credential.service.js +10 -2
- package/dist/src/data-marts/credentials/use-cases/update-credential.service.d.ts +1 -0
- package/dist/src/data-marts/credentials/use-cases/update-credential.service.js +28 -4
- package/dist/src/data-marts/credentials/use-cases/validate-credential.service.js +2 -5
- package/dist/src/data-marts/data-destination-types/ee/email/services/email-credentials-validator.js +1 -3
- package/dist/src/data-marts/data-destination-types/ee/google-chat/services/google-chat-credentials-validator.js +1 -3
- package/dist/src/data-marts/data-destination-types/google-sheets/services/google-sheets-credentials-validator.js +1 -3
- package/dist/src/data-marts/data-destination-types/google-sheets/services/google-sheets-report-writer.d.ts +1 -0
- package/dist/src/data-marts/data-destination-types/google-sheets/services/google-sheets-report-writer.js +13 -1
- package/dist/src/data-marts/data-destination-types/interfaces/data-destination-credentials-validator.interface.d.ts +2 -0
- package/dist/src/data-marts/data-destination-types/interfaces/data-destination-credentials-validator.interface.js +7 -0
- package/dist/src/data-marts/data-destination-types/looker-studio-connector/services/looker-studio-connector-credentials-validator.js +1 -3
- package/dist/src/data-marts/data-marts.module.js +8 -0
- package/dist/src/data-marts/data-storage-types/athena/adapters/athena-api.adapter.js +2 -1
- package/dist/src/data-marts/data-storage-types/athena/adapters/s3-api.adapter.js +5 -3
- package/dist/src/data-marts/data-storage-types/athena/services/athena-access.validator.js +2 -4
- package/dist/src/data-marts/data-storage-types/athena/utils/athena-output-location.util.d.ts +5 -0
- package/dist/src/data-marts/data-storage-types/athena/utils/athena-output-location.util.js +13 -0
- package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-access.validator.js +2 -4
- package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-resource-location.util.d.ts +3 -0
- package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-resource-location.util.js +18 -0
- package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-sharded-tables.util.d.ts +1 -0
- package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-sharded-tables.util.js +4 -1
- package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-storage-resource-browser.service.js +12 -5
- package/dist/src/data-marts/data-storage-types/databricks/services/databricks-access.validator.js +2 -4
- package/dist/src/data-marts/data-storage-types/interfaces/data-storage-access-validator.interface.d.ts +3 -0
- package/dist/src/data-marts/data-storage-types/interfaces/data-storage-access-validator.interface.js +7 -0
- package/dist/src/data-marts/data-storage-types/interfaces/storage-resource-browser.interface.d.ts +2 -0
- package/dist/src/data-marts/data-storage-types/redshift/services/redshift-access.validator.js +2 -6
- package/dist/src/data-marts/data-storage-types/snowflake/adapters/snowflake-api.adapter.js +1 -0
- package/dist/src/data-marts/data-storage-types/snowflake/services/snowflake-access.validator.js +2 -4
- package/dist/src/data-marts/dto/domain/list-data-marts.command.d.ts +2 -1
- package/dist/src/data-marts/dto/domain/list-data-marts.command.js +3 -1
- package/dist/src/data-marts/dto/presentation/run-data-mart-request-api.dto.js +4 -2
- package/dist/src/data-marts/dto/presentation/sql-dry-run-request-api.dto.js +3 -0
- package/dist/src/data-marts/dto/presentation/storage-resources/list-storage-resources-response.dto.d.ts +2 -0
- package/dist/src/data-marts/dto/presentation/storage-resources/list-storage-resources-response.dto.js +17 -0
- package/dist/src/data-marts/errors/google-sheets-api-call.error.d.ts +6 -0
- package/dist/src/data-marts/errors/google-sheets-api-call.error.js +34 -0
- package/dist/src/data-marts/facades/mcp-contexts.facade.d.ts +13 -0
- package/dist/src/data-marts/facades/mcp-contexts.facade.impl.d.ts +9 -0
- package/dist/src/data-marts/facades/mcp-contexts.facade.impl.js +35 -0
- package/dist/src/data-marts/facades/mcp-contexts.facade.js +5 -0
- package/dist/src/data-marts/facades/mcp-data-marts.facade.d.ts +9 -0
- package/dist/src/data-marts/facades/mcp-data-marts.facade.impl.js +4 -1
- package/dist/src/data-marts/mappers/context.mapper.d.ts +4 -0
- package/dist/src/data-marts/mappers/context.mapper.js +12 -0
- package/dist/src/data-marts/search/engine/advanced-search.service.js +1 -0
- package/dist/src/data-marts/search/engine/in-memory-paginated.search.js +17 -1
- package/dist/src/data-marts/search/engine/vector-search.port.d.ts +1 -0
- package/dist/src/data-marts/services/connector/backfill-segment.d.ts +22 -0
- package/dist/src/data-marts/services/connector/backfill-segment.js +91 -0
- package/dist/src/data-marts/services/connector/connector-execution.service.d.ts +1 -0
- package/dist/src/data-marts/services/connector/connector-execution.service.js +3 -0
- package/dist/src/data-marts/services/connector/connector-executor.service.d.ts +4 -1
- package/dist/src/data-marts/services/connector/connector-executor.service.js +107 -23
- package/dist/src/data-marts/services/connector/connector-run.service.d.ts +3 -0
- package/dist/src/data-marts/services/connector/connector-run.service.js +98 -4
- package/dist/src/data-marts/services/context/context.service.d.ts +2 -0
- package/dist/src/data-marts/services/context/context.service.js +21 -0
- package/dist/src/data-marts/services/data-mart-run.service.d.ts +1 -0
- package/dist/src/data-marts/services/data-mart-run.service.js +9 -0
- package/dist/src/data-marts/services/data-mart.service.d.ts +1 -0
- package/dist/src/data-marts/services/data-mart.service.js +3 -0
- package/dist/src/data-marts/system-triggers/processors/repair-backfill-chains-processor.d.ts +14 -0
- package/dist/src/data-marts/system-triggers/processors/repair-backfill-chains-processor.js +45 -0
- package/dist/src/data-marts/use-cases/cancel-data-mart-run.service.d.ts +4 -0
- package/dist/src/data-marts/use-cases/cancel-data-mart-run.service.js +46 -1
- package/dist/src/data-marts/use-cases/list-data-marts.service.js +1 -0
- package/dist/src/data-marts/use-cases/stream-http-data.service.d.ts +0 -1
- package/dist/src/data-marts/use-cases/stream-http-data.service.js +2 -6
- package/dist/src/data-marts/use-cases/update-data-storage.service.js +7 -7
- package/dist/src/data-marts/utils/field-errors.utils.d.ts +9 -0
- package/dist/src/data-marts/utils/field-errors.utils.js +51 -0
- package/dist/src/data-marts/utils/manual-backfill-range.d.ts +52 -0
- package/dist/src/data-marts/utils/manual-backfill-range.js +110 -8
- package/dist/src/ee/mcp/instructions/mcp-system-instructions.d.ts +1 -1
- package/dist/src/ee/mcp/instructions/mcp-system-instructions.js +4 -0
- package/dist/src/ee/mcp/sdk/mcp-output-schema.d.ts +3 -0
- package/dist/src/ee/mcp/sdk/mcp-output-schema.js +53 -0
- package/dist/src/ee/mcp/sdk/mcp-schema-refresh.d.ts +8 -0
- package/dist/src/ee/mcp/sdk/mcp-schema-refresh.js +44 -0
- package/dist/src/ee/mcp/sdk/mcp-sdk-server.factory.d.ts +8 -1
- package/dist/src/ee/mcp/sdk/mcp-sdk-server.factory.js +35 -4
- package/dist/src/ee/mcp/tools/context-input.d.ts +6 -0
- package/dist/src/ee/mcp/tools/context-input.js +13 -0
- package/dist/src/ee/mcp/tools/data-mart-catalog.tool.d.ts +10 -2
- package/dist/src/ee/mcp/tools/data-mart-catalog.tool.js +17 -5
- package/dist/src/ee/mcp/tools/data-mart-details.tool.d.ts +5 -1
- package/dist/src/ee/mcp/tools/data-mart-details.tool.js +4 -1
- package/dist/src/ee/mcp/tools/list-contexts.tool.d.ts +131 -0
- package/dist/src/ee/mcp/tools/list-contexts.tool.js +50 -0
- package/dist/src/ee/mcp/tools/mcp-tool.providers.js +2 -0
- package/dist/src/ee/mcp/tools/search-data-marts.tool.d.ts +10 -2
- package/dist/src/ee/mcp/tools/search-data-marts.tool.js +17 -3
- package/dist/src/ee/mcp/transport/mcp-http-entry.service.js +1 -1
- package/dist/src/idp/decorators/auth-context.decorator.js +1 -0
- package/dist/src/idp/guards/idp.guard.d.ts +3 -0
- package/dist/src/idp/guards/idp.guard.js +38 -8
- package/dist/src/idp/oauth/controllers/oauth-authorization.controller.js +8 -6
- package/dist/src/idp/oauth/mcp-client-integration.d.ts +1 -0
- package/dist/src/idp/oauth/mcp-client-integration.js +15 -0
- package/dist/src/idp/ports/plugin-runtime-authorizer.port.d.ts +6 -0
- package/dist/src/idp/types/auth.types.d.ts +1 -0
- package/dist/src/migrations/1790830000000-widen-sql-dry-run-trigger-sql-column.d.ts +6 -0
- package/dist/src/migrations/1790830000000-widen-sql-dry-run-trigger-sql-column.js +21 -0
- package/dist/src/migrations/1790900000000-add-plugin-version-backend.d.ts +6 -0
- package/dist/src/migrations/1790900000000-add-plugin-version-backend.js +21 -0
- package/dist/src/migrations/1790900000001-create-plugin-action-execution.d.ts +6 -0
- package/dist/src/migrations/1790900000001-create-plugin-action-execution.js +77 -0
- package/dist/src/migrations/1791000000000-add-credential-public-metadata.d.ts +6 -0
- package/dist/src/migrations/1791000000000-add-credential-public-metadata.js +23 -0
- package/dist/src/plugin-host/collections/dto/domain/plugin-collection.types.d.ts +1 -0
- package/dist/src/plugin-host/collections/errors/plugin-collection.errors.d.ts +6 -0
- package/dist/src/plugin-host/collections/errors/plugin-collection.errors.js +19 -1
- package/dist/src/plugin-host/collections/services/plugin-collection-declaration.service.js +3 -3
- package/dist/src/plugin-host/collections/use-cases/put-plugin-collection-document.service.js +7 -0
- package/dist/src/plugin-host/constants/plugin-action-limits.d.ts +34 -0
- package/dist/src/plugin-host/constants/plugin-action-limits.js +51 -0
- package/dist/src/plugin-host/controllers/plugin-action-runtime.controller.d.ts +20 -0
- package/dist/src/plugin-host/controllers/plugin-action-runtime.controller.js +123 -0
- package/dist/src/plugin-host/controllers/plugin-credential-runtime.controller.js +11 -19
- package/dist/src/plugin-host/controllers/plugin-gallery.controller.d.ts +5 -1
- package/dist/src/plugin-host/controllers/plugin-gallery.controller.js +25 -1
- package/dist/src/plugin-host/controllers/plugin-history.controller.d.ts +10 -0
- package/dist/src/plugin-host/controllers/plugin-history.controller.js +57 -0
- package/dist/src/plugin-host/controllers/plugin-release-check.controller.d.ts +10 -0
- package/dist/src/plugin-host/controllers/plugin-release-check.controller.js +58 -0
- package/dist/src/plugin-host/dto/domain/check-plugin-release.command.d.ts +22 -0
- package/dist/src/plugin-host/dto/domain/check-plugin-release.command.js +17 -0
- package/dist/src/plugin-host/dto/domain/find-plugin-by-repository.command.d.ts +6 -0
- package/dist/src/plugin-host/dto/domain/find-plugin-by-repository.command.js +13 -0
- package/dist/src/plugin-host/dto/domain/list-plugin-history.command.d.ts +10 -0
- package/dist/src/plugin-host/dto/domain/list-plugin-history.command.js +18 -0
- package/dist/src/plugin-host/dto/domain/plugin-action-execution.command.d.ts +23 -0
- package/dist/src/plugin-host/dto/domain/plugin-action-execution.command.js +44 -0
- package/dist/src/plugin-host/dto/domain/plugin-action-execution.dto.d.ts +36 -0
- package/dist/src/plugin-host/dto/domain/plugin-action-execution.dto.js +3 -0
- package/dist/src/plugin-host/dto/domain/plugin-history.dto.d.ts +29 -0
- package/dist/src/plugin-host/dto/domain/plugin-history.dto.js +3 -0
- package/dist/src/plugin-host/dto/domain/plugin-view.dto.d.ts +1 -0
- package/dist/src/plugin-host/dto/presentation/plugin-action-api.dto.d.ts +44 -0
- package/dist/src/plugin-host/dto/presentation/plugin-action-api.dto.js +208 -0
- package/dist/src/plugin-host/dto/presentation/plugin-gallery-api.dto.d.ts +2 -0
- package/dist/src/plugin-host/dto/presentation/plugin-gallery-api.dto.js +7 -0
- package/dist/src/plugin-host/dto/presentation/plugin-history-api.dto.d.ts +29 -0
- package/dist/src/plugin-host/dto/presentation/plugin-history-api.dto.js +148 -0
- package/dist/src/plugin-host/dto/presentation/plugin-lookup-api.dto.d.ts +3 -0
- package/dist/src/plugin-host/dto/presentation/plugin-lookup-api.dto.js +22 -0
- package/dist/src/plugin-host/dto/presentation/publication-api.dto.d.ts +17 -0
- package/dist/src/plugin-host/dto/presentation/publication-api.dto.js +95 -1
- package/dist/src/plugin-host/entities/plugin-action-execution.entity.d.ts +24 -0
- package/dist/src/plugin-host/entities/plugin-action-execution.entity.js +136 -0
- package/dist/src/plugin-host/entities/plugin-version.entity.d.ts +2 -1
- package/dist/src/plugin-host/entities/plugin-version.entity.js +5 -0
- package/dist/src/plugin-host/enums/plugin-action-execution-status.enum.d.ts +9 -0
- package/dist/src/plugin-host/enums/plugin-action-execution-status.enum.js +22 -0
- package/dist/src/plugin-host/enums/release-rejection-code.enum.d.ts +3 -0
- package/dist/src/plugin-host/enums/release-rejection-code.enum.js +6 -0
- package/dist/src/plugin-host/errors/plugin-action.errors.d.ts +45 -0
- package/dist/src/plugin-host/errors/plugin-action.errors.js +70 -0
- package/dist/src/plugin-host/errors/plugin-host.errors.d.ts +6 -0
- package/dist/src/plugin-host/errors/plugin-host.errors.js +10 -1
- package/dist/src/plugin-host/filters/plugin-host-exception.filter.js +2 -2
- package/dist/src/plugin-host/mappers/plugin-action-execution.mapper.d.ts +3 -0
- package/dist/src/plugin-host/mappers/plugin-action-execution.mapper.js +22 -0
- package/dist/src/plugin-host/mappers/plugin-presentation.mapper.d.ts +22 -1
- package/dist/src/plugin-host/mappers/plugin-presentation.mapper.js +87 -1
- package/dist/src/plugin-host/plugin-host.module.js +34 -0
- package/dist/src/plugin-host/services/action-input-validator.service.d.ts +23 -0
- package/dist/src/plugin-host/services/action-input-validator.service.js +277 -0
- package/dist/src/plugin-host/services/external-credential-definition-sync.service.d.ts +3 -0
- package/dist/src/plugin-host/services/external-credential-definition-sync.service.js +47 -15
- package/dist/src/plugin-host/services/plugin-action-dispatcher.service.d.ts +13 -0
- package/dist/src/plugin-host/services/plugin-action-dispatcher.service.js +140 -0
- package/dist/src/plugin-host/services/plugin-action-execution.service.d.ts +69 -0
- package/dist/src/plugin-host/services/plugin-action-execution.service.js +239 -0
- package/dist/src/plugin-host/services/plugin-action-starter.service.d.ts +22 -0
- package/dist/src/plugin-host/services/plugin-action-starter.service.js +81 -0
- package/dist/src/plugin-host/services/plugin-audit.service.d.ts +13 -0
- package/dist/src/plugin-host/services/plugin-audit.service.js +78 -0
- package/dist/src/plugin-host/services/plugin-publication.service.d.ts +4 -0
- package/dist/src/plugin-host/services/plugin-publication.service.js +51 -23
- package/dist/src/plugin-host/services/plugin-runtime-authorizer.service.d.ts +5 -2
- package/dist/src/plugin-host/services/plugin-runtime-authorizer.service.js +31 -3
- package/dist/src/plugin-host/services/plugin-version.service.d.ts +2 -1
- package/dist/src/plugin-host/services/release-candidate-rules.service.d.ts +51 -0
- package/dist/src/plugin-host/services/release-candidate-rules.service.js +198 -0
- package/dist/src/plugin-host/services/remote-url-validator.service.d.ts +7 -0
- package/dist/src/plugin-host/services/remote-url-validator.service.js +4 -0
- package/dist/src/plugin-host/system-triggers/plugin-action-execution-sweep.processor.d.ts +14 -0
- package/dist/src/plugin-host/system-triggers/plugin-action-execution-sweep.processor.js +50 -0
- package/dist/src/plugin-host/use-cases/cancel-plugin-action-execution.service.d.ts +8 -0
- package/dist/src/plugin-host/use-cases/cancel-plugin-action-execution.service.js +39 -0
- package/dist/src/plugin-host/use-cases/check-plugin-release.service.d.ts +22 -0
- package/dist/src/plugin-host/use-cases/check-plugin-release.service.js +152 -0
- package/dist/src/plugin-host/use-cases/find-plugin-by-repository.service.d.ts +9 -0
- package/dist/src/plugin-host/use-cases/find-plugin-by-repository.service.js +35 -0
- package/dist/src/plugin-host/use-cases/get-current-plugin-action-execution.service.d.ts +14 -0
- package/dist/src/plugin-host/use-cases/get-current-plugin-action-execution.service.js +85 -0
- package/dist/src/plugin-host/use-cases/get-plugin-action-execution.service.d.ts +9 -0
- package/dist/src/plugin-host/use-cases/get-plugin-action-execution.service.js +67 -0
- package/dist/src/plugin-host/use-cases/get-plugin-installation-entry.service.js +2 -7
- package/dist/src/plugin-host/use-cases/install-plugin.service.js +4 -0
- package/dist/src/plugin-host/use-cases/list-installations.service.d.ts +3 -1
- package/dist/src/plugin-host/use-cases/list-installations.service.js +14 -3
- package/dist/src/plugin-host/use-cases/list-plugin-history.service.d.ts +25 -0
- package/dist/src/plugin-host/use-cases/list-plugin-history.service.js +147 -0
- package/dist/src/plugin-host/use-cases/plugin-publisher-access.d.ts +5 -0
- package/dist/src/plugin-host/use-cases/plugin-publisher-access.js +28 -0
- package/dist/src/plugin-host/use-cases/start-plugin-action-execution.service.d.ts +12 -0
- package/dist/src/plugin-host/use-cases/start-plugin-action-execution.service.js +64 -0
- package/dist/src/plugin-host/use-cases/sync-plugin-releases.service.d.ts +3 -5
- package/dist/src/plugin-host/use-cases/sync-plugin-releases.service.js +15 -59
- package/dist/src/plugin-host/use-cases/uninstall-plugin.service.js +3 -1
- package/dist/src/plugin-host/use-cases/update-plugin.service.d.ts +0 -1
- package/dist/src/plugin-host/use-cases/update-plugin.service.js +3 -25
- package/dist/src/plugin-host/utils/action-input-schema.util.d.ts +14 -0
- package/dist/src/plugin-host/utils/action-input-schema.util.js +133 -0
- package/dist/src/plugin-host/utils/credential-handles.util.d.ts +3 -0
- package/dist/src/plugin-host/utils/credential-handles.util.js +13 -0
- package/dist/src/plugin-host/utils/execution-token.util.d.ts +5 -0
- package/dist/src/plugin-host/utils/execution-token.util.js +13 -0
- package/dist/src/plugin-host/utils/github-repo-locator.util.js +1 -1
- package/dist/src/plugin-host/utils/json-shape.util.d.ts +1 -0
- package/dist/src/plugin-host/utils/json-shape.util.js +21 -0
- package/dist/src/plugin-host/utils/plugin-action-outcome.util.d.ts +10 -0
- package/dist/src/plugin-host/utils/plugin-action-outcome.util.js +67 -0
- package/dist/src/plugin-host/utils/plugin-manifest.util.d.ts +121 -0
- package/dist/src/plugin-host/utils/plugin-manifest.util.js +111 -1
- package/dist/src/plugin-host/utils/request-abort-signal.util.d.ts +5 -0
- package/dist/src/plugin-host/utils/request-abort-signal.util.js +19 -0
- package/package.json +10 -8
|
@@ -17,6 +17,7 @@ const credential_external_definition_registry_service_1 = require("../../data-ma
|
|
|
17
17
|
const external_credential_manifest_1 = require("../../data-marts/credentials/services/external-credential-manifest");
|
|
18
18
|
const credential_types_1 = require("../../data-marts/credentials/credential.types");
|
|
19
19
|
const github_read_policy_enum_1 = require("../enums/github-read-policy.enum");
|
|
20
|
+
const plugin_host_errors_1 = require("../errors/plugin-host.errors");
|
|
20
21
|
const github_repo_locator_util_1 = require("../utils/github-repo-locator.util");
|
|
21
22
|
const semver_util_1 = require("../utils/semver.util");
|
|
22
23
|
const github_api_service_1 = require("./github-api.service");
|
|
@@ -30,7 +31,10 @@ let ExternalCredentialDefinitionSyncService = class ExternalCredentialDefinition
|
|
|
30
31
|
this.github = github;
|
|
31
32
|
this.registry = registry;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
syncLocator(locator) {
|
|
35
|
+
return this.settleLocator(locator, input => this.registry.register(input));
|
|
36
|
+
}
|
|
37
|
+
async settleLocator(locator, settle) {
|
|
34
38
|
const ref = parseExternalLocator(locator);
|
|
35
39
|
const repo = await this.github.getRepo(ref, github_read_policy_enum_1.GithubReadPolicy.CONFIGURED);
|
|
36
40
|
const releases = (await this.github.listReleases(ref, github_read_policy_enum_1.GithubReadPolicy.CONFIGURED))
|
|
@@ -54,7 +58,7 @@ let ExternalCredentialDefinitionSyncService = class ExternalCredentialDefinition
|
|
|
54
58
|
continue;
|
|
55
59
|
}
|
|
56
60
|
try {
|
|
57
|
-
return await
|
|
61
|
+
return await settle({
|
|
58
62
|
githubRepoId: repo.githubRepoId,
|
|
59
63
|
repoOwner: repo.owner,
|
|
60
64
|
repoName: repo.name,
|
|
@@ -77,19 +81,51 @@ let ExternalCredentialDefinitionSyncService = class ExternalCredentialDefinition
|
|
|
77
81
|
throw new ExternalCredentialRequirementError('No eligible Credential definition release was found');
|
|
78
82
|
}
|
|
79
83
|
async resolveRequirements(requirements) {
|
|
80
|
-
const
|
|
84
|
+
const settled = await this.settleRequirements(requirements, locator => this.syncLocator(locator));
|
|
85
|
+
return settled.map(({ requirement, definition }) => {
|
|
86
|
+
if (!definition)
|
|
87
|
+
return requirement;
|
|
88
|
+
const external = {
|
|
89
|
+
id: definition.contract.id,
|
|
90
|
+
definitionId: definition.definitionId,
|
|
91
|
+
optional: typeof requirement === 'string' ? false : requirement.optional,
|
|
92
|
+
models: typeof requirement === 'string' ? undefined : requirement.models,
|
|
93
|
+
};
|
|
94
|
+
return external;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
async previewRequirements(requirements) {
|
|
98
|
+
await this.settleRequirements(requirements, async (locator) => {
|
|
99
|
+
try {
|
|
100
|
+
return await this.settleLocator(locator, input => this.registry.preview(input));
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (error instanceof plugin_host_errors_1.InvalidRepoLocatorError ||
|
|
104
|
+
error instanceof plugin_host_errors_1.GithubRepoNotFoundError ||
|
|
105
|
+
error instanceof plugin_host_errors_1.GithubRepoNotAccessibleError) {
|
|
106
|
+
const installationUrl = error instanceof plugin_host_errors_1.GithubRepoNotAccessibleError
|
|
107
|
+
? error.errorDetails?.installationUrl
|
|
108
|
+
: undefined;
|
|
109
|
+
throw new ExternalCredentialRequirementError(`${locator}: ${error.message}${installationUrl ? ` ${installationUrl}` : ''}`);
|
|
110
|
+
}
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async settleRequirements(requirements, settle) {
|
|
116
|
+
const settled = [];
|
|
81
117
|
for (const requirement of requirements) {
|
|
82
118
|
const locator = typeof requirement === 'string' ? requirement : requirement.id;
|
|
83
119
|
if (!locator.startsWith('@')) {
|
|
84
120
|
if (locator !== 'ai' && !builtin_credential_definitions_1.BUILTIN_CREDENTIAL_DEFINITION_IDS.has(locator)) {
|
|
85
121
|
throw new ExternalCredentialRequirementError(`Unknown Credential requirement "${locator}"; use ai, a built-in definition, or @owner/repository`);
|
|
86
122
|
}
|
|
87
|
-
|
|
123
|
+
settled.push({ requirement, definition: null });
|
|
88
124
|
continue;
|
|
89
125
|
}
|
|
90
126
|
let definition;
|
|
91
127
|
try {
|
|
92
|
-
definition = await
|
|
128
|
+
definition = await settle(locator);
|
|
93
129
|
}
|
|
94
130
|
catch (error) {
|
|
95
131
|
if (error instanceof ExternalCredentialRequirementError)
|
|
@@ -99,23 +135,19 @@ let ExternalCredentialDefinitionSyncService = class ExternalCredentialDefinition
|
|
|
99
135
|
}
|
|
100
136
|
throw error;
|
|
101
137
|
}
|
|
102
|
-
|
|
103
|
-
id: definition.contract.id,
|
|
104
|
-
definitionId: definition.definitionId,
|
|
105
|
-
optional: typeof requirement === 'string' ? false : requirement.optional,
|
|
106
|
-
models: typeof requirement === 'string' ? undefined : requirement.models,
|
|
107
|
-
};
|
|
108
|
-
resolved.push(external);
|
|
138
|
+
settled.push({ requirement, definition });
|
|
109
139
|
}
|
|
110
140
|
const keys = new Set();
|
|
111
|
-
for (const requirement of
|
|
112
|
-
const key =
|
|
141
|
+
for (const { requirement, definition } of settled) {
|
|
142
|
+
const key = definition
|
|
143
|
+
? definition.contract.id
|
|
144
|
+
: (0, credential_types_1.normalizeCredentialRequirement)(requirement).key;
|
|
113
145
|
if (keys.has(key)) {
|
|
114
146
|
throw new ExternalCredentialRequirementError(`Duplicate resolved Credential handle ${key}`);
|
|
115
147
|
}
|
|
116
148
|
keys.add(key);
|
|
117
149
|
}
|
|
118
|
-
return
|
|
150
|
+
return settled;
|
|
119
151
|
}
|
|
120
152
|
};
|
|
121
153
|
exports.ExternalCredentialDefinitionSyncService = ExternalCredentialDefinitionSyncService;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { GracefulShutdownService } from '../../common/scheduler/services/graceful-shutdown.service';
|
|
2
|
+
import { PluginHostConfigService } from '../config/plugin-host.config';
|
|
3
|
+
import type { PluginActionExecution } from '../entities/plugin-action-execution.entity';
|
|
4
|
+
import { PluginActionExecutionService } from './plugin-action-execution.service';
|
|
5
|
+
export declare class PluginActionDispatcherService {
|
|
6
|
+
private readonly executions;
|
|
7
|
+
private readonly shutdown;
|
|
8
|
+
private readonly config;
|
|
9
|
+
private readonly logger;
|
|
10
|
+
constructor(executions: PluginActionExecutionService, shutdown: GracefulShutdownService, config: PluginHostConfigService);
|
|
11
|
+
dispatch(execution: PluginActionExecution, backendUrl: string, token: string, timeoutSeconds: number): Promise<void>;
|
|
12
|
+
private call;
|
|
13
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var PluginActionDispatcherService_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.PluginActionDispatcherService = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const internal_helpers_1 = require("@owox/internal-helpers");
|
|
16
|
+
const guarded_dispatcher_1 = require("../../common/helpers/guarded-dispatcher");
|
|
17
|
+
const read_bounded_body_helper_1 = require("../../common/helpers/read-bounded-body.helper");
|
|
18
|
+
const safe_url_helper_1 = require("../../common/helpers/safe-url.helper");
|
|
19
|
+
const graceful_shutdown_service_1 = require("../../common/scheduler/services/graceful-shutdown.service");
|
|
20
|
+
const plugin_host_config_1 = require("../config/plugin-host.config");
|
|
21
|
+
const plugin_action_limits_1 = require("../constants/plugin-action-limits");
|
|
22
|
+
const plugin_action_execution_status_enum_1 = require("../enums/plugin-action-execution-status.enum");
|
|
23
|
+
const plugin_action_outcome_util_1 = require("../utils/plugin-action-outcome.util");
|
|
24
|
+
const plugin_action_execution_service_1 = require("./plugin-action-execution.service");
|
|
25
|
+
const MAX_RESPONSE_BYTES = plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxResultBytes + 1024;
|
|
26
|
+
const UNSTORABLE_RESULT = {
|
|
27
|
+
status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.FAILED,
|
|
28
|
+
errorCode: 'BACKEND_INVALID_RESPONSE',
|
|
29
|
+
errorMessage: 'The result could not be stored',
|
|
30
|
+
};
|
|
31
|
+
let PluginActionDispatcherService = PluginActionDispatcherService_1 = class PluginActionDispatcherService {
|
|
32
|
+
executions;
|
|
33
|
+
shutdown;
|
|
34
|
+
config;
|
|
35
|
+
logger = new common_1.Logger(PluginActionDispatcherService_1.name);
|
|
36
|
+
constructor(executions, shutdown, config) {
|
|
37
|
+
this.executions = executions;
|
|
38
|
+
this.shutdown = shutdown;
|
|
39
|
+
this.config = config;
|
|
40
|
+
}
|
|
41
|
+
async dispatch(execution, backendUrl, token, timeoutSeconds) {
|
|
42
|
+
const processId = this.shutdown.registerActiveProcess(`plugin-action-${execution.id}`);
|
|
43
|
+
const startedAt = Date.now();
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
let stopReason;
|
|
46
|
+
const stop = (reason) => {
|
|
47
|
+
stopReason ??= reason;
|
|
48
|
+
controller.abort();
|
|
49
|
+
};
|
|
50
|
+
const deadline = setTimeout(() => stop('deadline'), Math.max(0, (execution.deadlineAt?.getTime() ?? startedAt) - startedAt));
|
|
51
|
+
const poll = setInterval(() => {
|
|
52
|
+
this.executions.findStatus(execution.id).then(status => {
|
|
53
|
+
if (status !== plugin_action_execution_status_enum_1.PluginActionExecutionStatus.RUNNING)
|
|
54
|
+
stop('ended');
|
|
55
|
+
}, () => undefined);
|
|
56
|
+
}, plugin_action_limits_1.PLUGIN_ACTION_LIMITS.cancelPollMs);
|
|
57
|
+
try {
|
|
58
|
+
let outcome;
|
|
59
|
+
try {
|
|
60
|
+
outcome = await this.call(execution.id, backendUrl, token, controller.signal);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
outcome =
|
|
64
|
+
stopReason === 'deadline'
|
|
65
|
+
? timedOut(timeoutSeconds)
|
|
66
|
+
: stopReason === 'ended'
|
|
67
|
+
? null
|
|
68
|
+
: unreachable(error);
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
clearTimeout(deadline);
|
|
72
|
+
clearInterval(poll);
|
|
73
|
+
}
|
|
74
|
+
let recorded = false;
|
|
75
|
+
if (outcome) {
|
|
76
|
+
try {
|
|
77
|
+
recorded = await this.executions.finish(execution.id, outcome);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (outcome.status !== plugin_action_execution_status_enum_1.PluginActionExecutionStatus.SUCCEEDED)
|
|
81
|
+
throw error;
|
|
82
|
+
this.logger.error(`Plugin action ${execution.id} could not store its result`, (0, internal_helpers_1.castError)(error).stack);
|
|
83
|
+
outcome = UNSTORABLE_RESULT;
|
|
84
|
+
recorded = await this.executions.finish(execution.id, outcome);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const status = recorded && outcome ? outcome.status : await this.executions.findStatus(execution.id);
|
|
88
|
+
const errorCode = recorded && outcome?.status === plugin_action_execution_status_enum_1.PluginActionExecutionStatus.FAILED
|
|
89
|
+
? outcome.errorCode
|
|
90
|
+
: '-';
|
|
91
|
+
this.logger.log(`Plugin action finished executionId=${execution.id} action=${execution.action} status=${status} errorCode=${errorCode} durationMs=${Date.now() - startedAt}`);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
this.logger.error(`Plugin action ${execution.id} could not record its outcome`, (0, internal_helpers_1.castError)(error).stack);
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
this.shutdown.unregisterActiveProcess(processId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async call(executionId, backendUrl, token, signal) {
|
|
101
|
+
await (0, safe_url_helper_1.assertPublicHttpUrl)(backendUrl, { allowedProtocols: ['https:'] });
|
|
102
|
+
const response = await fetch(backendUrl, (0, guarded_dispatcher_1.withGuardedDispatcher)({
|
|
103
|
+
method: 'POST',
|
|
104
|
+
redirect: 'manual',
|
|
105
|
+
signal,
|
|
106
|
+
headers: { 'content-type': 'application/json', 'x-owox-execution-token': token },
|
|
107
|
+
body: JSON.stringify({ owox: 1, host: this.config.publicOrigin, executionId }),
|
|
108
|
+
}));
|
|
109
|
+
const body = await (0, read_bounded_body_helper_1.readBoundedBody)(response, MAX_RESPONSE_BYTES);
|
|
110
|
+
return (0, plugin_action_outcome_util_1.classifyBackendResponse)(response.status, body?.toString('utf8') ?? null);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
exports.PluginActionDispatcherService = PluginActionDispatcherService;
|
|
114
|
+
exports.PluginActionDispatcherService = PluginActionDispatcherService = PluginActionDispatcherService_1 = __decorate([
|
|
115
|
+
(0, common_1.Injectable)(),
|
|
116
|
+
__metadata("design:paramtypes", [plugin_action_execution_service_1.PluginActionExecutionService,
|
|
117
|
+
graceful_shutdown_service_1.GracefulShutdownService,
|
|
118
|
+
plugin_host_config_1.PluginHostConfigService])
|
|
119
|
+
], PluginActionDispatcherService);
|
|
120
|
+
function timedOut(seconds) {
|
|
121
|
+
return {
|
|
122
|
+
status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.TIMED_OUT,
|
|
123
|
+
errorMessage: `The action did not finish within ${seconds} s`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function unreachable(error) {
|
|
127
|
+
return {
|
|
128
|
+
status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.FAILED,
|
|
129
|
+
errorCode: 'BACKEND_UNREACHABLE',
|
|
130
|
+
errorMessage: `The backend could not be reached (${reasonOf(error)})`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function reasonOf(error) {
|
|
134
|
+
if (error instanceof safe_url_helper_1.UnsafeUrlError)
|
|
135
|
+
return error.reason;
|
|
136
|
+
const { cause, name } = (0, internal_helpers_1.castError)(error);
|
|
137
|
+
const code = cause?.code;
|
|
138
|
+
return typeof code === 'string' ? code : name;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=plugin-action-dispatcher.service.js.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Repository } from 'typeorm';
|
|
2
|
+
import { PluginActionExecution } from '../entities/plugin-action-execution.entity';
|
|
3
|
+
import { PluginInstallation } from '../entities/plugin-installation.entity';
|
|
4
|
+
import { PluginActionExecutionStatus, type PluginActionTrigger } from '../enums/plugin-action-execution-status.enum';
|
|
5
|
+
export interface InsertRunningExecutionInput {
|
|
6
|
+
pluginId: string;
|
|
7
|
+
pluginVersionId: string;
|
|
8
|
+
installationId: string;
|
|
9
|
+
projectId: string;
|
|
10
|
+
userId: string;
|
|
11
|
+
action: string;
|
|
12
|
+
input: unknown;
|
|
13
|
+
inputBytes: number;
|
|
14
|
+
role: string;
|
|
15
|
+
timeoutSeconds: number;
|
|
16
|
+
tokenHash: string;
|
|
17
|
+
trigger: PluginActionTrigger;
|
|
18
|
+
}
|
|
19
|
+
declare const TOKEN_OWNER_COLUMNS: {
|
|
20
|
+
readonly id: true;
|
|
21
|
+
readonly pluginId: true;
|
|
22
|
+
readonly installationId: true;
|
|
23
|
+
readonly projectId: true;
|
|
24
|
+
readonly userId: true;
|
|
25
|
+
readonly role: true;
|
|
26
|
+
};
|
|
27
|
+
export type ExecutionTokenOwner = Pick<PluginActionExecution, keyof typeof TOKEN_OWNER_COLUMNS>;
|
|
28
|
+
declare const SUMMARY_COLUMNS: {
|
|
29
|
+
readonly id: true;
|
|
30
|
+
readonly installationId: true;
|
|
31
|
+
readonly action: true;
|
|
32
|
+
readonly status: true;
|
|
33
|
+
readonly trigger: true;
|
|
34
|
+
readonly startedAt: true;
|
|
35
|
+
readonly deadlineAt: true;
|
|
36
|
+
readonly finishedAt: true;
|
|
37
|
+
readonly errorCode: true;
|
|
38
|
+
readonly errorMessage: true;
|
|
39
|
+
readonly result: true;
|
|
40
|
+
};
|
|
41
|
+
export type PluginActionExecutionSummary = Pick<PluginActionExecution, keyof typeof SUMMARY_COLUMNS>;
|
|
42
|
+
export type FinishExecutionInput = {
|
|
43
|
+
status: PluginActionExecutionStatus.SUCCEEDED;
|
|
44
|
+
result: unknown;
|
|
45
|
+
} | {
|
|
46
|
+
status: PluginActionExecutionStatus.FAILED;
|
|
47
|
+
errorCode: string;
|
|
48
|
+
errorMessage: string;
|
|
49
|
+
} | {
|
|
50
|
+
status: PluginActionExecutionStatus.TIMED_OUT;
|
|
51
|
+
errorMessage: string;
|
|
52
|
+
};
|
|
53
|
+
export declare class PluginActionExecutionService {
|
|
54
|
+
private readonly executions;
|
|
55
|
+
private readonly installations;
|
|
56
|
+
constructor(executions: Repository<PluginActionExecution>, installations: Repository<PluginInstallation>);
|
|
57
|
+
insertRunning(request: InsertRunningExecutionInput): Promise<PluginActionExecution>;
|
|
58
|
+
assertWithinStartLimits(installationId: string, now: number): Promise<void>;
|
|
59
|
+
findById(id: string): Promise<PluginActionExecutionSummary | null>;
|
|
60
|
+
findWithInput(id: string): Promise<PluginActionExecution | null>;
|
|
61
|
+
findStatus(id: string): Promise<PluginActionExecutionStatus | null>;
|
|
62
|
+
findRunningByTokenHash(tokenHash: string, now: Date): Promise<ExecutionTokenOwner | null>;
|
|
63
|
+
finish(id: string, outcome: FinishExecutionInput): Promise<boolean>;
|
|
64
|
+
cancel(id: string, installationId: string): Promise<boolean>;
|
|
65
|
+
timeOutOrphans(deadlineBefore: Date): Promise<number>;
|
|
66
|
+
clearPayloads(finishedBefore: Date, signal?: AbortSignal): Promise<number>;
|
|
67
|
+
deleteFinished(finishedBefore: Date, signal?: AbortSignal): Promise<number>;
|
|
68
|
+
}
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PluginActionExecutionService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
18
|
+
const typeorm_2 = require("typeorm");
|
|
19
|
+
const typeorm_transactional_1 = require("typeorm-transactional");
|
|
20
|
+
const plugin_action_limits_1 = require("../constants/plugin-action-limits");
|
|
21
|
+
const plugin_action_execution_entity_1 = require("../entities/plugin-action-execution.entity");
|
|
22
|
+
const plugin_installation_entity_1 = require("../entities/plugin-installation.entity");
|
|
23
|
+
const plugin_action_execution_status_enum_1 = require("../enums/plugin-action-execution-status.enum");
|
|
24
|
+
const plugin_action_errors_1 = require("../errors/plugin-action.errors");
|
|
25
|
+
const HOUR_MS = 60 * 60 * 1000;
|
|
26
|
+
const MINUTE_MS = 60 * 1000;
|
|
27
|
+
const DAY_MS = 24 * HOUR_MS;
|
|
28
|
+
function byteLength(value) {
|
|
29
|
+
return value === null || value === undefined ? 0 : Buffer.byteLength(JSON.stringify(value) ?? '');
|
|
30
|
+
}
|
|
31
|
+
const TOKEN_OWNER_COLUMNS = {
|
|
32
|
+
id: true,
|
|
33
|
+
pluginId: true,
|
|
34
|
+
installationId: true,
|
|
35
|
+
projectId: true,
|
|
36
|
+
userId: true,
|
|
37
|
+
role: true,
|
|
38
|
+
};
|
|
39
|
+
const SUMMARY_COLUMNS = {
|
|
40
|
+
id: true,
|
|
41
|
+
installationId: true,
|
|
42
|
+
action: true,
|
|
43
|
+
status: true,
|
|
44
|
+
trigger: true,
|
|
45
|
+
startedAt: true,
|
|
46
|
+
deadlineAt: true,
|
|
47
|
+
finishedAt: true,
|
|
48
|
+
errorCode: true,
|
|
49
|
+
errorMessage: true,
|
|
50
|
+
result: true,
|
|
51
|
+
};
|
|
52
|
+
let PluginActionExecutionService = class PluginActionExecutionService {
|
|
53
|
+
executions;
|
|
54
|
+
installations;
|
|
55
|
+
constructor(executions, installations) {
|
|
56
|
+
this.executions = executions;
|
|
57
|
+
this.installations = installations;
|
|
58
|
+
}
|
|
59
|
+
async insertRunning(request) {
|
|
60
|
+
const lock = await this.installations
|
|
61
|
+
.createQueryBuilder()
|
|
62
|
+
.update(plugin_installation_entity_1.PluginInstallation)
|
|
63
|
+
.set({ modifiedAt: () => 'modifiedAt' })
|
|
64
|
+
.where('id = :id', { id: request.installationId })
|
|
65
|
+
.andWhere('uninstalledAt IS NULL')
|
|
66
|
+
.execute();
|
|
67
|
+
if (lock.affected !== 1) {
|
|
68
|
+
throw new plugin_action_errors_1.InstallationInactiveError();
|
|
69
|
+
}
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
const running = await this.executions.countBy({
|
|
72
|
+
installationId: request.installationId,
|
|
73
|
+
status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.RUNNING,
|
|
74
|
+
deadlineAt: (0, typeorm_2.MoreThan)(new Date(now)),
|
|
75
|
+
});
|
|
76
|
+
if (running >= plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxRunningPerInstallation) {
|
|
77
|
+
throw new plugin_action_errors_1.TooManyExecutionsError();
|
|
78
|
+
}
|
|
79
|
+
await this.assertWithinStartLimits(request.installationId, now);
|
|
80
|
+
const startedAt = new Date(Math.floor(now / 1000) * 1000);
|
|
81
|
+
return this.executions.save(this.executions.create({
|
|
82
|
+
pluginId: request.pluginId,
|
|
83
|
+
pluginVersionId: request.pluginVersionId,
|
|
84
|
+
installationId: request.installationId,
|
|
85
|
+
projectId: request.projectId,
|
|
86
|
+
userId: request.userId,
|
|
87
|
+
action: request.action,
|
|
88
|
+
input: request.input,
|
|
89
|
+
trigger: request.trigger,
|
|
90
|
+
status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.RUNNING,
|
|
91
|
+
role: request.role,
|
|
92
|
+
tokenHash: request.tokenHash,
|
|
93
|
+
startedAt,
|
|
94
|
+
deadlineAt: new Date(Math.ceil((now + request.timeoutSeconds * 1000) / 1000) * 1000),
|
|
95
|
+
finishedAt: null,
|
|
96
|
+
errorCode: null,
|
|
97
|
+
errorMessage: null,
|
|
98
|
+
result: null,
|
|
99
|
+
payloadBytes: request.inputBytes,
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
async assertWithinStartLimits(installationId, now) {
|
|
103
|
+
const raw = await this.executions
|
|
104
|
+
.createQueryBuilder('e')
|
|
105
|
+
.select('SUM(CASE WHEN e.startedAt > :minuteAgo THEN 1 ELSE 0 END)', 'perMinute')
|
|
106
|
+
.addSelect('SUM(CASE WHEN e.startedAt > :dayAgo THEN 1 ELSE 0 END)', 'perDay')
|
|
107
|
+
.addSelect('SUM(e.payloadBytes)', 'bytes')
|
|
108
|
+
.where('e.installationId = :installationId', { installationId })
|
|
109
|
+
.andWhere('e.startedAt > :bytesSince')
|
|
110
|
+
.setParameters({
|
|
111
|
+
minuteAgo: new Date(now - MINUTE_MS),
|
|
112
|
+
dayAgo: new Date(now - DAY_MS),
|
|
113
|
+
bytesSince: new Date(now - 2 * plugin_action_limits_1.PLUGIN_ACTION_LIMITS.payloadRetentionHours * HOUR_MS),
|
|
114
|
+
})
|
|
115
|
+
.getRawOne();
|
|
116
|
+
const perMinute = Number(raw?.perMinute ?? 0);
|
|
117
|
+
const perDay = Number(raw?.perDay ?? 0);
|
|
118
|
+
const bytes = Number(raw?.bytes ?? 0);
|
|
119
|
+
if (perMinute >= plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxStartsPerInstallationPerMinute) {
|
|
120
|
+
throw new plugin_action_errors_1.TooManyExecutionsError(`${plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxStartsPerInstallationPerMinute} starts per minute reached`);
|
|
121
|
+
}
|
|
122
|
+
if (perDay >= plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxStartsPerInstallationPerDay) {
|
|
123
|
+
throw new plugin_action_errors_1.TooManyExecutionsError(`${plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxStartsPerInstallationPerDay} starts per day reached`);
|
|
124
|
+
}
|
|
125
|
+
if (bytes >= plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxPayloadBytesPerInstallation) {
|
|
126
|
+
throw new plugin_action_errors_1.TooManyExecutionsError(`${plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxPayloadBytesPerInstallation / (1024 * 1024)} MiB of stored payloads reached`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
findById(id) {
|
|
130
|
+
return this.executions.findOne({ select: SUMMARY_COLUMNS, where: { id } });
|
|
131
|
+
}
|
|
132
|
+
findWithInput(id) {
|
|
133
|
+
return this.executions.findOneBy({ id });
|
|
134
|
+
}
|
|
135
|
+
async findStatus(id) {
|
|
136
|
+
const row = await this.executions.findOne({
|
|
137
|
+
select: { id: true, status: true },
|
|
138
|
+
where: { id },
|
|
139
|
+
});
|
|
140
|
+
return row?.status ?? null;
|
|
141
|
+
}
|
|
142
|
+
findRunningByTokenHash(tokenHash, now) {
|
|
143
|
+
return this.executions.findOne({
|
|
144
|
+
select: TOKEN_OWNER_COLUMNS,
|
|
145
|
+
where: { tokenHash, status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.RUNNING, deadlineAt: (0, typeorm_2.MoreThan)(now) },
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async finish(id, outcome) {
|
|
149
|
+
const { affected } = await this.executions.update({ id, status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.RUNNING }, {
|
|
150
|
+
status: outcome.status,
|
|
151
|
+
finishedAt: new Date(),
|
|
152
|
+
errorCode: outcome.status === plugin_action_execution_status_enum_1.PluginActionExecutionStatus.FAILED ? outcome.errorCode : null,
|
|
153
|
+
errorMessage: 'errorMessage' in outcome ? outcome.errorMessage : null,
|
|
154
|
+
result: (outcome.status === plugin_action_execution_status_enum_1.PluginActionExecutionStatus.SUCCEEDED
|
|
155
|
+
? outcome.result
|
|
156
|
+
: null),
|
|
157
|
+
...(outcome.status === plugin_action_execution_status_enum_1.PluginActionExecutionStatus.SUCCEEDED && {
|
|
158
|
+
payloadBytes: () => `payloadBytes + ${byteLength(outcome.result)}`,
|
|
159
|
+
}),
|
|
160
|
+
});
|
|
161
|
+
return affected === 1;
|
|
162
|
+
}
|
|
163
|
+
async cancel(id, installationId) {
|
|
164
|
+
const { affected } = await this.executions.update({ id, installationId, status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.RUNNING }, {
|
|
165
|
+
status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.CANCELLED,
|
|
166
|
+
finishedAt: new Date(),
|
|
167
|
+
errorMessage: 'The execution was cancelled',
|
|
168
|
+
});
|
|
169
|
+
return affected === 1;
|
|
170
|
+
}
|
|
171
|
+
async timeOutOrphans(deadlineBefore) {
|
|
172
|
+
const { affected } = await this.executions.update({ status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.RUNNING, deadlineAt: (0, typeorm_2.LessThan)(deadlineBefore) }, {
|
|
173
|
+
status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.TIMED_OUT,
|
|
174
|
+
finishedAt: new Date(),
|
|
175
|
+
errorMessage: 'The execution outlived its replica',
|
|
176
|
+
});
|
|
177
|
+
return affected ?? 0;
|
|
178
|
+
}
|
|
179
|
+
clearPayloads(finishedBefore, signal) {
|
|
180
|
+
return inBatches(signal, async () => {
|
|
181
|
+
const rows = await this.executions.find({
|
|
182
|
+
select: { id: true, errorCode: true },
|
|
183
|
+
where: { payloadsClearedAt: (0, typeorm_2.IsNull)(), finishedAt: (0, typeorm_2.LessThan)(finishedBefore) },
|
|
184
|
+
take: plugin_action_limits_1.PLUGIN_ACTION_LIMITS.sweepBatchSize,
|
|
185
|
+
});
|
|
186
|
+
if (rows.length === 0)
|
|
187
|
+
return 0;
|
|
188
|
+
const pluginAuthored = rows.filter(row => (0, plugin_action_limits_1.isPluginOwnedErrorCode)(row.errorCode));
|
|
189
|
+
if (pluginAuthored.length > 0) {
|
|
190
|
+
await this.executions.update({ id: (0, typeorm_2.In)(pluginAuthored.map(row => row.id)) }, { errorMessage: null });
|
|
191
|
+
}
|
|
192
|
+
await this.executions.update({ id: (0, typeorm_2.In)(rows.map(row => row.id)) }, {
|
|
193
|
+
input: () => 'NULL',
|
|
194
|
+
result: () => 'NULL',
|
|
195
|
+
payloadsClearedAt: new Date(),
|
|
196
|
+
payloadBytes: 0,
|
|
197
|
+
});
|
|
198
|
+
return rows.length;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
deleteFinished(finishedBefore, signal) {
|
|
202
|
+
return inBatches(signal, async () => {
|
|
203
|
+
const rows = await this.executions.find({
|
|
204
|
+
select: { id: true },
|
|
205
|
+
where: { finishedAt: (0, typeorm_2.LessThan)(finishedBefore) },
|
|
206
|
+
take: plugin_action_limits_1.PLUGIN_ACTION_LIMITS.sweepBatchSize,
|
|
207
|
+
});
|
|
208
|
+
if (rows.length > 0) {
|
|
209
|
+
await this.executions.delete({ id: (0, typeorm_2.In)(rows.map(row => row.id)) });
|
|
210
|
+
}
|
|
211
|
+
return rows.length;
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
exports.PluginActionExecutionService = PluginActionExecutionService;
|
|
216
|
+
__decorate([
|
|
217
|
+
(0, typeorm_transactional_1.Transactional)(),
|
|
218
|
+
__metadata("design:type", Function),
|
|
219
|
+
__metadata("design:paramtypes", [Object]),
|
|
220
|
+
__metadata("design:returntype", Promise)
|
|
221
|
+
], PluginActionExecutionService.prototype, "insertRunning", null);
|
|
222
|
+
exports.PluginActionExecutionService = PluginActionExecutionService = __decorate([
|
|
223
|
+
(0, common_1.Injectable)(),
|
|
224
|
+
__param(0, (0, typeorm_1.InjectRepository)(plugin_action_execution_entity_1.PluginActionExecution)),
|
|
225
|
+
__param(1, (0, typeorm_1.InjectRepository)(plugin_installation_entity_1.PluginInstallation)),
|
|
226
|
+
__metadata("design:paramtypes", [typeorm_2.Repository,
|
|
227
|
+
typeorm_2.Repository])
|
|
228
|
+
], PluginActionExecutionService);
|
|
229
|
+
async function inBatches(signal, batch) {
|
|
230
|
+
let total = 0;
|
|
231
|
+
while (!signal?.aborted) {
|
|
232
|
+
const handled = await batch();
|
|
233
|
+
total += handled;
|
|
234
|
+
if (handled < plugin_action_limits_1.PLUGIN_ACTION_LIMITS.sweepBatchSize)
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
return total;
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=plugin-action-execution.service.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { StartedPluginActionExecution } from '../dto/domain/plugin-action-execution.dto';
|
|
2
|
+
import type { PluginInstallation } from '../entities/plugin-installation.entity';
|
|
3
|
+
import type { PluginVersion } from '../entities/plugin-version.entity';
|
|
4
|
+
import { type PluginActionTrigger } from '../enums/plugin-action-execution-status.enum';
|
|
5
|
+
import { ActionInputValidatorService } from './action-input-validator.service';
|
|
6
|
+
import { PluginActionDispatcherService } from './plugin-action-dispatcher.service';
|
|
7
|
+
import { PluginActionExecutionService } from './plugin-action-execution.service';
|
|
8
|
+
export interface PluginActionStart {
|
|
9
|
+
readonly installation: Pick<PluginInstallation, 'id' | 'projectId' | 'userId'>;
|
|
10
|
+
readonly version: PluginVersion;
|
|
11
|
+
readonly action: string;
|
|
12
|
+
readonly input: unknown;
|
|
13
|
+
readonly role: string;
|
|
14
|
+
readonly trigger: PluginActionTrigger;
|
|
15
|
+
}
|
|
16
|
+
export declare class PluginActionStarterService {
|
|
17
|
+
private readonly validator;
|
|
18
|
+
private readonly executions;
|
|
19
|
+
private readonly dispatcher;
|
|
20
|
+
constructor(validator: ActionInputValidatorService, executions: PluginActionExecutionService, dispatcher: PluginActionDispatcherService);
|
|
21
|
+
start(request: PluginActionStart): Promise<StartedPluginActionExecution>;
|
|
22
|
+
}
|