@tradejs/node 3.1.11 → 3.1.12-beta.218

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.
@@ -589,7 +589,6 @@ import {
589
589
  registerIndicatorEntries,
590
590
  resetIndicatorRegistryCache
591
591
  } from "@tradejs/core/indicators";
592
- import { logger } from "@tradejs/infra/logger";
593
592
  var SHARED_STRATEGY_REGISTRY_KEY = "__tradejsNodeSharedStrategyRegistryV1__";
594
593
  var sharedRegistryScope = globalThis;
595
594
  var sharedStrategyRegistry = sharedRegistryScope[SHARED_STRATEGY_REGISTRY_KEY] ?? (sharedRegistryScope[SHARED_STRATEGY_REGISTRY_KEY] = {
@@ -653,21 +652,34 @@ var extractIndicatorPluginDefinition = (moduleExport) => {
653
652
  );
654
653
  return indicatorEntries ? { indicatorEntries } : null;
655
654
  };
656
- var registerEntries = (entries, source, state) => {
657
- for (const entry of entries) {
658
- const strategyName = entry.manifest?.name;
659
- if (!strategyName) {
660
- logger.warn("Skip strategy entry without name from %s", source);
661
- continue;
655
+ var validateStrategyEntries = (moduleName, entries, state) => {
656
+ const issues = [];
657
+ const names = /* @__PURE__ */ new Set();
658
+ entries.forEach((entry, index) => {
659
+ const entryPath = `${moduleName}.strategyEntries[${index}]`;
660
+ const strategyName = entry?.manifest?.name;
661
+ if (typeof strategyName !== "string" || !strategyName.trim()) {
662
+ issues.push(`${entryPath}: manifest.name is required`);
663
+ } else if (names.has(strategyName) || state.strategyEntriesMap.has(strategyName)) {
664
+ issues.push(`${entryPath}: duplicate strategy ${strategyName}`);
665
+ } else {
666
+ names.add(strategyName);
662
667
  }
663
- if (state.strategyCreators.has(strategyName)) {
664
- logger.warn(
665
- 'Skip duplicate strategy "%s" from %s: already registered',
666
- strategyName,
667
- source
668
- );
669
- continue;
668
+ if (!entry || typeof entry !== "object" || !entry.defaults || typeof entry.defaults !== "object" || Array.isArray(entry.defaults)) {
669
+ issues.push(`${entryPath}: defaults must be an object`);
670
+ }
671
+ if (typeof entry?.parseConfig !== "function") {
672
+ issues.push(`${entryPath}: parseConfig is required`);
673
+ }
674
+ if (typeof entry?.createCore !== "function") {
675
+ issues.push(`${entryPath}: createCore is required`);
670
676
  }
677
+ });
678
+ return issues;
679
+ };
680
+ var registerEntries = (entries, source, state) => {
681
+ for (const entry of entries) {
682
+ const strategyName = entry.manifest.name;
671
683
  state.strategyManifestsMap.set(strategyName, entry.manifest);
672
684
  state.strategyEntriesMap.set(strategyName, entry);
673
685
  state.strategySourcesMap.set(strategyName, source);
@@ -724,6 +736,7 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
724
736
  if (!pluginModuleNames.length) {
725
737
  return;
726
738
  }
739
+ const issues = [];
727
740
  for (const moduleName of pluginModuleNames) {
728
741
  try {
729
742
  const resolvedModuleName = resolvePluginModuleSpecifier(
@@ -737,24 +750,30 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
737
750
  if (strategySet.has(moduleName)) {
738
751
  const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
739
752
  if (!pluginDefinition) {
740
- logger.warn(
741
- 'Skip strategy plugin "%s": export { strategyEntries } is missing',
742
- moduleName
753
+ issues.push(
754
+ `${moduleName}: export { strategyEntries } is missing`
743
755
  );
744
756
  } else {
745
- registerEntries(
746
- pluginDefinition.strategyEntries,
757
+ const entryIssues = validateStrategyEntries(
747
758
  moduleName,
759
+ pluginDefinition.strategyEntries,
748
760
  state
749
761
  );
762
+ issues.push(...entryIssues);
763
+ if (entryIssues.length === 0) {
764
+ registerEntries(
765
+ pluginDefinition.strategyEntries,
766
+ moduleName,
767
+ state
768
+ );
769
+ }
750
770
  }
751
771
  }
752
772
  if (indicatorSet.has(moduleName)) {
753
773
  const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
754
774
  if (!indicatorPluginDefinition) {
755
- logger.warn(
756
- 'Skip indicator plugin "%s": export { indicatorEntries } is missing',
757
- moduleName
775
+ issues.push(
776
+ `${moduleName}: export { indicatorEntries } is missing`
758
777
  );
759
778
  } else {
760
779
  registerIndicatorEntries(
@@ -765,19 +784,17 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
765
784
  }
766
785
  }
767
786
  if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
768
- logger.warn(
769
- 'Skip plugin "%s": no strategy/indicator sections requested in config',
770
- moduleName
771
- );
787
+ issues.push(`${moduleName}: plugin is not declared in config`);
772
788
  }
773
789
  } catch (error) {
774
- logger.warn(
775
- 'Failed to load plugin "%s": %s',
776
- moduleName,
777
- String(error)
778
- );
790
+ issues.push(`${moduleName}: failed to import: ${String(error)}`);
779
791
  }
780
792
  }
793
+ if (issues.length > 0) {
794
+ throw new Error(
795
+ ["Invalid TradeJS plugin catalog:", ...issues].join("\n")
796
+ );
797
+ }
781
798
  })();
782
799
  }
783
800
  await state.pluginsLoadPromise;
@@ -793,6 +810,11 @@ var getStrategyDefaults = async (name, cwd = getTradejsProjectCwd()) => {
793
810
  const { state } = getStrategyRegistryState(cwd);
794
811
  return state.strategyEntriesMap.get(name)?.defaults;
795
812
  };
813
+ var getStrategyEntry = async (name, cwd = getTradejsProjectCwd()) => {
814
+ await ensureStrategyPluginsLoaded(cwd);
815
+ const { state } = getStrategyRegistryState(cwd);
816
+ return state.strategyEntriesMap.get(name);
817
+ };
796
818
  var getStrategyPluginSource = async (name, cwd = getTradejsProjectCwd()) => {
797
819
  await ensureStrategyPluginsLoaded(cwd);
798
820
  const { state } = getStrategyRegistryState(cwd);
@@ -824,6 +846,10 @@ var isKnownStrategy = (name, cwd = getTradejsProjectCwd()) => {
824
846
  };
825
847
  var registerStrategyEntries = (entries, cwd = getTradejsProjectCwd()) => {
826
848
  const { state } = getStrategyRegistryState(cwd);
849
+ const issues = validateStrategyEntries("runtime", entries, state);
850
+ if (issues.length > 0) {
851
+ throw new Error(["Invalid TradeJS plugin catalog:", ...issues].join("\n"));
852
+ }
827
853
  registerEntries(entries, "runtime", state);
828
854
  };
829
855
  var resetStrategyRegistryCache = (cwd) => {
@@ -1451,6 +1477,7 @@ export {
1451
1477
  ensureIndicatorPluginsLoaded,
1452
1478
  getStrategyCreator,
1453
1479
  getStrategyDefaults,
1480
+ getStrategyEntry,
1454
1481
  getStrategyPluginSource,
1455
1482
  getAvailableStrategyNames,
1456
1483
  getRegisteredStrategies,