@versori/run 0.2.0-alpha.1 → 0.2.0-alpha.11

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 (117) hide show
  1. package/{script/deps/jsr.io/@std/fmt/1.0.6 → esm/deps/jsr.io/@std/fmt/1.0.7}/colors.d.ts.map +1 -1
  2. package/esm/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.d.ts.map +1 -1
  3. package/esm/deps/jsr.io/@std/log/0.224.14/console_handler.js +1 -1
  4. package/esm/deps/jsr.io/@std/log/0.224.14/rotating_file_handler.js +1 -1
  5. package/esm/src/context/Context.d.ts +7 -1
  6. package/esm/src/context/Context.d.ts.map +1 -1
  7. package/esm/src/context/Context.js +30 -4
  8. package/esm/src/context/ContextProvider.d.ts +3 -1
  9. package/esm/src/context/ContextProvider.d.ts.map +1 -1
  10. package/esm/src/context/ContextProvider.js +9 -2
  11. package/esm/src/dsl/http/default.d.ts +2 -0
  12. package/esm/src/dsl/http/default.d.ts.map +1 -1
  13. package/esm/src/dsl/http/default.js +10 -0
  14. package/esm/src/dsl/http/types.d.ts +13 -2
  15. package/esm/src/dsl/http/types.d.ts.map +1 -1
  16. package/esm/src/dsl/http/versori/activation.d.ts +13 -0
  17. package/esm/src/dsl/http/versori/activation.d.ts.map +1 -0
  18. package/esm/src/dsl/http/versori/activation.js +65 -0
  19. package/esm/src/dsl/http/versori/constants.d.ts +5 -0
  20. package/esm/src/dsl/http/versori/constants.d.ts.map +1 -1
  21. package/esm/src/dsl/http/versori/constants.js +5 -0
  22. package/esm/src/dsl/http/versori/contextcredentials.d.ts +10 -0
  23. package/esm/src/dsl/http/versori/contextcredentials.d.ts.map +1 -0
  24. package/esm/src/dsl/http/versori/contextcredentials.js +1 -0
  25. package/esm/src/dsl/http/versori/credentials/client.d.ts +4 -4
  26. package/esm/src/dsl/http/versori/credentials/client.d.ts.map +1 -1
  27. package/esm/src/dsl/http/versori/credentials/client.js +8 -13
  28. package/esm/src/dsl/http/versori/credentials/credentials.d.ts +38 -0
  29. package/esm/src/dsl/http/versori/credentials/credentials.d.ts.map +1 -1
  30. package/esm/src/dsl/http/versori/credentials/credentials.js +7 -8
  31. package/esm/src/dsl/http/versori/credentials/v1alpha1/common_pb.d.ts +31 -0
  32. package/esm/src/dsl/http/versori/credentials/v1alpha1/common_pb.d.ts.map +1 -0
  33. package/esm/src/dsl/http/versori/credentials/v1alpha1/common_pb.js +31 -0
  34. package/esm/src/dsl/http/versori/credentials/v1alpha1/credential_service_pb.d.ts +84 -0
  35. package/esm/src/dsl/http/versori/credentials/v1alpha1/credential_service_pb.d.ts.map +1 -0
  36. package/esm/src/dsl/http/versori/credentials/v1alpha1/credential_service_pb.js +128 -0
  37. package/esm/src/dsl/http/versori/cronapi.d.ts +10 -0
  38. package/esm/src/dsl/http/versori/cronapi.d.ts.map +1 -0
  39. package/esm/src/dsl/http/versori/cronapi.js +51 -0
  40. package/esm/src/dsl/http/versori/platformapi.d.ts +4 -1
  41. package/esm/src/dsl/http/versori/platformapi.d.ts.map +1 -1
  42. package/esm/src/dsl/http/versori/platformapi.js +38 -6
  43. package/esm/src/dsl/http/versori/roundtripper.d.ts +11 -5
  44. package/esm/src/dsl/http/versori/roundtripper.d.ts.map +1 -1
  45. package/esm/src/dsl/http/versori/roundtripper.js +168 -75
  46. package/esm/src/interpreter/memory/MemoryInterpreter.d.ts +4 -2
  47. package/esm/src/interpreter/memory/MemoryInterpreter.d.ts.map +1 -1
  48. package/esm/src/interpreter/memory/MemoryInterpreter.js +49 -10
  49. package/esm/src/interpreter/memory/ObservableCompiler.d.ts +1 -0
  50. package/esm/src/interpreter/memory/ObservableCompiler.d.ts.map +1 -1
  51. package/esm/src/interpreter/memory/compilers/schedule.d.ts.map +1 -1
  52. package/esm/src/interpreter/memory/compilers/schedule.js +18 -23
  53. package/esm/src/observability/logging/ConsoleLogger.d.ts.map +1 -1
  54. package/esm/src/observability/logging/ConsoleLogger.js +55 -10
  55. package/package.json +1 -1
  56. package/{esm/deps/jsr.io/@std/fmt/1.0.6 → script/deps/jsr.io/@std/fmt/1.0.7}/colors.d.ts.map +1 -1
  57. package/script/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.d.ts.map +1 -1
  58. package/script/deps/jsr.io/@std/log/0.224.14/console_handler.js +1 -1
  59. package/script/deps/jsr.io/@std/log/0.224.14/rotating_file_handler.js +1 -1
  60. package/script/src/context/Context.d.ts +7 -1
  61. package/script/src/context/Context.d.ts.map +1 -1
  62. package/script/src/context/Context.js +30 -4
  63. package/script/src/context/ContextProvider.d.ts +3 -1
  64. package/script/src/context/ContextProvider.d.ts.map +1 -1
  65. package/script/src/context/ContextProvider.js +9 -2
  66. package/script/src/dsl/http/default.d.ts +2 -0
  67. package/script/src/dsl/http/default.d.ts.map +1 -1
  68. package/script/src/dsl/http/default.js +10 -0
  69. package/script/src/dsl/http/types.d.ts +13 -2
  70. package/script/src/dsl/http/types.d.ts.map +1 -1
  71. package/script/src/dsl/http/versori/activation.d.ts +13 -0
  72. package/script/src/dsl/http/versori/activation.d.ts.map +1 -0
  73. package/script/src/dsl/http/versori/activation.js +69 -0
  74. package/script/src/dsl/http/versori/constants.d.ts +5 -0
  75. package/script/src/dsl/http/versori/constants.d.ts.map +1 -1
  76. package/script/src/dsl/http/versori/constants.js +6 -1
  77. package/script/src/dsl/http/versori/contextcredentials.d.ts +10 -0
  78. package/script/src/dsl/http/versori/contextcredentials.d.ts.map +1 -0
  79. package/script/src/dsl/http/versori/contextcredentials.js +2 -0
  80. package/script/src/dsl/http/versori/credentials/client.d.ts +4 -4
  81. package/script/src/dsl/http/versori/credentials/client.d.ts.map +1 -1
  82. package/script/src/dsl/http/versori/credentials/client.js +7 -10
  83. package/script/src/dsl/http/versori/credentials/credentials.d.ts +38 -0
  84. package/script/src/dsl/http/versori/credentials/credentials.d.ts.map +1 -1
  85. package/script/src/dsl/http/versori/credentials/credentials.js +8 -8
  86. package/script/src/dsl/http/versori/credentials/v1alpha1/common_pb.d.ts +31 -0
  87. package/script/src/dsl/http/versori/credentials/v1alpha1/common_pb.d.ts.map +1 -0
  88. package/script/src/dsl/http/versori/credentials/v1alpha1/common_pb.js +34 -0
  89. package/script/src/dsl/http/versori/credentials/v1alpha1/credential_service_pb.d.ts +84 -0
  90. package/script/src/dsl/http/versori/credentials/v1alpha1/credential_service_pb.d.ts.map +1 -0
  91. package/script/src/dsl/http/versori/credentials/v1alpha1/credential_service_pb.js +131 -0
  92. package/script/src/dsl/http/versori/cronapi.d.ts +10 -0
  93. package/script/src/dsl/http/versori/cronapi.d.ts.map +1 -0
  94. package/script/src/dsl/http/versori/cronapi.js +55 -0
  95. package/script/src/dsl/http/versori/platformapi.d.ts +4 -1
  96. package/script/src/dsl/http/versori/platformapi.d.ts.map +1 -1
  97. package/script/src/dsl/http/versori/platformapi.js +38 -6
  98. package/script/src/dsl/http/versori/roundtripper.d.ts +11 -5
  99. package/script/src/dsl/http/versori/roundtripper.d.ts.map +1 -1
  100. package/script/src/dsl/http/versori/roundtripper.js +170 -77
  101. package/script/src/interpreter/memory/MemoryInterpreter.d.ts +4 -2
  102. package/script/src/interpreter/memory/MemoryInterpreter.d.ts.map +1 -1
  103. package/script/src/interpreter/memory/MemoryInterpreter.js +48 -9
  104. package/script/src/interpreter/memory/ObservableCompiler.d.ts +1 -0
  105. package/script/src/interpreter/memory/ObservableCompiler.d.ts.map +1 -1
  106. package/script/src/interpreter/memory/compilers/schedule.d.ts.map +1 -1
  107. package/script/src/interpreter/memory/compilers/schedule.js +18 -23
  108. package/script/src/observability/logging/ConsoleLogger.d.ts.map +1 -1
  109. package/script/src/observability/logging/ConsoleLogger.js +55 -10
  110. /package/esm/deps/jsr.io/@std/fmt/{1.0.6 → 1.0.7}/colors.d.ts +0 -0
  111. /package/esm/deps/jsr.io/@std/fmt/{1.0.6 → 1.0.7}/colors.js +0 -0
  112. /package/esm/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.d.ts +0 -0
  113. /package/esm/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.js +0 -0
  114. /package/script/deps/jsr.io/@std/fmt/{1.0.6 → 1.0.7}/colors.d.ts +0 -0
  115. /package/script/deps/jsr.io/@std/fmt/{1.0.6 → 1.0.7}/colors.js +0 -0
  116. /package/script/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.d.ts +0 -0
  117. /package/script/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.js +0 -0
@@ -3,6 +3,7 @@ import { VersoriCredentialClient } from './credentials/mod.js';
3
3
  import { PlatformAPIClient } from './platformapi.js';
4
4
  import { ConsoleLogger } from '../../../observability/mod.js';
5
5
  import { envVarCredsBaseURL, envVarEnvId, envVarOrgId, envVarPlatformApiBaseURL, } from './constants.js';
6
+ import { ConnectError, Code } from '@connectrpc/connect';
6
7
  /**
7
8
  * VersoriRoundTripper is an implementation of the RoundTripperFactory interface for Versori connections.
8
9
  * This is the intended implementation for when projects/services are hosted on Versori infrastructure.
@@ -10,19 +11,25 @@ import { envVarCredsBaseURL, envVarEnvId, envVarOrgId, envVarPlatformApiBaseURL,
10
11
  *
11
12
  * @example
12
13
  * ```typescript
13
- * const factory = new VersoriRoundTripperFactory(connectAPIClient, tokenClient);
14
+ * const factory = new VersoriCredentialsFactory(connectAPIClient, tokenClient);
14
15
  * const customFetch = await factory.create('connectionName');
15
16
  * const response = await customFetch('https://api.example.com/data');
16
17
  * ```
17
18
  */
18
- export class VersoriRoundTripperFactory {
19
- constructor(credsClient, platformAPIClient, logger) {
19
+ export class VersoriCredentialsFactory {
20
+ constructor(credsClient, credsBaseURL, platformAPIClient, logger) {
20
21
  Object.defineProperty(this, "tokenClient", {
21
22
  enumerable: true,
22
23
  configurable: true,
23
24
  writable: true,
24
25
  value: void 0
25
26
  });
27
+ Object.defineProperty(this, "credsBaseURL", {
28
+ enumerable: true,
29
+ configurable: true,
30
+ writable: true,
31
+ value: void 0
32
+ });
26
33
  Object.defineProperty(this, "platformAPIClient", {
27
34
  enumerable: true,
28
35
  configurable: true,
@@ -53,9 +60,11 @@ export class VersoriRoundTripperFactory {
53
60
  }
54
61
  });
55
62
  this.tokenClient = credsClient;
63
+ this.credsBaseURL = credsBaseURL;
56
64
  this.platformAPIClient = platformAPIClient;
57
65
  this.versoriCfg = LoadConfigFromFile();
58
66
  this.log = logger;
67
+ this.credentials = this.credentials.bind(this);
59
68
  }
60
69
  static fromEnv(logger) {
61
70
  const credsBaseURL = Deno.env.get(envVarCredsBaseURL);
@@ -74,20 +83,23 @@ export class VersoriRoundTripperFactory {
74
83
  missingVars.push(envVarCredsBaseURL);
75
84
  throw new Error(`Missing environment variables: ${missingVars.join(', ')}`);
76
85
  }
77
- const pAPIClient = new PlatformAPIClient(platformApiBaseURL, orgId, envId);
78
- const tokenClient = new VersoriCredentialClient(credsBaseURL);
79
86
  const log = logger || new ConsoleLogger('debug');
80
- return new VersoriRoundTripperFactory(tokenClient, pAPIClient, log);
87
+ const pAPIClient = new PlatformAPIClient(platformApiBaseURL, orgId, envId, log);
88
+ const tokenClient = new VersoriCredentialClient(credsBaseURL);
89
+ return new VersoriCredentialsFactory(tokenClient, credsBaseURL, pAPIClient, log);
81
90
  }
82
91
  // takes the info and modifies the url using changeBaseUrl if necessary
92
+ // if a full valid URL is passed as a string, it will be returned as is
93
+ // if a valid URL object is passed, it will be returned as is
83
94
  changeRequestInit(info, conn) {
84
95
  if (typeof info === 'string') {
85
- // should be this most of the time assuming we're using pathnames
96
+ if (isValidURL(info)) {
97
+ return info;
98
+ }
86
99
  return this.changeBaseUrl(info, conn);
87
100
  }
88
101
  else if (info instanceof URL) {
89
- const newUrl = new URL(this.changeBaseUrl(info.toString(), conn));
90
- return newUrl;
102
+ return info;
91
103
  }
92
104
  else if (info instanceof Request) {
93
105
  const url = this.changeBaseUrl(info.url, conn);
@@ -99,6 +111,7 @@ export class VersoriRoundTripperFactory {
99
111
  const connBaseURL = conn.baseUrl;
100
112
  // if the connection has no baseUrl set, but the pathname is a valid URL, return it as is
101
113
  if (!connBaseURL && isValidURL(pathname)) {
114
+ this.log.debug('Using given URL as is', { url: pathname });
102
115
  return pathname;
103
116
  }
104
117
  const connBaseURLObj = new URL(connBaseURL);
@@ -108,36 +121,45 @@ export class VersoriRoundTripperFactory {
108
121
  _pathname = pathnameObj.pathname;
109
122
  }
110
123
  const newURL = new URL(_pathname, connBaseURLObj.origin);
124
+ this.log.debug('Using baseURL from connection', { url: newURL.toString() });
111
125
  return newURL.toString();
112
126
  }
113
- // TODO: Currently if the connection is edited, then the fetcher will not be updated.
114
- async create(connName, fn = globalThis.fetch) {
127
+ create(connName, fn = globalThis.fetch) {
115
128
  const cnxId = this.getConnectionID(connName);
116
- const conn = await this.platformAPIClient.getStaticConnection(cnxId);
117
- if (!conn) {
129
+ if (!cnxId) {
130
+ this.log.debug('Connection not found in config, could be a dynamic connection', {
131
+ connectionName: connName,
132
+ });
118
133
  return undefined;
119
134
  }
120
- const _fn = (input, init) => {
135
+ const _fn = async (input, init) => {
136
+ const conn = await this.platformAPIClient.getStaticConnection(cnxId);
137
+ if (!conn) {
138
+ this.log.error('Connection not found for user, using default fetch', {
139
+ connectionName: connName,
140
+ });
141
+ return globalThis.fetch(input, init);
142
+ }
121
143
  const _input = this.changeRequestInit(input, conn);
122
- return fn(_input, init);
144
+ switch (conn.credentials[0].authSchemeConfig.type) {
145
+ case 'api-key':
146
+ return (await this.apiKeyFetcher(conn, fn))(_input, init);
147
+ case 'basic-auth':
148
+ return (await this.basicAuthFetcher(conn, fn))(_input, init);
149
+ case 'jwt-bearer':
150
+ return (await this.bearerTokenFetcher(conn, fn))(_input, init);
151
+ case 'oauth2':
152
+ return (await this.oauth2Fetcher(conn, fn))(_input, init);
153
+ default:
154
+ return fn(_input, init);
155
+ }
123
156
  };
124
- switch (conn.credentials[0].authSchemeConfig.type) {
125
- case 'api-key':
126
- return this.apiKeyFetcher(conn, _fn);
127
- case 'basic-auth':
128
- return this.basicAuthFetcher(conn, _fn);
129
- case 'jwt-bearer':
130
- return this.bearerTokenFetcher(conn, _fn);
131
- case 'oauth2':
132
- return this.oauth2Fetcher(conn, _fn);
133
- default:
134
- return fn;
135
- }
157
+ return _fn;
136
158
  }
137
- async createDynamic(templateName, fn = globalThis.fetch) {
159
+ createDynamic(templateName, fn = globalThis.fetch) {
138
160
  const template = this.getTemplateID(templateName);
139
161
  if (!template) {
140
- this.log.info('Template not found in config, could be a static connection', {
162
+ this.log.debug('Template not found in config, could be a static connection', {
141
163
  templateName: templateName,
142
164
  });
143
165
  return undefined;
@@ -167,8 +189,50 @@ export class VersoriRoundTripperFactory {
167
189
  };
168
190
  return _fn;
169
191
  }
192
+ credentials() {
193
+ return {
194
+ getRaw: this.getRawByName.bind(this),
195
+ getAccessToken: this.getTokenByName.bind(this),
196
+ };
197
+ }
198
+ async getTokenByName(name) {
199
+ const credId = await this.getCredentialIDFromName(name);
200
+ const token = await this.tokenClient.getToken(credId);
201
+ if (!token?.token) {
202
+ throw new Error(`Token not found for connection ${name} with credential ID ${credId}`);
203
+ }
204
+ return {
205
+ accessToken: token.token.accessToken,
206
+ tokenType: token.token.tokenType,
207
+ expiry: token.token.expiry ? new Date(Number(token.token.expiry.seconds) * 1000) : undefined,
208
+ };
209
+ }
210
+ async getRawByName(name) {
211
+ const credId = await this.getCredentialIDFromName(name);
212
+ const raw = await this.tokenClient.getRaw(credId);
213
+ if (!raw) {
214
+ throw new Error(`Raw data not found for connection ${name} with credential ID ${credId}`);
215
+ }
216
+ let buffer = raw?.credential?.data['raw'];
217
+ return buffer;
218
+ }
219
+ async getCredentialIDFromName(name) {
220
+ const conId = this.getConnectionID(name);
221
+ if (!conId) {
222
+ throw new Error(`Connection ${name} not found`);
223
+ }
224
+ const conn = await this.platformAPIClient.getStaticConnection(conId);
225
+ if (!conn) {
226
+ throw new Error(`Connection ${name} not found`);
227
+ }
228
+ if (!conn?.credentials[0]?.credential?.id) {
229
+ throw new Error(`Connection ${name}/${conId} has no credentials defined on it`);
230
+ }
231
+ return conn.credentials[0].credential.id;
232
+ }
170
233
  getConnectionID(connName) {
171
- const conn = this.versoriCfg.mappings.find((c) => (c.dynamic === undefined || c.dynamic === false) && c.name.toLowerCase() === connName.toLowerCase());
234
+ const conn = this.versoriCfg.mappings.find((c) => (c.dynamic === undefined || c.dynamic === false) &&
235
+ c.name.toLowerCase() === connName.toLowerCase());
172
236
  if (!conn || !conn.connId) {
173
237
  return '';
174
238
  }
@@ -181,17 +245,17 @@ export class VersoriRoundTripperFactory {
181
245
  }
182
246
  return template.templateId;
183
247
  }
184
- async apiKeyFetcher(conn, fn) {
185
- const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
186
- const token = tokenResponse.token?.accessToken;
187
- const asc = conn.credentials[0].authSchemeConfig.apiKey;
188
- if (!token) {
189
- throw new Error('Token not found');
190
- }
191
- if (!asc) {
192
- throw new Error('API Key configuration not found');
193
- }
194
- const _fn = (input, init) => {
248
+ apiKeyFetcher(conn, fn) {
249
+ const _fn = async (input, init) => {
250
+ const tokenResponse = await this.getToken(conn.credentials[0].credential.id);
251
+ const token = tokenResponse.token?.accessToken;
252
+ const asc = conn.credentials[0].authSchemeConfig.apiKey;
253
+ if (!token) {
254
+ throw new Error('Token not found');
255
+ }
256
+ if (!asc) {
257
+ throw new Error('API Key configuration not found');
258
+ }
195
259
  if (!init) {
196
260
  init = {};
197
261
  }
@@ -229,13 +293,13 @@ export class VersoriRoundTripperFactory {
229
293
  };
230
294
  return _fn;
231
295
  }
232
- async basicAuthFetcher(conn, fn) {
233
- const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
234
- const token = tokenResponse.token?.accessToken;
235
- if (!token) {
236
- throw new Error('Token not found');
237
- }
238
- const _fn = (input, init) => {
296
+ basicAuthFetcher(conn, fn) {
297
+ const _fn = async (input, init) => {
298
+ const tokenResponse = await this.getToken(conn.credentials[0].credential.id);
299
+ const token = tokenResponse.token?.accessToken;
300
+ if (!token) {
301
+ throw new Error('Token not found');
302
+ }
239
303
  if (!init) {
240
304
  init = {};
241
305
  }
@@ -259,13 +323,13 @@ export class VersoriRoundTripperFactory {
259
323
  return _fn;
260
324
  }
261
325
  // TODO: need to make the prefix and header name configurable from authschemeconfig
262
- async bearerTokenFetcher(conn, fn) {
263
- const tokenResponse = await this.tokenClient.getToken(conn.credentials[0].credential.id);
264
- const token = tokenResponse.token?.accessToken;
265
- if (!token) {
266
- throw new Error('Token not found');
267
- }
268
- const _fn = (input, init) => {
326
+ bearerTokenFetcher(conn, fn) {
327
+ const _fn = async (input, init) => {
328
+ const tokenResponse = await this.getToken(conn.credentials[0].credential.id);
329
+ const token = tokenResponse.token?.accessToken;
330
+ if (!token) {
331
+ throw new Error('Token not found');
332
+ }
269
333
  if (!init) {
270
334
  init = {};
271
335
  }
@@ -288,27 +352,27 @@ export class VersoriRoundTripperFactory {
288
352
  };
289
353
  return _fn;
290
354
  }
291
- async oauth2Fetcher(conn, fn) {
292
- const tokenResponse = await this.tokenClient.getOAuth2Token(conn.credentials[0].credential.id);
293
- const token = tokenResponse.token?.accessToken;
294
- const tokenType = tokenResponse.token?.tokenType;
295
- if (!token) {
296
- throw new Error('Token not found');
297
- }
298
- const _tokenType = () => {
299
- const _tt = tokenType?.toLowerCase();
300
- switch (_tt) {
301
- case 'bearer':
302
- return 'Bearer';
303
- case 'mac':
304
- return 'MAC';
305
- case 'basic':
306
- return 'Basic';
307
- default:
308
- return 'Bearer';
355
+ oauth2Fetcher(conn, fn) {
356
+ const refreshFn = async (input, init, forceRefresh = false) => {
357
+ const tokenResponse = await this.getToken(conn.credentials[0].credential.id, forceRefresh);
358
+ const token = tokenResponse.token?.accessToken;
359
+ const tokenType = tokenResponse.token?.tokenType;
360
+ if (!token) {
361
+ throw new Error('Token not found');
309
362
  }
310
- };
311
- const _fn = (input, init) => {
363
+ const _tokenType = () => {
364
+ const _tt = tokenType?.toLowerCase();
365
+ switch (_tt) {
366
+ case 'bearer':
367
+ return 'Bearer';
368
+ case 'mac':
369
+ return 'MAC';
370
+ case 'basic':
371
+ return 'Basic';
372
+ default:
373
+ return 'Bearer';
374
+ }
375
+ };
312
376
  if (!init) {
313
377
  init = {};
314
378
  }
@@ -329,8 +393,37 @@ export class VersoriRoundTripperFactory {
329
393
  }
330
394
  return fn(input, init);
331
395
  };
396
+ const _fn = async (input, init) => {
397
+ const resp = await refreshFn(input, init, false);
398
+ if (resp.status === 401) {
399
+ this.log.debug('Received 401 Unauthorized response, attempting refresh', {
400
+ url: input,
401
+ status: resp.status,
402
+ });
403
+ // TODO: attempt refresh until precondition failed??
404
+ return refreshFn(input, init, true);
405
+ }
406
+ return Promise.resolve(resp);
407
+ };
332
408
  return _fn;
333
409
  }
410
+ async getToken(id) {
411
+ try {
412
+ return await this.tokenClient.getToken(id);
413
+ }
414
+ catch (error) {
415
+ this.log.error('unable to get credential', { error });
416
+ if (error instanceof ConnectError) {
417
+ if (error.rawMessage.includes("connection error received: not a result of an error") && error.code === Code.Internal) {
418
+ this.log.info('Connection error received, attempting to reconnect');
419
+ this.tokenClient = new VersoriCredentialClient(this.credsBaseURL);
420
+ return await this.tokenClient.getToken(id);
421
+ }
422
+ throw error;
423
+ }
424
+ throw error;
425
+ }
426
+ }
334
427
  }
335
428
  function isValidURL(url) {
336
429
  try {
@@ -1,7 +1,7 @@
1
1
  import { Router } from 'express';
2
2
  import { Observable, Subscription } from 'rxjs';
3
3
  import { ContextProvider } from '../../context/ContextProvider.js';
4
- import { ConnectionProvider, RoundTripperFactory } from '../../dsl/http/types.js';
4
+ import { ConnectionProvider, CronProvider, RoundTripperFactory } from '../../dsl/http/types.js';
5
5
  import { Workflow } from '../../dsl/Workflow.js';
6
6
  import { Logger } from '../../observability/logging/Logger.js';
7
7
  import { ObservableCompiler } from './ObservableCompiler.js';
@@ -26,12 +26,14 @@ export declare class MemoryInterpreter {
26
26
  private readonly contextProvider;
27
27
  private readonly roundTripperFactory;
28
28
  private readonly router;
29
+ private cronRegistry;
29
30
  private readonly connectionProvider;
31
+ private readonly cronProvider;
30
32
  private registeredWorkflows;
31
33
  private server?;
32
34
  private shutdownServer?;
33
35
  private isShuttingDown;
34
- constructor(log: Logger, compiler: ObservableCompiler, contextProvider: ContextProvider, roundTripperFactory: RoundTripperFactory, router: Router, connectionProvider: ConnectionProvider);
36
+ constructor(log: Logger, compiler: ObservableCompiler, contextProvider: ContextProvider, roundTripperFactory: RoundTripperFactory, router: Router, cronRegistry: Map<string, string>, connectionProvider: ConnectionProvider, cronProvider: CronProvider);
35
37
  static newInstance(options?: MemoryInterpreterOptions): Promise<MemoryInterpreter>;
36
38
  register<O>(workflow: Workflow<O>, options?: MemoryInterpreterOptions): Registration;
37
39
  start(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"MemoryInterpreter.d.ts","sourceRoot":"","sources":["../../../../src/src/interpreter/memory/MemoryInterpreter.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAqB,MAAM,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAA+B,UAAU,EAAW,YAAY,EAAE,MAAM,MAAM,CAAC;AACtF,OAAO,EAAE,eAAe,EAAuB,MAAM,kCAAkC,CAAC;AAExF,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGlF,OAAO,EAAE,QAAQ,EAAgB,MAAM,uBAAuB,CAAC;AAI/D,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAC/D,OAAO,EAAmB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAIpE,MAAM,MAAM,wBAAwB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF,KAAK,YAAY,GAAG;IAChB,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7C,KAAK,EAAE,uBAAuB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9C,oBAAoB,EAAE,eAAe,CAAC;IACtC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B,CAAA;AAED,qBAAa,iBAAiB;IAOtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAXvC,OAAO,CAAC,mBAAmB,CAA2B;IACtD,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,cAAc,CAAC,CAAa;IACpC,OAAO,CAAC,cAAc,CAAS;gBAGV,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,kBAAkB,EAC5B,eAAe,EAAE,eAAe,EAChC,mBAAmB,EAAE,mBAAmB,EACxC,MAAM,EAAE,MAAM,EACd,kBAAkB,EAAE,kBAAkB;WAS9C,WAAW,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAoC5F,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,wBAAwB;IA6C/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiHtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAK9B"}
1
+ {"version":3,"file":"MemoryInterpreter.d.ts","sourceRoot":"","sources":["../../../../src/src/interpreter/memory/MemoryInterpreter.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAqB,MAAM,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAA+B,UAAU,EAAW,YAAY,EAAE,MAAM,MAAM,CAAC;AACtF,OAAO,EAAE,eAAe,EAAuB,MAAM,kCAAkC,CAAC;AAExF,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGhG,OAAO,EAAE,QAAQ,EAAgB,MAAM,uBAAuB,CAAC;AAI/D,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAC/D,OAAO,EAAmB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAMpE,MAAM,MAAM,wBAAwB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF,KAAK,YAAY,GAAG;IAChB,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7C,KAAK,EAAE,uBAAuB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9C,oBAAoB,EAAE,eAAe,CAAC;IACtC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B,CAAA;AAED,qBAAa,iBAAiB;IAOtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAbjC,OAAO,CAAC,mBAAmB,CAA2B;IACtD,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,cAAc,CAAC,CAAa;IACpC,OAAO,CAAC,cAAc,CAAS;gBAGV,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,kBAAkB,EAC5B,eAAe,EAAE,eAAe,EAChC,mBAAmB,EAAE,mBAAmB,EACxC,MAAM,EAAE,MAAM,EACvB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACxB,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY;WASlC,WAAW,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAwC5F,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,wBAAwB;IA8C/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2ItB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAK9B"}
@@ -3,14 +3,15 @@ import { catchError, EMPTY, mergeMap, of, tap } from 'rxjs';
3
3
  import { ContextProviderImpl } from '../../context/ContextProvider.js';
4
4
  import { DefaultRoundTripperFactory } from '../../dsl/http/default.js';
5
5
  import { PlatformAPIClient } from '../../dsl/http/versori/platformapi.js';
6
- import { VersoriRoundTripperFactory } from '../../dsl/http/versori/roundtripper.js';
6
+ import { VersoriCredentialsFactory } from '../../dsl/http/versori/roundtripper.js';
7
7
  import { WorkflowImpl } from '../../dsl/Workflow.js';
8
8
  import { MemoryKeyValueProvider } from '../../kv/memory/MemoryKeyValueProvider.js';
9
9
  import { NatsKeyValueProvider } from '../../kv/nats/NatsKeyValueProvider.js';
10
10
  import { ConsoleLogger } from '../../observability/logging/ConsoleLogger.js';
11
11
  import { ObservableCompiler } from './ObservableCompiler.js';
12
+ import { CronAPIClient } from '../../dsl/http/versori/cronapi.js';
12
13
  export class MemoryInterpreter {
13
- constructor(log, compiler, contextProvider, roundTripperFactory, router, connectionProvider) {
14
+ constructor(log, compiler, contextProvider, roundTripperFactory, router, cronRegistry, connectionProvider, cronProvider) {
14
15
  Object.defineProperty(this, "log", {
15
16
  enumerable: true,
16
17
  configurable: true,
@@ -41,12 +42,24 @@ export class MemoryInterpreter {
41
42
  writable: true,
42
43
  value: router
43
44
  });
45
+ Object.defineProperty(this, "cronRegistry", {
46
+ enumerable: true,
47
+ configurable: true,
48
+ writable: true,
49
+ value: cronRegistry
50
+ });
44
51
  Object.defineProperty(this, "connectionProvider", {
45
52
  enumerable: true,
46
53
  configurable: true,
47
54
  writable: true,
48
55
  value: connectionProvider
49
56
  });
57
+ Object.defineProperty(this, "cronProvider", {
58
+ enumerable: true,
59
+ configurable: true,
60
+ writable: true,
61
+ value: cronProvider
62
+ });
50
63
  Object.defineProperty(this, "registeredWorkflows", {
51
64
  enumerable: true,
52
65
  configurable: true,
@@ -82,16 +95,16 @@ export class MemoryInterpreter {
82
95
  const compiler = options.compiler || new ObservableCompiler();
83
96
  const roundTripperFactory = options.skipVersoriCredentials
84
97
  ? new DefaultRoundTripperFactory()
85
- : VersoriRoundTripperFactory.fromEnv(log);
98
+ : VersoriCredentialsFactory.fromEnv(log);
86
99
  if (options.contextProvider) {
87
100
  // no need to set up a key-value provider if options.contextProvider is already
88
101
  // initialised.
89
- return new MemoryInterpreter(log, compiler, options.contextProvider, roundTripperFactory, express.Router(), PlatformAPIClient.fromEnv());
102
+ return new MemoryInterpreter(log, compiler, options.contextProvider, roundTripperFactory, express.Router(), new Map(), PlatformAPIClient.fromEnv(), CronAPIClient.fromEnv());
90
103
  }
91
104
  const kvp = await (options.skipVersoriCredentials
92
105
  ? new MemoryKeyValueProvider()
93
106
  : NatsKeyValueProvider.fromEnv());
94
- return new MemoryInterpreter(log, compiler, new ContextProviderImpl(log, kvp), roundTripperFactory, express.Router(), PlatformAPIClient.fromEnv());
107
+ return new MemoryInterpreter(log, compiler, new ContextProviderImpl(log, kvp, roundTripperFactory.credentials()), roundTripperFactory, express.Router(), new Map(), PlatformAPIClient.fromEnv(), CronAPIClient.fromEnv());
95
108
  }
96
109
  register(workflow, options) {
97
110
  const localAbortController = new AbortController();
@@ -108,6 +121,7 @@ export class MemoryInterpreter {
108
121
  contextProvider: this.contextProvider,
109
122
  roundTripperFactory: this.roundTripperFactory,
110
123
  router: this.router,
124
+ cronRegistry: this.cronRegistry,
111
125
  connectionProvider: this.connectionProvider
112
126
  };
113
127
  const trigger$ = this.compiler.compileTrigger(compilerContext, workflow.trigger, combinedSignal);
@@ -140,9 +154,18 @@ export class MemoryInterpreter {
140
154
  registration.subscription = registration.trigger$
141
155
  .pipe(tap((ctx) => {
142
156
  ctx.log.info('MemoryInterpreter.executionStarted', { data: ctx.data });
143
- }), mergeMap((ctx) => of(ctx).pipe(registration.task$, catchError((error) => {
144
- ctx.log.error('MemoryInterpreter.executionError', { error });
145
- ctx.options.onError?.(ctx.withData(error));
157
+ }), mergeMap((ctx) => of(ctx).pipe(registration.task$, catchError((err) => {
158
+ ctx.log.error('MemoryInterpreter.executionError', { error: err instanceof Error ? err.toString() : err });
159
+ try {
160
+ ctx.options.onError?.(ctx.withData(err));
161
+ }
162
+ catch (err) {
163
+ ctx.log.error('MemoryInterpreter.onErrorError: failed to call onError handler', { error: err instanceof Error ? err.toString() : err });
164
+ ctx.options.onError?.(ctx.withData({
165
+ message: 'Internal server error',
166
+ error: err instanceof Error ? err.toString() : err,
167
+ }));
168
+ }
146
169
  return EMPTY;
147
170
  }))))
148
171
  .subscribe({
@@ -152,11 +175,20 @@ export class MemoryInterpreter {
152
175
  durationMs,
153
176
  data: ctx.data,
154
177
  });
155
- ctx.options.onSuccess?.(ctx);
178
+ try {
179
+ ctx.options.onSuccess?.(ctx);
180
+ }
181
+ catch (err) {
182
+ ctx.log.error('MemoryInterpreter.onSuccessError: failed to call onSuccess handler', { error: err instanceof Error ? err.toString() : err });
183
+ ctx.options.onSuccess?.(ctx.withData({
184
+ message: 'Internal server error',
185
+ error: err instanceof Error ? err.toString() : err,
186
+ }));
187
+ }
156
188
  this.contextProvider.destroy(ctx);
157
189
  },
158
190
  error: (err) => {
159
- this.log.error('MemoryInterpreter.error', { error: err });
191
+ this.log.error('MemoryInterpreter.error', { error: err instanceof Error ? err.toString() : err });
160
192
  Deno.removeSignalListener('SIGINT', registration.sigintListener);
161
193
  },
162
194
  complete: () => {
@@ -168,6 +200,13 @@ export class MemoryInterpreter {
168
200
  registration.subscription = undefined;
169
201
  });
170
202
  }
203
+ try {
204
+ this.cronProvider.updateCrons(this.cronRegistry);
205
+ }
206
+ catch (err) {
207
+ this.log.error('MemoryInterpreter.updateCronsError', { error: err instanceof Error ? err.toString() : err });
208
+ throw new Error('Unable to register scheduler tasks with central cron provider');
209
+ }
171
210
  this.server = app.listen(port, () => {
172
211
  this.log.info(`Express server listening on http://localhost:${port}`);
173
212
  });
@@ -14,6 +14,7 @@ export type CompilerContext = {
14
14
  roundTripperFactory: RoundTripperFactory;
15
15
  connectionProvider: ConnectionProvider;
16
16
  router: Router;
17
+ cronRegistry: Map<string, string>;
17
18
  };
18
19
  export type CompilerFunc<In = any, Out = any, T extends Task<In, Out> = Task<In, Out>> = (ctx: CompilerContext, task: T) => OperatorFunction<In, Out>;
19
20
  export declare class ObservableCompiler {
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableCompiler.d.ts","sourceRoot":"","sources":["../../../../src/src/interpreter/memory/ObservableCompiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AACpD,OAAO,EAAE,IAAI,EAAY,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAO/D,OAAO,EAAE,uBAAuB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE9F,OAAO,EAAE,OAAO,EAAe,MAAM,sBAAsB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,MAAM,eAAe,GAAG;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CACrF,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,CAAC,KACN,gBAAgB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAE/B,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,gBAAgB,CAAgD;;IAgBxE,WAAW,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,KAAK,GAAG,IAAI,EACzC,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,GACpB,uBAAuB,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC;IAe1C,cAAc,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,EAC3D,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,WAAW,GACpB,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAerC,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,SAAS,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAKjF,eAAe,CAAC,GAAG,EAAE,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC;CAIjF"}
1
+ {"version":3,"file":"ObservableCompiler.d.ts","sourceRoot":"","sources":["../../../../src/src/interpreter/memory/ObservableCompiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AACpD,OAAO,EAAE,IAAI,EAAY,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAO/D,OAAO,EAAE,uBAAuB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE9F,OAAO,EAAE,OAAO,EAAe,MAAM,sBAAsB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,MAAM,eAAe,GAAG;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CACrF,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,CAAC,KACN,gBAAgB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAE/B,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,gBAAgB,CAAgD;;IAgBxE,WAAW,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,KAAK,GAAG,IAAI,EACzC,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,GACpB,uBAAuB,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC;IAe1C,cAAc,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,EAC3D,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,WAAW,GACpB,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAerC,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,SAAS,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAKjF,eAAe,CAAC,GAAG,EAAE,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC;CAIjF"}
@@ -1 +1 @@
1
- {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../../../../src/src/interpreter/memory/compilers/schedule.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAEzF,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA6F7C,eAAO,MAAM,gBAAgB,EAAE,eAAe,CAAC,YAAY,EAAE,eAAe,CAG3E,CAAC"}
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../../../../src/src/interpreter/memory/compilers/schedule.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAEzF,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuF7C,eAAO,MAAM,gBAAgB,EAAE,eAAe,CAAC,YAAY,EAAE,eAAe,CAG3E,CAAC"}
@@ -1,12 +1,15 @@
1
- import { CronJob } from 'cron';
2
1
  import { Observable } from 'rxjs';
3
2
  import { ScheduleTrigger } from '../../../dsl/triggers/ScheduleTrigger.js';
4
3
  function compileSchedule(ctx, trigger, signal) {
5
4
  return new Observable((subscriber) => {
5
+ // Add HTTP endpoint for manual triggering
6
+ if (!ctx.router) {
7
+ throw new Error('Router not available in compiler context');
8
+ }
6
9
  const client = ctx.connectionProvider;
7
- const job = CronJob.from({
8
- cronTime: trigger.schedule,
9
- onTick: async () => {
10
+ ctx.cronRegistry.set(trigger.id, trigger.schedule);
11
+ ctx.router.post(`/cron/${trigger.id}`, async (req, res) => {
12
+ try {
10
13
  if (trigger.activationPredicate === undefined) {
11
14
  const executionCtx = ctx.contextProvider.create({}, undefined);
12
15
  try {
@@ -15,6 +18,7 @@ function compileSchedule(ctx, trigger, signal) {
15
18
  catch (error) {
16
19
  executionCtx.log.error('execution error inside schedule', { error });
17
20
  }
21
+ res.status(200).json({ status: 'triggered', executionId: executionCtx.executionId });
18
22
  return;
19
23
  }
20
24
  const activations = await client.listActivations();
@@ -27,6 +31,7 @@ function compileSchedule(ctx, trigger, signal) {
27
31
  catch (error) {
28
32
  executionCtx.log.error('execution error inside schedule', { error });
29
33
  }
34
+ res.status(200).json({ status: 'triggered', executionId: executionCtx.executionId });
30
35
  return;
31
36
  }
32
37
  activations.forEach((activation) => {
@@ -39,31 +44,21 @@ function compileSchedule(ctx, trigger, signal) {
39
44
  executionCtx.log.error('execution error inside schedule', { error });
40
45
  }
41
46
  });
42
- },
43
- onComplete: () => {
44
- if (subscriber.closed) {
45
- return;
46
- }
47
- ctx.log.debug('schedule execution completed');
48
- subscriber.complete();
49
- },
50
- errorHandler: (error) => {
51
- ctx.log.error('schedule execution error', { error });
52
- subscriber.error(error);
53
- },
54
- start: true,
47
+ res.status(200).json({ status: 'triggered' });
48
+ }
49
+ catch (error) {
50
+ executionCtx.log.error('execution error inside schedule', { error });
51
+ res.status(500).json({ error: 'Failed to trigger schedule' });
52
+ }
55
53
  });
56
54
  function cleanup() {
57
- ctx.log.debug('schedule execution stopped');
58
- job.stop();
55
+ ctx.log.debug('scheduler trigger stopped');
56
+ subscriber.complete();
59
57
  }
60
58
  signal.addEventListener('abort', cleanup, { once: true });
61
59
  return () => {
62
60
  signal.removeEventListener('abort', cleanup);
63
- ctx.log.debug('schedule execution unsubscribed');
64
- // call job.stop() directly rather than using cleanup since cleanup is called when the
65
- // signal is aborted and we don't want duplicate logs when the unsubscription happens.
66
- job.stop();
61
+ ctx.log.debug('scheduler execution unsubscribed');
67
62
  };
68
63
  });
69
64
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ConsoleLogger.d.ts","sourceRoot":"","sources":["../../../../src/src/observability/logging/ConsoleLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,+CAA+C,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA+B/C;;GAEG;AACH,qBAAa,aAAc,YAAW,MAAM;IACxC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC;IAEhB,KAAK,EAAE,QAAQ,CAAC;IAEhB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAEpB,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAOjE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAO9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAO7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAO9D,KAAK,CAAC,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,aAAa;IAOvD,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAGlC"}
1
+ {"version":3,"file":"ConsoleLogger.d.ts","sourceRoot":"","sources":["../../../../src/src/observability/logging/ConsoleLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,+CAA+C,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAmF/C;;GAEG;AACH,qBAAa,aAAc,YAAW,MAAM;IACxC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC;IAEhB,KAAK,EAAE,QAAQ,CAAC;IAEhB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAEpB,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAOjE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAO9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAO7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAO9D,KAAK,CAAC,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,aAAa;IAOvD,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAGlC"}