@owox/backend 0.38.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.
Files changed (179) hide show
  1. package/dist/src/common/helpers/read-bounded-body.helper.d.ts +1 -0
  2. package/dist/src/common/helpers/read-bounded-body.helper.js +28 -0
  3. package/dist/src/common/scheduler/system-tasks/system-trigger-type.d.ts +3 -1
  4. package/dist/src/common/scheduler/system-tasks/system-trigger-type.js +2 -0
  5. package/dist/src/config/data-source-options.config.d.ts +4 -3
  6. package/dist/src/config/data-source-options.config.js +10 -3
  7. package/dist/src/config/plugin-collections-body-parser.config.js +3 -0
  8. package/dist/src/data-marts/credentials/credential.types.d.ts +26 -2
  9. package/dist/src/data-marts/credentials/credential.types.js +18 -6
  10. package/dist/src/data-marts/credentials/dto/credential-api.dto.d.ts +5 -1
  11. package/dist/src/data-marts/credentials/dto/credential-api.dto.js +21 -0
  12. package/dist/src/data-marts/credentials/dto/credential.dto.d.ts +2 -1
  13. package/dist/src/data-marts/credentials/entities/credential.entity.d.ts +2 -1
  14. package/dist/src/data-marts/credentials/entities/credential.entity.js +5 -0
  15. package/dist/src/data-marts/credentials/facades/credential-consumer-binding.facade.impl.js +6 -1
  16. package/dist/src/data-marts/credentials/mappers/credential.mapper.js +2 -0
  17. package/dist/src/data-marts/credentials/services/builtin-credential-definitions.js +8 -0
  18. package/dist/src/data-marts/credentials/services/credential-external-definition-registry.service.d.ts +4 -0
  19. package/dist/src/data-marts/credentials/services/credential-external-definition-registry.service.js +36 -17
  20. package/dist/src/data-marts/credentials/services/credential-fetch.service.d.ts +8 -0
  21. package/dist/src/data-marts/credentials/services/credential-fetch.service.js +115 -46
  22. package/dist/src/data-marts/credentials/services/credential-validation-probe.service.d.ts +3 -1
  23. package/dist/src/data-marts/credentials/services/credential-validation-probe.service.js +10 -2
  24. package/dist/src/data-marts/credentials/services/credential.service.d.ts +4 -0
  25. package/dist/src/data-marts/credentials/services/credential.service.js +36 -0
  26. package/dist/src/data-marts/credentials/services/google-service-account-key.d.ts +6 -0
  27. package/dist/src/data-marts/credentials/services/google-service-account-key.js +46 -0
  28. package/dist/src/data-marts/credentials/services/google-service-account-token.service.d.ts +25 -0
  29. package/dist/src/data-marts/credentials/services/google-service-account-token.service.js +177 -0
  30. package/dist/src/data-marts/credentials/use-cases/create-credential.service.d.ts +1 -0
  31. package/dist/src/data-marts/credentials/use-cases/create-credential.service.js +10 -2
  32. package/dist/src/data-marts/credentials/use-cases/update-credential.service.d.ts +1 -0
  33. package/dist/src/data-marts/credentials/use-cases/update-credential.service.js +28 -4
  34. package/dist/src/data-marts/credentials/use-cases/validate-credential.service.js +2 -5
  35. package/dist/src/data-marts/data-marts.module.js +4 -0
  36. package/dist/src/data-marts/data-storage-types/snowflake/adapters/snowflake-api.adapter.js +1 -0
  37. package/dist/src/data-marts/dto/presentation/run-data-mart-request-api.dto.js +4 -2
  38. package/dist/src/data-marts/services/connector/backfill-segment.d.ts +22 -0
  39. package/dist/src/data-marts/services/connector/backfill-segment.js +91 -0
  40. package/dist/src/data-marts/services/connector/connector-execution.service.d.ts +1 -0
  41. package/dist/src/data-marts/services/connector/connector-execution.service.js +3 -0
  42. package/dist/src/data-marts/services/connector/connector-executor.service.d.ts +4 -1
  43. package/dist/src/data-marts/services/connector/connector-executor.service.js +107 -23
  44. package/dist/src/data-marts/services/connector/connector-run.service.d.ts +3 -0
  45. package/dist/src/data-marts/services/connector/connector-run.service.js +98 -4
  46. package/dist/src/data-marts/services/data-mart-run.service.d.ts +1 -0
  47. package/dist/src/data-marts/services/data-mart-run.service.js +9 -0
  48. package/dist/src/data-marts/system-triggers/processors/repair-backfill-chains-processor.d.ts +14 -0
  49. package/dist/src/data-marts/system-triggers/processors/repair-backfill-chains-processor.js +45 -0
  50. package/dist/src/data-marts/use-cases/cancel-data-mart-run.service.d.ts +4 -0
  51. package/dist/src/data-marts/use-cases/cancel-data-mart-run.service.js +46 -1
  52. package/dist/src/data-marts/utils/manual-backfill-range.d.ts +52 -0
  53. package/dist/src/data-marts/utils/manual-backfill-range.js +110 -8
  54. package/dist/src/ee/mcp/instructions/mcp-system-instructions.d.ts +1 -1
  55. package/dist/src/ee/mcp/instructions/mcp-system-instructions.js +1 -0
  56. package/dist/src/idp/decorators/auth-context.decorator.js +1 -0
  57. package/dist/src/idp/guards/idp.guard.d.ts +3 -0
  58. package/dist/src/idp/guards/idp.guard.js +38 -8
  59. package/dist/src/idp/oauth/controllers/oauth-authorization.controller.js +8 -6
  60. package/dist/src/idp/oauth/mcp-client-integration.d.ts +1 -0
  61. package/dist/src/idp/oauth/mcp-client-integration.js +15 -0
  62. package/dist/src/idp/ports/plugin-runtime-authorizer.port.d.ts +6 -0
  63. package/dist/src/idp/types/auth.types.d.ts +1 -0
  64. package/dist/src/migrations/1790900000000-add-plugin-version-backend.d.ts +6 -0
  65. package/dist/src/migrations/1790900000000-add-plugin-version-backend.js +21 -0
  66. package/dist/src/migrations/1790900000001-create-plugin-action-execution.d.ts +6 -0
  67. package/dist/src/migrations/1790900000001-create-plugin-action-execution.js +77 -0
  68. package/dist/src/migrations/1791000000000-add-credential-public-metadata.d.ts +6 -0
  69. package/dist/src/migrations/1791000000000-add-credential-public-metadata.js +23 -0
  70. package/dist/src/plugin-host/collections/dto/domain/plugin-collection.types.d.ts +1 -0
  71. package/dist/src/plugin-host/collections/errors/plugin-collection.errors.d.ts +6 -0
  72. package/dist/src/plugin-host/collections/errors/plugin-collection.errors.js +19 -1
  73. package/dist/src/plugin-host/collections/services/plugin-collection-declaration.service.js +3 -3
  74. package/dist/src/plugin-host/collections/use-cases/put-plugin-collection-document.service.js +7 -0
  75. package/dist/src/plugin-host/constants/plugin-action-limits.d.ts +34 -0
  76. package/dist/src/plugin-host/constants/plugin-action-limits.js +51 -0
  77. package/dist/src/plugin-host/controllers/plugin-action-runtime.controller.d.ts +20 -0
  78. package/dist/src/plugin-host/controllers/plugin-action-runtime.controller.js +123 -0
  79. package/dist/src/plugin-host/controllers/plugin-credential-runtime.controller.js +11 -19
  80. package/dist/src/plugin-host/controllers/plugin-history.controller.d.ts +10 -0
  81. package/dist/src/plugin-host/controllers/plugin-history.controller.js +57 -0
  82. package/dist/src/plugin-host/controllers/plugin-release-check.controller.d.ts +10 -0
  83. package/dist/src/plugin-host/controllers/plugin-release-check.controller.js +58 -0
  84. package/dist/src/plugin-host/dto/domain/check-plugin-release.command.d.ts +22 -0
  85. package/dist/src/plugin-host/dto/domain/check-plugin-release.command.js +17 -0
  86. package/dist/src/plugin-host/dto/domain/list-plugin-history.command.d.ts +10 -0
  87. package/dist/src/plugin-host/dto/domain/list-plugin-history.command.js +18 -0
  88. package/dist/src/plugin-host/dto/domain/plugin-action-execution.command.d.ts +23 -0
  89. package/dist/src/plugin-host/dto/domain/plugin-action-execution.command.js +44 -0
  90. package/dist/src/plugin-host/dto/domain/plugin-action-execution.dto.d.ts +36 -0
  91. package/dist/src/plugin-host/dto/domain/plugin-action-execution.dto.js +3 -0
  92. package/dist/src/plugin-host/dto/domain/plugin-history.dto.d.ts +29 -0
  93. package/dist/src/plugin-host/dto/domain/plugin-history.dto.js +3 -0
  94. package/dist/src/plugin-host/dto/domain/plugin-view.dto.d.ts +1 -0
  95. package/dist/src/plugin-host/dto/presentation/plugin-action-api.dto.d.ts +44 -0
  96. package/dist/src/plugin-host/dto/presentation/plugin-action-api.dto.js +208 -0
  97. package/dist/src/plugin-host/dto/presentation/plugin-gallery-api.dto.d.ts +2 -0
  98. package/dist/src/plugin-host/dto/presentation/plugin-gallery-api.dto.js +7 -0
  99. package/dist/src/plugin-host/dto/presentation/plugin-history-api.dto.d.ts +29 -0
  100. package/dist/src/plugin-host/dto/presentation/plugin-history-api.dto.js +148 -0
  101. package/dist/src/plugin-host/dto/presentation/publication-api.dto.d.ts +17 -0
  102. package/dist/src/plugin-host/dto/presentation/publication-api.dto.js +95 -1
  103. package/dist/src/plugin-host/entities/plugin-action-execution.entity.d.ts +24 -0
  104. package/dist/src/plugin-host/entities/plugin-action-execution.entity.js +136 -0
  105. package/dist/src/plugin-host/entities/plugin-version.entity.d.ts +2 -1
  106. package/dist/src/plugin-host/entities/plugin-version.entity.js +5 -0
  107. package/dist/src/plugin-host/enums/plugin-action-execution-status.enum.d.ts +9 -0
  108. package/dist/src/plugin-host/enums/plugin-action-execution-status.enum.js +22 -0
  109. package/dist/src/plugin-host/enums/release-rejection-code.enum.d.ts +3 -0
  110. package/dist/src/plugin-host/enums/release-rejection-code.enum.js +6 -0
  111. package/dist/src/plugin-host/errors/plugin-action.errors.d.ts +45 -0
  112. package/dist/src/plugin-host/errors/plugin-action.errors.js +70 -0
  113. package/dist/src/plugin-host/errors/plugin-host.errors.d.ts +6 -0
  114. package/dist/src/plugin-host/errors/plugin-host.errors.js +10 -1
  115. package/dist/src/plugin-host/filters/plugin-host-exception.filter.js +2 -2
  116. package/dist/src/plugin-host/mappers/plugin-action-execution.mapper.d.ts +3 -0
  117. package/dist/src/plugin-host/mappers/plugin-action-execution.mapper.js +22 -0
  118. package/dist/src/plugin-host/mappers/plugin-presentation.mapper.d.ts +16 -1
  119. package/dist/src/plugin-host/mappers/plugin-presentation.mapper.js +80 -1
  120. package/dist/src/plugin-host/plugin-host.module.js +32 -0
  121. package/dist/src/plugin-host/services/action-input-validator.service.d.ts +23 -0
  122. package/dist/src/plugin-host/services/action-input-validator.service.js +277 -0
  123. package/dist/src/plugin-host/services/external-credential-definition-sync.service.d.ts +3 -0
  124. package/dist/src/plugin-host/services/external-credential-definition-sync.service.js +47 -15
  125. package/dist/src/plugin-host/services/plugin-action-dispatcher.service.d.ts +13 -0
  126. package/dist/src/plugin-host/services/plugin-action-dispatcher.service.js +140 -0
  127. package/dist/src/plugin-host/services/plugin-action-execution.service.d.ts +69 -0
  128. package/dist/src/plugin-host/services/plugin-action-execution.service.js +239 -0
  129. package/dist/src/plugin-host/services/plugin-action-starter.service.d.ts +22 -0
  130. package/dist/src/plugin-host/services/plugin-action-starter.service.js +81 -0
  131. package/dist/src/plugin-host/services/plugin-audit.service.d.ts +13 -0
  132. package/dist/src/plugin-host/services/plugin-audit.service.js +78 -0
  133. package/dist/src/plugin-host/services/plugin-publication.service.d.ts +2 -0
  134. package/dist/src/plugin-host/services/plugin-publication.service.js +18 -10
  135. package/dist/src/plugin-host/services/plugin-runtime-authorizer.service.d.ts +5 -2
  136. package/dist/src/plugin-host/services/plugin-runtime-authorizer.service.js +31 -3
  137. package/dist/src/plugin-host/services/plugin-version.service.d.ts +2 -1
  138. package/dist/src/plugin-host/services/release-candidate-rules.service.d.ts +51 -0
  139. package/dist/src/plugin-host/services/release-candidate-rules.service.js +198 -0
  140. package/dist/src/plugin-host/services/remote-url-validator.service.d.ts +7 -0
  141. package/dist/src/plugin-host/services/remote-url-validator.service.js +4 -0
  142. package/dist/src/plugin-host/system-triggers/plugin-action-execution-sweep.processor.d.ts +14 -0
  143. package/dist/src/plugin-host/system-triggers/plugin-action-execution-sweep.processor.js +50 -0
  144. package/dist/src/plugin-host/use-cases/cancel-plugin-action-execution.service.d.ts +8 -0
  145. package/dist/src/plugin-host/use-cases/cancel-plugin-action-execution.service.js +39 -0
  146. package/dist/src/plugin-host/use-cases/check-plugin-release.service.d.ts +22 -0
  147. package/dist/src/plugin-host/use-cases/check-plugin-release.service.js +152 -0
  148. package/dist/src/plugin-host/use-cases/get-current-plugin-action-execution.service.d.ts +14 -0
  149. package/dist/src/plugin-host/use-cases/get-current-plugin-action-execution.service.js +85 -0
  150. package/dist/src/plugin-host/use-cases/get-plugin-action-execution.service.d.ts +9 -0
  151. package/dist/src/plugin-host/use-cases/get-plugin-action-execution.service.js +67 -0
  152. package/dist/src/plugin-host/use-cases/get-plugin-installation-entry.service.js +2 -7
  153. package/dist/src/plugin-host/use-cases/install-plugin.service.js +4 -0
  154. package/dist/src/plugin-host/use-cases/list-plugin-history.service.d.ts +25 -0
  155. package/dist/src/plugin-host/use-cases/list-plugin-history.service.js +147 -0
  156. package/dist/src/plugin-host/use-cases/plugin-publisher-access.d.ts +5 -0
  157. package/dist/src/plugin-host/use-cases/plugin-publisher-access.js +28 -0
  158. package/dist/src/plugin-host/use-cases/start-plugin-action-execution.service.d.ts +12 -0
  159. package/dist/src/plugin-host/use-cases/start-plugin-action-execution.service.js +64 -0
  160. package/dist/src/plugin-host/use-cases/sync-plugin-releases.service.d.ts +3 -5
  161. package/dist/src/plugin-host/use-cases/sync-plugin-releases.service.js +15 -59
  162. package/dist/src/plugin-host/use-cases/uninstall-plugin.service.js +3 -1
  163. package/dist/src/plugin-host/use-cases/update-plugin.service.d.ts +0 -1
  164. package/dist/src/plugin-host/use-cases/update-plugin.service.js +3 -25
  165. package/dist/src/plugin-host/utils/action-input-schema.util.d.ts +14 -0
  166. package/dist/src/plugin-host/utils/action-input-schema.util.js +133 -0
  167. package/dist/src/plugin-host/utils/credential-handles.util.d.ts +3 -0
  168. package/dist/src/plugin-host/utils/credential-handles.util.js +13 -0
  169. package/dist/src/plugin-host/utils/execution-token.util.d.ts +5 -0
  170. package/dist/src/plugin-host/utils/execution-token.util.js +13 -0
  171. package/dist/src/plugin-host/utils/json-shape.util.d.ts +1 -0
  172. package/dist/src/plugin-host/utils/json-shape.util.js +21 -0
  173. package/dist/src/plugin-host/utils/plugin-action-outcome.util.d.ts +10 -0
  174. package/dist/src/plugin-host/utils/plugin-action-outcome.util.js +67 -0
  175. package/dist/src/plugin-host/utils/plugin-manifest.util.d.ts +121 -0
  176. package/dist/src/plugin-host/utils/plugin-manifest.util.js +111 -1
  177. package/dist/src/plugin-host/utils/request-abort-signal.util.d.ts +5 -0
  178. package/dist/src/plugin-host/utils/request-abort-signal.util.js +19 -0
  179. package/package.json +10 -8
@@ -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
+ }
@@ -0,0 +1,81 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PluginActionStarterService = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const plugin_action_limits_1 = require("../constants/plugin-action-limits");
15
+ const plugin_action_execution_status_enum_1 = require("../enums/plugin-action-execution-status.enum");
16
+ const plugin_action_errors_1 = require("../errors/plugin-action.errors");
17
+ const execution_token_util_1 = require("../utils/execution-token.util");
18
+ const json_shape_util_1 = require("../utils/json-shape.util");
19
+ const plugin_manifest_util_1 = require("../utils/plugin-manifest.util");
20
+ const action_input_validator_service_1 = require("./action-input-validator.service");
21
+ const plugin_action_dispatcher_service_1 = require("./plugin-action-dispatcher.service");
22
+ const plugin_action_execution_service_1 = require("./plugin-action-execution.service");
23
+ let PluginActionStarterService = class PluginActionStarterService {
24
+ validator;
25
+ executions;
26
+ dispatcher;
27
+ constructor(validator, executions, dispatcher) {
28
+ this.validator = validator;
29
+ this.executions = executions;
30
+ this.dispatcher = dispatcher;
31
+ }
32
+ async start(request) {
33
+ const { installation, version, action } = request;
34
+ if (!version.backend || !Object.hasOwn(version.backend.actions, action)) {
35
+ throw new plugin_action_errors_1.ActionNotDeclaredError(action);
36
+ }
37
+ const declaration = version.backend.actions[action];
38
+ const input = request.input ?? null;
39
+ const shapeProblem = (0, json_shape_util_1.findJsonShapeProblem)(input);
40
+ if (shapeProblem) {
41
+ throw new plugin_action_errors_1.ActionInputInvalidError([{ instancePath: '', message: shapeProblem }]);
42
+ }
43
+ const inputBytes = input === null ? 0 : Buffer.byteLength(JSON.stringify(input));
44
+ if (inputBytes > plugin_action_limits_1.PLUGIN_ACTION_LIMITS.maxInputBytes) {
45
+ throw new plugin_action_errors_1.ActionInputTooLargeError();
46
+ }
47
+ await this.executions.assertWithinStartLimits(installation.id, Date.now());
48
+ if (declaration.input) {
49
+ const errors = await this.validator.validate(version.id, action, declaration.input, input);
50
+ if (errors.length > 0) {
51
+ throw new plugin_action_errors_1.ActionInputInvalidError(errors);
52
+ }
53
+ }
54
+ const backendUrl = (0, plugin_manifest_util_1.resolveBackendUrl)(version.backend, version.deliveryUrl);
55
+ const { token, tokenHash } = (0, execution_token_util_1.createExecutionToken)();
56
+ const execution = await this.executions.insertRunning({
57
+ pluginId: version.pluginId,
58
+ pluginVersionId: version.id,
59
+ installationId: installation.id,
60
+ projectId: installation.projectId,
61
+ userId: installation.userId,
62
+ action,
63
+ input,
64
+ inputBytes,
65
+ role: request.role,
66
+ timeoutSeconds: declaration.timeoutSeconds,
67
+ tokenHash,
68
+ trigger: request.trigger,
69
+ });
70
+ void this.dispatcher.dispatch(execution, backendUrl, token, declaration.timeoutSeconds);
71
+ return { id: execution.id, status: plugin_action_execution_status_enum_1.PluginActionExecutionStatus.RUNNING };
72
+ }
73
+ };
74
+ exports.PluginActionStarterService = PluginActionStarterService;
75
+ exports.PluginActionStarterService = PluginActionStarterService = __decorate([
76
+ (0, common_1.Injectable)(),
77
+ __metadata("design:paramtypes", [action_input_validator_service_1.ActionInputValidatorService,
78
+ plugin_action_execution_service_1.PluginActionExecutionService,
79
+ plugin_action_dispatcher_service_1.PluginActionDispatcherService])
80
+ ], PluginActionStarterService);
81
+ //# sourceMappingURL=plugin-action-starter.service.js.map
@@ -3,6 +3,17 @@ import { OwoxEventDispatcher } from '../../common/event-dispatcher/owox-event-di
3
3
  import { PluginAuditEvent } from '../entities/plugin-audit-event.entity';
4
4
  import { PluginAuditAction } from '../enums/plugin-audit-action.enum';
5
5
  import { PluginPublicationScope } from '../enums/plugin-publication-scope.enum';
6
+ export interface PluginHistoryQuery {
7
+ readonly projectId: string;
8
+ readonly userId: string;
9
+ readonly installations: boolean;
10
+ readonly publications: boolean;
11
+ readonly changes: boolean;
12
+ readonly deploymentPluginIds: readonly string[];
13
+ readonly relevantPluginIds: readonly string[];
14
+ readonly afterId: string | null;
15
+ readonly take: number;
16
+ }
6
17
  export interface PluginAuditRecord {
7
18
  readonly pluginId: string;
8
19
  readonly action: PluginAuditAction;
@@ -19,4 +30,6 @@ export declare class PluginAuditService {
19
30
  private readonly logger;
20
31
  constructor(repository: Repository<PluginAuditEvent>, eventDispatcher: OwoxEventDispatcher);
21
32
  record(entry: PluginAuditRecord): Promise<void>;
33
+ exists(id: string): Promise<boolean>;
34
+ findHistory(query: PluginHistoryQuery): Promise<PluginAuditEvent[]>;
22
35
  }
@@ -19,7 +19,20 @@ const typeorm_1 = require("@nestjs/typeorm");
19
19
  const typeorm_2 = require("typeorm");
20
20
  const owox_event_dispatcher_1 = require("../../common/event-dispatcher/owox-event-dispatcher");
21
21
  const plugin_audit_event_entity_1 = require("../entities/plugin-audit-event.entity");
22
+ const plugin_audit_action_enum_1 = require("../enums/plugin-audit-action.enum");
23
+ const plugin_publication_scope_enum_1 = require("../enums/plugin-publication-scope.enum");
22
24
  const plugin_lifecycle_event_1 = require("../events/plugin-lifecycle.event");
25
+ const INSTALLATION_ACTIONS = [
26
+ plugin_audit_action_enum_1.PluginAuditAction.INSTALL,
27
+ plugin_audit_action_enum_1.PluginAuditAction.RESTORE,
28
+ plugin_audit_action_enum_1.PluginAuditAction.UNINSTALL,
29
+ ];
30
+ const PUBLICATION_ACTIONS = [plugin_audit_action_enum_1.PluginAuditAction.PUBLISH, plugin_audit_action_enum_1.PluginAuditAction.UNPUBLISH];
31
+ const CHANGE_ACTIONS = [
32
+ plugin_audit_action_enum_1.PluginAuditAction.UPDATE,
33
+ plugin_audit_action_enum_1.PluginAuditAction.SUSPEND,
34
+ plugin_audit_action_enum_1.PluginAuditAction.RESUME,
35
+ ];
23
36
  let PluginAuditService = PluginAuditService_1 = class PluginAuditService {
24
37
  repository;
25
38
  eventDispatcher;
@@ -53,6 +66,71 @@ let PluginAuditService = PluginAuditService_1 = class PluginAuditService {
53
66
  this.logger.warn(`Audit event for plugin ${entry.pluginId} was not published: ${error instanceof Error ? error.message : String(error)}`);
54
67
  }
55
68
  }
69
+ exists(id) {
70
+ return this.repository.existsBy({ id });
71
+ }
72
+ findHistory(query) {
73
+ const builder = this.repository
74
+ .createQueryBuilder('event')
75
+ .where(new typeorm_2.Brackets(visible => {
76
+ if (query.installations) {
77
+ visible.orWhere(new typeorm_2.Brackets(own => own
78
+ .where('event.action IN (:...installationActions)', {
79
+ installationActions: INSTALLATION_ACTIONS,
80
+ })
81
+ .andWhere('event.projectId = :projectId')
82
+ .andWhere('event.userId = :userId')));
83
+ }
84
+ if (query.publications) {
85
+ visible.orWhere(new typeorm_2.Brackets(project => project
86
+ .where('event.action IN (:...publicationActions)')
87
+ .andWhere('event.authorityScope = :projectScope', {
88
+ projectScope: plugin_publication_scope_enum_1.PluginPublicationScope.PROJECT,
89
+ })
90
+ .andWhere('event.projectId = :projectId')));
91
+ visible.orWhere(new typeorm_2.Brackets(member => member
92
+ .where('event.action IN (:...publicationActions)')
93
+ .andWhere('event.authorityScope = :memberScope', {
94
+ memberScope: plugin_publication_scope_enum_1.PluginPublicationScope.MEMBER,
95
+ })
96
+ .andWhere('event.projectId = :projectId')
97
+ .andWhere('event.userId = :userId')));
98
+ if (query.deploymentPluginIds.length > 0) {
99
+ visible.orWhere(new typeorm_2.Brackets(deployment => deployment
100
+ .where('event.action IN (:...publicationActions)')
101
+ .andWhere('event.authorityScope = :deploymentScope', {
102
+ deploymentScope: plugin_publication_scope_enum_1.PluginPublicationScope.DEPLOYMENT,
103
+ })
104
+ .andWhere('event.pluginId IN (:...deploymentPluginIds)', {
105
+ deploymentPluginIds: query.deploymentPluginIds,
106
+ })));
107
+ }
108
+ }
109
+ if (query.changes && query.relevantPluginIds.length > 0) {
110
+ visible.orWhere(new typeorm_2.Brackets(change => change
111
+ .where('event.action IN (:...changeActions)', { changeActions: CHANGE_ACTIONS })
112
+ .andWhere('event.pluginId IN (:...relevantPluginIds)', {
113
+ relevantPluginIds: query.relevantPluginIds,
114
+ })));
115
+ }
116
+ }))
117
+ .setParameters({
118
+ projectId: query.projectId,
119
+ userId: query.userId,
120
+ publicationActions: PUBLICATION_ACTIONS,
121
+ });
122
+ if (query.afterId) {
123
+ const anchor = '(SELECT anchor.createdAt FROM plugin_audit_event anchor WHERE anchor.id = :afterId)';
124
+ builder.andWhere(new typeorm_2.Brackets(after => after
125
+ .where(`event.createdAt < ${anchor}`)
126
+ .orWhere(new typeorm_2.Brackets(tie => tie.where(`event.createdAt = ${anchor}`).andWhere('event.id < :afterId')))), { afterId: query.afterId });
127
+ }
128
+ return builder
129
+ .orderBy('event.createdAt', 'DESC')
130
+ .addOrderBy('event.id', 'DESC')
131
+ .limit(query.take)
132
+ .getMany();
133
+ }
56
134
  };
57
135
  exports.PluginAuditService = PluginAuditService;
58
136
  exports.PluginAuditService = PluginAuditService = PluginAuditService_1 = __decorate([