@solidactions/sdk 0.1.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 (167) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.clavix/outputs/dbos-http-sdk/full-prd.md +142 -0
  3. package/.clavix/outputs/dbos-http-sdk/quick-prd.md +12 -0
  4. package/.clavix/outputs/dbos-http-sdk/tasks.md +630 -0
  5. package/.clavix/outputs/prompts/dbos-http-api-20260110-033219.md +91 -0
  6. package/.husky/pre-commit +1 -0
  7. package/.prettierignore +3 -0
  8. package/.prettierrc +9 -0
  9. package/CODE_OF_CONDUCT.md +49 -0
  10. package/CONTRIBUTING.md +47 -0
  11. package/LICENSE +21 -0
  12. package/README.md +172 -0
  13. package/dist/dbos-config.schema.json +132 -0
  14. package/dist/schemas/system_db_schema.d.ts +73 -0
  15. package/dist/schemas/system_db_schema.d.ts.map +1 -0
  16. package/dist/schemas/system_db_schema.js +3 -0
  17. package/dist/schemas/system_db_schema.js.map +1 -0
  18. package/dist/src/adminserver.d.ts +79 -0
  19. package/dist/src/adminserver.d.ts.map +1 -0
  20. package/dist/src/adminserver.js +495 -0
  21. package/dist/src/adminserver.js.map +1 -0
  22. package/dist/src/authdecorators.d.ts +2 -0
  23. package/dist/src/authdecorators.d.ts.map +1 -0
  24. package/dist/src/authdecorators.js +48 -0
  25. package/dist/src/authdecorators.js.map +1 -0
  26. package/dist/src/cli/cli.d.ts +9 -0
  27. package/dist/src/cli/cli.d.ts.map +1 -0
  28. package/dist/src/cli/cli.js +116 -0
  29. package/dist/src/cli/cli.js.map +1 -0
  30. package/dist/src/cli/commands.d.ts +3 -0
  31. package/dist/src/cli/commands.d.ts.map +1 -0
  32. package/dist/src/cli/commands.js +46 -0
  33. package/dist/src/cli/commands.js.map +1 -0
  34. package/dist/src/client.d.ts +85 -0
  35. package/dist/src/client.d.ts.map +1 -0
  36. package/dist/src/client.js +186 -0
  37. package/dist/src/client.js.map +1 -0
  38. package/dist/src/conductor/conductor.d.ts +28 -0
  39. package/dist/src/conductor/conductor.d.ts.map +1 -0
  40. package/dist/src/conductor/conductor.js +376 -0
  41. package/dist/src/conductor/conductor.js.map +1 -0
  42. package/dist/src/conductor/protocol.d.ts +238 -0
  43. package/dist/src/conductor/protocol.d.ts.map +1 -0
  44. package/dist/src/conductor/protocol.js +353 -0
  45. package/dist/src/conductor/protocol.js.map +1 -0
  46. package/dist/src/config.d.ts +91 -0
  47. package/dist/src/config.d.ts.map +1 -0
  48. package/dist/src/config.js +199 -0
  49. package/dist/src/config.js.map +1 -0
  50. package/dist/src/context.d.ts +62 -0
  51. package/dist/src/context.d.ts.map +1 -0
  52. package/dist/src/context.js +118 -0
  53. package/dist/src/context.js.map +1 -0
  54. package/dist/src/database_utils.d.ts +17 -0
  55. package/dist/src/database_utils.d.ts.map +1 -0
  56. package/dist/src/database_utils.js +53 -0
  57. package/dist/src/database_utils.js.map +1 -0
  58. package/dist/src/datasource.d.ts +109 -0
  59. package/dist/src/datasource.d.ts.map +1 -0
  60. package/dist/src/datasource.js +204 -0
  61. package/dist/src/datasource.js.map +1 -0
  62. package/dist/src/dbos-executor.d.ts +189 -0
  63. package/dist/src/dbos-executor.d.ts.map +1 -0
  64. package/dist/src/dbos-executor.js +817 -0
  65. package/dist/src/dbos-executor.js.map +1 -0
  66. package/dist/src/dbos.d.ts +519 -0
  67. package/dist/src/dbos.d.ts.map +1 -0
  68. package/dist/src/dbos.js +1282 -0
  69. package/dist/src/dbos.js.map +1 -0
  70. package/dist/src/debouncer.d.ts +33 -0
  71. package/dist/src/debouncer.d.ts.map +1 -0
  72. package/dist/src/debouncer.js +170 -0
  73. package/dist/src/debouncer.js.map +1 -0
  74. package/dist/src/debugpoint.d.ts +26 -0
  75. package/dist/src/debugpoint.d.ts.map +1 -0
  76. package/dist/src/debugpoint.js +65 -0
  77. package/dist/src/debugpoint.js.map +1 -0
  78. package/dist/src/decorators.d.ts +219 -0
  79. package/dist/src/decorators.d.ts.map +1 -0
  80. package/dist/src/decorators.js +873 -0
  81. package/dist/src/decorators.js.map +1 -0
  82. package/dist/src/error.d.ts +130 -0
  83. package/dist/src/error.d.ts.map +1 -0
  84. package/dist/src/error.js +290 -0
  85. package/dist/src/error.js.map +1 -0
  86. package/dist/src/http_client.d.ts +82 -0
  87. package/dist/src/http_client.d.ts.map +1 -0
  88. package/dist/src/http_client.js +286 -0
  89. package/dist/src/http_client.js.map +1 -0
  90. package/dist/src/http_system_database.d.ts +84 -0
  91. package/dist/src/http_system_database.d.ts.map +1 -0
  92. package/dist/src/http_system_database.js +429 -0
  93. package/dist/src/http_system_database.js.map +1 -0
  94. package/dist/src/index.d.ts +14 -0
  95. package/dist/src/index.d.ts.map +1 -0
  96. package/dist/src/index.js +53 -0
  97. package/dist/src/index.js.map +1 -0
  98. package/dist/src/scheduler/crontab.d.ts +14 -0
  99. package/dist/src/scheduler/crontab.d.ts.map +1 -0
  100. package/dist/src/scheduler/crontab.js +308 -0
  101. package/dist/src/scheduler/crontab.js.map +1 -0
  102. package/dist/src/scheduler/scheduler.d.ts +41 -0
  103. package/dist/src/scheduler/scheduler.d.ts.map +1 -0
  104. package/dist/src/scheduler/scheduler.js +165 -0
  105. package/dist/src/scheduler/scheduler.js.map +1 -0
  106. package/dist/src/serialization.d.ts +57 -0
  107. package/dist/src/serialization.d.ts.map +1 -0
  108. package/dist/src/serialization.js +306 -0
  109. package/dist/src/serialization.js.map +1 -0
  110. package/dist/src/solidactions-executor.d.ts +177 -0
  111. package/dist/src/solidactions-executor.d.ts.map +1 -0
  112. package/dist/src/solidactions-executor.js +817 -0
  113. package/dist/src/solidactions-executor.js.map +1 -0
  114. package/dist/src/solidactions.d.ts +519 -0
  115. package/dist/src/solidactions.d.ts.map +1 -0
  116. package/dist/src/solidactions.js +1284 -0
  117. package/dist/src/solidactions.js.map +1 -0
  118. package/dist/src/step.d.ts +16 -0
  119. package/dist/src/step.d.ts.map +1 -0
  120. package/dist/src/step.js +3 -0
  121. package/dist/src/step.js.map +1 -0
  122. package/dist/src/system_database.d.ts +141 -0
  123. package/dist/src/system_database.d.ts.map +1 -0
  124. package/dist/src/system_database.js +25 -0
  125. package/dist/src/system_database.js.map +1 -0
  126. package/dist/src/telemetry/collector.d.ts +13 -0
  127. package/dist/src/telemetry/collector.d.ts.map +1 -0
  128. package/dist/src/telemetry/collector.js +63 -0
  129. package/dist/src/telemetry/collector.js.map +1 -0
  130. package/dist/src/telemetry/exporters.d.ts +13 -0
  131. package/dist/src/telemetry/exporters.d.ts.map +1 -0
  132. package/dist/src/telemetry/exporters.js +101 -0
  133. package/dist/src/telemetry/exporters.js.map +1 -0
  134. package/dist/src/telemetry/logs.d.ts +52 -0
  135. package/dist/src/telemetry/logs.d.ts.map +1 -0
  136. package/dist/src/telemetry/logs.js +287 -0
  137. package/dist/src/telemetry/logs.js.map +1 -0
  138. package/dist/src/telemetry/traces.d.ts +52 -0
  139. package/dist/src/telemetry/traces.d.ts.map +1 -0
  140. package/dist/src/telemetry/traces.js +150 -0
  141. package/dist/src/telemetry/traces.js.map +1 -0
  142. package/dist/src/utils.d.ts +26 -0
  143. package/dist/src/utils.d.ts.map +1 -0
  144. package/dist/src/utils.js +136 -0
  145. package/dist/src/utils.js.map +1 -0
  146. package/dist/src/wfqueue.d.ts +64 -0
  147. package/dist/src/wfqueue.d.ts.map +1 -0
  148. package/dist/src/wfqueue.js +147 -0
  149. package/dist/src/wfqueue.js.map +1 -0
  150. package/dist/src/workflow.d.ts +154 -0
  151. package/dist/src/workflow.d.ts.map +1 -0
  152. package/dist/src/workflow.js +99 -0
  153. package/dist/src/workflow.js.map +1 -0
  154. package/dist/src/workflow_management.d.ts +15 -0
  155. package/dist/src/workflow_management.d.ts.map +1 -0
  156. package/dist/src/workflow_management.js +87 -0
  157. package/dist/src/workflow_management.js.map +1 -0
  158. package/dist/tsconfig.tsbuildinfo +1 -0
  159. package/docs/api-schema.md +1441 -0
  160. package/docs/migration-guide.md +460 -0
  161. package/docs/phase-14-changes.md +156 -0
  162. package/docs/solidsteps-ai-prompt.md +534 -0
  163. package/eslint.config.cjs +50 -0
  164. package/package.json +84 -0
  165. package/solidactions-ai-prompt.md +1504 -0
  166. package/solidactions-config.schema.json +132 -0
  167. package/solidactions-test-config.yaml +15 -0
@@ -0,0 +1,1284 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SolidActions = exports.runInternalStep = exports.getExecutor = void 0;
7
+ const context_1 = require("./context");
8
+ const solidactions_executor_1 = require("./solidactions-executor");
9
+ const traces_1 = require("./telemetry/traces");
10
+ const workflow_1 = require("./workflow");
11
+ const logs_1 = require("./telemetry/logs");
12
+ const error_1 = require("./error");
13
+ const config_1 = require("./config");
14
+ const decorators_1 = require("./decorators");
15
+ const utils_1 = require("./utils");
16
+ const serialization_1 = require("./serialization");
17
+ const adminserver_1 = require("./adminserver");
18
+ const node_crypto_1 = require("node:crypto");
19
+ const conductor_1 = require("./conductor/conductor");
20
+ const system_database_1 = require("./system_database");
21
+ const authdecorators_1 = require("./authdecorators");
22
+ const node_assert_1 = __importDefault(require("node:assert"));
23
+ function getExecutor() {
24
+ if (!solidactions_executor_1.SolidActionsExecutor.globalInstance) {
25
+ throw new error_1.SolidActionsExecutorNotInitializedError();
26
+ }
27
+ return solidactions_executor_1.SolidActionsExecutor.globalInstance;
28
+ }
29
+ exports.getExecutor = getExecutor;
30
+ function runInternalStep(callback, funcName, childWFID, assignedFuncID) {
31
+ if (SolidActions.isWithinWorkflow()) {
32
+ if (SolidActions.isInStep()) {
33
+ // OK to use directly
34
+ return callback();
35
+ }
36
+ else if (SolidActions.isInWorkflow()) {
37
+ return solidactions_executor_1.SolidActionsExecutor.globalInstance.runInternalStep(callback, funcName, SolidActions.workflowID, assignedFuncID ?? (0, context_1.functionIDGetIncrement)(), childWFID);
38
+ }
39
+ else {
40
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError(`Invalid call to \`${funcName}\` inside a \`transaction\` or \`procedure\``);
41
+ }
42
+ }
43
+ return callback();
44
+ }
45
+ exports.runInternalStep = runInternalStep;
46
+ class SolidActions {
47
+ ///////
48
+ // Lifecycle
49
+ ///////
50
+ static adminServer = undefined;
51
+ static conductor = undefined;
52
+ /**
53
+ * Set configuration of `SolidActions` prior to `launch`
54
+ * @param config - configuration of services needed by SolidActions
55
+ */
56
+ static setConfig(config) {
57
+ (0, node_assert_1.default)(!SolidActions.isInitialized(), 'Cannot call SolidActions.setConfig after SolidActions.launch');
58
+ SolidActions.#solidActionsConfig = config;
59
+ }
60
+ /**
61
+ * Check if SolidActions has been `launch`ed (and not `shutdown`)
62
+ * @returns `true` if SolidActions has been launched, or `false` otherwise
63
+ */
64
+ static isInitialized() {
65
+ return !!solidactions_executor_1.SolidActionsExecutor.globalInstance?.initialized;
66
+ }
67
+ /**
68
+ * Launch SolidActions, starting recovery and request handling
69
+ * @param options - Launch options for connecting to SolidActions Conductor
70
+ */
71
+ static async launch(options) {
72
+ const debugMode = options?.debugMode ?? process.env.SOLIDACTIONS_DEBUG_WORKFLOW_ID !== undefined;
73
+ const configFile = await (0, config_1.readConfigFile)();
74
+ // If no setConfig() was called, try to auto-configure from solidsteps.yaml + env vars
75
+ if (!SolidActions.#solidActionsConfig) {
76
+ const solidStepsConfig = await (0, config_1.readSolidStepsConfig)();
77
+ if (solidStepsConfig.project || process.env.SOLIDACTIONS_API_URL) {
78
+ // Auto-configure: use project name from solidsteps.yaml, API config from env vars
79
+ try {
80
+ const httpConfig = (0, config_1.getHttpConfig)(configFile);
81
+ SolidActions.#solidActionsConfig = {
82
+ name: solidStepsConfig.project || configFile.name,
83
+ api: {
84
+ url: httpConfig.apiUrl,
85
+ key: httpConfig.apiKey,
86
+ timeout: httpConfig.timeout,
87
+ maxRetries: httpConfig.maxRetries,
88
+ },
89
+ };
90
+ }
91
+ catch {
92
+ // If we can't get HTTP config, fall back to normal config file handling
93
+ }
94
+ }
95
+ }
96
+ let internalConfig = SolidActions.#solidActionsConfig
97
+ ? (0, config_1.translateSolidActionsConfig)(SolidActions.#solidActionsConfig, debugMode)
98
+ : (0, config_1.getSolidActionsConfig)(configFile);
99
+ let runtimeConfig = SolidActions.#solidActionsConfig
100
+ ? (0, config_1.translateRuntimeConfig)(SolidActions.#solidActionsConfig)
101
+ : (0, config_1.getRuntimeConfig)(configFile);
102
+ if (process.env.SOLIDACTIONS__CLOUD === 'true' || process.env.SOLIDACTIONS__CLOUD === 'true') {
103
+ [internalConfig, runtimeConfig] = (0, config_1.overwriteConfigForCloud)(internalConfig, runtimeConfig, configFile);
104
+ }
105
+ utils_1.globalParams.enableOTLP = SolidActions.#solidActionsConfig?.enableOTLP ?? (0, utils_1.defaultEnableOTLP)();
106
+ if (!(0, traces_1.isTraceContextWorking)())
107
+ (0, traces_1.installTraceContextManager)(internalConfig.name);
108
+ // Do nothing if SolidActions is already initialized
109
+ if (SolidActions.isInitialized()) {
110
+ return;
111
+ }
112
+ (0, decorators_1.finalizeClassRegistrations)();
113
+ (0, decorators_1.insertAllMiddleware)();
114
+ // Globally set the application version and executor ID.
115
+ // In SolidActions Cloud, instead use the value supplied through environment variables.
116
+ if (process.env.SOLIDACTIONS__CLOUD !== 'true') {
117
+ if (SolidActions.#solidActionsConfig?.applicationVersion) {
118
+ utils_1.globalParams.appVersion = SolidActions.#solidActionsConfig.applicationVersion;
119
+ }
120
+ else if (SolidActions.#solidActionsConfig?.enablePatching) {
121
+ utils_1.globalParams.appVersion = 'PATCHING_ENABLED';
122
+ }
123
+ if (SolidActions.#solidActionsConfig?.executorID) {
124
+ utils_1.globalParams.executorID = SolidActions.#solidActionsConfig.executorID;
125
+ }
126
+ }
127
+ if (options?.conductorKey) {
128
+ // Always use a generated executor ID in Conductor.
129
+ utils_1.globalParams.executorID = (0, node_crypto_1.randomUUID)();
130
+ }
131
+ solidactions_executor_1.SolidActionsExecutor.globalInstance = new solidactions_executor_1.SolidActionsExecutor(internalConfig, { debugMode });
132
+ (0, decorators_1.recordSolidActionsLaunch)();
133
+ const executor = solidactions_executor_1.SolidActionsExecutor.globalInstance;
134
+ await executor.init();
135
+ const debugWorkflowId = process.env.SOLIDACTIONS_DEBUG_WORKFLOW_ID;
136
+ if (debugWorkflowId) {
137
+ SolidActions.logger.info(`Debugging workflow "${debugWorkflowId}"`);
138
+ const handle = await executor.executeWorkflowId(debugWorkflowId);
139
+ await handle.getResult();
140
+ SolidActions.logger.info(`Workflow Debugging complete. Exiting process.`);
141
+ await executor.destroy();
142
+ process.exit(0);
143
+ return; // return for cases where process.exit is mocked
144
+ }
145
+ await solidactions_executor_1.SolidActionsExecutor.globalInstance.initEventReceivers();
146
+ if (options?.conductorKey) {
147
+ if (!options.conductorURL) {
148
+ const solidActionsDomain = process.env.SOLIDACTIONS_DOMAIN || 'cloud.dbos.dev';
149
+ options.conductorURL = `wss://${solidActionsDomain}/conductor/v1alpha1`;
150
+ }
151
+ SolidActions.conductor = new conductor_1.Conductor(solidactions_executor_1.SolidActionsExecutor.globalInstance, options.conductorKey, options.conductorURL);
152
+ SolidActions.conductor.dispatchLoop();
153
+ }
154
+ // Start the SolidActions admin server
155
+ const logger = SolidActions.logger;
156
+ if (runtimeConfig.runAdminServer) {
157
+ const adminApp = adminserver_1.SolidActionsAdminServer.setupAdminApp(executor);
158
+ try {
159
+ await adminserver_1.SolidActionsAdminServer.checkPortAvailabilityIPv4Ipv6(runtimeConfig.admin_port, logger);
160
+ // Wrap the listen call in a promise to properly catch errors
161
+ SolidActions.adminServer = await new Promise((resolve, reject) => {
162
+ const server = adminApp.listen(runtimeConfig?.admin_port, () => {
163
+ SolidActions.logger.debug(`SolidActions Admin Server is running at http://localhost:${runtimeConfig?.admin_port}`);
164
+ resolve(server);
165
+ });
166
+ server.on('error', (err) => {
167
+ reject(err);
168
+ });
169
+ });
170
+ }
171
+ catch (e) {
172
+ logger.warn(`Unable to start SolidActions admin server on port ${runtimeConfig.admin_port}`);
173
+ }
174
+ }
175
+ }
176
+ /**
177
+ * Logs all workflows that can be invoked externally.
178
+ */
179
+ static logRegisteredEndpoints() {
180
+ if (!solidactions_executor_1.SolidActionsExecutor.globalInstance)
181
+ return;
182
+ for (const lcl of (0, decorators_1.getLifecycleListeners)()) {
183
+ lcl.logRegisteredEndpoints?.();
184
+ }
185
+ }
186
+ /**
187
+ * Shut down SolidActions processing:
188
+ * Stops receiving external workflow requests
189
+ * Disconnects from administration / Conductor
190
+ * Stops workflow processing and disconnects from databases
191
+ */
192
+ static async shutdown() {
193
+ // Stop the admin server
194
+ if (SolidActions.adminServer) {
195
+ SolidActions.adminServer.close();
196
+ SolidActions.adminServer = undefined;
197
+ }
198
+ // Stop the conductor
199
+ if (SolidActions.conductor) {
200
+ SolidActions.conductor.stop();
201
+ while (!SolidActions.conductor.isClosed) {
202
+ await (0, utils_1.sleepms)(500);
203
+ }
204
+ SolidActions.conductor = undefined;
205
+ }
206
+ // Stop the executor
207
+ if (solidactions_executor_1.SolidActionsExecutor.globalInstance) {
208
+ await solidactions_executor_1.SolidActionsExecutor.globalInstance.deactivateEventReceivers();
209
+ await solidactions_executor_1.SolidActionsExecutor.globalInstance.destroy();
210
+ solidactions_executor_1.SolidActionsExecutor.globalInstance = undefined;
211
+ }
212
+ // Reset the global app version and executor ID
213
+ utils_1.globalParams.appVersion = process.env.SOLIDACTIONS__APPVERSION || '';
214
+ utils_1.globalParams.wasComputed = false;
215
+ utils_1.globalParams.appID = process.env.SOLIDACTIONS__APPID || '';
216
+ utils_1.globalParams.executorID = process.env.SOLIDACTIONS__VMID || 'local';
217
+ (0, decorators_1.recordSolidActionsShutdown)();
218
+ }
219
+ //////
220
+ // Convenience APIs for SolidSteps workflows
221
+ //////
222
+ /**
223
+ * Get the workflow input from WORKFLOW_INPUT environment variable.
224
+ * This is set by the SolidSteps runner from the webhook payload.
225
+ * @returns Parsed input or empty object if not set
226
+ */
227
+ static getInput() {
228
+ const raw = process.env.WORKFLOW_INPUT;
229
+ if (!raw) {
230
+ return {};
231
+ }
232
+ try {
233
+ return JSON.parse(raw);
234
+ }
235
+ catch {
236
+ return {};
237
+ }
238
+ }
239
+ /**
240
+ * Run a workflow with minimal boilerplate.
241
+ * Handles launch(), startWorkflow(), getResult(), and shutdown().
242
+ *
243
+ * @param workflow - The workflow function to run
244
+ * @param options - Optional settings for input and workflow ID
245
+ * @returns Promise that resolves when workflow completes (or rejects on error)
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * async function myWorkflow(input: MyInput): Promise<MyOutput> {
250
+ * // workflow logic
251
+ * }
252
+ *
253
+ * const wf = SolidActions.registerWorkflow(myWorkflow, { name: 'my-workflow' });
254
+ * await SolidActions.run(wf);
255
+ * ```
256
+ */
257
+ static async run(workflow, options) {
258
+ try {
259
+ await SolidActions.launch();
260
+ const input = options?.input ?? SolidActions.getInput();
261
+ const handle = await SolidActions.startWorkflow(workflow, {
262
+ workflowID: options?.workflowID,
263
+ })(input);
264
+ await handle.getResult();
265
+ await SolidActions.shutdown();
266
+ process.exit(0);
267
+ }
268
+ catch (error) {
269
+ console.error('Workflow failed:', error);
270
+ try {
271
+ await SolidActions.shutdown();
272
+ }
273
+ catch {
274
+ // Ignore shutdown errors
275
+ }
276
+ process.exit(1);
277
+ }
278
+ }
279
+ /**
280
+ * Interface for signal URLs returned by getSignalUrls()
281
+ */
282
+ static getSignalUrls(topic) {
283
+ const baseApiUrl = process.env.SOLIDACTIONS_API_URL?.replace('/api/internal', '') ||
284
+ process.env.SOLIDACTIONS_API_URL?.replace('/api/internal', '') ||
285
+ process.env.APP_URL ||
286
+ 'http://localhost:8000';
287
+ const workflowId = SolidActions.workflowID;
288
+ if (!workflowId) {
289
+ throw new error_1.SolidActionsError('getSignalUrls() must be called from within a workflow');
290
+ }
291
+ const topicParam = topic ? `&topic=${encodeURIComponent(topic)}` : '';
292
+ const base = `${baseApiUrl}/api/signal/${workflowId}`;
293
+ return {
294
+ base,
295
+ approve: `${base}?choice=approve${topicParam}`,
296
+ reject: `${base}?choice=reject${topicParam}`,
297
+ custom: (action) => `${base}?choice=${encodeURIComponent(action)}${topicParam}`,
298
+ };
299
+ }
300
+ /** Stop listening for external events (for testing) */
301
+ static async deactivateEventReceivers() {
302
+ return solidactions_executor_1.SolidActionsExecutor.globalInstance?.deactivateEventReceivers();
303
+ }
304
+ /** Start listening for external events (for testing) */
305
+ static async initEventReceivers() {
306
+ return solidactions_executor_1.SolidActionsExecutor.globalInstance?.initEventReceivers();
307
+ }
308
+ // Global SolidActions executor instance
309
+ static get #executor() {
310
+ return getExecutor();
311
+ }
312
+ //////
313
+ // Globals
314
+ //////
315
+ static #solidActionsConfig;
316
+ //////
317
+ // Context
318
+ //////
319
+ /** Get the current SolidActions Logger, appropriate to the current context */
320
+ static get logger() {
321
+ const lctx = (0, context_1.getCurrentContextStore)();
322
+ if (lctx?.logger)
323
+ return lctx.logger;
324
+ const executor = solidactions_executor_1.SolidActionsExecutor.globalInstance;
325
+ if (executor)
326
+ return executor.logger;
327
+ return new logs_1.GlobalLogger();
328
+ }
329
+ /** Get the current SolidActions Tracer, for starting spans */
330
+ static get tracer() {
331
+ const executor = solidactions_executor_1.SolidActionsExecutor.globalInstance;
332
+ if (executor)
333
+ return executor.tracer;
334
+ }
335
+ /** Get the current SolidActions tracing span, appropriate to the current context */
336
+ static get span() {
337
+ return (0, traces_1.getActiveSpan)();
338
+ }
339
+ /**
340
+ * Get the current request object (such as an HTTP request)
341
+ * This is intended for use in event libraries that know the type of the current request,
342
+ * and set it using `withTracedContext` or `runWithContext`
343
+ */
344
+ static requestObject() {
345
+ return (0, context_1.getCurrentContextStore)()?.request;
346
+ }
347
+ /** Get the current HTTP request (within `@SolidActions.getApi` et al) */
348
+ static getRequest() {
349
+ return this.requestObject();
350
+ }
351
+ /** Get the current HTTP request (within `@SolidActions.getApi` et al) */
352
+ static get request() {
353
+ const r = SolidActions.getRequest();
354
+ if (!r)
355
+ throw new error_1.SolidActionsError('`SolidActions.request` accessed from outside of HTTP requests');
356
+ return r;
357
+ }
358
+ /** Get the current application version */
359
+ static get applicationVersion() {
360
+ return utils_1.globalParams.appVersion;
361
+ }
362
+ /** Get the current workflow ID */
363
+ static get workflowID() {
364
+ return (0, context_1.getCurrentContextStore)()?.workflowId;
365
+ }
366
+ /**
367
+ * Get the current run ID (alias for workflowID).
368
+ * This is the unique identifier assigned by SolidSteps at trigger time.
369
+ */
370
+ static get runID() {
371
+ return SolidActions.workflowID;
372
+ }
373
+ /** Get the current step number, within the current workflow */
374
+ static get stepID() {
375
+ if (SolidActions.isInStep()) {
376
+ return (0, context_1.getCurrentContextStore)()?.curStepFunctionId;
377
+ }
378
+ else if (SolidActions.isInTransaction()) {
379
+ return (0, context_1.getCurrentContextStore)()?.curTxFunctionId;
380
+ }
381
+ else {
382
+ return undefined;
383
+ }
384
+ }
385
+ static get stepStatus() {
386
+ return (0, context_1.getCurrentContextStore)()?.stepStatus;
387
+ }
388
+ /** Get the current authenticated user */
389
+ static get authenticatedUser() {
390
+ return (0, context_1.getCurrentContextStore)()?.authenticatedUser ?? '';
391
+ }
392
+ /** Get the roles granted to the current authenticated user */
393
+ static get authenticatedRoles() {
394
+ return (0, context_1.getCurrentContextStore)()?.authenticatedRoles ?? [];
395
+ }
396
+ /** Get the role assumed by the current user giving authorization to execute the current function */
397
+ static get assumedRole() {
398
+ return (0, context_1.getCurrentContextStore)()?.assumedRole ?? '';
399
+ }
400
+ /** @returns true if called from within a transaction, false otherwise */
401
+ static isInTransaction() {
402
+ return (0, context_1.getCurrentContextStore)()?.curTxFunctionId !== undefined;
403
+ }
404
+ /** @returns true if called from within a step, false otherwise */
405
+ static isInStep() {
406
+ return (0, context_1.getCurrentContextStore)()?.curStepFunctionId !== undefined;
407
+ }
408
+ /**
409
+ * @returns true if called from within a workflow
410
+ * (regardless of whether the workflow is currently executing a step,
411
+ * transaction, or procedure), false otherwise
412
+ */
413
+ static isWithinWorkflow() {
414
+ return (0, context_1.getCurrentContextStore)()?.workflowId !== undefined;
415
+ }
416
+ /**
417
+ * @returns true if called from within a workflow that is not currently executing
418
+ * a step, transaction, or procedure, or false otherwise
419
+ */
420
+ static isInWorkflow() {
421
+ return SolidActions.isWithinWorkflow() && !SolidActions.isInTransaction() && !SolidActions.isInStep();
422
+ }
423
+ //////
424
+ // Access to system DB, for event receivers etc.
425
+ //////
426
+ /**
427
+ * Get a state item from the system database, which provides a key/value store interface for event dispatchers.
428
+ * The full key for the database state should include the service, function, and item.
429
+ * Values are versioned. A version can either be a sequence number (long integer), or a time (high precision floating point).
430
+ * If versions are in use, any upsert is discarded if the version field is less than what is already stored.
431
+ *
432
+ * Examples of state that could be kept:
433
+ * Offsets into kafka topics, per topic partition
434
+ * Last time for which a scheduling service completed schedule dispatch
435
+ *
436
+ * @param service - should be unique to the event receiver keeping state, to separate from others
437
+ * @param workflowFnName - function name; should be the fully qualified / unique function name dispatched
438
+ * @param key - The subitem kept by event receiver service for the function, allowing multiple values to be stored per function
439
+ * @returns The latest system database state for the specified service+workflow+item
440
+ */
441
+ static async getEventDispatchState(svc, wfn, key) {
442
+ (0, decorators_1.ensureSolidActionsIsLaunched)('getEventDispatchState');
443
+ return await SolidActions.#executor.getEventDispatchState(svc, wfn, key);
444
+ }
445
+ /**
446
+ * Set a state item into the system database, which provides a key/value store interface for event dispatchers.
447
+ * The full key for the database state should include the service, function, and item; these fields are part of `state`.
448
+ * Values are versioned. A version can either be a sequence number (long integer), or a time (high precision floating point).
449
+ * If versions are in use, any upsert is discarded if the version field is less than what is already stored.
450
+ *
451
+ * @param state - the service, workflow, item, version, and value to write to the database
452
+ * @returns The upsert returns the current record, which may be useful if it is more recent than the `state` provided.
453
+ */
454
+ static async upsertEventDispatchState(state) {
455
+ (0, decorators_1.ensureSolidActionsIsLaunched)('upsertEventDispatchState');
456
+ return await SolidActions.#executor.upsertEventDispatchState(state);
457
+ }
458
+ //////
459
+ // Workflow and other operations
460
+ //////
461
+ /**
462
+ * Get the workflow status given a workflow ID
463
+ * @param workflowID - ID of the workflow
464
+ * @returns status of the workflow as `WorkflowStatus`, or `null` if there is no workflow with `workflowID`
465
+ */
466
+ static getWorkflowStatus(workflowID) {
467
+ (0, decorators_1.ensureSolidActionsIsLaunched)('getWorkflowStatus');
468
+ if (SolidActions.isWithinWorkflow()) {
469
+ if (SolidActions.isInStep()) {
470
+ // OK to use directly
471
+ return SolidActions.#executor.getWorkflowStatus(workflowID);
472
+ }
473
+ else if (SolidActions.isInWorkflow()) {
474
+ return SolidActions.#executor.getWorkflowStatus(workflowID, SolidActions.workflowID, (0, context_1.functionIDGetIncrement)());
475
+ }
476
+ else {
477
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `getWorkflowStatus` inside a `transaction` or `procedure`');
478
+ }
479
+ }
480
+ return SolidActions.#executor.getWorkflowStatus(workflowID);
481
+ }
482
+ /**
483
+ * Get the workflow result, given a workflow ID
484
+ * @param workflowID - ID of the workflow
485
+ * @param timeoutSeconds - Maximum time to wait for result
486
+ * @returns The return value of the workflow, or throws the exception thrown by the workflow, or `null` if times out
487
+ */
488
+ static async getResult(workflowID, timeoutSeconds) {
489
+ (0, decorators_1.ensureSolidActionsIsLaunched)('getResult');
490
+ let timerFuncID = undefined;
491
+ if (SolidActions.isWithinWorkflow() && timeoutSeconds !== undefined) {
492
+ timerFuncID = (0, context_1.functionIDGetIncrement)();
493
+ }
494
+ return await SolidActions.getResultInternal(workflowID, timeoutSeconds, timerFuncID, undefined);
495
+ }
496
+ static async getResultInternal(workflowID, timeoutSeconds, timerFuncID, assignedFuncID) {
497
+ return await runInternalStep(async () => {
498
+ const rres = await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.awaitWorkflowResult(workflowID, timeoutSeconds, SolidActions.workflowID, timerFuncID);
499
+ if (!rres)
500
+ return null;
501
+ if (rres?.cancelled) {
502
+ throw new error_1.SolidActionsAwaitedWorkflowCancelledError(workflowID);
503
+ }
504
+ return solidactions_executor_1.SolidActionsExecutor.reviveResultOrError(rres, SolidActions.#executor.serializer);
505
+ }, 'SolidActions.getResult', workflowID, assignedFuncID);
506
+ }
507
+ /**
508
+ * Create a workflow handle with a given workflow ID.
509
+ * This call always returns a handle, even if the workflow does not exist.
510
+ * The resulting handle will check the database to provide any workflow information.
511
+ * @param workflowID - ID of the workflow
512
+ * @returns `WorkflowHandle` that can be used to poll for the status or result of any workflow with `workflowID`
513
+ */
514
+ static retrieveWorkflow(workflowID) {
515
+ (0, decorators_1.ensureSolidActionsIsLaunched)('retrieveWorkflow');
516
+ if (SolidActions.isWithinWorkflow()) {
517
+ if (!SolidActions.isInWorkflow()) {
518
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `retrieveWorkflow` inside a `transaction` or `step`');
519
+ }
520
+ return new workflow_1.RetrievedHandle(solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase, workflowID);
521
+ }
522
+ return SolidActions.#executor.retrieveWorkflow(workflowID);
523
+ }
524
+ /**
525
+ * Query the system database for all workflows matching the provided predicate
526
+ * @param input - `GetWorkflowsInput` predicate for filtering returned workflows
527
+ * @returns `WorkflowStatus` array containing details of the matching workflows
528
+ */
529
+ static async listWorkflows(input) {
530
+ (0, decorators_1.ensureSolidActionsIsLaunched)('listWorkflows');
531
+ return await runInternalStep(async () => {
532
+ return await SolidActions.#executor.listWorkflows(input);
533
+ }, 'SolidActions.listWorkflows');
534
+ }
535
+ /**
536
+ * Retrieve the steps of a workflow
537
+ * @param workflowID - ID of the workflow
538
+ * @returns `StepInfo` array listing the executed steps of the workflow. If the workflow is not found, `undefined` is returned.
539
+ */
540
+ static async listWorkflowSteps(workflowID) {
541
+ (0, decorators_1.ensureSolidActionsIsLaunched)('listWorkflowSteps');
542
+ return await runInternalStep(async () => {
543
+ return await SolidActions.#executor.listWorkflowSteps(workflowID);
544
+ }, 'SolidActions.listWorkflowSteps');
545
+ }
546
+ /**
547
+ * Cancel a workflow given its ID.
548
+ * If the workflow is currently running, `SolidActionsWorkflowCancelledError` will be
549
+ * thrown from its next SolidActions call.
550
+ * @param workflowID - ID of the workflow
551
+ */
552
+ static async cancelWorkflow(workflowID) {
553
+ (0, decorators_1.ensureSolidActionsIsLaunched)('cancelWorkflow');
554
+ return await runInternalStep(async () => {
555
+ return await SolidActions.#executor.cancelWorkflow(workflowID);
556
+ }, 'SolidActions.cancelWorkflow');
557
+ }
558
+ /**
559
+ * Resume a workflow given its ID.
560
+ * @param workflowID - ID of the workflow
561
+ */
562
+ static async resumeWorkflow(workflowID) {
563
+ (0, decorators_1.ensureSolidActionsIsLaunched)('resumeWorkflow');
564
+ await runInternalStep(async () => {
565
+ return await SolidActions.#executor.resumeWorkflow(workflowID);
566
+ }, 'SolidActions.resumeWorkflow');
567
+ return this.retrieveWorkflow(workflowID);
568
+ }
569
+ /**
570
+ * Fork a workflow given its ID.
571
+ * @param workflowID - ID of the workflow
572
+ * @param startStep - Step ID to start the forked workflow from
573
+ * @param applicationVersion - Version of the application to use for the forked workflow
574
+ * @returns A handle to the forked workflow
575
+ * @throws SolidActionsInvalidStepIDError if the `startStep` is greater than the maximum step ID of the workflow
576
+ */
577
+ static async forkWorkflow(workflowID, startStep, options) {
578
+ (0, decorators_1.ensureSolidActionsIsLaunched)('forkWorkflow');
579
+ const forkedID = await runInternalStep(async () => {
580
+ return await SolidActions.#executor.forkWorkflow(workflowID, startStep, options);
581
+ }, 'SolidActions.forkWorkflow');
582
+ return this.retrieveWorkflow(forkedID);
583
+ }
584
+ /**
585
+ * Sleep for the specified amount of time.
586
+ * If called from within a workflow, the sleep is "durable",
587
+ * meaning that the workflow will sleep until the wakeup time
588
+ * (calculated by adding `durationMS` to the original invocation time),
589
+ * regardless of workflow recovery.
590
+ * @param durationMS - Length of sleep, in milliseconds.
591
+ */
592
+ static async sleepms(durationMS) {
593
+ if (SolidActions.isWithinWorkflow() && !SolidActions.isInStep()) {
594
+ if (SolidActions.isInTransaction()) {
595
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.sleep` inside a `transaction`');
596
+ }
597
+ const functionID = (0, context_1.functionIDGetIncrement)();
598
+ if (durationMS <= 0) {
599
+ return;
600
+ }
601
+ return await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.durableSleepms(SolidActions.workflowID, functionID, durationMS);
602
+ }
603
+ await (0, utils_1.sleepms)(durationMS);
604
+ }
605
+ /** @see sleepms */
606
+ static async sleepSeconds(durationSec) {
607
+ return SolidActions.sleepms(durationSec * 1000);
608
+ }
609
+ /** @see sleepms */
610
+ static async sleep(durationMS) {
611
+ return SolidActions.sleepms(durationMS);
612
+ }
613
+ /**
614
+ * Get the current time in milliseconds, similar to `Date.now()`.
615
+ * This function is deterministic and can be used within workflows.
616
+ */
617
+ static async now() {
618
+ if (SolidActions.isInWorkflow()) {
619
+ return runInternalStep(async () => Promise.resolve(Date.now()), 'SolidActions.now');
620
+ }
621
+ return Date.now();
622
+ }
623
+ /**
624
+ * Generate a random (v4) UUUID, similar to `node:crypto.randomUUID`.
625
+ * This function is deterministic and can be used within workflows.
626
+ */
627
+ static async randomUUID() {
628
+ if (SolidActions.isInWorkflow()) {
629
+ return runInternalStep(async () => Promise.resolve((0, node_crypto_1.randomUUID)()), 'SolidActions.randomUUID');
630
+ }
631
+ return (0, node_crypto_1.randomUUID)();
632
+ }
633
+ /**
634
+ * Use the provided `workflowID` as the identifier for first workflow started
635
+ * within the `callback` function.
636
+ * @param workflowID - ID to assign to the first workflow started
637
+ * @param callback - Function to run, which would start a workflow
638
+ * @returns - Return value from `callback`
639
+ */
640
+ static async withNextWorkflowID(workflowID, callback) {
641
+ (0, decorators_1.ensureSolidActionsIsLaunched)('workflows');
642
+ return SolidActions.#withTopContext({ idAssignedForNextWorkflow: workflowID }, callback);
643
+ }
644
+ /**
645
+ * Use the provided `authedUser` and `authedRoles` as the authenticated user for
646
+ * any security checks or calls to `SolidActions.authenticatedUser`
647
+ * or `SolidActions.authenticatedRoles` placed within the `callback` function.
648
+ * @param authedUser - Authenticated user
649
+ * @param authedRoles - Authenticated roles
650
+ * @param callback - Function to run with authentication context in place
651
+ * @returns - Return value from `callback`
652
+ */
653
+ static async withAuthedContext(authedUser, authedRoles, callback) {
654
+ (0, decorators_1.ensureSolidActionsIsLaunched)('auth');
655
+ return SolidActions.#withTopContext({
656
+ authenticatedUser: authedUser,
657
+ authenticatedRoles: authedRoles,
658
+ }, callback);
659
+ }
660
+ /**
661
+ * This generic setter helps users calling SolidActions operation to pass a name,
662
+ * later used in seeding a parent OTel span for the operation.
663
+ * @param callerName - Tracing caller name
664
+ * @param callback - Function to run with tracing context in place
665
+ * @returns - Return value from `callback`
666
+ */
667
+ static async withNamedContext(callerName, callback) {
668
+ (0, decorators_1.ensureSolidActionsIsLaunched)('tracing');
669
+ return SolidActions.#withTopContext({ operationCaller: callerName }, callback);
670
+ }
671
+ /**
672
+ * Specify workflow timeout for any workflows started within the `callback`.
673
+ * @param timeoutMS - timeout length for all workflows started within `callback` will be run
674
+ * @param callback - Function to run, which would call or start workflows
675
+ * @returns - Return value from `callback`
676
+ */
677
+ static async withWorkflowTimeout(timeoutMS, callback) {
678
+ (0, decorators_1.ensureSolidActionsIsLaunched)('workflows');
679
+ return SolidActions.#withTopContext({ workflowTimeoutMS: timeoutMS }, callback);
680
+ }
681
+ /**
682
+ * Run a workflow with the option to set any of the contextual items
683
+ *
684
+ * @param options - Overrides for options
685
+ * @param callback - Function to run, which would call or start workflows
686
+ * @returns - Return value from `callback`
687
+ */
688
+ static async runWithContext(options, callback) {
689
+ (0, decorators_1.ensureSolidActionsIsLaunched)('contexts');
690
+ return SolidActions.#withTopContext(options, callback);
691
+ }
692
+ static async #withTopContext(options, callback) {
693
+ const pctx = (0, context_1.getCurrentContextStore)();
694
+ if (pctx) {
695
+ // Save existing values and overwrite with new; hard to do cleanly but is actually type correct
696
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
697
+ const existing = {};
698
+ for (const k of Object.keys(options)) {
699
+ if (Object.hasOwn(pctx, k))
700
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
701
+ existing[k] = options[k];
702
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
703
+ pctx[k] = options[k];
704
+ }
705
+ try {
706
+ return await callback();
707
+ }
708
+ finally {
709
+ for (const k of Object.keys(options)) {
710
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
711
+ if (Object.hasOwn(existing, k))
712
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
713
+ pctx[k] = existing[k];
714
+ else
715
+ delete pctx[k];
716
+ }
717
+ }
718
+ }
719
+ else {
720
+ return await (0, context_1.runWithTopContext)(options, callback);
721
+ }
722
+ }
723
+ static startWorkflow(target, params) {
724
+ (0, decorators_1.ensureSolidActionsIsLaunched)('workflows');
725
+ const instance = typeof target === 'function' ? null : target;
726
+ if (instance && typeof instance !== 'function' && !(instance instanceof decorators_1.ConfiguredInstance)) {
727
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Attempt to call `startWorkflow` on an object that is not a `ConfiguredInstance`');
728
+ }
729
+ const regOps = (0, decorators_1.getRegisteredOperations)(target);
730
+ const handler = {
731
+ apply(target, _thisArg, args) {
732
+ const regOp = (0, decorators_1.getFunctionRegistration)(target);
733
+ if (!regOp) {
734
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
735
+ const name = typeof target === 'function' ? target.name : target.toString();
736
+ throw new error_1.SolidActionsNotRegisteredError(name, `${name} is not a registered SolidActions workflow function`);
737
+ }
738
+ return SolidActions.#invokeWorkflow(instance, regOp, args, params);
739
+ },
740
+ get(target, p, receiver) {
741
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
742
+ const func = Reflect.get(target, p, receiver);
743
+ const regOp = (0, decorators_1.getFunctionRegistration)(func) ?? regOps.find((op) => op.name === p);
744
+ if (regOp) {
745
+ return (...args) => SolidActions.#invokeWorkflow(instance, regOp, args, params);
746
+ }
747
+ const name = typeof p === 'string' ? p : String(p);
748
+ throw new error_1.SolidActionsNotRegisteredError(name, `${name} is not a registered SolidActions workflow function`);
749
+ },
750
+ };
751
+ return new Proxy(target, handler);
752
+ }
753
+ /**
754
+ * Send `message` on optional `topic` to the workflow with `destinationID`
755
+ * This can be done from inside or outside of SolidActions workflow functions
756
+ * Use the optional `idempotencyKey` to guarantee that the message is sent exactly once
757
+ * @see `SolidActions.recv`
758
+ *
759
+ * @param destinationID - ID of the workflow that will `recv` the message
760
+ * @param message - Message to send, which must be serializable as JSON
761
+ * @param topic - Optional topic; if specified the `recv` command can specify the same topic to receive selectively
762
+ * @param idempotencyKey - Optional key for sending the message exactly once
763
+ */
764
+ static async send(destinationID, message, topic, idempotencyKey) {
765
+ (0, decorators_1.ensureSolidActionsIsLaunched)('send');
766
+ if (SolidActions.isWithinWorkflow()) {
767
+ if (!SolidActions.isInWorkflow()) {
768
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.send` inside a `step` or `transaction`');
769
+ }
770
+ if (idempotencyKey) {
771
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.send` with an idempotency key from within a workflow');
772
+ }
773
+ const functionID = (0, context_1.functionIDGetIncrement)();
774
+ return await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.send(SolidActions.workflowID, functionID, destinationID, SolidActions.#executor.serializer.stringify(message), topic);
775
+ }
776
+ return SolidActions.#executor.runSendTempWF(destinationID, message, topic, idempotencyKey); // Temp WF variant
777
+ }
778
+ /**
779
+ * Receive a message on optional `topic` from within a workflow.
780
+ * This must be called from within a workflow; this workflow's ID is used to check for messages sent by `SolidActions.send`
781
+ * This can be configured to time out.
782
+ * Messages are received in the order in which they are sent (per-sender / causal order).
783
+ * @see `SolidActions.send`
784
+ *
785
+ * @param topic - Optional topic; if specified the `recv` command can specify the same topic to receive selectively
786
+ * @param timeoutSeconds - Optional timeout; if no message is received before the timeout, `null` will be returned
787
+ * @template T - The type of message that is expected to be received
788
+ * @returns Any message received, or `null` if the timeout expires
789
+ */
790
+ static async recv(topic, timeoutSeconds) {
791
+ (0, decorators_1.ensureSolidActionsIsLaunched)('recv');
792
+ if (SolidActions.isWithinWorkflow()) {
793
+ if (!SolidActions.isInWorkflow()) {
794
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.recv` inside a `step` or `transaction`');
795
+ }
796
+ const functionID = (0, context_1.functionIDGetIncrement)();
797
+ const timeoutFunctionID = (0, context_1.functionIDGetIncrement)();
798
+ return SolidActions.#executor.serializer.parse(await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.recv(SolidActions.workflowID, functionID, timeoutFunctionID, topic, timeoutSeconds));
799
+ }
800
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Attempt to call `SolidActions.recv` outside of a workflow'); // Only workflows can recv
801
+ }
802
+ /**
803
+ * Set an event, from within a SolidActions workflow. This value can be retrieved with `SolidActions.getEvent`.
804
+ * If the event `key` already exists, its `value` is updated.
805
+ * This function can only be called from within a workflow.
806
+ * @see `SolidActions.getEvent`
807
+ *
808
+ * @param key - The key for the event; at most one value is associated with a key at any given time.
809
+ * @param value - The value to associate with `key`
810
+ */
811
+ static async setEvent(key, value) {
812
+ (0, decorators_1.ensureSolidActionsIsLaunched)('setEvent');
813
+ if (SolidActions.isWithinWorkflow()) {
814
+ if (!SolidActions.isInWorkflow()) {
815
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.setEvent` inside a `step` or `transaction`');
816
+ }
817
+ const functionID = (0, context_1.functionIDGetIncrement)();
818
+ return solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.setEvent(SolidActions.workflowID, functionID, key, SolidActions.#executor.serializer.stringify(value));
819
+ }
820
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Attempt to call `SolidActions.setEvent` outside of a workflow'); // Only workflows can set event
821
+ }
822
+ /**
823
+ * Get the value of a workflow event, or wait for it to be set.
824
+ * This function can be called inside or outside of SolidActions workflow functions.
825
+ * If this function is called from within a workflow, its result is durably checkpointed.
826
+ * @see `SolidActions.setEvent`
827
+ *
828
+ * @param workflowID - The ID of the workflow with the corresponding `setEvent`
829
+ * @param key - The key for the event; at most one value is associated with a key at any given time.
830
+ * @param timeoutSeconds - Optional timeout; if a value for `key` is not set before the timeout, `null` will be returned
831
+ * @template T - The expected type for the value assigned to `key`
832
+ * @returns The value to associate with `key`, or `null` if the timeout is hit
833
+ */
834
+ static async getEvent(workflowID, key, timeoutSeconds) {
835
+ (0, decorators_1.ensureSolidActionsIsLaunched)('getEvent');
836
+ if (SolidActions.isWithinWorkflow()) {
837
+ if (!SolidActions.isInWorkflow()) {
838
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.getEvent` inside a `step` or `transaction`');
839
+ }
840
+ const functionID = (0, context_1.functionIDGetIncrement)();
841
+ const timeoutFunctionID = (0, context_1.functionIDGetIncrement)();
842
+ const params = {
843
+ workflowID: SolidActions.workflowID,
844
+ functionID,
845
+ timeoutFunctionID,
846
+ };
847
+ return SolidActions.#executor.serializer.parse(await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.getEvent(workflowID, key, timeoutSeconds ?? solidactions_executor_1.SolidActionsExecutor.defaultNotificationTimeoutSec, params));
848
+ }
849
+ return SolidActions.#executor.getEvent(workflowID, key, timeoutSeconds);
850
+ }
851
+ /**
852
+ * Write a value to a stream.
853
+ * @param key - The stream key/name within the workflow
854
+ * @param value - A serializable value to write to the stream
855
+ */
856
+ static async writeStream(key, value) {
857
+ (0, decorators_1.ensureSolidActionsIsLaunched)('writeStream');
858
+ if (SolidActions.isWithinWorkflow()) {
859
+ if (SolidActions.isInWorkflow()) {
860
+ const functionID = (0, context_1.functionIDGetIncrement)();
861
+ return await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.writeStreamFromWorkflow(SolidActions.workflowID, functionID, key, value);
862
+ }
863
+ else if (SolidActions.isInStep()) {
864
+ return await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.writeStreamFromStep(SolidActions.workflowID, key, value);
865
+ }
866
+ else {
867
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.writeStream` outside of a workflow or step');
868
+ }
869
+ }
870
+ else {
871
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.writeStream` outside of a workflow or step');
872
+ }
873
+ }
874
+ /**
875
+ * Close a stream by writing a sentinel value.
876
+ * @param key - The stream key/name within the workflow
877
+ */
878
+ static async closeStream(key) {
879
+ (0, decorators_1.ensureSolidActionsIsLaunched)('closeStream');
880
+ if (SolidActions.isWithinWorkflow()) {
881
+ if (SolidActions.isInWorkflow()) {
882
+ const functionID = (0, context_1.functionIDGetIncrement)();
883
+ return await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.closeStream(SolidActions.workflowID, functionID, key);
884
+ }
885
+ else {
886
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.closeStream` outside of a workflow or step');
887
+ }
888
+ }
889
+ else {
890
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to `SolidActions.closeStream` outside of a workflow');
891
+ }
892
+ }
893
+ /**
894
+ * Read values from a stream as an async generator.
895
+ * This function reads values from a stream identified by the workflowID and key,
896
+ * yielding each value in order until the stream is closed or the workflow terminates.
897
+ * @param workflowID - The workflow instance ID that owns the stream
898
+ * @param key - The stream key/name within the workflow
899
+ * @returns An async generator that yields each value in the stream until the stream is closed
900
+ */
901
+ static async *readStream(workflowID, key) {
902
+ (0, decorators_1.ensureSolidActionsIsLaunched)('readStream');
903
+ let offset = 0;
904
+ while (true) {
905
+ try {
906
+ const value = await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.readStream(workflowID, key, offset);
907
+ if (value === system_database_1.SOLIDACTIONS_STREAM_CLOSED_SENTINEL) {
908
+ break;
909
+ }
910
+ yield value;
911
+ offset += 1;
912
+ }
913
+ catch (error) {
914
+ if (error instanceof Error && error.message.includes('No value found')) {
915
+ // Poll the offset until a value arrives or the workflow terminates
916
+ const status = await SolidActions.getWorkflowStatus(workflowID);
917
+ if (!status || !(0, workflow_1.isWorkflowActive)(status.status)) {
918
+ break;
919
+ }
920
+ await (0, utils_1.sleepms)(1000); // 1 second polling interval
921
+ continue;
922
+ }
923
+ throw error;
924
+ }
925
+ }
926
+ }
927
+ //////
928
+ // Decorators
929
+ //////
930
+ /**
931
+ * Allow a class to be assigned a name
932
+ */
933
+ static className(name) {
934
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
935
+ function clsdec(ctor) {
936
+ const clsreg = (0, decorators_1.getClassRegistration)(ctor, true);
937
+ if (clsreg.reg?.name && clsreg.reg.name !== name && clsreg.reg.name !== ctor.name) {
938
+ throw new error_1.SolidActionsConflictingRegistrationError(`Attempt to assign name ${name} to class ${ctor.name}, which has already been aliased to ${clsreg.reg.name}`);
939
+ }
940
+ clsreg.reg.name = name;
941
+ }
942
+ return clsdec;
943
+ }
944
+ /**
945
+ * Decorator designating a method as a SolidActions workflow
946
+ * Durable execution will be applied within calls to the workflow function
947
+ * This also registers the function so that it is available during recovery
948
+ * @param config - Configuration information for the workflow
949
+ */
950
+ static workflow(config = {}) {
951
+ function decorator(target, propertyKey, inDescriptor) {
952
+ const { descriptor, registration } = (0, decorators_1.wrapSolidActionsFunctionAndRegisterByTarget)(target, propertyKey, config.name ?? propertyKey, inDescriptor);
953
+ const invoker = SolidActions.#getWorkflowInvoker(registration, config);
954
+ descriptor.value = invoker;
955
+ registration.wrappedFunction = invoker;
956
+ (0, decorators_1.registerFunctionWrapper)(invoker, registration);
957
+ return descriptor;
958
+ }
959
+ return decorator;
960
+ }
961
+ /**
962
+ * Create a SolidActions workflow function from a provided function.
963
+ * Similar to the SolidActions.workflow, but without requiring a decorator
964
+ * Durable execution will be applied to calls to the function returned by registerWorkflow
965
+ * This also registers the function so that it is available during recovery
966
+ * @param func - The function to register as a workflow
967
+ * @param name - The name of the registered workflow
968
+ * @param options - Configuration information for the registered workflow
969
+ */
970
+ static registerWorkflow(func, config) {
971
+ const registration = (0, decorators_1.wrapSolidActionsFunctionAndRegisterByUniqueName)(config?.ctorOrProto, config?.className, config?.name ?? func.name, config?.name ?? func.name, func);
972
+ return SolidActions.#getWorkflowInvoker(registration, config);
973
+ }
974
+ static async #invokeWorkflow($this, regOP, args, params = {}, startWfFuncId) {
975
+ (0, decorators_1.ensureSolidActionsIsLaunched)('workflows');
976
+ const wfId = (0, context_1.getNextWFID)(params.workflowID);
977
+ const ppctx = (0, context_1.getCurrentContextStore)();
978
+ const queueName = params.queueName ?? ppctx?.queueAssignedForWorkflows;
979
+ const timeoutMS = params.timeoutMS ?? ppctx?.workflowTimeoutMS;
980
+ const instance = $this === undefined || typeof $this === 'function' ? undefined : $this;
981
+ if (instance && !(instance instanceof decorators_1.ConfiguredInstance)) {
982
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Attempt to call a `workflow` function on an object that is not a `ConfiguredInstance`');
983
+ }
984
+ // If this is called from within a workflow, this is a child workflow,
985
+ // For OAOO, we will need a consistent ID formed from the parent WF and call number
986
+ if (SolidActions.isWithinWorkflow()) {
987
+ if (!SolidActions.isInWorkflow()) {
988
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to a `workflow` function from within a `step` or `transaction`');
989
+ }
990
+ const funcId = startWfFuncId ?? (0, context_1.functionIDGetIncrement)();
991
+ const pctx = (0, context_1.getCurrentContextStore)();
992
+ const pwfid = pctx.workflowId;
993
+ const wfParams = {
994
+ workflowUUID: wfId || pwfid + '-' + funcId,
995
+ configuredInstance: instance,
996
+ queueName,
997
+ timeoutMS,
998
+ // Detach child deadline if a null timeout is configured
999
+ deadlineEpochMS: params.timeoutMS === null || pctx?.workflowTimeoutMS === null ? undefined : pctx?.deadlineEpochMS,
1000
+ enqueueOptions: params.enqueueOptions,
1001
+ };
1002
+ return await invokeRegOp(wfParams, pwfid, funcId);
1003
+ }
1004
+ else {
1005
+ const wfParams = {
1006
+ workflowUUID: wfId,
1007
+ queueName,
1008
+ enqueueOptions: params.enqueueOptions,
1009
+ configuredInstance: instance,
1010
+ timeoutMS,
1011
+ };
1012
+ return await invokeRegOp(wfParams, undefined, undefined);
1013
+ }
1014
+ function invokeRegOp(wfParams, workflowID, funcNum) {
1015
+ if (regOP.workflowConfig) {
1016
+ const func = regOP.registeredFunction;
1017
+ return solidactions_executor_1.SolidActionsExecutor.globalInstance.internalWorkflow(func, wfParams, workflowID, funcNum, ...args);
1018
+ }
1019
+ if (regOP.stepConfig) {
1020
+ const func = regOP.registeredFunction;
1021
+ return solidactions_executor_1.SolidActionsExecutor.globalInstance.startStepTempWF(func, wfParams, workflowID, funcNum, ...args);
1022
+ }
1023
+ throw new error_1.SolidActionsNotRegisteredError(regOP.name, `${regOP.name} is not a registered SolidActions workflow, step, or transaction function`);
1024
+ }
1025
+ }
1026
+ static #getWorkflowInvoker(registration, config) {
1027
+ registration.setWorkflowConfig(config ?? {});
1028
+ const invoker = async function (...rawArgs) {
1029
+ (0, decorators_1.ensureSolidActionsIsLaunched)('workflows');
1030
+ if (SolidActions.isInWorkflow()) {
1031
+ const startWfFuncId = (0, context_1.functionIDGetIncrement)();
1032
+ const getResFuncID = (0, context_1.functionIDGetIncrement)();
1033
+ const handle = await SolidActions.#invokeWorkflow(this, registration, rawArgs, undefined, startWfFuncId);
1034
+ return await handle.getResult(getResFuncID);
1035
+ }
1036
+ const handle = await SolidActions.#invokeWorkflow(this, registration, rawArgs);
1037
+ return await handle.getResult();
1038
+ };
1039
+ (0, decorators_1.registerFunctionWrapper)(invoker, registration);
1040
+ Object.defineProperty(invoker, 'name', {
1041
+ value: registration.name,
1042
+ });
1043
+ return invoker;
1044
+ }
1045
+ /**
1046
+ * Decorator designating a method as a SolidActions step.
1047
+ * A durable checkpoint will be made after the step completes
1048
+ * This ensures "at least once" execution of the step, and that the step will not
1049
+ * be executed again once the checkpoint is recorded
1050
+ *
1051
+ * @param config - Configuration information for the step, particularly the retry policy
1052
+ */
1053
+ static step(config = {}) {
1054
+ function decorator(target, propertyKey, inDescriptor) {
1055
+ const { descriptor, registration } = (0, decorators_1.wrapSolidActionsFunctionAndRegisterByTarget)(target, propertyKey, config.name, inDescriptor);
1056
+ registration.setStepConfig(config);
1057
+ const invokeWrapper = async function (...rawArgs) {
1058
+ (0, decorators_1.ensureSolidActionsIsLaunched)('steps');
1059
+ let inst = undefined;
1060
+ if (this === undefined || typeof this === 'function') {
1061
+ // This is static
1062
+ }
1063
+ else {
1064
+ inst = this;
1065
+ if (!(inst instanceof decorators_1.ConfiguredInstance)) {
1066
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Attempt to call a `step` function on an object that is not a `ConfiguredInstance`');
1067
+ }
1068
+ }
1069
+ if (SolidActions.isWithinWorkflow()) {
1070
+ if (SolidActions.isInTransaction()) {
1071
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to a `step` function from within a `transaction`');
1072
+ }
1073
+ if (SolidActions.isInStep()) {
1074
+ // There should probably be checks here about the compatibility of the StepConfig...
1075
+ return registration.registeredFunction.call(this, ...rawArgs);
1076
+ }
1077
+ return await solidactions_executor_1.SolidActionsExecutor.globalInstance.callStepFunction(registration.registeredFunction, undefined, undefined, inst ?? null, ...rawArgs);
1078
+ }
1079
+ const wfId = (0, context_1.getNextWFID)(undefined);
1080
+ const wfParams = {
1081
+ configuredInstance: inst,
1082
+ workflowUUID: wfId,
1083
+ };
1084
+ return await SolidActions.#executor.runStepTempWF(registration.registeredFunction, wfParams, ...rawArgs);
1085
+ };
1086
+ descriptor.value = invokeWrapper;
1087
+ registration.wrappedFunction = invokeWrapper;
1088
+ (0, decorators_1.registerFunctionWrapper)(invokeWrapper, registration);
1089
+ Object.defineProperty(invokeWrapper, 'name', {
1090
+ value: registration.name,
1091
+ });
1092
+ return descriptor;
1093
+ }
1094
+ return decorator;
1095
+ }
1096
+ /**
1097
+ * Create a check pointed SolidActions step function from a provided function
1098
+ * Similar to the SolidActions.step decorator, but without requiring a decorator
1099
+ * A durable checkpoint will be made after the step completes
1100
+ * This ensures "at least once" execution of the step, and that the step will not
1101
+ * be executed again once the checkpoint is recorded
1102
+ * @param func - The function to register as a step
1103
+ * @param config - Configuration information for the step, particularly the retry policy and name
1104
+ */
1105
+ static registerStep(func, config = {}) {
1106
+ const name = config.name ?? func.name;
1107
+ const reg = (0, decorators_1.wrapSolidActionsFunctionAndRegister)(config?.ctorOrProto, config?.className, name, name, func);
1108
+ const invokeWrapper = async function (...rawArgs) {
1109
+ (0, decorators_1.ensureSolidActionsIsLaunched)('steps');
1110
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
1111
+ const inst = this;
1112
+ const callFunc = reg.registeredFunction ?? reg.origFunction;
1113
+ if (SolidActions.isWithinWorkflow()) {
1114
+ if (SolidActions.isInTransaction()) {
1115
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to a `step` function from within a `transaction`');
1116
+ }
1117
+ if (SolidActions.isInStep()) {
1118
+ // There should probably be checks here about the compatibility of the StepConfig...
1119
+ return callFunc.call(this, ...rawArgs);
1120
+ }
1121
+ return await solidactions_executor_1.SolidActionsExecutor.globalInstance.callStepFunction(callFunc, name, config, inst ?? null, ...rawArgs);
1122
+ }
1123
+ if ((0, context_1.getNextWFID)(undefined)) {
1124
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError(`Invalid call to step '${name}' outside of a workflow; with directive to start a workflow.`);
1125
+ }
1126
+ return callFunc.call(this, ...rawArgs);
1127
+ };
1128
+ (0, decorators_1.registerFunctionWrapper)(invokeWrapper, reg);
1129
+ Object.defineProperty(invokeWrapper, 'name', { value: name });
1130
+ return invokeWrapper;
1131
+ }
1132
+ /**
1133
+ * Run the enclosed `callback` as a checkpointed step within a SolidActions workflow
1134
+ * @param callback - function containing code to run
1135
+ * @param config - Configuration information for the step, particularly the retry policy
1136
+ * @param config.name - The name of the step; if not provided, the function name will be used
1137
+ * @returns - result (either obtained from invoking function, or retrieved if run before)
1138
+ */
1139
+ static runStep(func, config = {}) {
1140
+ (0, decorators_1.ensureSolidActionsIsLaunched)('steps');
1141
+ const name = config.name ?? func.name;
1142
+ if (SolidActions.isWithinWorkflow()) {
1143
+ if (SolidActions.isInTransaction()) {
1144
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Invalid call to a runStep from within a `transaction`');
1145
+ }
1146
+ if (SolidActions.isInStep()) {
1147
+ // There should probably be checks here about the compatibility of the StepConfig...
1148
+ return func();
1149
+ }
1150
+ return solidactions_executor_1.SolidActionsExecutor.globalInstance.callStepFunction(func, name, config, null);
1151
+ }
1152
+ if ((0, context_1.getNextWFID)(undefined)) {
1153
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError(`Invalid call to step '${name}' outside of a workflow; with directive to start a workflow.`);
1154
+ }
1155
+ return func();
1156
+ }
1157
+ /**
1158
+ * Register serialization recipe; this is used to save/retrieve objects from the SolidActions system
1159
+ * database. This includes workflow inputs, function return values, messages, and events.
1160
+ */
1161
+ static registerSerialization(serReg) {
1162
+ if (SolidActions.isInitialized()) {
1163
+ throw new TypeError(`Serializers/deserializers should not be registered after SolidActions.launch()`);
1164
+ }
1165
+ (0, serialization_1.registerSerializationRecipe)(serReg);
1166
+ }
1167
+ /**
1168
+ * Decorate a class with the default list of required roles.
1169
+ * This class-level default can be overridden on a per-function basis with `requiredRole`.
1170
+ * @param anyOf - The list of roles allowed access; authorization is granted if the authenticated user has any role on the list
1171
+ */
1172
+ static defaultRequiredRole(anyOf) {
1173
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1174
+ function clsdec(ctor) {
1175
+ const clsreg = (0, decorators_1.associateClassWithExternal)(decorators_1.SOLIDACTIONS_AUTH, ctor);
1176
+ clsreg.requiredRole = anyOf;
1177
+ (0, authdecorators_1.registerAuthChecker)();
1178
+ }
1179
+ return clsdec;
1180
+ }
1181
+ /**
1182
+ * Decorate a method with the default list of required roles.
1183
+ * @see `SolidActions.defaultRequiredRole`
1184
+ * @param anyOf - The list of roles allowed access; authorization is granted if the authenticated user has any role on the list
1185
+ */
1186
+ static requiredRole(anyOf) {
1187
+ function apidec(target, propertyKey, inDescriptor) {
1188
+ const rr = (0, decorators_1.associateMethodWithExternal)(decorators_1.SOLIDACTIONS_AUTH, target, undefined, propertyKey.toString(), inDescriptor.value);
1189
+ rr.regInfo.requiredRole = anyOf;
1190
+ (0, authdecorators_1.registerAuthChecker)();
1191
+ inDescriptor.value = rr.registration.wrappedFunction ?? rr.registration.registeredFunction;
1192
+ return inDescriptor;
1193
+ }
1194
+ return apidec;
1195
+ }
1196
+ /////
1197
+ // Patching
1198
+ /////
1199
+ /**
1200
+ * Check if a workflow execution has been patched.
1201
+ *
1202
+ * Patching allows reexecution of workflows to accommate changes to the workflow logic.
1203
+ *
1204
+ * Patches check the system database to see which code branch to take. As this adds overhead,
1205
+ * they may eventually be removed; see `deprecatePatch`.
1206
+ *
1207
+ * @param patchName Name of the patch to check.
1208
+ * @returns true if this is the patched(new) workflow variant, or false if the execution predates the patch
1209
+ */
1210
+ static async patch(patchName) {
1211
+ if (!SolidActions.isInWorkflow()) {
1212
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('`SolidActions.patch` must be called from a workflow, and not within a step');
1213
+ }
1214
+ if (!SolidActions.#solidActionsConfig?.enablePatching) {
1215
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Patching is not enabled. See `enablePatching` in `SolidActionsConfig`');
1216
+ }
1217
+ const patched = await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.checkPatch(SolidActions.workflowID, (0, context_1.functionIDGet)(), patchName, false);
1218
+ if (patched.hasEntry) {
1219
+ (0, context_1.functionIDGetIncrement)();
1220
+ }
1221
+ return patched.isPatched;
1222
+ }
1223
+ /**
1224
+ * Check if a workflow execution has been patched, within a plan to eventually remove the unpatched (old) variant.
1225
+ *
1226
+ * `patch` may be changed to `deprecatePatch` after all unpatched workflows have completed and will not be reexecuted.
1227
+ * Once all workflows started with `patch` have completed (in favor of those using `deprecatePatch`), the `deprecatePatch` may then be removed.
1228
+ *
1229
+ * @param patchName Name of the patch to check.
1230
+ * @returns true if this is the patched(new) workflow variant, which it should always be if all unpatched workflows have been retired
1231
+ */
1232
+ static async deprecatePatch(patchName) {
1233
+ if (!SolidActions.isInWorkflow()) {
1234
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('`SolidActions.deprecatePatch` must be called from a workflow, and not within a step');
1235
+ }
1236
+ if (!SolidActions.#solidActionsConfig?.enablePatching) {
1237
+ throw new error_1.SolidActionsInvalidWorkflowTransitionError('Patching is not enabled. See `enablePatching` in `SolidActionsConfig`');
1238
+ }
1239
+ const patched = await solidactions_executor_1.SolidActionsExecutor.globalInstance.systemDatabase.checkPatch(SolidActions.workflowID, (0, context_1.functionIDGet)(), patchName, true);
1240
+ if (patched.hasEntry) {
1241
+ (0, context_1.functionIDGetIncrement)();
1242
+ }
1243
+ return patched.isPatched;
1244
+ }
1245
+ /////
1246
+ // Registration, etc
1247
+ /////
1248
+ /**
1249
+ * Register a lifecycle listener
1250
+ */
1251
+ static registerLifecycleCallback(lcl) {
1252
+ (0, decorators_1.registerLifecycleCallback)(lcl);
1253
+ }
1254
+ /**
1255
+ * Register a middleware provider
1256
+ */
1257
+ static registerMiddlewareInstaller(mwp) {
1258
+ (0, decorators_1.registerMiddlewareInstaller)(mwp);
1259
+ }
1260
+ /**
1261
+ * Register information to be associated with a SolidActions class
1262
+ */
1263
+ static associateClassWithInfo(external, cls) {
1264
+ return (0, decorators_1.associateClassWithExternal)(external, cls);
1265
+ }
1266
+ /**
1267
+ * Register information to be associated with a SolidActions function
1268
+ */
1269
+ static associateFunctionWithInfo(external, func, target) {
1270
+ return (0, decorators_1.associateMethodWithExternal)(external, target.ctorOrProto, target.className, target.name ?? func.name, func);
1271
+ }
1272
+ /**
1273
+ * Register information to be associated with a SolidActions function
1274
+ */
1275
+ static associateParamWithInfo(external, func, target) {
1276
+ return (0, decorators_1.associateParameterWithExternal)(external, target.ctorOrProto, target.className, target.name ?? func?.name ?? '<unknown>', func, target.param);
1277
+ }
1278
+ /** Get registrations */
1279
+ static getAssociatedInfo(external, cls, funcName) {
1280
+ return (0, decorators_1.getRegistrationsForExternal)(external, cls, funcName);
1281
+ }
1282
+ }
1283
+ exports.SolidActions = SolidActions;
1284
+ //# sourceMappingURL=solidactions.js.map