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

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 (81) 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 +2 -0
  6. package/esm/src/context/Context.d.ts.map +1 -1
  7. package/esm/src/context/Context.js +15 -0
  8. package/esm/src/dsl/http/types.d.ts +13 -2
  9. package/esm/src/dsl/http/types.d.ts.map +1 -1
  10. package/esm/src/dsl/http/versori/activation.d.ts +13 -0
  11. package/esm/src/dsl/http/versori/activation.d.ts.map +1 -0
  12. package/esm/src/dsl/http/versori/activation.js +65 -0
  13. package/esm/src/dsl/http/versori/constants.d.ts +5 -0
  14. package/esm/src/dsl/http/versori/constants.d.ts.map +1 -1
  15. package/esm/src/dsl/http/versori/constants.js +5 -0
  16. package/esm/src/dsl/http/versori/credentials/client.d.ts +1 -4
  17. package/esm/src/dsl/http/versori/credentials/client.d.ts.map +1 -1
  18. package/esm/src/dsl/http/versori/credentials/client.js +3 -16
  19. package/esm/src/dsl/http/versori/cronapi.d.ts +10 -0
  20. package/esm/src/dsl/http/versori/cronapi.d.ts.map +1 -0
  21. package/esm/src/dsl/http/versori/cronapi.js +51 -0
  22. package/esm/src/dsl/http/versori/platformapi.d.ts +4 -1
  23. package/esm/src/dsl/http/versori/platformapi.d.ts.map +1 -1
  24. package/esm/src/dsl/http/versori/platformapi.js +38 -6
  25. package/esm/src/dsl/http/versori/roundtripper.d.ts +3 -2
  26. package/esm/src/dsl/http/versori/roundtripper.d.ts.map +1 -1
  27. package/esm/src/dsl/http/versori/roundtripper.js +124 -73
  28. package/esm/src/interpreter/memory/MemoryInterpreter.d.ts +4 -2
  29. package/esm/src/interpreter/memory/MemoryInterpreter.d.ts.map +1 -1
  30. package/esm/src/interpreter/memory/MemoryInterpreter.js +47 -8
  31. package/esm/src/interpreter/memory/ObservableCompiler.d.ts +1 -0
  32. package/esm/src/interpreter/memory/ObservableCompiler.d.ts.map +1 -1
  33. package/esm/src/interpreter/memory/compilers/schedule.d.ts.map +1 -1
  34. package/esm/src/interpreter/memory/compilers/schedule.js +18 -23
  35. package/esm/src/observability/logging/ConsoleLogger.d.ts.map +1 -1
  36. package/esm/src/observability/logging/ConsoleLogger.js +55 -10
  37. package/package.json +1 -1
  38. 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
  39. package/script/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.d.ts.map +1 -1
  40. package/script/deps/jsr.io/@std/log/0.224.14/console_handler.js +1 -1
  41. package/script/deps/jsr.io/@std/log/0.224.14/rotating_file_handler.js +1 -1
  42. package/script/src/context/Context.d.ts +2 -0
  43. package/script/src/context/Context.d.ts.map +1 -1
  44. package/script/src/context/Context.js +15 -0
  45. package/script/src/dsl/http/types.d.ts +13 -2
  46. package/script/src/dsl/http/types.d.ts.map +1 -1
  47. package/script/src/dsl/http/versori/activation.d.ts +13 -0
  48. package/script/src/dsl/http/versori/activation.d.ts.map +1 -0
  49. package/script/src/dsl/http/versori/activation.js +69 -0
  50. package/script/src/dsl/http/versori/constants.d.ts +5 -0
  51. package/script/src/dsl/http/versori/constants.d.ts.map +1 -1
  52. package/script/src/dsl/http/versori/constants.js +6 -1
  53. package/script/src/dsl/http/versori/credentials/client.d.ts +1 -4
  54. package/script/src/dsl/http/versori/credentials/client.d.ts.map +1 -1
  55. package/script/src/dsl/http/versori/credentials/client.js +2 -15
  56. package/script/src/dsl/http/versori/cronapi.d.ts +10 -0
  57. package/script/src/dsl/http/versori/cronapi.d.ts.map +1 -0
  58. package/script/src/dsl/http/versori/cronapi.js +55 -0
  59. package/script/src/dsl/http/versori/platformapi.d.ts +4 -1
  60. package/script/src/dsl/http/versori/platformapi.d.ts.map +1 -1
  61. package/script/src/dsl/http/versori/platformapi.js +38 -6
  62. package/script/src/dsl/http/versori/roundtripper.d.ts +3 -2
  63. package/script/src/dsl/http/versori/roundtripper.d.ts.map +1 -1
  64. package/script/src/dsl/http/versori/roundtripper.js +124 -73
  65. package/script/src/interpreter/memory/MemoryInterpreter.d.ts +4 -2
  66. package/script/src/interpreter/memory/MemoryInterpreter.d.ts.map +1 -1
  67. package/script/src/interpreter/memory/MemoryInterpreter.js +47 -8
  68. package/script/src/interpreter/memory/ObservableCompiler.d.ts +1 -0
  69. package/script/src/interpreter/memory/ObservableCompiler.d.ts.map +1 -1
  70. package/script/src/interpreter/memory/compilers/schedule.d.ts.map +1 -1
  71. package/script/src/interpreter/memory/compilers/schedule.js +18 -23
  72. package/script/src/observability/logging/ConsoleLogger.d.ts.map +1 -1
  73. package/script/src/observability/logging/ConsoleLogger.js +55 -10
  74. /package/esm/deps/jsr.io/@std/fmt/{1.0.6 → 1.0.7}/colors.d.ts +0 -0
  75. /package/esm/deps/jsr.io/@std/fmt/{1.0.6 → 1.0.7}/colors.js +0 -0
  76. /package/esm/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.d.ts +0 -0
  77. /package/esm/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.js +0 -0
  78. /package/script/deps/jsr.io/@std/fmt/{1.0.6 → 1.0.7}/colors.d.ts +0 -0
  79. /package/script/deps/jsr.io/@std/fmt/{1.0.6 → 1.0.7}/colors.js +0 -0
  80. /package/script/deps/jsr.io/@std/fs/{1.0.16 → 1.0.17}/exists.d.ts +0 -0
  81. /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.
@@ -16,13 +17,19 @@ import { envVarCredsBaseURL, envVarEnvId, envVarOrgId, envVarPlatformApiBaseURL,
16
17
  * ```
17
18
  */
18
19
  export class VersoriRoundTripperFactory {
19
- constructor(credsClient, platformAPIClient, logger) {
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,6 +60,7 @@ 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;
@@ -74,20 +82,23 @@ export class VersoriRoundTripperFactory {
74
82
  missingVars.push(envVarCredsBaseURL);
75
83
  throw new Error(`Missing environment variables: ${missingVars.join(', ')}`);
76
84
  }
77
- const pAPIClient = new PlatformAPIClient(platformApiBaseURL, orgId, envId);
78
- const tokenClient = new VersoriCredentialClient(credsBaseURL);
79
85
  const log = logger || new ConsoleLogger('debug');
80
- return new VersoriRoundTripperFactory(tokenClient, pAPIClient, log);
86
+ const pAPIClient = new PlatformAPIClient(platformApiBaseURL, orgId, envId, log);
87
+ const tokenClient = new VersoriCredentialClient(credsBaseURL);
88
+ return new VersoriRoundTripperFactory(tokenClient, credsBaseURL, pAPIClient, log);
81
89
  }
82
90
  // takes the info and modifies the url using changeBaseUrl if necessary
91
+ // if a full valid URL is passed as a string, it will be returned as is
92
+ // if a valid URL object is passed, it will be returned as is
83
93
  changeRequestInit(info, conn) {
84
94
  if (typeof info === 'string') {
85
- // should be this most of the time assuming we're using pathnames
95
+ if (isValidURL(info)) {
96
+ return info;
97
+ }
86
98
  return this.changeBaseUrl(info, conn);
87
99
  }
88
100
  else if (info instanceof URL) {
89
- const newUrl = new URL(this.changeBaseUrl(info.toString(), conn));
90
- return newUrl;
101
+ return info;
91
102
  }
92
103
  else if (info instanceof Request) {
93
104
  const url = this.changeBaseUrl(info.url, conn);
@@ -99,6 +110,7 @@ export class VersoriRoundTripperFactory {
99
110
  const connBaseURL = conn.baseUrl;
100
111
  // if the connection has no baseUrl set, but the pathname is a valid URL, return it as is
101
112
  if (!connBaseURL && isValidURL(pathname)) {
113
+ this.log.debug('Using given URL as is', { url: pathname });
102
114
  return pathname;
103
115
  }
104
116
  const connBaseURLObj = new URL(connBaseURL);
@@ -108,36 +120,45 @@ export class VersoriRoundTripperFactory {
108
120
  _pathname = pathnameObj.pathname;
109
121
  }
110
122
  const newURL = new URL(_pathname, connBaseURLObj.origin);
123
+ this.log.debug('Using baseURL from connection', { url: newURL.toString() });
111
124
  return newURL.toString();
112
125
  }
113
- // TODO: Currently if the connection is edited, then the fetcher will not be updated.
114
- async create(connName, fn = globalThis.fetch) {
126
+ create(connName, fn = globalThis.fetch) {
115
127
  const cnxId = this.getConnectionID(connName);
116
- const conn = await this.platformAPIClient.getStaticConnection(cnxId);
117
- if (!conn) {
128
+ if (!cnxId) {
129
+ this.log.debug('Connection not found in config, could be a dynamic connection', {
130
+ connectionName: connName,
131
+ });
118
132
  return undefined;
119
133
  }
120
- const _fn = (input, init) => {
134
+ const _fn = async (input, init) => {
135
+ const conn = await this.platformAPIClient.getStaticConnection(cnxId);
136
+ if (!conn) {
137
+ this.log.error('Connection not found for user, using default fetch', {
138
+ connectionName: connName,
139
+ });
140
+ return globalThis.fetch(input, init);
141
+ }
121
142
  const _input = this.changeRequestInit(input, conn);
122
- return fn(_input, init);
143
+ switch (conn.credentials[0].authSchemeConfig.type) {
144
+ case 'api-key':
145
+ return (await this.apiKeyFetcher(conn, fn))(_input, init);
146
+ case 'basic-auth':
147
+ return (await this.basicAuthFetcher(conn, fn))(_input, init);
148
+ case 'jwt-bearer':
149
+ return (await this.bearerTokenFetcher(conn, fn))(_input, init);
150
+ case 'oauth2':
151
+ return (await this.oauth2Fetcher(conn, fn))(_input, init);
152
+ default:
153
+ return fn(_input, init);
154
+ }
123
155
  };
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
- }
156
+ return _fn;
136
157
  }
137
- async createDynamic(templateName, fn = globalThis.fetch) {
158
+ createDynamic(templateName, fn = globalThis.fetch) {
138
159
  const template = this.getTemplateID(templateName);
139
160
  if (!template) {
140
- this.log.info('Template not found in config, could be a static connection', {
161
+ this.log.debug('Template not found in config, could be a static connection', {
141
162
  templateName: templateName,
142
163
  });
143
164
  return undefined;
@@ -168,7 +189,8 @@ export class VersoriRoundTripperFactory {
168
189
  return _fn;
169
190
  }
170
191
  getConnectionID(connName) {
171
- const conn = this.versoriCfg.mappings.find((c) => (c.dynamic === undefined || c.dynamic === false) && c.name.toLowerCase() === connName.toLowerCase());
192
+ const conn = this.versoriCfg.mappings.find((c) => (c.dynamic === undefined || c.dynamic === false) &&
193
+ c.name.toLowerCase() === connName.toLowerCase());
172
194
  if (!conn || !conn.connId) {
173
195
  return '';
174
196
  }
@@ -181,17 +203,17 @@ export class VersoriRoundTripperFactory {
181
203
  }
182
204
  return template.templateId;
183
205
  }
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) => {
206
+ apiKeyFetcher(conn, fn) {
207
+ const _fn = async (input, init) => {
208
+ const tokenResponse = await this.getToken(conn.credentials[0].credential.id);
209
+ const token = tokenResponse.token?.accessToken;
210
+ const asc = conn.credentials[0].authSchemeConfig.apiKey;
211
+ if (!token) {
212
+ throw new Error('Token not found');
213
+ }
214
+ if (!asc) {
215
+ throw new Error('API Key configuration not found');
216
+ }
195
217
  if (!init) {
196
218
  init = {};
197
219
  }
@@ -229,13 +251,13 @@ export class VersoriRoundTripperFactory {
229
251
  };
230
252
  return _fn;
231
253
  }
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) => {
254
+ basicAuthFetcher(conn, fn) {
255
+ const _fn = async (input, init) => {
256
+ const tokenResponse = await this.getToken(conn.credentials[0].credential.id);
257
+ const token = tokenResponse.token?.accessToken;
258
+ if (!token) {
259
+ throw new Error('Token not found');
260
+ }
239
261
  if (!init) {
240
262
  init = {};
241
263
  }
@@ -259,13 +281,13 @@ export class VersoriRoundTripperFactory {
259
281
  return _fn;
260
282
  }
261
283
  // 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) => {
284
+ bearerTokenFetcher(conn, fn) {
285
+ const _fn = async (input, init) => {
286
+ const tokenResponse = await this.getToken(conn.credentials[0].credential.id);
287
+ const token = tokenResponse.token?.accessToken;
288
+ if (!token) {
289
+ throw new Error('Token not found');
290
+ }
269
291
  if (!init) {
270
292
  init = {};
271
293
  }
@@ -288,27 +310,27 @@ export class VersoriRoundTripperFactory {
288
310
  };
289
311
  return _fn;
290
312
  }
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';
313
+ oauth2Fetcher(conn, fn) {
314
+ const refreshFn = async (input, init, forceRefresh = false) => {
315
+ const tokenResponse = await this.getToken(conn.credentials[0].credential.id, forceRefresh);
316
+ const token = tokenResponse.token?.accessToken;
317
+ const tokenType = tokenResponse.token?.tokenType;
318
+ if (!token) {
319
+ throw new Error('Token not found');
309
320
  }
310
- };
311
- const _fn = (input, init) => {
321
+ const _tokenType = () => {
322
+ const _tt = tokenType?.toLowerCase();
323
+ switch (_tt) {
324
+ case 'bearer':
325
+ return 'Bearer';
326
+ case 'mac':
327
+ return 'MAC';
328
+ case 'basic':
329
+ return 'Basic';
330
+ default:
331
+ return 'Bearer';
332
+ }
333
+ };
312
334
  if (!init) {
313
335
  init = {};
314
336
  }
@@ -329,8 +351,37 @@ export class VersoriRoundTripperFactory {
329
351
  }
330
352
  return fn(input, init);
331
353
  };
354
+ const _fn = async (input, init) => {
355
+ const resp = await refreshFn(input, init, false);
356
+ if (resp.status === 401) {
357
+ this.log.debug('Received 401 Unauthorized response, attempting refresh', {
358
+ url: input,
359
+ status: resp.status,
360
+ });
361
+ // TODO: attempt refresh until precondition failed??
362
+ return refreshFn(input, init, true);
363
+ }
364
+ return Promise.resolve(resp);
365
+ };
332
366
  return _fn;
333
367
  }
368
+ async getToken(id) {
369
+ try {
370
+ return await this.tokenClient.getToken(id);
371
+ }
372
+ catch (error) {
373
+ this.log.error('unable to get credential', { error });
374
+ if (error instanceof ConnectError) {
375
+ if (error.rawMessage.includes("connection error received: not a result of an error") && error.code === Code.Internal) {
376
+ this.log.info('Connection error received, attempting to reconnect');
377
+ this.tokenClient = new VersoriCredentialClient(this.credsBaseURL);
378
+ return await this.tokenClient.getToken(id);
379
+ }
380
+ throw error;
381
+ }
382
+ throw error;
383
+ }
384
+ }
334
385
  }
335
386
  function isValidURL(url) {
336
387
  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;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,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"}
@@ -9,8 +9,9 @@ import { MemoryKeyValueProvider } from '../../kv/memory/MemoryKeyValueProvider.j
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,
@@ -86,12 +99,12 @@ export class MemoryInterpreter {
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, 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"}
@@ -1,4 +1,36 @@
1
1
  import * as log from '../../../deps/jsr.io/@std/log/0.224.14/mod.js';
2
+ function valueOfUnknown(obj, idx) {
3
+ switch (typeof obj) {
4
+ case 'object':
5
+ if (obj instanceof Object) {
6
+ const valueOf = obj.valueOf();
7
+ if (typeof valueOf === 'object' && !Array.isArray(valueOf)) {
8
+ return valueOf;
9
+ }
10
+ return {
11
+ [`arg${idx}`]: obj,
12
+ };
13
+ }
14
+ if (obj === null) {
15
+ return {
16
+ [`arg${idx}`]: null,
17
+ };
18
+ }
19
+ return obj;
20
+ case 'undefined':
21
+ return {
22
+ [`arg${idx}`]: undefined,
23
+ };
24
+ case 'function':
25
+ return {
26
+ [`arg${idx}`]: obj.valueOf(),
27
+ };
28
+ default:
29
+ return {
30
+ [`arg${idx}`]: obj,
31
+ };
32
+ }
33
+ }
2
34
  log.setup({
3
35
  handlers: {
4
36
  default: new log.ConsoleHandler('DEBUG', {
@@ -8,16 +40,29 @@ log.setup({
8
40
  // - args are rendered as a nested object named `args`.
9
41
  //
10
42
  // This implementation uses ISO 8601 time and flattens the args object.
11
- return JSON.stringify({
12
- level: record.levelName,
13
- time: record.datetime.toISOString(),
14
- ...(record.loggerName ? { name: record.loggerName } : {}),
15
- msg: record.msg,
16
- ...(Array.isArray(record.args) ? record.args.reduce((acc, next) => ({
17
- ...acc,
18
- ...(typeof next === 'object' ? next : {}),
19
- }), {}) : {})
20
- });
43
+ try {
44
+ return JSON.stringify({
45
+ level: record.levelName,
46
+ time: record.datetime.toISOString(),
47
+ ...(record.loggerName ? { name: record.loggerName } : {}),
48
+ msg: record.msg,
49
+ ...(Array.isArray(record.args)
50
+ ? (record.args.reduce((acc, next, idx) => ({
51
+ ...acc,
52
+ ...(valueOfUnknown(next, idx)),
53
+ }), {}))
54
+ : {}),
55
+ });
56
+ }
57
+ catch (err) {
58
+ return JSON.stringify({
59
+ level: record.levelName,
60
+ time: record.datetime.toISOString(),
61
+ ...(record.loggerName ? { name: record.loggerName } : {}),
62
+ msg: record.msg,
63
+ LOG_ERROR: `Failed to render args: ${err instanceof Error ? err.message : err}`,
64
+ });
65
+ }
21
66
  },
22
67
  }),
23
68
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versori/run",
3
- "version": "v0.2.0-alpha.1",
3
+ "version": "v0.2.0-alpha.10",
4
4
  "description": "Versori Run",
5
5
  "homepage": "https://github.com/versori/versori-run#readme",
6
6
  "repository": {