javonet-nodejs-sdk 2.6.8 → 2.6.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.
@@ -22,6 +22,11 @@ __export(Handler_exports, {
22
22
  handlers: () => handlers
23
23
  });
24
24
  module.exports = __toCommonJS(Handler_exports);
25
+ var import_CommandType = require("../../utils/CommandType.cjs");
26
+ var import_Command = require("../../utils/Command.cjs");
27
+ var import_TypesHandler = require("../../utils/TypesHandler.cjs");
28
+ var import_ExceptionSerializer = require("../../utils/exception/ExceptionSerializer.cjs");
29
+ var import_AbstractHandler = require("./AbstractHandler.cjs");
25
30
  var import_ReferencesCache = require("../referenceCache/ReferencesCache.cjs");
26
31
  var import_ValueHandler = require("./ValueHandler.cjs");
27
32
  var import_LoadLibraryHandler = require("./LoadLibraryHandler.cjs");
@@ -71,11 +76,8 @@ var import_GetAsyncOperationResultHandler = require("./GetAsyncOperationResultHa
71
76
  var import_AsKwargsHandler = require("./AsKwargsHandler.cjs");
72
77
  var import_GetResultTypeHandler = require("./GetResultTypeHandler.cjs");
73
78
  var import_GetGlobalFieldHandler = require("./GetGlobalFieldHandler.cjs");
74
- var import_CommandType = require("../../utils/CommandType.cjs");
75
- var import_Command = require("../../utils/Command.cjs");
76
- var import_TypesHandler = require("../../utils/TypesHandler.cjs");
77
- var import_ExceptionSerializer = require("../../utils/exception/ExceptionSerializer.cjs");
78
- var import_AbstractHandler = require("./AbstractHandler.cjs");
79
+ var import_RegisterForUpdateHandler = require("./RegisterForUpdateHandler.cjs");
80
+ var import_ValueForUpdateHandler = require("./ValueForUpdateHandler.cjs");
79
81
  const handlers = {
80
82
  [import_CommandType.CommandType.Value]: new import_ValueHandler.ValueHandler(),
81
83
  [import_CommandType.CommandType.LoadLibrary]: new import_LoadLibraryHandler.LoadLibraryHandler(),
@@ -124,7 +126,9 @@ const handlers = {
124
126
  [import_CommandType.CommandType.GetAsyncOperationResult]: new import_GetAsyncOperationResultHandler.GetAsyncOperationResultHandler(),
125
127
  [import_CommandType.CommandType.AsKwargs]: new import_AsKwargsHandler.AsKwargsHandler(),
126
128
  [import_CommandType.CommandType.GetResultType]: new import_GetResultTypeHandler.GetResultTypeHandler(),
127
- [import_CommandType.CommandType.GetGlobalField]: new import_GetGlobalFieldHandler.GetGlobalFieldHandler()
129
+ [import_CommandType.CommandType.GetGlobalField]: new import_GetGlobalFieldHandler.GetGlobalFieldHandler(),
130
+ [import_CommandType.CommandType.RegisterForUpdate]: new import_RegisterForUpdateHandler.RegisterForUpdateHandler(),
131
+ [import_CommandType.CommandType.ValueForUpdate]: new import_ValueForUpdateHandler.ValueForUpdateHandler()
128
132
  };
129
133
  class Handler {
130
134
  /**
@@ -153,9 +157,19 @@ class Handler {
153
157
  const response = handlers[command.commandType].handleCommand(command);
154
158
  return this.parseCommand(response, command.runtimeName);
155
159
  } catch (e) {
156
- return import_ExceptionSerializer.ExceptionSerializer.serializeException(e, command);
160
+ return Handler.resolveException(e, command);
157
161
  }
158
162
  }
163
+ /**
164
+ * Prefer innerException (or cause) when available.
165
+ * @param {any} error
166
+ * @param {Command} command
167
+ * @returns {Command}
168
+ */
169
+ static resolveException(error, command) {
170
+ const inner = error?.cause;
171
+ return import_ExceptionSerializer.ExceptionSerializer.serializeException(inner ?? error, command);
172
+ }
159
173
  /**
160
174
  * @param {any} response
161
175
  * @param {RuntimeName} runtimeName
@@ -167,13 +181,37 @@ class Handler {
167
181
  return this.parseCommand(resolvedResponse, runtimeName);
168
182
  });
169
183
  }
184
+ let responseCommand;
170
185
  if (import_TypesHandler.TypesHandler.isPrimitiveOrNullOrUndefined(response)) {
171
- return import_Command.Command.createResponse(response, runtimeName);
186
+ responseCommand = import_Command.Command.createResponse(response, runtimeName);
172
187
  } else {
173
- let cache = import_ReferencesCache.ReferencesCache.getInstance();
174
- let uuid = cache.cacheReference(response);
175
- return import_Command.Command.createReference(uuid, runtimeName);
188
+ const refCache = import_ReferencesCache.ReferencesCache.getInstance();
189
+ const uuid = refCache.cacheReference(response);
190
+ responseCommand = import_Command.Command.createReference(uuid, runtimeName);
191
+ }
192
+ const invocationContexts = import_RegisterForUpdateHandler.RegisterForUpdateHandler._invocationContexts.Value;
193
+ if (invocationContexts && invocationContexts.size > 0) {
194
+ const refCache = import_ReferencesCache.ReferencesCache.getInstance();
195
+ for (const [contextKey, instance] of invocationContexts.entries()) {
196
+ const instanceGuid = refCache.cacheReference(instance);
197
+ const updateContextCommand = new import_Command.Command(
198
+ runtimeName,
199
+ import_CommandType.CommandType.ValueForUpdate,
200
+ [
201
+ contextKey.toString(),
202
+ instanceGuid
203
+ ]
204
+ );
205
+ if (typeof responseCommand.addArgToPayload === "function") {
206
+ responseCommand = responseCommand.addArgToPayload(updateContextCommand);
207
+ } else {
208
+ responseCommand.payload = responseCommand.payload || [];
209
+ responseCommand.payload.push(updateContextCommand);
210
+ }
211
+ }
212
+ invocationContexts.clear();
176
213
  }
214
+ return responseCommand;
177
215
  }
178
216
  }
179
217
  // Annotate the CommonJS export names for ESM import in node:
@@ -44,7 +44,7 @@ class InvokeInstanceMethodHandler extends import_AbstractHandler.AbstractHandler
44
44
  let methods = Object.getOwnPropertyNames(instance.__proto__).filter(function(property) {
45
45
  return typeof instance.__proto__[property] === "function";
46
46
  });
47
- let message = `Method ${methodName} not found in object. Available methods:
47
+ let message = `Method ${methodName} not found in object ${instance.constructor.name}. Available methods:
48
48
  `;
49
49
  methods.forEach((methodIter) => {
50
50
  message += `${methodIter}
@@ -44,7 +44,7 @@ class InvokeStaticMethodHandler extends import_AbstractHandler.AbstractHandler {
44
44
  let methods = Object.getOwnPropertyNames(type).filter(function(property) {
45
45
  return typeof type[property] === "function";
46
46
  });
47
- let message = `Method ${methodName} not found in class. Available methods:
47
+ let message = `Method ${methodName} not found in class ${type.name}. Available methods:
48
48
  `;
49
49
  methods.forEach((methodIter) => {
50
50
  message += `${methodIter}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var RegisterForUpdateHandler_exports = {};
20
+ __export(RegisterForUpdateHandler_exports, {
21
+ RegisterForUpdateHandler: () => RegisterForUpdateHandler
22
+ });
23
+ module.exports = __toCommonJS(RegisterForUpdateHandler_exports);
24
+ var import_AbstractHandler = require("./AbstractHandler.cjs");
25
+ class RegisterForUpdateHandler extends import_AbstractHandler.AbstractHandler {
26
+ requiredParametersCount = 2;
27
+ /* type {Map<string, any>} */
28
+ static _invocationContexts = { Value: /* @__PURE__ */ new Map() };
29
+ /**
30
+ * Ensure context map exists and return it.
31
+ * @returns {Map<string, any>}
32
+ */
33
+ static getOrCreateContextMap() {
34
+ const container = RegisterForUpdateHandler._invocationContexts;
35
+ if (!container.Value) {
36
+ container.Value = /* @__PURE__ */ new Map();
37
+ }
38
+ return container.Value;
39
+ }
40
+ /**
41
+ * @param {any} command
42
+ * @returns {any}
43
+ */
44
+ process(command) {
45
+ if (command.payload.length < this.requiredParametersCount) {
46
+ throw new Error("RegisterForUpdateHandler parameters mismatch");
47
+ }
48
+ const objectToRegister = command.payload[0];
49
+ const guidToRegister = command.payload.length > 1 && typeof command.payload[1] === "string" ? command.payload[1] : "";
50
+ const contextMap = RegisterForUpdateHandler.getOrCreateContextMap();
51
+ if (!contextMap.has(guidToRegister)) {
52
+ contextMap.set(guidToRegister, objectToRegister);
53
+ }
54
+ return objectToRegister;
55
+ }
56
+ }
57
+ // Annotate the CommonJS export names for ESM import in node:
58
+ 0 && (module.exports = {
59
+ RegisterForUpdateHandler
60
+ });
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var ValueForUpdateHandler_exports = {};
20
+ __export(ValueForUpdateHandler_exports, {
21
+ ValueForUpdateHandler: () => ValueForUpdateHandler
22
+ });
23
+ module.exports = __toCommonJS(ValueForUpdateHandler_exports);
24
+ var import_AbstractHandler = require("./AbstractHandler.cjs");
25
+ class ValueForUpdateHandler extends import_AbstractHandler.AbstractHandler {
26
+ /**
27
+ * @param {any} command
28
+ */
29
+ process(command) {
30
+ throw new Error(`${this.constructor.name} is not implemented in Node.js`);
31
+ }
32
+ }
33
+ // Annotate the CommonJS export names for ESM import in node:
34
+ 0 && (module.exports = {
35
+ ValueForUpdateHandler
36
+ });
@@ -25,10 +25,22 @@ var import_DelegatesCache = require("../core/delegatesCache/DelegatesCache.cjs")
25
25
  var import_Interpreter = require("../core/interpreter/Interpreter.cjs");
26
26
  var import_Command = require("../utils/Command.cjs");
27
27
  var import_CommandType = require("../utils/CommandType.cjs");
28
- var import_ConnectionType = require("../utils/ConnectionType.cjs");
29
28
  var import_ExceptionThrower = require("../utils/exception/ExceptionThrower.cjs");
30
29
  var import_RuntimeName = require("../utils/RuntimeName.cjs");
31
30
  var import_TypesHandler = require("../utils/TypesHandler.cjs");
31
+ var import_uuid = require("uuid");
32
+ class AsyncLock {
33
+ constructor() {
34
+ this._tail = Promise.resolve();
35
+ }
36
+ async lock() {
37
+ let release;
38
+ const prev = this._tail;
39
+ this._tail = new Promise((res) => release = res);
40
+ await prev;
41
+ return () => release(void 0);
42
+ }
43
+ }
32
44
  class InvocationContext {
33
45
  /** @type {RuntimeNameType} */
34
46
  #runtimeName;
@@ -42,6 +54,12 @@ class InvocationContext {
42
54
  #isExecuted = false;
43
55
  /** @type {Interpreter | null} */
44
56
  #interpreter = null;
57
+ /** @type {string | null} */
58
+ #guid = null;
59
+ /** @type {AsyncLock} */
60
+ #materializationLock = new AsyncLock();
61
+ // Static map holding contexts waiting for materialization (guid -> InvocationContext)
62
+ static _invocationContexts = /* @__PURE__ */ new Map();
45
63
  /**
46
64
  *
47
65
  * @param {RuntimeNameType} runtimeName
@@ -56,6 +74,13 @@ class InvocationContext {
56
74
  this.#responseCommand = null;
57
75
  this.#isExecuted = isExecuted;
58
76
  this.#interpreter = null;
77
+ this.#guid = (0, import_uuid.v4)();
78
+ }
79
+ /**
80
+ * @returns {string} guid of this InvocationContext
81
+ */
82
+ getGuid() {
83
+ return this.#guid;
59
84
  }
60
85
  /**
61
86
  * @param {Command} localCommand
@@ -71,7 +96,7 @@ class InvocationContext {
71
96
  /**
72
97
  * @returns {Command|null}
73
98
  */
74
- get_current_command() {
99
+ getCurrentCommand() {
75
100
  return this.#currentCommand;
76
101
  }
77
102
  //destructor() {
@@ -101,13 +126,8 @@ class InvocationContext {
101
126
  }
102
127
  /**
103
128
  * Executes the current command.
104
- * Because invocation context is building the intent of executing particular expression on target environment, we call the initial state of invocation context as non-materialized.
105
- * The non-materialized context wraps either single command or chain of recursively nested commands.
106
- * Commands are becoming nested through each invocation of methods on Invocation Context.
107
- * Each invocation triggers the creation of new Invocation Context instance wrapping the current command with new parent command valid for invoked method.
108
- * Developer can decide on any moment of the materialization for the context taking full control of the chunks of the expression being transferred and processed on target runtime.
109
- * @returns {Promise<InvocationContext>} the InvocationContext after executing the command.
110
- * @see [Javonet Guides](https://www.javonet.com/guides/v2/javascript/foundations/execute-method)
129
+ * Returns the InvocationContext after executing the command.
130
+ * @returns {Promise<InvocationContext>}
111
131
  * @method
112
132
  */
113
133
  async execute() {
@@ -117,19 +137,73 @@ class InvocationContext {
117
137
  if (!this.#interpreter) {
118
138
  this.#interpreter = new import_Interpreter.Interpreter();
119
139
  }
120
- this.#responseCommand = await this.#interpreter.execute(this.#currentCommand, this.#connectionData);
121
- if (!this.#responseCommand) {
122
- throw new Error("responseCommand is undefined in Invocation Context execute method");
140
+ const entries = Array.from(InvocationContext._invocationContexts.entries());
141
+ entries.sort((a, b) => String(a[0]).localeCompare(String(b[0])));
142
+ const releases = [];
143
+ for (const [, ic] of entries) {
144
+ const release = await ic.#materializationLock.lock();
145
+ releases.push(release);
123
146
  }
124
- if (this.#responseCommand.commandType === import_CommandType.CommandType.Exception) {
125
- throw import_ExceptionThrower.ExceptionThrower.throwException(this.#responseCommand);
147
+ try {
148
+ this.#responseCommand = await this.#interpreter.execute(this.#currentCommand, this.#connectionData);
149
+ if (!this.#responseCommand) {
150
+ throw new Error("responseCommand is undefined in Invocation Context execute method");
151
+ }
152
+ if (this.#responseCommand.commandType === import_CommandType.CommandType.Exception) {
153
+ throw import_ExceptionThrower.ExceptionThrower.throwException(this.#responseCommand);
154
+ }
155
+ this.#responseCommand = this.#processUpdateInvocationContextCommands(this.#responseCommand);
156
+ if (this.#responseCommand.commandType === import_CommandType.CommandType.CreateClassInstance) {
157
+ this.#currentCommand = this.#responseCommand;
158
+ this.#isExecuted = true;
159
+ return this;
160
+ }
161
+ return new InvocationContext(this.#runtimeName, this.#connectionData, this.#responseCommand, true);
162
+ } finally {
163
+ for (let i = releases.length - 1; i >= 0; i--) {
164
+ try {
165
+ releases[i]();
166
+ } catch {
167
+ }
168
+ }
126
169
  }
127
- if (this.#responseCommand.commandType === import_CommandType.CommandType.CreateClassInstance) {
128
- this.#currentCommand = this.#responseCommand;
129
- this.#isExecuted = true;
130
- return this;
170
+ }
171
+ /**
172
+ * Process UpdateInvocationContext commands in the provided responseCommand payload.
173
+ * For each ValueForUpdate command, set the referenced InvocationContext's currentCommand to a Reference command,
174
+ * remove that InvocationContext from the static map and remove ValueForUpdate items from response payload.
175
+ * @param {Command} responseCommand
176
+ * @returns {Command}
177
+ */
178
+ #processUpdateInvocationContextCommands(responseCommand) {
179
+ if (!responseCommand?.payload || responseCommand.payload.length === 0) {
180
+ return responseCommand;
181
+ }
182
+ const commandsToUpdate = [];
183
+ for (const item of responseCommand.payload) {
184
+ if (item instanceof import_Command.Command && item.commandType === import_CommandType.CommandType.ValueForUpdate) {
185
+ commandsToUpdate.push(item);
186
+ }
187
+ }
188
+ if (commandsToUpdate.length === 0) {
189
+ return responseCommand;
190
+ }
191
+ const updatedPayload = Array.from(responseCommand.payload);
192
+ for (const cmd of commandsToUpdate) {
193
+ const cmdPayload = cmd.payload;
194
+ if (cmdPayload && cmdPayload.length >= 2) {
195
+ const contextGuid = String(cmdPayload[0]);
196
+ const instanceGuid = String(cmdPayload[1]);
197
+ const invCtx = InvocationContext._invocationContexts.get(contextGuid);
198
+ if (invCtx) {
199
+ invCtx.#currentCommand = new import_Command.Command(invCtx.#runtimeName, import_CommandType.CommandType.Reference, [instanceGuid]);
200
+ InvocationContext._invocationContexts.delete(contextGuid);
201
+ }
202
+ }
203
+ const idx = updatedPayload.indexOf(cmd);
204
+ if (idx >= 0) updatedPayload.splice(idx, 1);
131
205
  }
132
- return new InvocationContext(this.#runtimeName, this.#connectionData, this.#responseCommand, true);
206
+ return new import_Command.Command(responseCommand.runtimeName, responseCommand.commandType, updatedPayload);
133
207
  }
134
208
  /**
135
209
  * Invokes a static method on the target runtime.
@@ -171,14 +245,25 @@ class InvocationContext {
171
245
  }
172
246
  /**
173
247
  * Creates a new instance of a class in the target runtime.
248
+ * Adds the newly created context to the static invocation contexts map and
249
+ * includes the context GUID as the first argument of CreateClassInstance command payload.
174
250
  * @param {...any} args - The arguments to pass to the class constructor
175
251
  * @returns {InvocationContext} A new InvocationContext instance that wraps the command to create the instance.
176
- * @see [Javonet Guides](https://www.javonet.com/guides/v2/javascript/calling-methods/creating-instance-and-calling-instance-methods)
177
252
  * @method
178
253
  */
179
254
  createInstance(...args) {
180
- let localCommand = new import_Command.Command(this.#runtimeName, import_CommandType.CommandType.CreateClassInstance, args);
181
- return this.#createInstanceContext(localCommand);
255
+ const localCommand = new import_Command.Command(this.#runtimeName, import_CommandType.CommandType.CreateClassInstance, [...args]);
256
+ const createInstanceInvCtx = this.#createInstanceContext(localCommand);
257
+ return createInstanceInvCtx.#registerForUpdate();
258
+ }
259
+ /**
260
+ * Registers the current InvocationContext for updates.
261
+ * @returns {InvocationContext}
262
+ */
263
+ #registerForUpdate() {
264
+ this.#currentCommand = this.#buildCommand(new import_Command.Command(this.#runtimeName, import_CommandType.CommandType.RegisterForUpdate, [this.getGuid()]));
265
+ InvocationContext._invocationContexts.set(this.getGuid(), this);
266
+ return this;
182
267
  }
183
268
  /**
184
269
  * Retrieves the value of an instance field from the target runtime.
@@ -450,7 +535,7 @@ class InvocationContext {
450
535
  }
451
536
  return payloadItem;
452
537
  } else if (payloadItem instanceof InvocationContext) {
453
- return payloadItem.get_current_command();
538
+ return payloadItem.getCurrentCommand();
454
539
  } else if (payloadItem instanceof Array) {
455
540
  const copiedArray = payloadItem.map((item) => this.#encapsulatePayloadItem(item));
456
541
  return new import_Command.Command(this.#runtimeName, import_CommandType.CommandType.Array, copiedArray);
@@ -284,7 +284,7 @@ class RuntimeContext {
284
284
  }
285
285
  return payloadItem;
286
286
  } else if (payloadItem instanceof import_InvocationContext.InvocationContext) {
287
- const command = payloadItem?.get_current_command();
287
+ const command = payloadItem?.getCurrentCommand();
288
288
  if (!command) {
289
289
  throw new Error("Command not found");
290
290
  }
@@ -1,5 +1,12 @@
1
1
  export type RuntimeName = import("../../types.d.ts").RuntimeName;
2
2
  export class Handler {
3
+ /**
4
+ * Prefer innerException (or cause) when available.
5
+ * @param {any} error
6
+ * @param {Command} command
7
+ * @returns {Command}
8
+ */
9
+ static resolveException(error: any, command: Command): Command;
3
10
  /**
4
11
  * @param {import('../interpreter/Interpreter.js').Interpreter} interpreter
5
12
  */
@@ -0,0 +1,17 @@
1
+ export class RegisterForUpdateHandler extends AbstractHandler {
2
+ static _invocationContexts: {
3
+ Value: Map<any, any>;
4
+ };
5
+ /**
6
+ * Ensure context map exists and return it.
7
+ * @returns {Map<string, any>}
8
+ */
9
+ static getOrCreateContextMap(): Map<string, any>;
10
+ requiredParametersCount: number;
11
+ /**
12
+ * @param {any} command
13
+ * @returns {any}
14
+ */
15
+ process(command: any): any;
16
+ }
17
+ import { AbstractHandler } from './AbstractHandler.js';
@@ -0,0 +1,7 @@
1
+ export class ValueForUpdateHandler extends AbstractHandler {
2
+ /**
3
+ * @param {any} command
4
+ */
5
+ process(command: any): void;
6
+ }
7
+ import { AbstractHandler } from './AbstractHandler.js';
@@ -1,9 +1,5 @@
1
1
  export type RuntimeNameType = import("../types.d.ts").RuntimeName;
2
2
  export type IConnectionData = import("../utils/connectionData/IConnectionData.js").IConnectionData;
3
- /**
4
- * @typedef {import('../types.d.ts').RuntimeName} RuntimeNameType
5
- * @typedef {import('../utils/connectionData/IConnectionData.js').IConnectionData} IConnectionData
6
- */
7
3
  /**
8
4
  * InvocationContext is a class that represents a context for invoking commands.
9
5
  * It implements several interfaces for different types of interactions.
@@ -12,6 +8,7 @@ export type IConnectionData = import("../utils/connectionData/IConnectionData.js
12
8
  * @class
13
9
  */
14
10
  export class InvocationContext {
11
+ static _invocationContexts: Map<any, any>;
15
12
  /**
16
13
  *
17
14
  * @param {RuntimeNameType} runtimeName
@@ -20,19 +17,18 @@ export class InvocationContext {
20
17
  * @param {boolean} isExecuted
21
18
  */
22
19
  constructor(runtimeName: RuntimeNameType, connectionData: IConnectionData, command: Command, isExecuted?: boolean);
20
+ /**
21
+ * @returns {string} guid of this InvocationContext
22
+ */
23
+ getGuid(): string;
23
24
  /**
24
25
  * @returns {Command|null}
25
26
  */
26
- get_current_command(): Command | null;
27
+ getCurrentCommand(): Command | null;
27
28
  /**
28
29
  * Executes the current command.
29
- * Because invocation context is building the intent of executing particular expression on target environment, we call the initial state of invocation context as non-materialized.
30
- * The non-materialized context wraps either single command or chain of recursively nested commands.
31
- * Commands are becoming nested through each invocation of methods on Invocation Context.
32
- * Each invocation triggers the creation of new Invocation Context instance wrapping the current command with new parent command valid for invoked method.
33
- * Developer can decide on any moment of the materialization for the context taking full control of the chunks of the expression being transferred and processed on target runtime.
34
- * @returns {Promise<InvocationContext>} the InvocationContext after executing the command.
35
- * @see [Javonet Guides](https://www.javonet.com/guides/v2/javascript/foundations/execute-method)
30
+ * Returns the InvocationContext after executing the command.
31
+ * @returns {Promise<InvocationContext>}
36
32
  * @method
37
33
  */
38
34
  execute(): Promise<InvocationContext>;
@@ -64,9 +60,10 @@ export class InvocationContext {
64
60
  setStaticField(fieldName: string, value: any): InvocationContext;
65
61
  /**
66
62
  * Creates a new instance of a class in the target runtime.
63
+ * Adds the newly created context to the static invocation contexts map and
64
+ * includes the context GUID as the first argument of CreateClassInstance command payload.
67
65
  * @param {...any} args - The arguments to pass to the class constructor
68
66
  * @returns {InvocationContext} A new InvocationContext instance that wraps the command to create the instance.
69
- * @see [Javonet Guides](https://www.javonet.com/guides/v2/javascript/calling-methods/creating-instance-and-calling-instance-methods)
70
67
  * @method
71
68
  */
72
69
  createInstance(...args: any[]): InvocationContext;
@@ -47,4 +47,6 @@ export namespace CommandType {
47
47
  let AsKwargs: 45;
48
48
  let GetResultType: 46;
49
49
  let GetGlobalField: 47;
50
+ let RegisterForUpdate: 48;
51
+ let ValueForUpdate: 49;
50
52
  }
@@ -71,7 +71,9 @@ const CommandType = (
71
71
  GetAsyncOperationResult: 44,
72
72
  AsKwargs: 45,
73
73
  GetResultType: 46,
74
- GetGlobalField: 47
74
+ GetGlobalField: 47,
75
+ RegisterForUpdate: 48,
76
+ ValueForUpdate: 49
75
77
  }
76
78
  );
77
79
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,4 +1,11 @@
1
1
  //@ts-check
2
+
3
+ import { CommandType } from '../../utils/CommandType.js'
4
+ import { Command } from '../../utils/Command.js'
5
+ import { TypesHandler } from '../../utils/TypesHandler.js'
6
+ import { ExceptionSerializer } from '../../utils/exception/ExceptionSerializer.js'
7
+ import { AbstractHandler } from './AbstractHandler.js'
8
+
2
9
  import { ReferencesCache } from '../referenceCache/ReferencesCache.js'
3
10
  import { ValueHandler } from './ValueHandler.js'
4
11
  import { LoadLibraryHandler } from './LoadLibraryHandler.js'
@@ -48,11 +55,8 @@ import { GetAsyncOperationResultHandler } from './GetAsyncOperationResultHandler
48
55
  import { AsKwargsHandler } from './AsKwargsHandler.js'
49
56
  import { GetResultTypeHandler } from './GetResultTypeHandler.js'
50
57
  import { GetGlobalFieldHandler } from './GetGlobalFieldHandler.js'
51
- import { CommandType } from '../../utils/CommandType.js'
52
- import { Command } from '../../utils/Command.js'
53
- import { TypesHandler } from '../../utils/TypesHandler.js'
54
- import { ExceptionSerializer } from '../../utils/exception/ExceptionSerializer.js'
55
- import { AbstractHandler } from './AbstractHandler.js'
58
+ import { RegisterForUpdateHandler } from './RegisterForUpdateHandler.js'
59
+ import { ValueForUpdateHandler } from './ValueForUpdateHandler.js'
56
60
 
57
61
  /**
58
62
  * @typedef {import('../../types.d.ts').RuntimeName} RuntimeName
@@ -110,6 +114,8 @@ const handlers = {
110
114
  [CommandType.AsKwargs]: new AsKwargsHandler(),
111
115
  [CommandType.GetResultType]: new GetResultTypeHandler(),
112
116
  [CommandType.GetGlobalField]: new GetGlobalFieldHandler(),
117
+ [CommandType.RegisterForUpdate]: new RegisterForUpdateHandler(),
118
+ [CommandType.ValueForUpdate]: new ValueForUpdateHandler(),
113
119
  }
114
120
 
115
121
  class Handler {
@@ -144,14 +150,26 @@ class Handler {
144
150
  const responseArray = handlers[CommandType.Reference].handleCommand(command.payload[0])
145
151
  return Command.createArrayResponse(responseArray, command.runtimeName)
146
152
  }
153
+
147
154
  /** @type {any} */
148
155
  const response = handlers[command.commandType].handleCommand(command)
149
156
  return this.parseCommand(response, command.runtimeName)
150
157
  } catch (e) {
151
- return ExceptionSerializer.serializeException(e, command)
158
+ return Handler.resolveException(e, command)
152
159
  }
153
160
  }
154
161
 
162
+ /**
163
+ * Prefer innerException (or cause) when available.
164
+ * @param {any} error
165
+ * @param {Command} command
166
+ * @returns {Command}
167
+ */
168
+ static resolveException(error, command) {
169
+ const inner = error?.cause
170
+ return ExceptionSerializer.serializeException(inner ?? error, command)
171
+ }
172
+
155
173
  /**
156
174
  * @param {any} response
157
175
  * @param {RuntimeName} runtimeName
@@ -164,13 +182,41 @@ class Handler {
164
182
  })
165
183
  }
166
184
 
185
+ let responseCommand
167
186
  if (TypesHandler.isPrimitiveOrNullOrUndefined(response)) {
168
- return Command.createResponse(response, runtimeName)
187
+ responseCommand = Command.createResponse(response, runtimeName)
169
188
  } else {
170
- let cache = ReferencesCache.getInstance()
171
- let uuid = cache.cacheReference(response)
172
- return Command.createReference(uuid, runtimeName)
189
+ const refCache = ReferencesCache.getInstance()
190
+ const uuid = refCache.cacheReference(response)
191
+ responseCommand = Command.createReference(uuid, runtimeName)
192
+ }
193
+
194
+ const invocationContexts = RegisterForUpdateHandler._invocationContexts.Value
195
+ if (invocationContexts && invocationContexts.size > 0) {
196
+ const refCache = ReferencesCache.getInstance()
197
+ for (const [contextKey, instance] of invocationContexts.entries()) {
198
+ const instanceGuid = refCache.cacheReference(instance)
199
+
200
+ const updateContextCommand = new Command(
201
+ runtimeName,
202
+ CommandType.ValueForUpdate,
203
+ [contextKey.toString(),
204
+ instanceGuid]
205
+ )
206
+
207
+ if (typeof responseCommand.addArgToPayload === 'function') {
208
+ responseCommand = responseCommand.addArgToPayload(updateContextCommand)
209
+ } else {
210
+ responseCommand.payload = responseCommand.payload || []
211
+ responseCommand.payload.push(updateContextCommand)
212
+ }
213
+ }
214
+
215
+ // Clear all entries after processing this request
216
+ invocationContexts.clear()
173
217
  }
218
+
219
+ return responseCommand
174
220
  }
175
221
  }
176
222
 
@@ -29,7 +29,7 @@ class InvokeInstanceMethodHandler extends AbstractHandler {
29
29
  let methods = Object.getOwnPropertyNames(instance.__proto__).filter(function (property) {
30
30
  return typeof instance.__proto__[property] === 'function'
31
31
  })
32
- let message = `Method ${methodName} not found in object. Available methods:\n`
32
+ let message = `Method ${methodName} not found in object ${instance.constructor.name}. Available methods:\n`
33
33
  methods.forEach((methodIter) => {
34
34
  message += `${methodIter}\n`
35
35
  })
@@ -29,7 +29,7 @@ class InvokeStaticMethodHandler extends AbstractHandler {
29
29
  let methods = Object.getOwnPropertyNames(type).filter(function (property) {
30
30
  return typeof type[property] === 'function'
31
31
  })
32
- let message = `Method ${methodName} not found in class. Available methods:\n`
32
+ let message = `Method ${methodName} not found in class ${type.name}. Available methods:\n`
33
33
  methods.forEach((methodIter) => {
34
34
  message += `${methodIter}\n`
35
35
  })
@@ -0,0 +1,40 @@
1
+ // @ts-check
2
+ import { AbstractHandler } from './AbstractHandler.js'
3
+
4
+ export class RegisterForUpdateHandler extends AbstractHandler {
5
+ requiredParametersCount = 2
6
+ /* type {Map<string, any>} */
7
+ static _invocationContexts = { Value: new Map() }
8
+
9
+ /**
10
+ * Ensure context map exists and return it.
11
+ * @returns {Map<string, any>}
12
+ */
13
+ static getOrCreateContextMap() {
14
+ const container = RegisterForUpdateHandler._invocationContexts
15
+ if (!container.Value) {
16
+ container.Value = new Map()
17
+ }
18
+ return container.Value
19
+ }
20
+
21
+ /**
22
+ * @param {any} command
23
+ * @returns {any}
24
+ */
25
+ process(command) {
26
+ if (command.payload.length < this.requiredParametersCount) {
27
+ throw new Error('RegisterForUpdateHandler parameters mismatch')
28
+ }
29
+
30
+ const objectToRegister = command.payload[0]
31
+ const guidToRegister = command.payload.length > 1 && typeof command.payload[1] === 'string' ? command.payload[1] : '' // Guid.Empty -> empty string
32
+
33
+ const contextMap = RegisterForUpdateHandler.getOrCreateContextMap()
34
+ if (!contextMap.has(guidToRegister)) {
35
+ contextMap.set(guidToRegister, objectToRegister)
36
+ }
37
+
38
+ return objectToRegister
39
+ }
40
+ }
@@ -0,0 +1,11 @@
1
+ // @ts-check
2
+ import { AbstractHandler } from './AbstractHandler.js'
3
+
4
+ export class ValueForUpdateHandler extends AbstractHandler {
5
+ /**
6
+ * @param {any} command
7
+ */
8
+ process(command) {
9
+ throw new Error(`${this.constructor.name} is not implemented in Node.js`)
10
+ }
11
+ }
@@ -3,16 +3,35 @@ import { delegatesCacheInstance } from '../core/delegatesCache/DelegatesCache.js
3
3
  import { Interpreter } from '../core/interpreter/Interpreter.js'
4
4
  import { Command } from '../utils/Command.js'
5
5
  import { CommandType } from '../utils/CommandType.js'
6
- import { ConnectionType } from '../utils/ConnectionType.js'
7
6
  import { ExceptionThrower } from '../utils/exception/ExceptionThrower.js'
8
7
  import { RuntimeName } from '../utils/RuntimeName.js'
9
8
  import { TypesHandler } from '../utils/TypesHandler.js'
9
+ import { v4 as uuidv4 } from 'uuid' // add lightweight uuid generation
10
10
 
11
11
  /**
12
12
  * @typedef {import('../types.d.ts').RuntimeName} RuntimeNameType
13
13
  * @typedef {import('../utils/connectionData/IConnectionData.js').IConnectionData} IConnectionData
14
14
  */
15
15
 
16
+ /**
17
+ * Simple async lock implementation to ensure sequential execution of critical sections.
18
+ */
19
+ class AsyncLock {
20
+ constructor() {
21
+ this._tail = Promise.resolve()
22
+ }
23
+ async lock() {
24
+ /**
25
+ * @type {(value?: any) => void}
26
+ */
27
+ let release
28
+ const prev = this._tail
29
+ this._tail = new Promise((res) => (release = res))
30
+ await prev
31
+ return () => release(undefined)
32
+ }
33
+ }
34
+
16
35
  /**
17
36
  * InvocationContext is a class that represents a context for invoking commands.
18
37
  * It implements several interfaces for different types of interactions.
@@ -33,6 +52,13 @@ class InvocationContext {
33
52
  #isExecuted = false
34
53
  /** @type {Interpreter | null} */
35
54
  #interpreter = null
55
+ /** @type {string | null} */
56
+ #guid = null
57
+ /** @type {AsyncLock} */
58
+ #materializationLock = new AsyncLock()
59
+
60
+ // Static map holding contexts waiting for materialization (guid -> InvocationContext)
61
+ static _invocationContexts = new Map()
36
62
 
37
63
  /**
38
64
  *
@@ -48,6 +74,15 @@ class InvocationContext {
48
74
  this.#responseCommand = null
49
75
  this.#isExecuted = isExecuted
50
76
  this.#interpreter = null
77
+ this.#guid = uuidv4()
78
+ }
79
+
80
+ /**
81
+ * @returns {string} guid of this InvocationContext
82
+ */
83
+ getGuid() {
84
+ // @ts-ignore
85
+ return this.#guid
51
86
  }
52
87
 
53
88
  /**
@@ -65,7 +100,7 @@ class InvocationContext {
65
100
  /**
66
101
  * @returns {Command|null}
67
102
  */
68
- get_current_command() {
103
+ getCurrentCommand() {
69
104
  return this.#currentCommand
70
105
  }
71
106
 
@@ -99,38 +134,100 @@ class InvocationContext {
99
134
 
100
135
  /**
101
136
  * Executes the current command.
102
- * Because invocation context is building the intent of executing particular expression on target environment, we call the initial state of invocation context as non-materialized.
103
- * The non-materialized context wraps either single command or chain of recursively nested commands.
104
- * Commands are becoming nested through each invocation of methods on Invocation Context.
105
- * Each invocation triggers the creation of new Invocation Context instance wrapping the current command with new parent command valid for invoked method.
106
- * Developer can decide on any moment of the materialization for the context taking full control of the chunks of the expression being transferred and processed on target runtime.
107
- * @returns {Promise<InvocationContext>} the InvocationContext after executing the command.
108
- * @see [Javonet Guides](https://www.javonet.com/guides/v2/javascript/foundations/execute-method)
137
+ * Returns the InvocationContext after executing the command.
138
+ * @returns {Promise<InvocationContext>}
109
139
  * @method
110
140
  */
111
141
  async execute() {
112
142
  if (this.#currentCommand === null) {
113
143
  throw new Error('currentCommand is undefined in Invocation Context execute method')
114
144
  }
115
-
116
145
  if (!this.#interpreter) {
117
146
  this.#interpreter = new Interpreter()
118
147
  }
119
148
 
120
- this.#responseCommand = await this.#interpreter.execute(this.#currentCommand, this.#connectionData)
149
+ // Zablokuj wszystkie konteksty do materializacji w deterministycznej kolejności (po GUID)
150
+ const entries = Array.from(InvocationContext._invocationContexts.entries())
151
+ entries.sort((a, b) => String(a[0]).localeCompare(String(b[0])))
152
+ const releases = []
153
+ for (const [, ic] of entries) {
154
+ // eslint-disable-next-line no-await-in-loop
155
+ const release = await ic.#materializationLock.lock()
156
+ releases.push(release)
157
+ }
158
+
159
+ try {
160
+ // Execute command on interpreter
161
+ this.#responseCommand = await this.#interpreter.execute(this.#currentCommand, this.#connectionData)
162
+
163
+ if (!this.#responseCommand) {
164
+ throw new Error('responseCommand is undefined in Invocation Context execute method')
165
+ }
166
+ if (this.#responseCommand.commandType === CommandType.Exception) {
167
+ throw ExceptionThrower.throwException(this.#responseCommand)
168
+ }
169
+
170
+ // Process ValueForUpdate commands (jeśli są) przychodzące z runtime
171
+ this.#responseCommand = this.#processUpdateInvocationContextCommands(this.#responseCommand)
121
172
 
122
- if (!this.#responseCommand) {
123
- throw new Error('responseCommand is undefined in Invocation Context execute method')
173
+ if (this.#responseCommand.commandType === CommandType.CreateClassInstance) {
174
+ this.#currentCommand = this.#responseCommand
175
+ this.#isExecuted = true
176
+ return this
177
+ }
178
+ return new InvocationContext(this.#runtimeName, this.#connectionData, this.#responseCommand, true)
179
+ } finally {
180
+ // Zwolnij locki w odwrotnej kolejności
181
+ for (let i = releases.length - 1; i >= 0; i--) {
182
+ try { releases[i]() } catch { /* ignore */ }
183
+ }
124
184
  }
125
- if (this.#responseCommand.commandType === CommandType.Exception) {
126
- throw ExceptionThrower.throwException(this.#responseCommand)
185
+ }
186
+
187
+ /**
188
+ * Process UpdateInvocationContext commands in the provided responseCommand payload.
189
+ * For each ValueForUpdate command, set the referenced InvocationContext's currentCommand to a Reference command,
190
+ * remove that InvocationContext from the static map and remove ValueForUpdate items from response payload.
191
+ * @param {Command} responseCommand
192
+ * @returns {Command}
193
+ */
194
+ #processUpdateInvocationContextCommands(responseCommand) {
195
+ if (!responseCommand?.payload || responseCommand.payload.length === 0) {
196
+ return responseCommand
127
197
  }
128
- if (this.#responseCommand.commandType === CommandType.CreateClassInstance) {
129
- this.#currentCommand = this.#responseCommand
130
- this.#isExecuted = true
131
- return this
198
+
199
+ /** @type {Command[]} */
200
+ const commandsToUpdate = []
201
+ for (const item of responseCommand.payload) {
202
+ if (item instanceof Command && item.commandType === CommandType.ValueForUpdate) {
203
+ commandsToUpdate.push(item)
204
+ }
205
+ }
206
+ if (commandsToUpdate.length === 0) {
207
+ return responseCommand
208
+ }
209
+
210
+ // create a copy of the payload to modify
211
+ const updatedPayload = Array.from(responseCommand.payload)
212
+
213
+ // update each InvocationContext referenced in ValueForUpdate commands
214
+ for (const cmd of commandsToUpdate) {
215
+ const cmdPayload = cmd.payload
216
+ if (cmdPayload && cmdPayload.length >= 2) {
217
+ const contextGuid = String(cmdPayload[0])
218
+ const instanceGuid = String(cmdPayload[1])
219
+ const invCtx = InvocationContext._invocationContexts.get(contextGuid)
220
+ if (invCtx) {
221
+ invCtx.#currentCommand = new Command(invCtx.#runtimeName, CommandType.Reference, [instanceGuid])
222
+ InvocationContext._invocationContexts.delete(contextGuid)
223
+ }
224
+ }
225
+ // remove ValueForUpdate command from payload
226
+ const idx = updatedPayload.indexOf(cmd)
227
+ if (idx >= 0) updatedPayload.splice(idx, 1)
132
228
  }
133
- return new InvocationContext(this.#runtimeName, this.#connectionData, this.#responseCommand, true)
229
+
230
+ return new Command(responseCommand.runtimeName, responseCommand.commandType, updatedPayload)
134
231
  }
135
232
 
136
233
  /**
@@ -176,14 +273,26 @@ class InvocationContext {
176
273
 
177
274
  /**
178
275
  * Creates a new instance of a class in the target runtime.
276
+ * Adds the newly created context to the static invocation contexts map and
277
+ * includes the context GUID as the first argument of CreateClassInstance command payload.
179
278
  * @param {...any} args - The arguments to pass to the class constructor
180
279
  * @returns {InvocationContext} A new InvocationContext instance that wraps the command to create the instance.
181
- * @see [Javonet Guides](https://www.javonet.com/guides/v2/javascript/calling-methods/creating-instance-and-calling-instance-methods)
182
280
  * @method
183
281
  */
184
282
  createInstance(...args) {
185
- let localCommand = new Command(this.#runtimeName, CommandType.CreateClassInstance, args)
186
- return this.#createInstanceContext(localCommand)
283
+ const localCommand = new Command(this.#runtimeName, CommandType.CreateClassInstance, [...args])
284
+ const createInstanceInvCtx = this.#createInstanceContext(localCommand)
285
+ return createInstanceInvCtx.#registerForUpdate()
286
+ }
287
+
288
+ /**
289
+ * Registers the current InvocationContext for updates.
290
+ * @returns {InvocationContext}
291
+ */
292
+ #registerForUpdate() {
293
+ this.#currentCommand = this.#buildCommand(new Command(this.#runtimeName, CommandType.RegisterForUpdate, [this.getGuid()]))
294
+ InvocationContext._invocationContexts.set(this.getGuid(), this)
295
+ return this
187
296
  }
188
297
 
189
298
  /**
@@ -429,7 +538,7 @@ class InvocationContext {
429
538
  await localInvCtx.execute()
430
539
 
431
540
  const resolve = (/** @type {any} */ item) => {
432
- return item?.commandType === CommandType.Reference ?
541
+ return item?.commandType === CommandType.Reference ?
433
542
  new InvocationContext(
434
543
  this.#runtimeName,
435
544
  this.#connectionData,
@@ -441,11 +550,11 @@ class InvocationContext {
441
550
  if (!respCommand) {
442
551
  return []
443
552
  }
444
-
553
+
445
554
  if (respCommand.payload) {
446
555
  return respCommand.payload.map((/** @type {any} */ item) => resolve(item))
447
556
  }
448
-
557
+
449
558
  return respCommand.payload || []
450
559
  }
451
560
 
@@ -484,7 +593,7 @@ class InvocationContext {
484
593
  return payloadItem
485
594
  // eslint-disable-next-line valid-typeof
486
595
  } else if (payloadItem instanceof InvocationContext) {
487
- return payloadItem.get_current_command()
596
+ return payloadItem.getCurrentCommand()
488
597
  } else if (payloadItem instanceof Array) {
489
598
  const copiedArray = payloadItem.map((item) => this.#encapsulatePayloadItem(item))
490
599
  return new Command(this.#runtimeName, CommandType.Array, copiedArray)
@@ -303,7 +303,7 @@ class RuntimeContext {
303
303
  }
304
304
  return payloadItem
305
305
  } else if (payloadItem instanceof InvocationContext) {
306
- const command = payloadItem?.get_current_command()
306
+ const command = payloadItem?.getCurrentCommand()
307
307
  if (!command) {
308
308
  throw new Error('Command not found')
309
309
  }
@@ -48,4 +48,6 @@ export const CommandType = /** @type {const} */ ({
48
48
  AsKwargs: 45,
49
49
  GetResultType: 46,
50
50
  GetGlobalField: 47,
51
+ RegisterForUpdate: 48,
52
+ ValueForUpdate: 49,
51
53
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "javonet-nodejs-sdk",
3
- "version": "2.6.8",
3
+ "version": "2.6.10",
4
4
  "description": "Javonet allows you to reference and use modules or packages written in (Java/Kotlin/Groovy/Clojure, C#/VB.NET, Ruby, Perl, Python, JavaScript/TypeScript) like they were created in your technology. It works on Linux/Windows and MacOS for applications created in JVM, CLR/Netcore, Perl, Python, Ruby, NodeJS, C++ or GoLang and gives you unparalleled freedom and flexibility with native performance in building your mixed-technologies products. Let it be accessing best AI or cryptography libraries, devices SDKs, legacy client modules, internal custom packages or anything from public repositories available on NPM, Nuget, PyPI, Maven/Gradle, RubyGems or GitHub. Get free from programming languages barriers today! For more information check out our guides at https://www.javonet.com/guides/v2/",
5
5
  "keywords": [],
6
6
  "author": "SdNCenter Sp. z o. o.",
@@ -40,12 +40,13 @@
40
40
  "format": "prettier --write ."
41
41
  },
42
42
  "dependencies": {
43
+ "@types/uuid": "^10.0.0",
43
44
  "@types/ws": "^8.18.1",
44
45
  "buffer": "^6.0.3",
45
46
  "glob": "^10.4.5",
46
47
  "js-yaml": "^4.1.0",
47
48
  "uuid": "^10.0.0",
48
- "ws": "^8.13.0"
49
+ "ws": "^8.18.1"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@babel/cli": "^7.25.9",
@@ -58,7 +59,7 @@
58
59
  "@types/js-yaml": "^4.0.9",
59
60
  "babel-loader": "^9.2.1",
60
61
  "cross-env": "^7.0.3",
61
- "esbuild": "^0.24.0",
62
+ "esbuild": "^0.27.0",
62
63
  "eslint": "^9.15.0",
63
64
  "eslint-config-prettier": "^9.1.0",
64
65
  "eslint-plugin-jest": "^28.9.0",