@wix/services-manager 1.0.0 → 1.0.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.
@@ -2,6 +2,7 @@ import { computed as pcomputed, effect as peffect, signal as psignal, } from '@p
2
2
  import { implementService } from '@wix/services-definitions';
3
3
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
4
4
  export const SignalsServiceFactory = implementService(SignalsServiceDefinition, () => {
5
+ const disposables = new Set();
5
6
  return {
6
7
  signal: (initialValue) => {
7
8
  const sig = psignal(initialValue);
@@ -20,6 +21,14 @@ export const SignalsServiceFactory = implementService(SignalsServiceDefinition,
20
21
  };
21
22
  return signal;
22
23
  },
23
- effect: peffect,
24
+ effect: (fn, options) => {
25
+ const dispose = peffect(fn, options);
26
+ disposables.add(dispose);
27
+ return dispose;
28
+ },
29
+ dispose: () => {
30
+ disposables.forEach((disposable) => disposable());
31
+ disposables.clear();
32
+ },
24
33
  };
25
34
  });
@@ -7,7 +7,17 @@ export function createServicesManager(servicesBindings, parentServicesManager) {
7
7
  ...coreRegisteredServices.registeredServices,
8
8
  ].map((service) => [service.definition.toString(), service]));
9
9
  const initializedServices = new Map();
10
+ const serviceInitializationOrder = [];
10
11
  const manager = {
12
+ dispose() {
13
+ // Dispose services in reverse order of initialization
14
+ for (let i = serviceInitializationOrder.length - 1; i >= 0; i--) {
15
+ const serviceKey = serviceInitializationOrder[i];
16
+ const service = initializedServices.get(serviceKey);
17
+ // consider services might be removed
18
+ service?.dispose?.();
19
+ }
20
+ },
11
21
  getService(definition) {
12
22
  if (!initializedServices.has(definition.toString())) {
13
23
  const service = bindingsByDefinition.get(definition.toString());
@@ -17,10 +27,12 @@ export function createServicesManager(servicesBindings, parentServicesManager) {
17
27
  }
18
28
  throw new Error(`Service ${definition} is not provided`);
19
29
  }
20
- initializedServices.set(definition.toString(), service.impl({
30
+ const serviceKey = definition.toString();
31
+ initializedServices.set(serviceKey, service.impl({
21
32
  config: service.config,
22
33
  getService: manager.getService,
23
34
  }));
35
+ serviceInitializationOrder.push(serviceKey);
24
36
  }
25
37
  return initializedServices.get(definition.toString());
26
38
  },
@@ -35,11 +47,13 @@ export function createServicesManager(servicesBindings, parentServicesManager) {
35
47
  config: config || {},
36
48
  });
37
49
  // Immediately initialize the service if not already initialized
38
- if (!initializedServices.has(definition.toString())) {
39
- initializedServices.set(definition.toString(), impl({
50
+ const serviceKey = definition.toString();
51
+ if (!initializedServices.has(serviceKey)) {
52
+ initializedServices.set(serviceKey, impl({
40
53
  config: config || {},
41
54
  getService: manager.getService,
42
55
  }));
56
+ serviceInitializationOrder.push(serviceKey);
43
57
  }
44
58
  }
45
59
  else {
@@ -47,6 +61,9 @@ export function createServicesManager(servicesBindings, parentServicesManager) {
47
61
  throw new Error(`Service ${definition.toString()} is already provided`);
48
62
  }
49
63
  },
64
+ extend(servicesMap) {
65
+ return createServicesManager(servicesMap, manager);
66
+ },
50
67
  addServices(servicesToAdd) {
51
68
  // First, check for duplicates
52
69
  servicesToAdd.registeredServices.forEach(({ definition }) => {
@@ -64,22 +81,26 @@ export function createServicesManager(servicesBindings, parentServicesManager) {
64
81
  });
65
82
  // Then initialize all, but only if not already initialized
66
83
  servicesToAdd.registeredServices.forEach(({ definition, impl, config }) => {
67
- if (!initializedServices.has(definition.toString())) {
68
- initializedServices.set(definition.toString(), impl({
84
+ const serviceKey = definition.toString();
85
+ if (!initializedServices.has(serviceKey)) {
86
+ initializedServices.set(serviceKey, impl({
69
87
  config: config || {},
70
88
  getService: manager.getService,
71
89
  }));
90
+ serviceInitializationOrder.push(serviceKey);
72
91
  }
73
92
  });
74
93
  },
75
94
  };
76
95
  // Then initialize all, but only if not already initialized
77
96
  bindingsByDefinition.forEach(({ definition, impl, config }) => {
78
- if (!initializedServices.has(definition.toString())) {
79
- initializedServices.set(definition, impl({
97
+ const serviceKey = definition.toString();
98
+ if (!initializedServices.has(serviceKey)) {
99
+ initializedServices.set(serviceKey, impl({
80
100
  config: config || {},
81
101
  getService: manager.getService,
82
102
  }));
103
+ serviceInitializationOrder.push(serviceKey);
83
104
  }
84
105
  });
85
106
  return manager;
package/build/types.d.ts CHANGED
@@ -5,9 +5,11 @@ export type ServicesRegistrar = {
5
5
  addService<T extends ServiceDefinition<any, any> = any, Impl extends ServiceFactory<T, any> = any>(definition: T, impl: Impl, config?: ServiceFactoryConfig<Impl>): ServicesRegistrar;
6
6
  };
7
7
  export type ServicesManager = {
8
+ extend(servicesMap: ServicesRegistrar): ServicesManager;
8
9
  getService: GetService;
9
10
  hasService<T extends ServiceDefinition<any, any>>(definition: T): boolean;
10
11
  addService<T extends ServiceDefinition<any, any>, Impl extends ServiceFactory<T, any>>(definition: T, impl: Impl, config: ServiceFactoryConfig<Impl>): void;
11
12
  addService<T extends ServiceDefinition<any, any>, Impl extends ServiceFactory<T, any>>(definition: T, impl: Impl): void;
12
13
  addServices(servicesBindings: ServicesRegistrar): void;
14
+ dispose(): void;
13
15
  };
@@ -5,6 +5,7 @@ const signals_core_1 = require("@preact/signals-core");
5
5
  const services_definitions_1 = require("@wix/services-definitions");
6
6
  const signals_1 = require("@wix/services-definitions/core-services/signals");
7
7
  exports.SignalsServiceFactory = (0, services_definitions_1.implementService)(signals_1.SignalsServiceDefinition, () => {
8
+ const disposables = new Set();
8
9
  return {
9
10
  signal: (initialValue) => {
10
11
  const sig = (0, signals_core_1.signal)(initialValue);
@@ -23,6 +24,14 @@ exports.SignalsServiceFactory = (0, services_definitions_1.implementService)(sig
23
24
  };
24
25
  return signal;
25
26
  },
26
- effect: signals_core_1.effect,
27
+ effect: (fn, options) => {
28
+ const dispose = (0, signals_core_1.effect)(fn, options);
29
+ disposables.add(dispose);
30
+ return dispose;
31
+ },
32
+ dispose: () => {
33
+ disposables.forEach((disposable) => disposable());
34
+ disposables.clear();
35
+ },
27
36
  };
28
37
  });
@@ -11,7 +11,17 @@ function createServicesManager(servicesBindings, parentServicesManager) {
11
11
  ...coreRegisteredServices.registeredServices,
12
12
  ].map((service) => [service.definition.toString(), service]));
13
13
  const initializedServices = new Map();
14
+ const serviceInitializationOrder = [];
14
15
  const manager = {
16
+ dispose() {
17
+ // Dispose services in reverse order of initialization
18
+ for (let i = serviceInitializationOrder.length - 1; i >= 0; i--) {
19
+ const serviceKey = serviceInitializationOrder[i];
20
+ const service = initializedServices.get(serviceKey);
21
+ // consider services might be removed
22
+ service?.dispose?.();
23
+ }
24
+ },
15
25
  getService(definition) {
16
26
  if (!initializedServices.has(definition.toString())) {
17
27
  const service = bindingsByDefinition.get(definition.toString());
@@ -21,10 +31,12 @@ function createServicesManager(servicesBindings, parentServicesManager) {
21
31
  }
22
32
  throw new Error(`Service ${definition} is not provided`);
23
33
  }
24
- initializedServices.set(definition.toString(), service.impl({
34
+ const serviceKey = definition.toString();
35
+ initializedServices.set(serviceKey, service.impl({
25
36
  config: service.config,
26
37
  getService: manager.getService,
27
38
  }));
39
+ serviceInitializationOrder.push(serviceKey);
28
40
  }
29
41
  return initializedServices.get(definition.toString());
30
42
  },
@@ -39,11 +51,13 @@ function createServicesManager(servicesBindings, parentServicesManager) {
39
51
  config: config || {},
40
52
  });
41
53
  // Immediately initialize the service if not already initialized
42
- if (!initializedServices.has(definition.toString())) {
43
- initializedServices.set(definition.toString(), impl({
54
+ const serviceKey = definition.toString();
55
+ if (!initializedServices.has(serviceKey)) {
56
+ initializedServices.set(serviceKey, impl({
44
57
  config: config || {},
45
58
  getService: manager.getService,
46
59
  }));
60
+ serviceInitializationOrder.push(serviceKey);
47
61
  }
48
62
  }
49
63
  else {
@@ -51,6 +65,9 @@ function createServicesManager(servicesBindings, parentServicesManager) {
51
65
  throw new Error(`Service ${definition.toString()} is already provided`);
52
66
  }
53
67
  },
68
+ extend(servicesMap) {
69
+ return createServicesManager(servicesMap, manager);
70
+ },
54
71
  addServices(servicesToAdd) {
55
72
  // First, check for duplicates
56
73
  servicesToAdd.registeredServices.forEach(({ definition }) => {
@@ -68,22 +85,26 @@ function createServicesManager(servicesBindings, parentServicesManager) {
68
85
  });
69
86
  // Then initialize all, but only if not already initialized
70
87
  servicesToAdd.registeredServices.forEach(({ definition, impl, config }) => {
71
- if (!initializedServices.has(definition.toString())) {
72
- initializedServices.set(definition.toString(), impl({
88
+ const serviceKey = definition.toString();
89
+ if (!initializedServices.has(serviceKey)) {
90
+ initializedServices.set(serviceKey, impl({
73
91
  config: config || {},
74
92
  getService: manager.getService,
75
93
  }));
94
+ serviceInitializationOrder.push(serviceKey);
76
95
  }
77
96
  });
78
97
  },
79
98
  };
80
99
  // Then initialize all, but only if not already initialized
81
100
  bindingsByDefinition.forEach(({ definition, impl, config }) => {
82
- if (!initializedServices.has(definition.toString())) {
83
- initializedServices.set(definition, impl({
101
+ const serviceKey = definition.toString();
102
+ if (!initializedServices.has(serviceKey)) {
103
+ initializedServices.set(serviceKey, impl({
84
104
  config: config || {},
85
105
  getService: manager.getService,
86
106
  }));
107
+ serviceInitializationOrder.push(serviceKey);
87
108
  }
88
109
  });
89
110
  return manager;
@@ -5,9 +5,11 @@ export type ServicesRegistrar = {
5
5
  addService<T extends ServiceDefinition<any, any> = any, Impl extends ServiceFactory<T, any> = any>(definition: T, impl: Impl, config?: ServiceFactoryConfig<Impl>): ServicesRegistrar;
6
6
  };
7
7
  export type ServicesManager = {
8
+ extend(servicesMap: ServicesRegistrar): ServicesManager;
8
9
  getService: GetService;
9
10
  hasService<T extends ServiceDefinition<any, any>>(definition: T): boolean;
10
11
  addService<T extends ServiceDefinition<any, any>, Impl extends ServiceFactory<T, any>>(definition: T, impl: Impl, config: ServiceFactoryConfig<Impl>): void;
11
12
  addService<T extends ServiceDefinition<any, any>, Impl extends ServiceFactory<T, any>>(definition: T, impl: Impl): void;
12
13
  addServices(servicesBindings: ServicesRegistrar): void;
14
+ dispose(): void;
13
15
  };
package/package.json CHANGED
@@ -1,8 +1,27 @@
1
1
  {
2
2
  "name": "@wix/services-manager",
3
- "version": "1.0.0",
4
- "type": "module",
5
- "main": "./cjs/build/services-manager.js",
3
+ "version": "1.0.2",
4
+ "dependencies": {
5
+ "@preact/signals-core": "^1.12.1",
6
+ "@wix/sdk-context": "0.0.1",
7
+ "@wix/services-definitions": "^1.0.1"
8
+ },
9
+ "devDependencies": {
10
+ "@types/is-ci": "^3.0.4",
11
+ "@types/node": "^20.19.25",
12
+ "@vitest/ui": "^1.6.1",
13
+ "eslint": "^8.57.1",
14
+ "eslint-config-sdk": "1.0.0",
15
+ "is-ci": "^3.0.1",
16
+ "jsdom": "^22.1.0",
17
+ "msw": "^2.12.2",
18
+ "typescript": "^5.9.3",
19
+ "vitest": "^1.6.1",
20
+ "vitest-teamcity-reporter": "^0.3.1"
21
+ },
22
+ "eslintConfig": {
23
+ "extends": "sdk"
24
+ },
6
25
  "exports": {
7
26
  ".": {
8
27
  "import": "./build/services-manager.js",
@@ -22,7 +41,6 @@
22
41
  "require": "./cjs/build/core-services/signals/definition.js"
23
42
  }
24
43
  },
25
- "sideEffects": false,
26
44
  "files": [
27
45
  "build",
28
46
  "cjs",
@@ -30,42 +48,24 @@
30
48
  "helpers",
31
49
  "types"
32
50
  ],
51
+ "lint-staged": {
52
+ "*.{js,ts}": "yarn lint"
53
+ },
54
+ "main": "./cjs/build/services-manager.js",
33
55
  "publishConfig": {
34
56
  "registry": "https://registry.npmjs.org/",
35
57
  "access": "public"
36
58
  },
37
59
  "scripts": {
38
- "dev": "npx vite dev ./src/__tests__/test-data",
39
60
  "build": "tsc && tsc --project tsconfig.cjs.json",
40
- "test": "vitest",
61
+ "dev": "npx vite dev ./src/__tests__/test-data",
41
62
  "lint": "eslint --max-warnings=0 .",
42
63
  "lint:fix": "eslint --max-warnings=0 . --fix",
64
+ "test": "vitest",
43
65
  "typecheck": "tsc --noEmit"
44
66
  },
45
- "lint-staged": {
46
- "*.{js,ts}": "yarn lint"
47
- },
48
- "dependencies": {
49
- "@preact/signals-core": "^1.12.1",
50
- "@wix/sdk-context": "0.0.1",
51
- "@wix/services-definitions": "^1.0.0"
52
- },
53
- "devDependencies": {
54
- "@types/is-ci": "^3.0.4",
55
- "@types/node": "^20.19.24",
56
- "@vitest/ui": "^1.6.1",
57
- "eslint": "^8.57.1",
58
- "eslint-config-sdk": "1.0.0",
59
- "is-ci": "^3.0.1",
60
- "jsdom": "^22.1.0",
61
- "msw": "^2.12.0",
62
- "typescript": "^5.9.3",
63
- "vitest": "^1.6.1",
64
- "vitest-teamcity-reporter": "^0.3.1"
65
- },
66
- "eslintConfig": {
67
- "extends": "sdk"
68
- },
67
+ "sideEffects": false,
68
+ "type": "module",
69
69
  "wix": {
70
70
  "artifact": {
71
71
  "groupId": "com.wixpress",
@@ -80,5 +80,5 @@
80
80
  ]
81
81
  }
82
82
  },
83
- "falconPackageHash": "22ac16096453ae347bfe9dcb050738a26331961d68044f59a55d2710"
83
+ "falconPackageHash": "08f6d10bd6709e7df2f6efc22ccb419292ccc561e0eba5197a21b383"
84
84
  }