@tradejs/node 1.0.2 → 1.0.3

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.
@@ -247,9 +247,24 @@ var loadTradejsConfig = async (cwd = getTradejsProjectCwd()) => {
247
247
  };
248
248
 
249
249
  // src/connectorsRegistry.ts
250
- var connectorCreators = /* @__PURE__ */ new Map();
251
- var providerToConnectorName = /* @__PURE__ */ new Map();
252
- var pluginsLoadPromise = null;
250
+ var createConnectorRegistryState = () => ({
251
+ connectorCreators: /* @__PURE__ */ new Map(),
252
+ providerToConnectorName: /* @__PURE__ */ new Map(),
253
+ pluginsLoadPromise: null
254
+ });
255
+ var registryStateByProjectRoot = /* @__PURE__ */ new Map();
256
+ var getConnectorRegistryState = (cwd = getTradejsProjectCwd()) => {
257
+ const projectRoot = getTradejsProjectCwd(cwd);
258
+ let state = registryStateByProjectRoot.get(projectRoot);
259
+ if (!state) {
260
+ state = createConnectorRegistryState();
261
+ registryStateByProjectRoot.set(projectRoot, state);
262
+ }
263
+ return {
264
+ projectRoot,
265
+ state
266
+ };
267
+ };
253
268
  var BUILTIN_CONNECTOR_NAMES = {
254
269
  ByBit: "ByBit",
255
270
  Binance: "Binance",
@@ -260,7 +275,7 @@ var normalizeProvider = (value) => String(value ?? "").trim().toLowerCase();
260
275
  var toUniqueModules = (modules = []) => [
261
276
  ...new Set(modules.map((moduleName) => moduleName.trim()).filter(Boolean))
262
277
  ];
263
- var findConnectorNameInsensitive = (name) => {
278
+ var findConnectorNameInsensitive = (name, connectorCreators) => {
264
279
  const normalized = name.trim().toLowerCase();
265
280
  if (!normalized) {
266
281
  return null;
@@ -280,7 +295,7 @@ var normalizeProviders = (providers, connectorName) => {
280
295
  }
281
296
  return [normalizeProvider(connectorName)];
282
297
  };
283
- var registerProvider = (provider, connectorName, source) => {
298
+ var registerProvider = (provider, connectorName, source, providerToConnectorName) => {
284
299
  const existing = providerToConnectorName.get(provider);
285
300
  if (existing && existing !== connectorName) {
286
301
  import_logger2.logger.warn(
@@ -293,7 +308,7 @@ var registerProvider = (provider, connectorName, source) => {
293
308
  }
294
309
  providerToConnectorName.set(provider, connectorName);
295
310
  };
296
- var registerEntry = (entry, source) => {
311
+ var registerEntry = (entry, source, state) => {
297
312
  const connectorName = String(entry?.name ?? "").trim();
298
313
  if (!connectorName) {
299
314
  import_logger2.logger.warn("Skip connector entry without name from %s", source);
@@ -307,7 +322,10 @@ var registerEntry = (entry, source) => {
307
322
  );
308
323
  return;
309
324
  }
310
- const existingByName = findConnectorNameInsensitive(connectorName);
325
+ const existingByName = findConnectorNameInsensitive(
326
+ connectorName,
327
+ state.connectorCreators
328
+ );
311
329
  if (existingByName) {
312
330
  import_logger2.logger.warn(
313
331
  'Skip duplicate connector "%s" from %s: already registered as %s',
@@ -317,15 +335,20 @@ var registerEntry = (entry, source) => {
317
335
  );
318
336
  return;
319
337
  }
320
- connectorCreators.set(connectorName, entry.creator);
338
+ state.connectorCreators.set(connectorName, entry.creator);
321
339
  const providers = normalizeProviders(entry.providers, connectorName);
322
340
  for (const provider of providers) {
323
- registerProvider(provider, connectorName, source);
341
+ registerProvider(
342
+ provider,
343
+ connectorName,
344
+ source,
345
+ state.providerToConnectorName
346
+ );
324
347
  }
325
348
  };
326
- var registerEntries = (entries, source) => {
349
+ var registerEntries = (entries, source, state) => {
327
350
  for (const entry of entries) {
328
- registerEntry(entry, source);
351
+ registerEntry(entry, source, state);
329
352
  }
330
353
  };
331
354
  var extractConnectorPluginDefinition = (moduleExport) => {
@@ -355,101 +378,118 @@ var importConnectorPluginModule = async (moduleName) => {
355
378
  moduleName
356
379
  );
357
380
  };
358
- var ensureConnectorPluginsLoaded = async () => {
359
- if (pluginsLoadPromise) {
360
- return pluginsLoadPromise;
361
- }
362
- pluginsLoadPromise = (async () => {
363
- const config = await loadTradejsConfig();
364
- const connectorModules = toUniqueModules(config.connectors);
365
- if (!connectorModules.length) {
366
- return;
367
- }
368
- for (const moduleName of connectorModules) {
369
- try {
370
- const resolvedModuleName = resolvePluginModuleSpecifier(moduleName);
371
- const moduleExport = await importConnectorPluginModule(resolvedModuleName);
372
- const pluginDefinition = extractConnectorPluginDefinition(moduleExport);
373
- if (!pluginDefinition) {
381
+ var ensureConnectorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
382
+ const { projectRoot, state } = getConnectorRegistryState(cwd);
383
+ if (!state.pluginsLoadPromise) {
384
+ state.pluginsLoadPromise = (async () => {
385
+ const config = await loadTradejsConfig(projectRoot);
386
+ const connectorModules = toUniqueModules(config.connectors);
387
+ if (!connectorModules.length) {
388
+ return;
389
+ }
390
+ for (const moduleName of connectorModules) {
391
+ try {
392
+ const resolvedModuleName = resolvePluginModuleSpecifier(
393
+ moduleName,
394
+ projectRoot
395
+ );
396
+ const moduleExport = await importConnectorPluginModule(resolvedModuleName);
397
+ const pluginDefinition = extractConnectorPluginDefinition(moduleExport);
398
+ if (!pluginDefinition) {
399
+ import_logger2.logger.warn(
400
+ 'Skip connector plugin "%s": export { connectorEntries } is missing',
401
+ moduleName
402
+ );
403
+ continue;
404
+ }
405
+ registerEntries(pluginDefinition.connectorEntries, moduleName, state);
406
+ } catch (error) {
374
407
  import_logger2.logger.warn(
375
- 'Skip connector plugin "%s": export { connectorEntries } is missing',
376
- moduleName
408
+ 'Failed to load connector plugin "%s": %s',
409
+ moduleName,
410
+ String(error)
377
411
  );
378
- continue;
379
412
  }
380
- registerEntries(pluginDefinition.connectorEntries, moduleName);
381
- } catch (error) {
382
- import_logger2.logger.warn(
383
- 'Failed to load connector plugin "%s": %s',
384
- moduleName,
385
- String(error)
386
- );
387
413
  }
388
- }
389
- })();
390
- return pluginsLoadPromise;
414
+ })();
415
+ }
416
+ await state.pluginsLoadPromise;
391
417
  };
392
- var getConnectorCreatorByName = async (connectorName) => {
393
- await ensureConnectorPluginsLoaded();
418
+ var getConnectorCreatorByName = async (connectorName, cwd = getTradejsProjectCwd()) => {
419
+ await ensureConnectorPluginsLoaded(cwd);
420
+ const { state } = getConnectorRegistryState(cwd);
394
421
  const raw = String(connectorName ?? "").trim();
395
422
  if (!raw) {
396
423
  return void 0;
397
424
  }
398
- const direct = connectorCreators.get(raw);
425
+ const direct = state.connectorCreators.get(raw);
399
426
  if (direct) {
400
427
  return direct;
401
428
  }
402
- const existing = findConnectorNameInsensitive(raw);
429
+ const existing = findConnectorNameInsensitive(raw, state.connectorCreators);
403
430
  if (!existing) {
404
431
  return void 0;
405
432
  }
406
- return connectorCreators.get(existing);
433
+ return state.connectorCreators.get(existing);
407
434
  };
408
- var getConnectorNameByProvider = async (provider) => {
409
- await ensureConnectorPluginsLoaded();
435
+ var getConnectorNameByProvider = async (provider, cwd = getTradejsProjectCwd()) => {
436
+ await ensureConnectorPluginsLoaded(cwd);
437
+ const { state } = getConnectorRegistryState(cwd);
410
438
  const normalized = normalizeProvider(provider);
411
439
  if (!normalized) {
412
440
  return void 0;
413
441
  }
414
- return providerToConnectorName.get(normalized);
442
+ return state.providerToConnectorName.get(normalized);
415
443
  };
416
- var getConnectorCreatorByProvider = async (provider) => {
417
- const connectorName = await getConnectorNameByProvider(provider);
444
+ var getConnectorCreatorByProvider = async (provider, cwd = getTradejsProjectCwd()) => {
445
+ await ensureConnectorPluginsLoaded(cwd);
446
+ const { state } = getConnectorRegistryState(cwd);
447
+ const normalized = normalizeProvider(provider);
448
+ if (!normalized) {
449
+ return void 0;
450
+ }
451
+ const connectorName = state.providerToConnectorName.get(normalized);
418
452
  if (!connectorName) {
419
453
  return void 0;
420
454
  }
421
- return connectorCreators.get(connectorName);
455
+ return state.connectorCreators.get(connectorName);
422
456
  };
423
- var resolveConnectorName = async (providerOrName) => {
457
+ var resolveConnectorName = async (providerOrName, cwd = getTradejsProjectCwd()) => {
458
+ await ensureConnectorPluginsLoaded(cwd);
459
+ const { state } = getConnectorRegistryState(cwd);
424
460
  const raw = String(providerOrName ?? "").trim();
425
461
  if (!raw) {
426
462
  return void 0;
427
463
  }
428
- const byProvider = await getConnectorNameByProvider(raw);
464
+ const byProvider = state.providerToConnectorName.get(normalizeProvider(raw));
429
465
  if (byProvider) {
430
466
  return byProvider;
431
467
  }
432
- const byName = await getConnectorCreatorByName(raw);
433
- if (!byName) {
434
- return void 0;
435
- }
436
- return findConnectorNameInsensitive(raw) ?? void 0;
468
+ return state.connectorCreators.get(raw) && raw ? raw : findConnectorNameInsensitive(raw, state.connectorCreators) ?? void 0;
437
469
  };
438
- var getAvailableConnectorNames = async () => {
439
- await ensureConnectorPluginsLoaded();
440
- return [...connectorCreators.keys()].sort((a, b) => a.localeCompare(b));
470
+ var getAvailableConnectorNames = async (cwd = getTradejsProjectCwd()) => {
471
+ await ensureConnectorPluginsLoaded(cwd);
472
+ const { state } = getConnectorRegistryState(cwd);
473
+ return [...state.connectorCreators.keys()].sort((a, b) => a.localeCompare(b));
441
474
  };
442
- var getAvailableConnectorProviders = async () => {
443
- await ensureConnectorPluginsLoaded();
444
- return [...providerToConnectorName.keys()].sort((a, b) => a.localeCompare(b));
475
+ var getAvailableConnectorProviders = async (cwd = getTradejsProjectCwd()) => {
476
+ await ensureConnectorPluginsLoaded(cwd);
477
+ const { state } = getConnectorRegistryState(cwd);
478
+ return [...state.providerToConnectorName.keys()].sort(
479
+ (a, b) => a.localeCompare(b)
480
+ );
445
481
  };
446
- var registerConnectorEntries = (entries) => {
447
- registerEntries(entries, "runtime");
482
+ var registerConnectorEntries = (entries, cwd = getTradejsProjectCwd()) => {
483
+ const { state } = getConnectorRegistryState(cwd);
484
+ registerEntries(entries, "runtime", state);
448
485
  };
449
- var resetConnectorRegistryCache = () => {
450
- connectorCreators.clear();
451
- providerToConnectorName.clear();
452
- pluginsLoadPromise = null;
486
+ var resetConnectorRegistryCache = (cwd) => {
487
+ const normalizedCwd = String(cwd ?? "").trim();
488
+ if (!normalizedCwd) {
489
+ registryStateByProjectRoot.clear();
490
+ return;
491
+ }
492
+ registryStateByProjectRoot.delete(getTradejsProjectCwd(normalizedCwd));
453
493
  };
454
494
  var DEFAULT_CONNECTOR_NAME = BUILTIN_CONNECTOR_NAMES.ByBit;
455
495
  // Annotate the CommonJS export names for ESM import in node:
@@ -10,8 +10,8 @@ import {
10
10
  registerConnectorEntries,
11
11
  resetConnectorRegistryCache,
12
12
  resolveConnectorName
13
- } from "./chunk-E2QNOA5M.mjs";
14
- import "./chunk-DE7ADBIR.mjs";
13
+ } from "./chunk-MGFEID6K.mjs";
14
+ import "./chunk-3C76HVLA.mjs";
15
15
  import "./chunk-6DZX6EAA.mjs";
16
16
  export {
17
17
  BUILTIN_CONNECTOR_NAMES,
package/dist/pine.d.mts CHANGED
@@ -25,7 +25,6 @@ declare const getPinePlotSeries: (context: PineContextLike, plotName: string) =>
25
25
  declare const getLatestPinePlotValue: (context: PineContextLike, plotName: string) => unknown;
26
26
  declare const asFiniteNumber: (value: unknown) => number | undefined;
27
27
  declare const asPineBoolean: (value: unknown) => boolean;
28
-
29
28
  declare const loadPineScript: (filePath: string, fallback?: string) => string;
30
29
  declare const createLoadPineScript: (baseDir: string) => ((fileNameOrPath: string, fallback?: string) => string);
31
30
  declare const runPineScript: ({ candles, script, symbol, timeframe, inputs, limit, }: RunPineScriptParams) => Promise<PineContextLike>;
package/dist/pine.d.ts CHANGED
@@ -25,7 +25,6 @@ declare const getPinePlotSeries: (context: PineContextLike, plotName: string) =>
25
25
  declare const getLatestPinePlotValue: (context: PineContextLike, plotName: string) => unknown;
26
26
  declare const asFiniteNumber: (value: unknown) => number | undefined;
27
27
  declare const asPineBoolean: (value: unknown) => boolean;
28
-
29
28
  declare const loadPineScript: (filePath: string, fallback?: string) => string;
30
29
  declare const createLoadPineScript: (baseDir: string) => ((fileNameOrPath: string, fallback?: string) => string);
31
30
  declare const runPineScript: ({ candles, script, symbol, timeframe, inputs, limit, }: RunPineScriptParams) => Promise<PineContextLike>;
package/dist/pine.js CHANGED
@@ -41,8 +41,6 @@ __export(pine_exports, {
41
41
  module.exports = __toCommonJS(pine_exports);
42
42
  var import_node_fs = __toESM(require("fs"));
43
43
  var import_node_path = __toESM(require("path"));
44
-
45
- // src/pineShared.ts
46
44
  var getPinePlotSeries = (context, plotName) => {
47
45
  const name = String(plotName || "").trim();
48
46
  if (!name) return [];
@@ -65,8 +63,6 @@ var asPineBoolean = (value) => {
65
63
  if (typeof value === "number") return Number.isFinite(value) && value !== 0;
66
64
  return false;
67
65
  };
68
-
69
- // src/pine.ts
70
66
  var loadPinets = () => {
71
67
  const resolvedPath = require.resolve("pinets");
72
68
  const cjsPath = resolvedPath.includes("pinets.min.browser") ? resolvedPath.replace(/pinets\.min\.browser(\.es)?\.js$/, "pinets.min.cjs") : resolvedPath;
package/dist/pine.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  getPinePlotSeries,
7
7
  loadPineScript,
8
8
  runPineScript
9
- } from "./chunk-OB4CSYDJ.mjs";
9
+ } from "./chunk-7ICOZAKA.mjs";
10
10
  import "./chunk-6DZX6EAA.mjs";
11
11
  export {
12
12
  asFiniteNumber,
@@ -1,15 +1,15 @@
1
1
  import { StrategyManifest, StrategyCreator, StrategyRegistryEntry } from '@tradejs/types';
2
2
 
3
- declare const ensureStrategyPluginsLoaded: () => Promise<void>;
4
- declare const ensureIndicatorPluginsLoaded: () => Promise<void>;
5
- declare const getStrategyCreator: (name: string) => Promise<StrategyCreator | undefined>;
6
- declare const getAvailableStrategyNames: () => Promise<string[]>;
7
- declare const getRegisteredStrategies: () => Record<string, StrategyCreator>;
8
- declare const getRegisteredManifests: () => StrategyManifest[];
9
- declare const getStrategyManifest: (name?: string) => StrategyManifest | undefined;
10
- declare const isKnownStrategy: (name: string) => boolean;
11
- declare const registerStrategyEntries: (entries: readonly StrategyRegistryEntry[]) => void;
12
- declare const resetStrategyRegistryCache: () => void;
3
+ declare const ensureStrategyPluginsLoaded: (cwd?: string) => Promise<void>;
4
+ declare const ensureIndicatorPluginsLoaded: (cwd?: string) => Promise<void>;
5
+ declare const getStrategyCreator: (name: string, cwd?: string) => Promise<StrategyCreator | undefined>;
6
+ declare const getAvailableStrategyNames: (cwd?: string) => Promise<string[]>;
7
+ declare const getRegisteredStrategies: (cwd?: string) => Record<string, StrategyCreator>;
8
+ declare const getRegisteredManifests: (cwd?: string) => StrategyManifest[];
9
+ declare const getStrategyManifest: (name?: string, cwd?: string) => StrategyManifest | undefined;
10
+ declare const isKnownStrategy: (name: string, cwd?: string) => boolean;
11
+ declare const registerStrategyEntries: (entries: readonly StrategyRegistryEntry[], cwd?: string) => void;
12
+ declare const resetStrategyRegistryCache: (cwd?: string) => void;
13
13
  declare const strategies: Record<string, StrategyCreator>;
14
14
 
15
15
  export { ensureIndicatorPluginsLoaded, ensureStrategyPluginsLoaded, getAvailableStrategyNames, getRegisteredManifests, getRegisteredStrategies, getStrategyCreator, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies };
@@ -1,15 +1,15 @@
1
1
  import { StrategyManifest, StrategyCreator, StrategyRegistryEntry } from '@tradejs/types';
2
2
 
3
- declare const ensureStrategyPluginsLoaded: () => Promise<void>;
4
- declare const ensureIndicatorPluginsLoaded: () => Promise<void>;
5
- declare const getStrategyCreator: (name: string) => Promise<StrategyCreator | undefined>;
6
- declare const getAvailableStrategyNames: () => Promise<string[]>;
7
- declare const getRegisteredStrategies: () => Record<string, StrategyCreator>;
8
- declare const getRegisteredManifests: () => StrategyManifest[];
9
- declare const getStrategyManifest: (name?: string) => StrategyManifest | undefined;
10
- declare const isKnownStrategy: (name: string) => boolean;
11
- declare const registerStrategyEntries: (entries: readonly StrategyRegistryEntry[]) => void;
12
- declare const resetStrategyRegistryCache: () => void;
3
+ declare const ensureStrategyPluginsLoaded: (cwd?: string) => Promise<void>;
4
+ declare const ensureIndicatorPluginsLoaded: (cwd?: string) => Promise<void>;
5
+ declare const getStrategyCreator: (name: string, cwd?: string) => Promise<StrategyCreator | undefined>;
6
+ declare const getAvailableStrategyNames: (cwd?: string) => Promise<string[]>;
7
+ declare const getRegisteredStrategies: (cwd?: string) => Record<string, StrategyCreator>;
8
+ declare const getRegisteredManifests: (cwd?: string) => StrategyManifest[];
9
+ declare const getStrategyManifest: (name?: string, cwd?: string) => StrategyManifest | undefined;
10
+ declare const isKnownStrategy: (name: string, cwd?: string) => boolean;
11
+ declare const registerStrategyEntries: (entries: readonly StrategyRegistryEntry[], cwd?: string) => void;
12
+ declare const resetStrategyRegistryCache: (cwd?: string) => void;
13
13
  declare const strategies: Record<string, StrategyCreator>;
14
14
 
15
15
  export { ensureIndicatorPluginsLoaded, ensureStrategyPluginsLoaded, getAvailableStrategyNames, getRegisteredManifests, getRegisteredStrategies, getStrategyCreator, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies };
package/dist/registry.js CHANGED
@@ -248,14 +248,29 @@ var loadTradejsConfig = async (cwd = getTradejsProjectCwd()) => {
248
248
  };
249
249
 
250
250
  // src/strategy/manifests.ts
251
- var strategyCreators = /* @__PURE__ */ new Map();
252
- var strategyManifestsMap = /* @__PURE__ */ new Map();
253
- var pluginsLoadPromise = null;
251
+ var createStrategyRegistryState = () => ({
252
+ strategyCreators: /* @__PURE__ */ new Map(),
253
+ strategyManifestsMap: /* @__PURE__ */ new Map(),
254
+ pluginsLoadPromise: null
255
+ });
256
+ var registryStateByProjectRoot = /* @__PURE__ */ new Map();
257
+ var getStrategyRegistryState = (cwd = getTradejsProjectCwd()) => {
258
+ const projectRoot = getTradejsProjectCwd(cwd);
259
+ let state = registryStateByProjectRoot.get(projectRoot);
260
+ if (!state) {
261
+ state = createStrategyRegistryState();
262
+ registryStateByProjectRoot.set(projectRoot, state);
263
+ }
264
+ return {
265
+ projectRoot,
266
+ state
267
+ };
268
+ };
254
269
  var toUniqueModules = (modules = []) => [
255
270
  ...new Set(modules.map((moduleName) => moduleName.trim()).filter(Boolean))
256
271
  ];
257
- var getConfiguredPluginModuleNames = async () => {
258
- const config = await loadTradejsConfig();
272
+ var getConfiguredPluginModuleNames = async (cwd = getTradejsProjectCwd()) => {
273
+ const config = await loadTradejsConfig(cwd);
259
274
  return {
260
275
  strategyModules: toUniqueModules(config.strategies),
261
276
  indicatorModules: toUniqueModules(config.indicators)
@@ -289,14 +304,14 @@ var extractIndicatorPluginDefinition = (moduleExport) => {
289
304
  );
290
305
  return indicatorEntries ? { indicatorEntries } : null;
291
306
  };
292
- var registerEntries = (entries, source) => {
307
+ var registerEntries = (entries, source, state) => {
293
308
  for (const entry of entries) {
294
309
  const strategyName = entry.manifest?.name;
295
310
  if (!strategyName) {
296
311
  import_logger2.logger.warn("Skip strategy entry without name from %s", source);
297
312
  continue;
298
313
  }
299
- if (strategyCreators.has(strategyName)) {
314
+ if (state.strategyCreators.has(strategyName)) {
300
315
  import_logger2.logger.warn(
301
316
  'Skip duplicate strategy "%s" from %s: already registered',
302
317
  strategyName,
@@ -304,8 +319,8 @@ var registerEntries = (entries, source) => {
304
319
  );
305
320
  continue;
306
321
  }
307
- strategyCreators.set(strategyName, entry.creator);
308
- strategyManifestsMap.set(strategyName, entry.manifest);
322
+ state.strategyCreators.set(strategyName, entry.creator);
323
+ state.strategyManifestsMap.set(strategyName, entry.manifest);
309
324
  }
310
325
  };
311
326
  var importStrategyPluginModule = async (moduleName) => {
@@ -317,93 +332,119 @@ var importStrategyPluginModule = async (moduleName) => {
317
332
  moduleName
318
333
  );
319
334
  };
320
- var ensureStrategyPluginsLoaded = async () => {
321
- if (pluginsLoadPromise) {
322
- return pluginsLoadPromise;
323
- }
324
- pluginsLoadPromise = (async () => {
325
- const { strategyModules, indicatorModules } = await getConfiguredPluginModuleNames();
326
- const strategySet = new Set(strategyModules);
327
- const indicatorSet = new Set(indicatorModules);
328
- const pluginModuleNames = [
329
- .../* @__PURE__ */ new Set([...strategyModules, ...indicatorModules])
330
- ];
331
- if (!pluginModuleNames.length) return;
332
- for (const moduleName of pluginModuleNames) {
333
- try {
334
- const resolvedModuleName = resolvePluginModuleSpecifier(moduleName);
335
- const moduleExport = await importStrategyPluginModule(resolvedModuleName);
336
- if (strategySet.has(moduleName)) {
337
- const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
338
- if (!pluginDefinition) {
339
- import_logger2.logger.warn(
340
- 'Skip strategy plugin "%s": export { strategyEntries } is missing',
341
- moduleName
342
- );
343
- } else {
344
- registerEntries(pluginDefinition.strategyEntries, moduleName);
335
+ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
336
+ const { projectRoot, state } = getStrategyRegistryState(cwd);
337
+ if (!state.pluginsLoadPromise) {
338
+ (0, import_indicators.resetIndicatorRegistryCache)(projectRoot);
339
+ state.pluginsLoadPromise = (async () => {
340
+ const { strategyModules, indicatorModules } = await getConfiguredPluginModuleNames(projectRoot);
341
+ const strategySet = new Set(strategyModules);
342
+ const indicatorSet = new Set(indicatorModules);
343
+ const pluginModuleNames = [
344
+ .../* @__PURE__ */ new Set([...strategyModules, ...indicatorModules])
345
+ ];
346
+ if (!pluginModuleNames.length) {
347
+ return;
348
+ }
349
+ for (const moduleName of pluginModuleNames) {
350
+ try {
351
+ const resolvedModuleName = resolvePluginModuleSpecifier(
352
+ moduleName,
353
+ projectRoot
354
+ );
355
+ const moduleExport = await importStrategyPluginModule(resolvedModuleName);
356
+ if (strategySet.has(moduleName)) {
357
+ const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
358
+ if (!pluginDefinition) {
359
+ import_logger2.logger.warn(
360
+ 'Skip strategy plugin "%s": export { strategyEntries } is missing',
361
+ moduleName
362
+ );
363
+ } else {
364
+ registerEntries(
365
+ pluginDefinition.strategyEntries,
366
+ moduleName,
367
+ state
368
+ );
369
+ }
345
370
  }
346
- }
347
- if (indicatorSet.has(moduleName)) {
348
- const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
349
- if (!indicatorPluginDefinition) {
371
+ if (indicatorSet.has(moduleName)) {
372
+ const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
373
+ if (!indicatorPluginDefinition) {
374
+ import_logger2.logger.warn(
375
+ 'Skip indicator plugin "%s": export { indicatorEntries } is missing',
376
+ moduleName
377
+ );
378
+ } else {
379
+ (0, import_indicators.registerIndicatorEntries)(
380
+ indicatorPluginDefinition.indicatorEntries,
381
+ moduleName,
382
+ projectRoot
383
+ );
384
+ }
385
+ }
386
+ if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
350
387
  import_logger2.logger.warn(
351
- 'Skip indicator plugin "%s": export { indicatorEntries } is missing',
352
- moduleName
353
- );
354
- } else {
355
- (0, import_indicators.registerIndicatorEntries)(
356
- indicatorPluginDefinition.indicatorEntries,
388
+ 'Skip plugin "%s": no strategy/indicator sections requested in config',
357
389
  moduleName
358
390
  );
359
391
  }
360
- }
361
- if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
392
+ } catch (error) {
362
393
  import_logger2.logger.warn(
363
- 'Skip plugin "%s": no strategy/indicator sections requested in config',
364
- moduleName
394
+ 'Failed to load plugin "%s": %s',
395
+ moduleName,
396
+ String(error)
365
397
  );
366
398
  }
367
- } catch (error) {
368
- import_logger2.logger.warn(
369
- 'Failed to load plugin "%s": %s',
370
- moduleName,
371
- String(error)
372
- );
373
399
  }
374
- }
375
- })();
376
- return pluginsLoadPromise;
400
+ })();
401
+ }
402
+ await state.pluginsLoadPromise;
377
403
  };
378
- var ensureIndicatorPluginsLoaded = ensureStrategyPluginsLoaded;
379
- var getStrategyCreator = async (name) => {
380
- await ensureStrategyPluginsLoaded();
381
- return strategyCreators.get(name);
404
+ var ensureIndicatorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => ensureStrategyPluginsLoaded(cwd);
405
+ var getStrategyCreator = async (name, cwd = getTradejsProjectCwd()) => {
406
+ await ensureStrategyPluginsLoaded(cwd);
407
+ const { state } = getStrategyRegistryState(cwd);
408
+ return state.strategyCreators.get(name);
382
409
  };
383
- var getAvailableStrategyNames = async () => {
384
- await ensureStrategyPluginsLoaded();
385
- return [...strategyCreators.keys()].sort((a, b) => a.localeCompare(b));
410
+ var getAvailableStrategyNames = async (cwd = getTradejsProjectCwd()) => {
411
+ await ensureStrategyPluginsLoaded(cwd);
412
+ const { state } = getStrategyRegistryState(cwd);
413
+ return [...state.strategyCreators.keys()].sort((a, b) => a.localeCompare(b));
386
414
  };
387
- var getRegisteredStrategies = () => {
388
- return Object.fromEntries(strategyCreators.entries());
415
+ var getRegisteredStrategies = (cwd = getTradejsProjectCwd()) => {
416
+ const { state } = getStrategyRegistryState(cwd);
417
+ return Object.fromEntries(state.strategyCreators.entries());
389
418
  };
390
- var getRegisteredManifests = () => {
391
- return [...strategyManifestsMap.values()];
419
+ var getRegisteredManifests = (cwd = getTradejsProjectCwd()) => {
420
+ const { state } = getStrategyRegistryState(cwd);
421
+ return [...state.strategyManifestsMap.values()];
392
422
  };
393
- var getStrategyManifest = (name) => {
394
- return name ? strategyManifestsMap.get(name) : void 0;
423
+ var getStrategyManifest = (name, cwd = getTradejsProjectCwd()) => {
424
+ if (!name) {
425
+ return void 0;
426
+ }
427
+ const { state } = getStrategyRegistryState(cwd);
428
+ return state.strategyManifestsMap.get(name);
395
429
  };
396
- var isKnownStrategy = (name) => {
397
- return strategyCreators.has(name);
430
+ var isKnownStrategy = (name, cwd = getTradejsProjectCwd()) => {
431
+ const { state } = getStrategyRegistryState(cwd);
432
+ return state.strategyCreators.has(name);
398
433
  };
399
- var registerStrategyEntries = (entries) => {
400
- registerEntries(entries, "runtime");
434
+ var registerStrategyEntries = (entries, cwd = getTradejsProjectCwd()) => {
435
+ const { state } = getStrategyRegistryState(cwd);
436
+ registerEntries(entries, "runtime", state);
401
437
  };
402
- var resetStrategyRegistryCache = () => {
403
- strategyCreators.clear();
404
- strategyManifestsMap.clear();
405
- (0, import_indicators.resetIndicatorRegistryCache)();
406
- pluginsLoadPromise = null;
438
+ var resetStrategyRegistryCache = (cwd) => {
439
+ const normalizedCwd = String(cwd ?? "").trim();
440
+ if (!normalizedCwd) {
441
+ registryStateByProjectRoot.clear();
442
+ (0, import_indicators.resetIndicatorRegistryCache)();
443
+ return;
444
+ }
445
+ const projectRoot = getTradejsProjectCwd(normalizedCwd);
446
+ registryStateByProjectRoot.delete(projectRoot);
447
+ (0, import_indicators.resetIndicatorRegistryCache)(projectRoot);
407
448
  };
408
449
  var strategies = new Proxy(
409
450
  {},
@@ -412,10 +453,10 @@ var strategies = new Proxy(
412
453
  if (typeof property !== "string") {
413
454
  return void 0;
414
455
  }
415
- return strategyCreators.get(property);
456
+ return getStrategyRegistryState().state.strategyCreators.get(property);
416
457
  },
417
458
  ownKeys: () => {
418
- return [...strategyCreators.keys()];
459
+ return [...getStrategyRegistryState().state.strategyCreators.keys()];
419
460
  },
420
461
  getOwnPropertyDescriptor: () => ({
421
462
  enumerable: true,
package/dist/registry.mjs CHANGED
@@ -11,8 +11,8 @@ import {
11
11
  registerStrategyEntries,
12
12
  resetStrategyRegistryCache,
13
13
  strategies
14
- } from "./chunk-MHCXPD2B.mjs";
15
- import "./chunk-DE7ADBIR.mjs";
14
+ } from "./chunk-CK2PW4L5.mjs";
15
+ import "./chunk-3C76HVLA.mjs";
16
16
  import "./chunk-6DZX6EAA.mjs";
17
17
  export {
18
18
  ensureIndicatorPluginsLoaded,