@backstage/backend-test-utils 0.2.2 → 0.2.3-next.2

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/index.cjs.js CHANGED
@@ -10,6 +10,7 @@ var uuid = require('uuid');
10
10
  var backendAppApi = require('@backstage/backend-app-api');
11
11
  var backendPluginApi = require('@backstage/backend-plugin-api');
12
12
  var express = require('express');
13
+ var errors = require('@backstage/errors');
13
14
 
14
15
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
15
16
 
@@ -391,26 +392,26 @@ class MockIdentityService {
391
392
  }
392
393
  }
393
394
 
394
- var __accessCheck = (obj, member, msg) => {
395
+ var __accessCheck$3 = (obj, member, msg) => {
395
396
  if (!member.has(obj))
396
397
  throw TypeError("Cannot " + msg);
397
398
  };
398
- var __privateGet = (obj, member, getter) => {
399
- __accessCheck(obj, member, "read from private field");
399
+ var __privateGet$3 = (obj, member, getter) => {
400
+ __accessCheck$3(obj, member, "read from private field");
400
401
  return getter ? getter.call(obj) : member.get(obj);
401
402
  };
402
- var __privateAdd = (obj, member, value) => {
403
+ var __privateAdd$3 = (obj, member, value) => {
403
404
  if (member.has(obj))
404
405
  throw TypeError("Cannot add the same private member more than once");
405
406
  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
406
407
  };
407
- var __privateSet = (obj, member, value, setter) => {
408
- __accessCheck(obj, member, "write to private field");
408
+ var __privateSet$3 = (obj, member, value, setter) => {
409
+ __accessCheck$3(obj, member, "write to private field");
409
410
  setter ? setter.call(obj, value) : member.set(obj, value);
410
411
  return value;
411
412
  };
412
- var __privateMethod = (obj, member, method) => {
413
- __accessCheck(obj, member, "access private method");
413
+ var __privateMethod$2 = (obj, member, method) => {
414
+ __accessCheck$3(obj, member, "access private method");
414
415
  return method;
415
416
  };
416
417
  var _level, _meta, _log, log_fn;
@@ -423,11 +424,11 @@ const levels = {
423
424
  };
424
425
  const _MockRootLoggerService = class _MockRootLoggerService {
425
426
  constructor(level, meta) {
426
- __privateAdd(this, _log);
427
- __privateAdd(this, _level, void 0);
428
- __privateAdd(this, _meta, void 0);
429
- __privateSet(this, _level, level);
430
- __privateSet(this, _meta, meta);
427
+ __privateAdd$3(this, _log);
428
+ __privateAdd$3(this, _level, void 0);
429
+ __privateAdd$3(this, _meta, void 0);
430
+ __privateSet$3(this, _level, level);
431
+ __privateSet$3(this, _meta, meta);
431
432
  }
432
433
  static create(options) {
433
434
  var _a;
@@ -438,19 +439,19 @@ const _MockRootLoggerService = class _MockRootLoggerService {
438
439
  return new _MockRootLoggerService(levels[level], {});
439
440
  }
440
441
  error(message, meta) {
441
- __privateMethod(this, _log, log_fn).call(this, "error", message, meta);
442
+ __privateMethod$2(this, _log, log_fn).call(this, "error", message, meta);
442
443
  }
443
444
  warn(message, meta) {
444
- __privateMethod(this, _log, log_fn).call(this, "warn", message, meta);
445
+ __privateMethod$2(this, _log, log_fn).call(this, "warn", message, meta);
445
446
  }
446
447
  info(message, meta) {
447
- __privateMethod(this, _log, log_fn).call(this, "info", message, meta);
448
+ __privateMethod$2(this, _log, log_fn).call(this, "info", message, meta);
448
449
  }
449
450
  debug(message, meta) {
450
- __privateMethod(this, _log, log_fn).call(this, "debug", message, meta);
451
+ __privateMethod$2(this, _log, log_fn).call(this, "debug", message, meta);
451
452
  }
452
453
  child(meta) {
453
- return new _MockRootLoggerService(__privateGet(this, _level), { ...__privateGet(this, _meta), ...meta });
454
+ return new _MockRootLoggerService(__privateGet$3(this, _level), { ...__privateGet$3(this, _meta), ...meta });
454
455
  }
455
456
  };
456
457
  _level = new WeakMap();
@@ -459,8 +460,8 @@ _log = new WeakSet();
459
460
  log_fn = function(level, message, meta) {
460
461
  var _a;
461
462
  const levelValue = (_a = levels[level]) != null ? _a : 0;
462
- if (levelValue <= __privateGet(this, _level)) {
463
- const labels = Object.entries(__privateGet(this, _meta)).map(([key, value]) => `${key}=${value}`).join(",");
463
+ if (levelValue <= __privateGet$3(this, _level)) {
464
+ const labels = Object.entries(__privateGet$3(this, _meta)).map(([key, value]) => `${key}=${value}`).join(",");
464
465
  console[level](`${labels} ${message}`, meta);
465
466
  }
466
467
  };
@@ -475,6 +476,27 @@ function simpleFactory(ref, factory) {
475
476
  }
476
477
  }));
477
478
  }
479
+ function simpleMock(ref, mockFactory) {
480
+ return (partialImpl) => {
481
+ const mock = mockFactory();
482
+ if (partialImpl) {
483
+ for (const [key, impl] of Object.entries(partialImpl)) {
484
+ if (typeof impl === "function") {
485
+ mock[key].mockImplementation(impl);
486
+ } else {
487
+ mock[key] = impl;
488
+ }
489
+ }
490
+ }
491
+ return Object.assign(mock, {
492
+ factory: backendPluginApi.createServiceFactory({
493
+ service: ref,
494
+ deps: {},
495
+ factory: () => mock
496
+ })()
497
+ });
498
+ };
499
+ }
478
500
  exports.mockServices = void 0;
479
501
  ((mockServices2) => {
480
502
  function rootConfig(options) {
@@ -490,6 +512,13 @@ exports.mockServices = void 0;
490
512
  mockServices2.rootLogger = rootLogger;
491
513
  ((rootLogger2) => {
492
514
  rootLogger2.factory = simpleFactory(backendPluginApi.coreServices.rootLogger, rootLogger2);
515
+ rootLogger2.mock = simpleMock(backendPluginApi.coreServices.rootLogger, () => ({
516
+ child: jest.fn(),
517
+ debug: jest.fn(),
518
+ error: jest.fn(),
519
+ info: jest.fn(),
520
+ warn: jest.fn()
521
+ }));
493
522
  })(rootLogger = mockServices2.rootLogger || (mockServices2.rootLogger = {}));
494
523
  function tokenManager() {
495
524
  return {
@@ -509,6 +538,10 @@ exports.mockServices = void 0;
509
538
  backendPluginApi.coreServices.tokenManager,
510
539
  tokenManager2
511
540
  );
541
+ tokenManager2.mock = simpleMock(backendPluginApi.coreServices.tokenManager, () => ({
542
+ authenticate: jest.fn(),
543
+ getToken: jest.fn()
544
+ }));
512
545
  })(tokenManager = mockServices2.tokenManager || (mockServices2.tokenManager = {}));
513
546
  function identity() {
514
547
  return new MockIdentityService();
@@ -516,33 +549,84 @@ exports.mockServices = void 0;
516
549
  mockServices2.identity = identity;
517
550
  ((identity2) => {
518
551
  identity2.factory = simpleFactory(backendPluginApi.coreServices.identity, identity2);
552
+ identity2.mock = simpleMock(backendPluginApi.coreServices.identity, () => ({
553
+ getIdentity: jest.fn()
554
+ }));
519
555
  })(identity = mockServices2.identity || (mockServices2.identity = {}));
520
556
  ((cache2) => {
521
557
  cache2.factory = backendAppApi.cacheServiceFactory;
558
+ cache2.mock = simpleMock(backendPluginApi.coreServices.cache, () => ({
559
+ delete: jest.fn(),
560
+ get: jest.fn(),
561
+ set: jest.fn(),
562
+ withOptions: jest.fn()
563
+ }));
522
564
  })(mockServices2.cache || (mockServices2.cache = {}));
523
565
  ((database2) => {
524
566
  database2.factory = backendAppApi.databaseServiceFactory;
567
+ database2.mock = simpleMock(backendPluginApi.coreServices.database, () => ({
568
+ getClient: jest.fn()
569
+ }));
525
570
  })(mockServices2.database || (mockServices2.database = {}));
526
571
  ((httpRouter2) => {
527
572
  httpRouter2.factory = backendAppApi.httpRouterServiceFactory;
573
+ httpRouter2.mock = simpleMock(backendPluginApi.coreServices.httpRouter, () => ({
574
+ use: jest.fn()
575
+ }));
528
576
  })(mockServices2.httpRouter || (mockServices2.httpRouter = {}));
577
+ ((rootHttpRouter2) => {
578
+ rootHttpRouter2.factory = backendAppApi.rootHttpRouterServiceFactory;
579
+ rootHttpRouter2.mock = simpleMock(backendPluginApi.coreServices.rootHttpRouter, () => ({
580
+ use: jest.fn()
581
+ }));
582
+ })(mockServices2.rootHttpRouter || (mockServices2.rootHttpRouter = {}));
529
583
  ((lifecycle2) => {
530
584
  lifecycle2.factory = backendAppApi.lifecycleServiceFactory;
585
+ lifecycle2.mock = simpleMock(backendPluginApi.coreServices.lifecycle, () => ({
586
+ addShutdownHook: jest.fn(),
587
+ addStartupHook: jest.fn()
588
+ }));
531
589
  })(mockServices2.lifecycle || (mockServices2.lifecycle = {}));
532
590
  ((logger2) => {
533
591
  logger2.factory = backendAppApi.loggerServiceFactory;
592
+ logger2.mock = simpleMock(backendPluginApi.coreServices.logger, () => ({
593
+ child: jest.fn(),
594
+ debug: jest.fn(),
595
+ error: jest.fn(),
596
+ info: jest.fn(),
597
+ warn: jest.fn()
598
+ }));
534
599
  })(mockServices2.logger || (mockServices2.logger = {}));
535
600
  ((permissions2) => {
536
601
  permissions2.factory = backendAppApi.permissionsServiceFactory;
602
+ permissions2.mock = simpleMock(backendPluginApi.coreServices.permissions, () => ({
603
+ authorize: jest.fn(),
604
+ authorizeConditional: jest.fn()
605
+ }));
537
606
  })(mockServices2.permissions || (mockServices2.permissions = {}));
538
607
  ((rootLifecycle2) => {
539
608
  rootLifecycle2.factory = backendAppApi.rootLifecycleServiceFactory;
609
+ rootLifecycle2.mock = simpleMock(backendPluginApi.coreServices.rootLifecycle, () => ({
610
+ addShutdownHook: jest.fn(),
611
+ addStartupHook: jest.fn()
612
+ }));
540
613
  })(mockServices2.rootLifecycle || (mockServices2.rootLifecycle = {}));
541
614
  ((scheduler2) => {
542
615
  scheduler2.factory = backendAppApi.schedulerServiceFactory;
616
+ scheduler2.mock = simpleMock(backendPluginApi.coreServices.scheduler, () => ({
617
+ createScheduledTaskRunner: jest.fn(),
618
+ getScheduledTasks: jest.fn(),
619
+ scheduleTask: jest.fn(),
620
+ triggerTask: jest.fn()
621
+ }));
543
622
  })(mockServices2.scheduler || (mockServices2.scheduler = {}));
544
623
  ((urlReader2) => {
545
624
  urlReader2.factory = backendAppApi.urlReaderServiceFactory;
625
+ urlReader2.mock = simpleMock(backendPluginApi.coreServices.urlReader, () => ({
626
+ readTree: jest.fn(),
627
+ readUrl: jest.fn(),
628
+ search: jest.fn()
629
+ }));
546
630
  })(mockServices2.urlReader || (mockServices2.urlReader = {}));
547
631
  })(exports.mockServices || (exports.mockServices = {}));
548
632
 
@@ -729,6 +813,504 @@ function isInternalBackendFeature(feature) {
729
813
  return typeof feature.getRegistrations === "function";
730
814
  }
731
815
 
816
+ var __accessCheck$2 = (obj, member, msg) => {
817
+ if (!member.has(obj))
818
+ throw TypeError("Cannot " + msg);
819
+ };
820
+ var __privateGet$2 = (obj, member, getter) => {
821
+ __accessCheck$2(obj, member, "read from private field");
822
+ return getter ? getter.call(obj) : member.get(obj);
823
+ };
824
+ var __privateAdd$2 = (obj, member, value) => {
825
+ if (member.has(obj))
826
+ throw TypeError("Cannot add the same private member more than once");
827
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
828
+ };
829
+ var __privateSet$2 = (obj, member, value, setter) => {
830
+ __accessCheck$2(obj, member, "write to private field");
831
+ setter ? setter.call(obj, value) : member.set(obj, value);
832
+ return value;
833
+ };
834
+ var __privateMethod$1 = (obj, member, method) => {
835
+ __accessCheck$2(obj, member, "access private method");
836
+ return method;
837
+ };
838
+ var _nodeIds, _cycleKeys, _getCycleKey, getCycleKey_fn, _nodes, _allProvided;
839
+ class Node {
840
+ constructor(value, consumes, provides) {
841
+ this.value = value;
842
+ this.consumes = consumes;
843
+ this.provides = provides;
844
+ }
845
+ static from(input) {
846
+ return new Node(
847
+ input.value,
848
+ input.consumes ? new Set(input.consumes) : /* @__PURE__ */ new Set(),
849
+ input.provides ? new Set(input.provides) : /* @__PURE__ */ new Set()
850
+ );
851
+ }
852
+ }
853
+ const _CycleKeySet = class _CycleKeySet {
854
+ constructor(nodes) {
855
+ __privateAdd$2(this, _getCycleKey);
856
+ __privateAdd$2(this, _nodeIds, void 0);
857
+ __privateAdd$2(this, _cycleKeys, void 0);
858
+ __privateSet$2(this, _nodeIds, new Map(nodes.map((n, i) => [n.value, i])));
859
+ __privateSet$2(this, _cycleKeys, /* @__PURE__ */ new Set());
860
+ }
861
+ static from(nodes) {
862
+ return new _CycleKeySet(nodes);
863
+ }
864
+ tryAdd(path) {
865
+ const cycleKey = __privateMethod$1(this, _getCycleKey, getCycleKey_fn).call(this, path);
866
+ if (__privateGet$2(this, _cycleKeys).has(cycleKey)) {
867
+ return false;
868
+ }
869
+ __privateGet$2(this, _cycleKeys).add(cycleKey);
870
+ return true;
871
+ }
872
+ };
873
+ _nodeIds = new WeakMap();
874
+ _cycleKeys = new WeakMap();
875
+ _getCycleKey = new WeakSet();
876
+ getCycleKey_fn = function(path) {
877
+ return path.map((n) => __privateGet$2(this, _nodeIds).get(n)).sort().join(",");
878
+ };
879
+ let CycleKeySet = _CycleKeySet;
880
+ const _DependencyGraph = class _DependencyGraph {
881
+ constructor(nodes) {
882
+ __privateAdd$2(this, _nodes, void 0);
883
+ __privateAdd$2(this, _allProvided, void 0);
884
+ __privateSet$2(this, _nodes, nodes);
885
+ __privateSet$2(this, _allProvided, /* @__PURE__ */ new Set());
886
+ for (const node of __privateGet$2(this, _nodes).values()) {
887
+ for (const produced of node.provides) {
888
+ __privateGet$2(this, _allProvided).add(produced);
889
+ }
890
+ }
891
+ }
892
+ static fromMap(nodes) {
893
+ return this.fromIterable(
894
+ Object.entries(nodes).map(([key, node]) => ({
895
+ value: String(key),
896
+ ...node
897
+ }))
898
+ );
899
+ }
900
+ static fromIterable(nodeInputs) {
901
+ const nodes = new Array();
902
+ for (const nodeInput of nodeInputs) {
903
+ nodes.push(Node.from(nodeInput));
904
+ }
905
+ return new _DependencyGraph(nodes);
906
+ }
907
+ /**
908
+ * Find all nodes that consume dependencies that are not provided by any other node.
909
+ */
910
+ findUnsatisfiedDeps() {
911
+ const unsatisfiedDependencies = [];
912
+ for (const node of __privateGet$2(this, _nodes).values()) {
913
+ const unsatisfied = Array.from(node.consumes).filter(
914
+ (id) => !__privateGet$2(this, _allProvided).has(id)
915
+ );
916
+ if (unsatisfied.length > 0) {
917
+ unsatisfiedDependencies.push({ value: node.value, unsatisfied });
918
+ }
919
+ }
920
+ return unsatisfiedDependencies;
921
+ }
922
+ /**
923
+ * Detect the first circular dependency within the graph, returning the path of nodes that
924
+ * form a cycle, with the same node as the first and last element of the array.
925
+ */
926
+ detectCircularDependency() {
927
+ return this.detectCircularDependencies().next().value;
928
+ }
929
+ /**
930
+ * Detect circular dependencies within the graph, returning the path of nodes that
931
+ * form a cycle, with the same node as the first and last element of the array.
932
+ */
933
+ *detectCircularDependencies() {
934
+ const cycleKeys = CycleKeySet.from(__privateGet$2(this, _nodes));
935
+ for (const startNode of __privateGet$2(this, _nodes)) {
936
+ const visited = /* @__PURE__ */ new Set();
937
+ const stack = new Array([
938
+ startNode,
939
+ [startNode.value]
940
+ ]);
941
+ while (stack.length > 0) {
942
+ const [node, path] = stack.pop();
943
+ if (visited.has(node)) {
944
+ continue;
945
+ }
946
+ visited.add(node);
947
+ for (const consumed of node.consumes) {
948
+ const providerNodes = __privateGet$2(this, _nodes).filter(
949
+ (other) => other.provides.has(consumed)
950
+ );
951
+ for (const provider of providerNodes) {
952
+ if (provider === startNode) {
953
+ if (cycleKeys.tryAdd(path)) {
954
+ yield [...path, startNode.value];
955
+ }
956
+ break;
957
+ }
958
+ if (!visited.has(provider)) {
959
+ stack.push([provider, [...path, provider.value]]);
960
+ }
961
+ }
962
+ }
963
+ }
964
+ }
965
+ return void 0;
966
+ }
967
+ /**
968
+ * Traverses the dependency graph in topological order, calling the provided
969
+ * function for each node and waiting for it to resolve.
970
+ *
971
+ * The nodes are traversed in parallel, but in such a way that no node is
972
+ * visited before all of its dependencies.
973
+ *
974
+ * Dependencies of nodes that are not produced by any other nodes will be ignored.
975
+ */
976
+ async parallelTopologicalTraversal(fn) {
977
+ const allProvided = __privateGet$2(this, _allProvided);
978
+ const producedSoFar = /* @__PURE__ */ new Set();
979
+ const waiting = new Set(__privateGet$2(this, _nodes).values());
980
+ const visited = /* @__PURE__ */ new Set();
981
+ const results = new Array();
982
+ let inFlight = 0;
983
+ async function processMoreNodes() {
984
+ if (waiting.size === 0) {
985
+ return;
986
+ }
987
+ const nodesToProcess = [];
988
+ for (const node of waiting) {
989
+ let ready = true;
990
+ for (const consumed of node.consumes) {
991
+ if (allProvided.has(consumed) && !producedSoFar.has(consumed)) {
992
+ ready = false;
993
+ continue;
994
+ }
995
+ }
996
+ if (ready) {
997
+ nodesToProcess.push(node);
998
+ }
999
+ }
1000
+ for (const node of nodesToProcess) {
1001
+ waiting.delete(node);
1002
+ }
1003
+ if (nodesToProcess.length === 0 && inFlight === 0) {
1004
+ throw new Error("Circular dependency detected");
1005
+ }
1006
+ await Promise.all(nodesToProcess.map(processNode));
1007
+ }
1008
+ async function processNode(node) {
1009
+ visited.add(node);
1010
+ inFlight += 1;
1011
+ const result = await fn(node.value);
1012
+ results.push(result);
1013
+ node.provides.forEach((produced) => producedSoFar.add(produced));
1014
+ inFlight -= 1;
1015
+ await processMoreNodes();
1016
+ }
1017
+ await processMoreNodes();
1018
+ return results;
1019
+ }
1020
+ };
1021
+ _nodes = new WeakMap();
1022
+ _allProvided = new WeakMap();
1023
+ let DependencyGraph = _DependencyGraph;
1024
+
1025
+ var __accessCheck$1 = (obj, member, msg) => {
1026
+ if (!member.has(obj))
1027
+ throw TypeError("Cannot " + msg);
1028
+ };
1029
+ var __privateGet$1 = (obj, member, getter) => {
1030
+ __accessCheck$1(obj, member, "read from private field");
1031
+ return getter ? getter.call(obj) : member.get(obj);
1032
+ };
1033
+ var __privateAdd$1 = (obj, member, value) => {
1034
+ if (member.has(obj))
1035
+ throw TypeError("Cannot add the same private member more than once");
1036
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1037
+ };
1038
+ var __privateSet$1 = (obj, member, value, setter) => {
1039
+ __accessCheck$1(obj, member, "write to private field");
1040
+ setter ? setter.call(obj, value) : member.set(obj, value);
1041
+ return value;
1042
+ };
1043
+ var __privateMethod = (obj, member, method) => {
1044
+ __accessCheck$1(obj, member, "access private method");
1045
+ return method;
1046
+ };
1047
+ var _providedFactories, _loadedDefaultFactories, _implementations, _rootServiceImplementations, _resolveFactory, resolveFactory_fn, _checkForMissingDeps, checkForMissingDeps_fn, _checkForCircularDeps, checkForCircularDeps_fn;
1048
+ function toInternalServiceFactory(factory) {
1049
+ const f = factory;
1050
+ if (f.$$type !== "@backstage/BackendFeature") {
1051
+ throw new Error(`Invalid service factory, bad type '${f.$$type}'`);
1052
+ }
1053
+ if (f.version !== "v1") {
1054
+ throw new Error(`Invalid service factory, bad version '${f.version}'`);
1055
+ }
1056
+ return f;
1057
+ }
1058
+ const pluginMetadataServiceFactory = backendPluginApi.createServiceFactory(
1059
+ (options) => ({
1060
+ service: backendPluginApi.coreServices.pluginMetadata,
1061
+ deps: {},
1062
+ factory: async () => ({ getId: () => options == null ? void 0 : options.pluginId })
1063
+ })
1064
+ );
1065
+ const _ServiceRegistry = class _ServiceRegistry {
1066
+ constructor(factories) {
1067
+ __privateAdd$1(this, _resolveFactory);
1068
+ __privateAdd$1(this, _checkForMissingDeps);
1069
+ __privateAdd$1(this, _checkForCircularDeps);
1070
+ __privateAdd$1(this, _providedFactories, void 0);
1071
+ __privateAdd$1(this, _loadedDefaultFactories, void 0);
1072
+ __privateAdd$1(this, _implementations, void 0);
1073
+ __privateAdd$1(this, _rootServiceImplementations, /* @__PURE__ */ new Map());
1074
+ __privateSet$1(this, _providedFactories, new Map(
1075
+ factories.map((sf) => [sf.service.id, toInternalServiceFactory(sf)])
1076
+ ));
1077
+ __privateSet$1(this, _loadedDefaultFactories, /* @__PURE__ */ new Map());
1078
+ __privateSet$1(this, _implementations, /* @__PURE__ */ new Map());
1079
+ }
1080
+ static create(factories) {
1081
+ var _a;
1082
+ const registry = new _ServiceRegistry(factories);
1083
+ __privateMethod(_a = registry, _checkForCircularDeps, checkForCircularDeps_fn).call(_a);
1084
+ return registry;
1085
+ }
1086
+ getServiceRefs() {
1087
+ return Array.from(__privateGet$1(this, _providedFactories).values()).map((f) => f.service);
1088
+ }
1089
+ get(ref, pluginId) {
1090
+ var _a;
1091
+ return (_a = __privateMethod(this, _resolveFactory, resolveFactory_fn).call(this, ref, pluginId)) == null ? void 0 : _a.then((factory) => {
1092
+ if (factory.service.scope === "root") {
1093
+ let existing = __privateGet$1(this, _rootServiceImplementations).get(factory);
1094
+ if (!existing) {
1095
+ __privateMethod(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
1096
+ const rootDeps = new Array();
1097
+ for (const [name, serviceRef] of Object.entries(factory.deps)) {
1098
+ if (serviceRef.scope !== "root") {
1099
+ throw new Error(
1100
+ `Failed to instantiate 'root' scoped service '${ref.id}' because it depends on '${serviceRef.scope}' scoped service '${serviceRef.id}'.`
1101
+ );
1102
+ }
1103
+ const target = this.get(serviceRef, pluginId);
1104
+ rootDeps.push(target.then((impl) => [name, impl]));
1105
+ }
1106
+ existing = Promise.all(rootDeps).then(
1107
+ (entries) => factory.factory(Object.fromEntries(entries), void 0)
1108
+ );
1109
+ __privateGet$1(this, _rootServiceImplementations).set(factory, existing);
1110
+ }
1111
+ return existing;
1112
+ }
1113
+ let implementation = __privateGet$1(this, _implementations).get(factory);
1114
+ if (!implementation) {
1115
+ __privateMethod(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
1116
+ const rootDeps = new Array();
1117
+ for (const [name, serviceRef] of Object.entries(factory.deps)) {
1118
+ if (serviceRef.scope === "root") {
1119
+ const target = this.get(serviceRef, pluginId);
1120
+ rootDeps.push(target.then((impl) => [name, impl]));
1121
+ }
1122
+ }
1123
+ implementation = {
1124
+ context: Promise.all(rootDeps).then(
1125
+ (entries) => {
1126
+ var _a2;
1127
+ return (_a2 = factory.createRootContext) == null ? void 0 : _a2.call(factory, Object.fromEntries(entries));
1128
+ }
1129
+ ).catch((error) => {
1130
+ const cause = errors.stringifyError(error);
1131
+ throw new Error(
1132
+ `Failed to instantiate service '${ref.id}' because createRootContext threw an error, ${cause}`
1133
+ );
1134
+ }),
1135
+ byPlugin: /* @__PURE__ */ new Map()
1136
+ };
1137
+ __privateGet$1(this, _implementations).set(factory, implementation);
1138
+ }
1139
+ let result = implementation.byPlugin.get(pluginId);
1140
+ if (!result) {
1141
+ const allDeps = new Array();
1142
+ for (const [name, serviceRef] of Object.entries(factory.deps)) {
1143
+ const target = this.get(serviceRef, pluginId);
1144
+ allDeps.push(target.then((impl) => [name, impl]));
1145
+ }
1146
+ result = implementation.context.then(
1147
+ (context) => Promise.all(allDeps).then(
1148
+ (entries) => factory.factory(Object.fromEntries(entries), context)
1149
+ )
1150
+ ).catch((error) => {
1151
+ const cause = errors.stringifyError(error);
1152
+ throw new Error(
1153
+ `Failed to instantiate service '${ref.id}' for '${pluginId}' because the factory function threw an error, ${cause}`
1154
+ );
1155
+ });
1156
+ implementation.byPlugin.set(pluginId, result);
1157
+ }
1158
+ return result;
1159
+ });
1160
+ }
1161
+ };
1162
+ _providedFactories = new WeakMap();
1163
+ _loadedDefaultFactories = new WeakMap();
1164
+ _implementations = new WeakMap();
1165
+ _rootServiceImplementations = new WeakMap();
1166
+ _resolveFactory = new WeakSet();
1167
+ resolveFactory_fn = function(ref, pluginId) {
1168
+ if (ref.id === backendPluginApi.coreServices.pluginMetadata.id) {
1169
+ return Promise.resolve(
1170
+ toInternalServiceFactory(pluginMetadataServiceFactory({ pluginId }))
1171
+ );
1172
+ }
1173
+ let resolvedFactory = __privateGet$1(this, _providedFactories).get(ref.id);
1174
+ const { __defaultFactory: defaultFactory } = ref;
1175
+ if (!resolvedFactory && !defaultFactory) {
1176
+ return void 0;
1177
+ }
1178
+ if (!resolvedFactory) {
1179
+ let loadedFactory = __privateGet$1(this, _loadedDefaultFactories).get(defaultFactory);
1180
+ if (!loadedFactory) {
1181
+ loadedFactory = Promise.resolve().then(() => defaultFactory(ref)).then(
1182
+ (f) => toInternalServiceFactory(typeof f === "function" ? f() : f)
1183
+ );
1184
+ __privateGet$1(this, _loadedDefaultFactories).set(defaultFactory, loadedFactory);
1185
+ }
1186
+ resolvedFactory = loadedFactory.catch((error) => {
1187
+ throw new Error(
1188
+ `Failed to instantiate service '${ref.id}' because the default factory loader threw an error, ${errors.stringifyError(
1189
+ error
1190
+ )}`
1191
+ );
1192
+ });
1193
+ }
1194
+ return Promise.resolve(resolvedFactory);
1195
+ };
1196
+ _checkForMissingDeps = new WeakSet();
1197
+ checkForMissingDeps_fn = function(factory, pluginId) {
1198
+ const missingDeps = Object.values(factory.deps).filter((ref) => {
1199
+ if (ref.id === backendPluginApi.coreServices.pluginMetadata.id) {
1200
+ return false;
1201
+ }
1202
+ if (__privateGet$1(this, _providedFactories).get(ref.id)) {
1203
+ return false;
1204
+ }
1205
+ return !ref.__defaultFactory;
1206
+ });
1207
+ if (missingDeps.length) {
1208
+ const missing = missingDeps.map((r) => `'${r.id}'`).join(", ");
1209
+ throw new Error(
1210
+ `Failed to instantiate service '${factory.service.id}' for '${pluginId}' because the following dependent services are missing: ${missing}`
1211
+ );
1212
+ }
1213
+ };
1214
+ _checkForCircularDeps = new WeakSet();
1215
+ checkForCircularDeps_fn = function() {
1216
+ const graph = DependencyGraph.fromIterable(
1217
+ Array.from(__privateGet$1(this, _providedFactories)).map(
1218
+ ([serviceId, serviceFactory]) => ({
1219
+ value: serviceId,
1220
+ provides: [serviceId],
1221
+ consumes: Object.values(serviceFactory.deps).map((d) => d.id)
1222
+ })
1223
+ )
1224
+ );
1225
+ const circularDependencies = Array.from(graph.detectCircularDependencies());
1226
+ if (circularDependencies.length) {
1227
+ const cycles = circularDependencies.map((c) => c.map((id) => `'${id}'`).join(" -> ")).join("\n ");
1228
+ throw new errors.ConflictError(`Circular dependencies detected:
1229
+ ${cycles}`);
1230
+ }
1231
+ };
1232
+ let ServiceRegistry = _ServiceRegistry;
1233
+
1234
+ var __accessCheck = (obj, member, msg) => {
1235
+ if (!member.has(obj))
1236
+ throw TypeError("Cannot " + msg);
1237
+ };
1238
+ var __privateGet = (obj, member, getter) => {
1239
+ __accessCheck(obj, member, "read from private field");
1240
+ return getter ? getter.call(obj) : member.get(obj);
1241
+ };
1242
+ var __privateAdd = (obj, member, value) => {
1243
+ if (member.has(obj))
1244
+ throw TypeError("Cannot add the same private member more than once");
1245
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1246
+ };
1247
+ var __privateSet = (obj, member, value, setter) => {
1248
+ __accessCheck(obj, member, "write to private field");
1249
+ setter ? setter.call(obj, value) : member.set(obj, value);
1250
+ return value;
1251
+ };
1252
+ var _subject, _registry;
1253
+ const _ServiceFactoryTester = class _ServiceFactoryTester {
1254
+ constructor(subject, registry) {
1255
+ __privateAdd(this, _subject, void 0);
1256
+ __privateAdd(this, _registry, void 0);
1257
+ __privateSet(this, _subject, subject);
1258
+ __privateSet(this, _registry, registry);
1259
+ }
1260
+ /**
1261
+ * Creates a new {@link ServiceFactoryTester} used to test the provided subject.
1262
+ *
1263
+ * @param subject - The service factory to test.
1264
+ * @param options - Additional options
1265
+ * @returns A new tester instance for the provided subject.
1266
+ */
1267
+ static from(subject, options) {
1268
+ var _a, _b;
1269
+ const subjectFactory = typeof subject === "function" ? subject() : subject;
1270
+ const registry = ServiceRegistry.create([
1271
+ ...defaultServiceFactories,
1272
+ ...(_b = (_a = options == null ? void 0 : options.dependencies) == null ? void 0 : _a.map(
1273
+ (f) => typeof f === "function" ? f() : f
1274
+ )) != null ? _b : [],
1275
+ subjectFactory
1276
+ ]);
1277
+ return new _ServiceFactoryTester(subjectFactory.service, registry);
1278
+ }
1279
+ /**
1280
+ * Returns the service instance for the subject.
1281
+ *
1282
+ * @remarks
1283
+ *
1284
+ * If the subject is a plugin scoped service factory a plugin ID
1285
+ * can be provided to instantiate the service for a specific plugin.
1286
+ *
1287
+ * By default the plugin ID 'test' is used.
1288
+ */
1289
+ async get(...args) {
1290
+ const [pluginId] = args;
1291
+ return __privateGet(this, _registry).get(__privateGet(this, _subject), pluginId != null ? pluginId : "test");
1292
+ }
1293
+ /**
1294
+ * Return the service instance for any of the provided dependencies or built-in services.
1295
+ *
1296
+ * @remarks
1297
+ *
1298
+ * A plugin ID can optionally be provided for plugin scoped services, otherwise the plugin ID 'test' is used.
1299
+ */
1300
+ async getService(service, ...args) {
1301
+ const [pluginId] = args;
1302
+ const instance = await __privateGet(this, _registry).get(service, pluginId != null ? pluginId : "test");
1303
+ if (instance === void 0) {
1304
+ throw new Error(`Service '${service.id}' not found`);
1305
+ }
1306
+ return instance;
1307
+ }
1308
+ };
1309
+ _subject = new WeakMap();
1310
+ _registry = new WeakMap();
1311
+ let ServiceFactoryTester = _ServiceFactoryTester;
1312
+
1313
+ exports.ServiceFactoryTester = ServiceFactoryTester;
732
1314
  exports.TestDatabases = TestDatabases;
733
1315
  exports.isDockerDisabledForTests = isDockerDisabledForTests;
734
1316
  exports.setupRequestMockHandlers = setupRequestMockHandlers;