@vida-global/core 2.4.1 → 2.4.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.
@@ -12,6 +12,7 @@ class AppDependencies {
12
12
  setDependency(name, dependency) {
13
13
  this.#dependencies[name] = dependency;
14
14
  this.#defineAccessor(name);
15
+ this.#defineSingletonAccessor(name);
15
16
  }
16
17
 
17
18
 
@@ -26,6 +27,17 @@ class AppDependencies {
26
27
  }
27
28
 
28
29
 
30
+ #defineSingletonAccessor(name) {
31
+ if (Object.getOwnPropertyDescriptor(this, name)) return;
32
+ if (name in this) return;
33
+
34
+ Object.defineProperty(this, name, {
35
+ configurable: false,
36
+ get: () => this.get(name)
37
+ });
38
+ }
39
+
40
+
29
41
  // Registering after `installOn` still defines the accessor, so wiring order does not matter.
30
42
  // An existing property is left alone: a controller that defines the name itself wins.
31
43
  #defineAccessor(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vida-global/core",
3
- "version": "2.4.1",
3
+ "version": "2.4.2",
4
4
  "description": "Core libraries for supporting Vida development",
5
5
  "author": "",
6
6
  "license": "ISC",
@@ -46,6 +46,44 @@ describe('AppDependencies', () => {
46
46
  });
47
47
 
48
48
 
49
+ describe('singleton accessors', () => {
50
+ it ('exposes a registered name as a property on the singleton', () => {
51
+ const helper = { name: 'helper' };
52
+
53
+ AppDependencies.setDependency('singletonHelper', helper);
54
+
55
+ expect(AppDependencies.singletonHelper).toBe(helper);
56
+ });
57
+
58
+
59
+ it ('reads through, so a later replacement is picked up', () => {
60
+ AppDependencies.setDependency('replacedHelper', 'first');
61
+
62
+ AppDependencies.setDependency('replacedHelper', 'second');
63
+
64
+ expect(AppDependencies.replacedHelper).toBe('second');
65
+ });
66
+
67
+
68
+ it ('reads null after a reset', () => {
69
+ AppDependencies.setDependency('resetHelper', 'something');
70
+
71
+ AppDependencies.reset();
72
+
73
+ expect(AppDependencies.resetHelper).toBeNull();
74
+ });
75
+
76
+
77
+ // `get`, `reset`, and friends must survive a hostile dependency name.
78
+ it ('does not overwrite the singleton API', () => {
79
+ AppDependencies.setDependency('get', 'not a function');
80
+
81
+ expect(typeof AppDependencies.get).toBe('function');
82
+ expect(AppDependencies.get('get')).toBe('not a function');
83
+ });
84
+ });
85
+
86
+
49
87
  describe('#installOn', () => {
50
88
  it ('exposes what was registered before the install as a getter', () => {
51
89
  AppDependencies.setDependency('myHelper', 'early');