@ticatec/dyna-js 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/DynaJs.js CHANGED
@@ -1,7 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const utils_1 = require("./utils");
4
+ /**
5
+ * DynaJs - A safe dynamic code execution library
6
+ *
7
+ * Provides secure execution of dynamic JavaScript code using new Function()
8
+ * with configurable security policies and sandboxing capabilities.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const loader = new DynaJs({
13
+ * defaultImports: { MyClass },
14
+ * validateCode: true,
15
+ * allowBrowserAPIs: false
16
+ * });
17
+ *
18
+ * const result = loader.executeSync(`return new MyClass()`);
19
+ * ```
20
+ */
4
21
  class DynaJs {
22
+ /**
23
+ * Creates a new DynaJs instance
24
+ *
25
+ * @param config - Configuration options for the DynaJs instance
26
+ * @param config.defaultTimeout - Default timeout for async execution in milliseconds (default: 5000)
27
+ * @param config.defaultStrict - Whether to use strict mode by default (default: true)
28
+ * @param config.allowedGlobals - Whitelist of allowed global variables (empty = allow all defaultImports)
29
+ * @param config.blockedGlobals - Blacklist of blocked global variables
30
+ * @param config.defaultImports - Pre-imported classes/functions available to dynamic code
31
+ * @param config.allowTimers - Allow setTimeout/setInterval in dynamic code (default: false)
32
+ * @param config.allowDynamicImports - Allow import()/require() in dynamic code (default: false)
33
+ * @param config.validateCode - Enable code validation before execution (default: true)
34
+ * @param config.allowBrowserAPIs - Allow access to browser APIs like window/document (default: false)
35
+ * @param config.allowNodeAPIs - Allow access to Node.js APIs like process/require (default: false)
36
+ */
5
37
  constructor(config = {}) {
6
38
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
7
39
  this.config = {
@@ -17,6 +49,18 @@ class DynaJs {
17
49
  allowNodeAPIs: (_k = config.allowNodeAPIs) !== null && _k !== void 0 ? _k : false
18
50
  };
19
51
  }
52
+ /**
53
+ * Asynchronously execute dynamic code with timeout support
54
+ *
55
+ * @template T - The expected return type of the executed code
56
+ * @param code - The JavaScript code to execute
57
+ * @param options - Execution options
58
+ * @param options.context - Additional context variables for the code
59
+ * @param options.timeout - Execution timeout in milliseconds (overrides defaultTimeout)
60
+ * @param options.strict - Whether to use strict mode (overrides defaultStrict)
61
+ * @param options.imports - Additional imports for this execution only
62
+ * @returns Promise resolving to the execution result
63
+ */
20
64
  async execute(code, options = {}) {
21
65
  var _a, _b;
22
66
  const startTime = performance.now();
@@ -31,17 +75,25 @@ class DynaJs {
31
75
  const timeout = (_a = options.timeout) !== null && _a !== void 0 ? _a : this.config.defaultTimeout;
32
76
  const strict = (_b = options.strict) !== null && _b !== void 0 ? _b : this.config.defaultStrict;
33
77
  const result = await this.executeWithTimeout(code, context, timeout, strict);
34
- const executionTime = performance.now() - startTime;
35
- return {
36
- result: result,
37
- executionTime
38
- };
78
+ console.info(`Build dyna code in ${performance.now() - startTime}ms`);
79
+ return result;
39
80
  }
40
81
  catch (error) {
41
82
  const executionTime = performance.now() - startTime;
42
83
  throw new Error(`Script execution failed after ${executionTime.toFixed(2)}ms: ${error instanceof Error ? error.message : String(error)}`);
43
84
  }
44
85
  }
86
+ /**
87
+ * Synchronously execute dynamic code and return result directly
88
+ *
89
+ * @template T - The expected return type of the executed code
90
+ * @param code - The JavaScript code to execute
91
+ * @param options - Execution options
92
+ * @param options.context - Additional context variables for the code
93
+ * @param options.strict - Whether to use strict mode (overrides defaultStrict)
94
+ * @param options.imports - Additional imports for this execution only
95
+ * @returns The direct result of code execution
96
+ */
45
97
  executeSync(code, options = {}) {
46
98
  var _a;
47
99
  const startTime = performance.now();
@@ -55,17 +107,26 @@ class DynaJs {
55
107
  const context = this.prepareContext(options.context, options.imports);
56
108
  const strict = (_a = options.strict) !== null && _a !== void 0 ? _a : this.config.defaultStrict;
57
109
  const result = this.executeCode(code, context, strict);
58
- const executionTime = performance.now() - startTime;
59
- return {
60
- result: result,
61
- executionTime
62
- };
110
+ console.info(`Build dyna code in ${performance.now() - startTime}ms`);
111
+ return result;
63
112
  }
64
113
  catch (error) {
65
114
  const executionTime = performance.now() - startTime;
66
115
  throw new Error(`Script execution failed after ${executionTime.toFixed(2)}ms: ${error instanceof Error ? error.message : String(error)}`);
67
116
  }
68
117
  }
118
+ /**
119
+ * Execute code with a timeout constraint
120
+ *
121
+ * @private
122
+ * @template T - The expected return type
123
+ * @param code - The JavaScript code to execute
124
+ * @param context - Execution context with available variables
125
+ * @param timeout - Maximum execution time in milliseconds
126
+ * @param strict - Whether to use strict mode
127
+ * @returns Promise resolving to the execution result
128
+ * @throws {Error} If execution exceeds timeout or runtime error occurs
129
+ */
69
130
  async executeWithTimeout(code, context, timeout, strict) {
70
131
  return new Promise((resolve, reject) => {
71
132
  const timer = setTimeout(() => {
@@ -82,6 +143,16 @@ class DynaJs {
82
143
  }
83
144
  });
84
145
  }
146
+ /**
147
+ * Core code execution engine using new Function()
148
+ *
149
+ * @private
150
+ * @param code - The JavaScript code to execute
151
+ * @param context - Execution context with available variables
152
+ * @param strict - Whether to use strict mode
153
+ * @returns The execution result
154
+ * @throws {Error} If code execution fails
155
+ */
85
156
  executeCode(code, context, strict) {
86
157
  const contextKeys = Object.keys(context);
87
158
  const contextValues = Object.values(context);
@@ -95,6 +166,29 @@ class DynaJs {
95
166
  throw new Error(`Code execution error: ${error instanceof Error ? error.message : String(error)}`);
96
167
  }
97
168
  }
169
+ /**
170
+ * Create a reusable function from dynamic code
171
+ *
172
+ * @template T - The function signature type
173
+ * @param code - The JavaScript code for the function body
174
+ * @param paramNames - Array of parameter names for the function
175
+ * @param options - Execution options
176
+ * @param options.context - Additional context variables
177
+ * @param options.strict - Whether to use strict mode
178
+ * @param options.imports - Additional imports
179
+ * @returns A function that can be called multiple times
180
+ * @throws {Error} If function creation fails
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const validator = loader.createFunction<(data: any) => boolean>(`
185
+ * return function(data) {
186
+ * return data.name && data.email;
187
+ * };
188
+ * `);
189
+ * const isValid = validator({ name: 'John', email: 'john@example.com' });
190
+ * ```
191
+ */
98
192
  createFunction(code, paramNames = [], options = {}) {
99
193
  var _a;
100
194
  const context = this.prepareContext(options.context, options.imports);
@@ -115,27 +209,118 @@ class DynaJs {
115
209
  throw new Error(`Function creation error: ${error instanceof Error ? error.message : String(error)}`);
116
210
  }
117
211
  }
212
+ /**
213
+ * Synchronously execute code with additional temporary imports
214
+ *
215
+ * @template T - The expected return type
216
+ * @param code - The JavaScript code to execute
217
+ * @param imports - Additional imports to merge with defaultImports
218
+ * @param options - Additional execution options
219
+ * @returns The direct result of code execution
220
+ * @throws {Error} If code validation fails or runtime error occurs
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * const result = loader.executeWithImports(`
225
+ * return new CustomComponent();
226
+ * `, {
227
+ * CustomComponent: MyCustomComponent
228
+ * });
229
+ * ```
230
+ */
118
231
  executeWithImports(code, imports, options = {}) {
119
232
  return this.executeSync(code, Object.assign(Object.assign({}, options), { imports: Object.assign(Object.assign({}, this.config.defaultImports), imports) }));
120
233
  }
234
+ /**
235
+ * Asynchronously execute code with additional temporary imports
236
+ *
237
+ * @template T - The expected return type
238
+ * @param code - The JavaScript code to execute
239
+ * @param imports - Additional imports to merge with defaultImports
240
+ * @param options - Additional execution options (including timeout)
241
+ * @returns Promise resolving to the execution result
242
+ * @throws {Error} If code validation fails, execution times out, or runtime error occurs
243
+ *
244
+ * @example
245
+ * ```typescript
246
+ * const result = await loader.executeWithImportsAsync(`
247
+ * return await fetchData();
248
+ * `, {
249
+ * fetchData: myFetchFunction
250
+ * }, { timeout: 5000 });
251
+ * ```
252
+ */
121
253
  async executeWithImportsAsync(code, imports, options = {}) {
122
254
  return this.execute(code, Object.assign(Object.assign({}, options), { imports: Object.assign(Object.assign({}, this.config.defaultImports), imports) }));
123
255
  }
256
+ /**
257
+ * Initialize the singleton instance of DynaJs
258
+ *
259
+ * @param config - Configuration options for the singleton instance
260
+ * @returns The initialized singleton instance
261
+ *
262
+ * @example
263
+ * ```typescript
264
+ * DynaJs.initialize({
265
+ * defaultImports: { MyClass, MyFunction },
266
+ * validateCode: true
267
+ * });
268
+ * ```
269
+ */
124
270
  static initialize(config) {
125
271
  if (DynaJs.instance == null) {
126
272
  DynaJs.instance = new DynaJs(config);
127
273
  }
128
274
  return DynaJs.instance;
129
275
  }
276
+ /**
277
+ * Get the singleton instance of DynaJs
278
+ *
279
+ * @returns The singleton instance
280
+ * @throws {Error} If DynaJs hasn't been initialized
281
+ *
282
+ * @example
283
+ * ```typescript
284
+ * const loader = DynaJs.getInstance();
285
+ * const result = loader.executeSync(`return 1 + 1`);
286
+ * ```
287
+ */
130
288
  static getInstance() {
131
289
  if (DynaJs.instance == null) {
132
290
  throw new Error("DynaJs hasn't been initialized. Call DynaJs.initialize() first.");
133
291
  }
134
292
  return DynaJs.instance;
135
293
  }
294
+ /**
295
+ * Reset the singleton instance (useful for testing)
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * DynaJs.reset();
300
+ * DynaJs.initialize(newConfig);
301
+ * ```
302
+ */
136
303
  static reset() {
137
304
  DynaJs.instance = null;
138
305
  }
306
+ /**
307
+ * Prepare the execution context by merging user context, imports, and applying security filters
308
+ *
309
+ * Execution flow:
310
+ * 1. Create safe context (filtering browser/node APIs based on config)
311
+ * 2. Merge with defaultImports and additional imports
312
+ * 3. Apply allowedGlobals whitelist filter if configured
313
+ *
314
+ * @private
315
+ * @param userContext - User-provided context variables
316
+ * @param imports - Additional imports for this execution
317
+ * @returns The final execution context
318
+ *
319
+ * @remarks
320
+ * If allowedGlobals is set and not empty, only variables in the whitelist will be available.
321
+ * This happens AFTER merging defaultImports, so make sure to include all needed imports
322
+ * in the allowedGlobals array if you use this feature.
323
+ */
139
324
  prepareContext(userContext = {}, imports = {}) {
140
325
  let context = (0, utils_1.createSafeContext)(userContext, {
141
326
  allowBrowserAPIs: this.config.allowBrowserAPIs,
@@ -155,5 +340,9 @@ class DynaJs {
155
340
  return context;
156
341
  }
157
342
  }
343
+ /**
344
+ * Singleton instance of DynaJs
345
+ * @private
346
+ */
158
347
  DynaJs.instance = null;
159
348
  exports.default = DynaJs;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Function type for checking if a module needs to be updated
3
+ * @param data - Module data containing code and digest information
4
+ * @returns true if the module is up-to-date, false if it needs to be reloaded
5
+ */
6
+ export type ModuleCheck = (data: any) => boolean;
7
+ /**
8
+ * Function type for loading a module from remote source
9
+ * @param data - Module data containing information needed to load the module
10
+ * @returns Promise that resolves to the loaded module data
11
+ */
12
+ export type LoadModule = (data: any) => Promise<any>;
13
+ /**
14
+ * Function type for saving a module to local storage
15
+ * @param data - Module data to be saved
16
+ */
17
+ export type SaveModuleToLocalStorage = (data: any) => void;
18
+ /**
19
+ * Function type for loading a module from local storage
20
+ * @param data - Module identifier or data
21
+ * @returns The module script text
22
+ */
23
+ export type LoadLocalModule = (data: any) => string;
24
+ /**
25
+ * Configuration options for ModuleLoader
26
+ */
27
+ export interface ModuleLoaderOptions {
28
+ /** Optional custom module check function */
29
+ moduleCheck?: ModuleCheck;
30
+ /** Optional custom save module function */
31
+ saveModule?: SaveModuleToLocalStorage;
32
+ /** Optional custom load local module function */
33
+ loadLocalModule?: LoadLocalModule;
34
+ }
35
+ /**
36
+ * ModuleLoader is a singleton class for managing dynamic module loading with caching
37
+ * It supports checking for module updates, loading from remote sources, and caching in localStorage
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * const loader = ModuleLoader.initialize(
42
+ * async (data) => fetch(`/api/modules/${data.code}`).then(r => r.json()),
43
+ * {}
44
+ * );
45
+ *
46
+ * await loader.checkFreshScripts([{ code: 'module1', digest: 'abc123' }]);
47
+ * const module = loader.createModule('module1', { React, ReactDOM });
48
+ * ```
49
+ */
50
+ export default class ModuleLoader {
51
+ private static instance;
52
+ private readonly loadModule;
53
+ private readonly moduleCheck;
54
+ private readonly saveModule;
55
+ private readonly loadLocalModule;
56
+ private modulesMap;
57
+ /**
58
+ * Private constructor for singleton pattern
59
+ * @param loadModule - Function to load module from remote
60
+ * @param moduleCheck - Function to check module freshness
61
+ * @param saveModule - Function to save module locally
62
+ * @param loadLocalModule - Function to load module from local storage
63
+ */
64
+ private constructor();
65
+ /**
66
+ * Initialize the ModuleLoader singleton instance
67
+ * @param loadModule - Function to load module from remote source
68
+ * @param options - Configuration options with optional custom implementations
69
+ * @returns The singleton ModuleLoader instance
70
+ */
71
+ static initialize(loadModule: LoadModule, options: ModuleLoaderOptions): ModuleLoader;
72
+ /**
73
+ * Check and update modules that are not fresh
74
+ * Iterates through the list, checks each module, and reloads if needed
75
+ * Clears the module cache after checking all modules
76
+ *
77
+ * @param list - Array of module data objects to check
78
+ * @returns Promise that resolves when all modules are checked and updated
79
+ * ```
80
+ */
81
+ checkFreshScripts(list: Array<any>): Promise<void>;
82
+ /**
83
+ * Create or retrieve a cached module instance
84
+ * Loads the module script from local storage and executes it with provided imports
85
+ * Caches the result for subsequent calls
86
+ *
87
+ * @param key - The module key/code to load
88
+ * @param imports - Object containing dependencies to inject into the module
89
+ * @returns The instantiated module
90
+ */
91
+ createModule(key: string, imports: any): any;
92
+ }
93
+ //# sourceMappingURL=ModuleLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModuleLoader.d.ts","sourceRoot":"","sources":["../src/ModuleLoader.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;AAEjD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC;AA+BpD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,4CAA4C;IAC5C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,iDAAiD;IACjD,eAAe,CAAC,EAAE,eAAe,CAAA;CACpC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;IAE7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2B;IACtD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,UAAU,CAAmB;IAErC;;;;;;OAMG;IACH,OAAO;IAQP;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,GAAG,YAAY;IAQrF;;;;;;;;OAQG;IACG,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;IAUxC;;;;;;;;OAQG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG;CAU/C"}
@@ -0,0 +1,106 @@
1
+ import { getDynaJs } from "./index";
2
+ /**
3
+ * Default module check function that compares message digest
4
+ * @param data - Module data containing code and digest
5
+ * @returns true if the local digest matches the remote digest
6
+ */
7
+ const checkMessageDigest = (data) => {
8
+ let localDigest = window.localStorage.getItem(`md:${data.code}`);
9
+ return localDigest == data.digest;
10
+ };
11
+ /**
12
+ * Default function to save module to localStorage
13
+ * Saves both the module digest and script text
14
+ * @param data - Module data containing code, digest, and scriptText
15
+ */
16
+ const saveModule = (data) => {
17
+ window.localStorage.setItem(`md:${data.code}`, data.digest);
18
+ window.localStorage.setItem(`script:${data.code}`, data.scriptText);
19
+ };
20
+ /**
21
+ * Default function to load module script from localStorage
22
+ * @param key - Module key/code
23
+ * @returns The module script text
24
+ */
25
+ const loadLocalModule = (key) => {
26
+ return window.localStorage.getItem(`script:${key}`);
27
+ };
28
+ /**
29
+ * ModuleLoader is a singleton class for managing dynamic module loading with caching
30
+ * It supports checking for module updates, loading from remote sources, and caching in localStorage
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const loader = ModuleLoader.initialize(
35
+ * async (data) => fetch(`/api/modules/${data.code}`).then(r => r.json()),
36
+ * {}
37
+ * );
38
+ *
39
+ * await loader.checkFreshScripts([{ code: 'module1', digest: 'abc123' }]);
40
+ * const module = loader.createModule('module1', { React, ReactDOM });
41
+ * ```
42
+ */
43
+ export default class ModuleLoader {
44
+ /**
45
+ * Private constructor for singleton pattern
46
+ * @param loadModule - Function to load module from remote
47
+ * @param moduleCheck - Function to check module freshness
48
+ * @param saveModule - Function to save module locally
49
+ * @param loadLocalModule - Function to load module from local storage
50
+ */
51
+ constructor(loadModule, moduleCheck, saveModule, loadLocalModule) {
52
+ this.loadModule = loadModule;
53
+ this.moduleCheck = moduleCheck;
54
+ this.saveModule = saveModule;
55
+ this.loadLocalModule = loadLocalModule;
56
+ this.modulesMap = new Map();
57
+ }
58
+ /**
59
+ * Initialize the ModuleLoader singleton instance
60
+ * @param loadModule - Function to load module from remote source
61
+ * @param options - Configuration options with optional custom implementations
62
+ * @returns The singleton ModuleLoader instance
63
+ */
64
+ static initialize(loadModule, options) {
65
+ if (ModuleLoader.instance == null) {
66
+ ModuleLoader.instance = new ModuleLoader(loadModule, options.moduleCheck ?? checkMessageDigest, options.saveModule ?? saveModule, options.loadLocalModule ?? loadLocalModule);
67
+ }
68
+ return ModuleLoader.instance;
69
+ }
70
+ /**
71
+ * Check and update modules that are not fresh
72
+ * Iterates through the list, checks each module, and reloads if needed
73
+ * Clears the module cache after checking all modules
74
+ *
75
+ * @param list - Array of module data objects to check
76
+ * @returns Promise that resolves when all modules are checked and updated
77
+ * ```
78
+ */
79
+ async checkFreshScripts(list) {
80
+ for (let item of list) {
81
+ if (!this.moduleCheck(item)) {
82
+ let data = await this.loadModule(item);
83
+ this.saveModule(data);
84
+ }
85
+ }
86
+ this.modulesMap.clear();
87
+ }
88
+ /**
89
+ * Create or retrieve a cached module instance
90
+ * Loads the module script from local storage and executes it with provided imports
91
+ * Caches the result for subsequent calls
92
+ *
93
+ * @param key - The module key/code to load
94
+ * @param imports - Object containing dependencies to inject into the module
95
+ * @returns The instantiated module
96
+ */
97
+ createModule(key, imports) {
98
+ let module = this.modulesMap.get(key);
99
+ if (module == null) {
100
+ let scriptText = this.loadLocalModule(key);
101
+ module = getDynaJs().executeSync(scriptText, { imports });
102
+ this.modulesMap.set(key, module);
103
+ }
104
+ return module;
105
+ }
106
+ }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("./index");
4
+ /**
5
+ * Default module check function that compares message digest
6
+ * @param data - Module data containing code and digest
7
+ * @returns true if the local digest matches the remote digest
8
+ */
9
+ const checkMessageDigest = (data) => {
10
+ let localDigest = window.localStorage.getItem(`md:${data.code}`);
11
+ return localDigest == data.digest;
12
+ };
13
+ /**
14
+ * Default function to save module to localStorage
15
+ * Saves both the module digest and script text
16
+ * @param data - Module data containing code, digest, and scriptText
17
+ */
18
+ const saveModule = (data) => {
19
+ window.localStorage.setItem(`md:${data.code}`, data.digest);
20
+ window.localStorage.setItem(`script:${data.code}`, data.scriptText);
21
+ };
22
+ /**
23
+ * Default function to load module script from localStorage
24
+ * @param key - Module key/code
25
+ * @returns The module script text
26
+ */
27
+ const loadLocalModule = (key) => {
28
+ return window.localStorage.getItem(`script:${key}`);
29
+ };
30
+ /**
31
+ * ModuleLoader is a singleton class for managing dynamic module loading with caching
32
+ * It supports checking for module updates, loading from remote sources, and caching in localStorage
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const loader = ModuleLoader.initialize(
37
+ * async (data) => fetch(`/api/modules/${data.code}`).then(r => r.json()),
38
+ * {}
39
+ * );
40
+ *
41
+ * await loader.checkFreshScripts([{ code: 'module1', digest: 'abc123' }]);
42
+ * const module = loader.createModule('module1', { React, ReactDOM });
43
+ * ```
44
+ */
45
+ class ModuleLoader {
46
+ /**
47
+ * Private constructor for singleton pattern
48
+ * @param loadModule - Function to load module from remote
49
+ * @param moduleCheck - Function to check module freshness
50
+ * @param saveModule - Function to save module locally
51
+ * @param loadLocalModule - Function to load module from local storage
52
+ */
53
+ constructor(loadModule, moduleCheck, saveModule, loadLocalModule) {
54
+ this.loadModule = loadModule;
55
+ this.moduleCheck = moduleCheck;
56
+ this.saveModule = saveModule;
57
+ this.loadLocalModule = loadLocalModule;
58
+ this.modulesMap = new Map();
59
+ }
60
+ /**
61
+ * Initialize the ModuleLoader singleton instance
62
+ * @param loadModule - Function to load module from remote source
63
+ * @param options - Configuration options with optional custom implementations
64
+ * @returns The singleton ModuleLoader instance
65
+ */
66
+ static initialize(loadModule, options) {
67
+ var _a, _b, _c;
68
+ if (ModuleLoader.instance == null) {
69
+ ModuleLoader.instance = new ModuleLoader(loadModule, (_a = options.moduleCheck) !== null && _a !== void 0 ? _a : checkMessageDigest, (_b = options.saveModule) !== null && _b !== void 0 ? _b : saveModule, (_c = options.loadLocalModule) !== null && _c !== void 0 ? _c : loadLocalModule);
70
+ }
71
+ return ModuleLoader.instance;
72
+ }
73
+ /**
74
+ * Check and update modules that are not fresh
75
+ * Iterates through the list, checks each module, and reloads if needed
76
+ * Clears the module cache after checking all modules
77
+ *
78
+ * @param list - Array of module data objects to check
79
+ * @returns Promise that resolves when all modules are checked and updated
80
+ * ```
81
+ */
82
+ async checkFreshScripts(list) {
83
+ for (let item of list) {
84
+ if (!this.moduleCheck(item)) {
85
+ let data = await this.loadModule(item);
86
+ this.saveModule(data);
87
+ }
88
+ }
89
+ this.modulesMap.clear();
90
+ }
91
+ /**
92
+ * Create or retrieve a cached module instance
93
+ * Loads the module script from local storage and executes it with provided imports
94
+ * Caches the result for subsequent calls
95
+ *
96
+ * @param key - The module key/code to load
97
+ * @param imports - Object containing dependencies to inject into the module
98
+ * @returns The instantiated module
99
+ */
100
+ createModule(key, imports) {
101
+ let module = this.modulesMap.get(key);
102
+ if (module == null) {
103
+ let scriptText = this.loadLocalModule(key);
104
+ module = (0, index_1.getDynaJs)().executeSync(scriptText, { imports });
105
+ this.modulesMap.set(key, module);
106
+ }
107
+ return module;
108
+ }
109
+ }
110
+ exports.default = ModuleLoader;
package/dist/types.d.ts CHANGED
@@ -9,12 +9,6 @@ export interface ExecutionOptions {
9
9
  timeout?: number;
10
10
  strict?: boolean;
11
11
  imports?: ModuleImports;
12
- injectedKeys?: string[];
13
- useProxy?: boolean;
14
- }
15
- export interface ExecutionResult<T = any> {
16
- result: T;
17
- executionTime: number;
18
12
  }
19
13
  export interface DynaJsConfig {
20
14
  defaultTimeout?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,GAAG;IACtC,MAAM,EAAE,CAAC,CAAC;IACV,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ticatec/dyna-js",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "description": "A TypeScript library for dynamic code execution using new Function() that works in both Node.js and browser environments",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -41,8 +41,7 @@
41
41
  "license": "MIT",
42
42
  "repository": {
43
43
  "type": "git",
44
- "url": "git+https://github.com/ticatec/DynaJS.git",
45
- "directory": "dynamic-script-loader"
44
+ "url": "git+https://github.com/ticatec/DynaJS.git"
46
45
  },
47
46
  "bugs": {
48
47
  "url": "https://github.com/ticatec/DynaJS/issues"