@timesplinter/pimple 2.0.0 → 2.1.0

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.
@@ -6,7 +6,7 @@ type ProviderDeclaration<T> = ServiceProviderFunction<T> | ServiceProvider<T>;
6
6
  type LazyServiceDefinition<T, S> = (container: Pimple<T>) => S;
7
7
  type ProtectedServiceDefinition<T, S> = () => LazyServiceDefinition<T, S>;
8
8
  type PlainServiceDefinition<S> = S extends Function ? () => S : S;
9
- type ServiceDefinition<T, S> = PlainServiceDefinition<S> | LazyServiceDefinition<T, S> | ProtectedServiceDefinition<T, S> | (S extends Function ? () => S : S);
9
+ type ServiceDefinition<T, S> = PlainServiceDefinition<S> | LazyServiceDefinition<T, S> | ProtectedServiceDefinition<T, S>;
10
10
  type ServiceMap<T> = {
11
11
  [key in ServiceKey<T>]: ServiceDefinition<T, T[ServiceKey<T>]>;
12
12
  };
@@ -17,28 +17,24 @@ type ServiceMap<T> = {
17
17
  * @copyright 2016 SerafimArts <nesk@xakep.ru>
18
18
  * @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
19
19
  * @license LGPL
20
- * @version 3.0.0
20
+ * @version 2.1.0
21
21
  */
22
22
  export default class Pimple<T> implements Container<T> {
23
- /**
24
- * @type {string}
25
- */
26
23
  static get VERSION(): string;
27
- /**
28
- * @type {{}}
29
- * @private
30
- */
31
24
  private _definitions;
32
- /**
33
- * @type {{}}
34
- * @private
35
- */
36
25
  private _raw;
26
+ private _resolved;
27
+ private _resolving;
37
28
  constructor(services?: Partial<ServiceMap<T>>);
38
29
  /**
39
- * Define a service
30
+ * Define a service (first-time registration only)
40
31
  */
41
32
  set<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T, T[K]>): Pimple<T>;
33
+ /**
34
+ * Replace an existing service definition before it has been resolved
35
+ */
36
+ replace<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T, T[K]>): Pimple<T>;
37
+ private define;
42
38
  /**
43
39
  * Register a factory
44
40
  */
package/lib/cjs/pimple.js CHANGED
@@ -15,33 +15,49 @@ const reservedProperties = [
15
15
  * @copyright 2016 SerafimArts <nesk@xakep.ru>
16
16
  * @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
17
17
  * @license LGPL
18
- * @version 3.0.0
18
+ * @version 2.1.0
19
19
  */
20
20
  class Pimple {
21
- /**
22
- * @type {string}
23
- */
24
- static get VERSION() { return '3.0.0'; }
21
+ static get VERSION() { return '2.1.0'; }
25
22
  constructor(services = {}) {
26
- /**
27
- * @type {{}}
28
- * @private
29
- */
30
23
  this._definitions = {};
31
- /**
32
- * @type {{}}
33
- * @private
34
- */
35
24
  this._raw = {};
25
+ this._resolved = new Map();
26
+ this._resolving = [];
36
27
  Object.keys(services).forEach((service) => {
37
28
  const serviceKey = service;
38
29
  this.set(serviceKey, services[serviceKey]);
39
30
  }, this);
40
31
  }
41
32
  /**
42
- * Define a service
33
+ * Define a service (first-time registration only)
43
34
  */
44
35
  set(name, service) {
36
+ if (this.has(name)) {
37
+ throw new Error(`Service "${name.toString()}" is already defined. Use replace() to overwrite it.`);
38
+ }
39
+ return this.define(name, service);
40
+ }
41
+ /**
42
+ * Replace an existing service definition before it has been resolved
43
+ */
44
+ replace(name, service) {
45
+ var _a;
46
+ if (!this.has(name)) {
47
+ throw new RangeError(`Service "${name.toString()}" is not defined in the container.`);
48
+ }
49
+ if (this._resolved.has(name)) {
50
+ const trace = [];
51
+ let current = name;
52
+ while (current !== null) {
53
+ trace.unshift(current.toString());
54
+ current = (_a = this._resolved.get(current)) !== null && _a !== void 0 ? _a : null;
55
+ }
56
+ throw new Error(`Service "${name.toString()}" has already been resolved and cannot be replaced. Resolution trace: ${trace.join(' → ')}`);
57
+ }
58
+ return this.define(name, service);
59
+ }
60
+ define(name, service) {
45
61
  this._raw[name] = service;
46
62
  this._definitions[name] = service instanceof Function ?
47
63
  (function () {
@@ -55,6 +71,7 @@ class Pimple {
55
71
  }()) : service;
56
72
  if (reservedProperties.indexOf(name.toString()) === -1) {
57
73
  Object.defineProperty(this, name, {
74
+ configurable: true,
58
75
  get: () => {
59
76
  return this.get(name);
60
77
  }
@@ -70,6 +87,7 @@ class Pimple {
70
87
  this._definitions[name] = callback;
71
88
  if (reservedProperties.indexOf(name.toString()) === -1) {
72
89
  Object.defineProperty(this, name, {
90
+ configurable: true,
73
91
  get: () => {
74
92
  return this.get(name);
75
93
  }
@@ -82,7 +100,20 @@ class Pimple {
82
100
  */
83
101
  get(name) {
84
102
  if (this._definitions[name] instanceof Function) {
85
- return this._definitions[name](this);
103
+ const firstResolution = !this._resolved.has(name);
104
+ if (firstResolution) {
105
+ const parent = this._resolving.length > 0 ? this._resolving[this._resolving.length - 1] : null;
106
+ this._resolved.set(name, parent);
107
+ this._resolving.push(name);
108
+ }
109
+ try {
110
+ return this._definitions[name](this);
111
+ }
112
+ finally {
113
+ if (firstResolution) {
114
+ this._resolving.pop();
115
+ }
116
+ }
86
117
  }
87
118
  return this._definitions[name];
88
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pimple.js","sourceRoot":"","sources":["../../src/pimple.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pimple.js","sourceRoot":"","sources":["../../src/pimple.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ type ProviderDeclaration<T> = ServiceProviderFunction<T> | ServiceProvider<T>;
6
6
  type LazyServiceDefinition<T, S> = (container: Pimple<T>) => S;
7
7
  type ProtectedServiceDefinition<T, S> = () => LazyServiceDefinition<T, S>;
8
8
  type PlainServiceDefinition<S> = S extends Function ? () => S : S;
9
- type ServiceDefinition<T, S> = PlainServiceDefinition<S> | LazyServiceDefinition<T, S> | ProtectedServiceDefinition<T, S> | (S extends Function ? () => S : S);
9
+ type ServiceDefinition<T, S> = PlainServiceDefinition<S> | LazyServiceDefinition<T, S> | ProtectedServiceDefinition<T, S>;
10
10
  type ServiceMap<T> = {
11
11
  [key in ServiceKey<T>]: ServiceDefinition<T, T[ServiceKey<T>]>;
12
12
  };
@@ -17,28 +17,24 @@ type ServiceMap<T> = {
17
17
  * @copyright 2016 SerafimArts <nesk@xakep.ru>
18
18
  * @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
19
19
  * @license LGPL
20
- * @version 3.0.0
20
+ * @version 2.1.0
21
21
  */
22
22
  export default class Pimple<T> implements Container<T> {
23
- /**
24
- * @type {string}
25
- */
26
23
  static get VERSION(): string;
27
- /**
28
- * @type {{}}
29
- * @private
30
- */
31
24
  private _definitions;
32
- /**
33
- * @type {{}}
34
- * @private
35
- */
36
25
  private _raw;
26
+ private _resolved;
27
+ private _resolving;
37
28
  constructor(services?: Partial<ServiceMap<T>>);
38
29
  /**
39
- * Define a service
30
+ * Define a service (first-time registration only)
40
31
  */
41
32
  set<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T, T[K]>): Pimple<T>;
33
+ /**
34
+ * Replace an existing service definition before it has been resolved
35
+ */
36
+ replace<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T, T[K]>): Pimple<T>;
37
+ private define;
42
38
  /**
43
39
  * Register a factory
44
40
  */
package/lib/esm/pimple.js CHANGED
@@ -14,33 +14,49 @@ const reservedProperties = [
14
14
  * @copyright 2016 SerafimArts <nesk@xakep.ru>
15
15
  * @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
16
16
  * @license LGPL
17
- * @version 3.0.0
17
+ * @version 2.1.0
18
18
  */
19
19
  export default class Pimple {
20
- /**
21
- * @type {string}
22
- */
23
- static get VERSION() { return '3.0.0'; }
20
+ static get VERSION() { return '2.1.0'; }
24
21
  constructor(services = {}) {
25
- /**
26
- * @type {{}}
27
- * @private
28
- */
29
22
  this._definitions = {};
30
- /**
31
- * @type {{}}
32
- * @private
33
- */
34
23
  this._raw = {};
24
+ this._resolved = new Map();
25
+ this._resolving = [];
35
26
  Object.keys(services).forEach((service) => {
36
27
  const serviceKey = service;
37
28
  this.set(serviceKey, services[serviceKey]);
38
29
  }, this);
39
30
  }
40
31
  /**
41
- * Define a service
32
+ * Define a service (first-time registration only)
42
33
  */
43
34
  set(name, service) {
35
+ if (this.has(name)) {
36
+ throw new Error(`Service "${name.toString()}" is already defined. Use replace() to overwrite it.`);
37
+ }
38
+ return this.define(name, service);
39
+ }
40
+ /**
41
+ * Replace an existing service definition before it has been resolved
42
+ */
43
+ replace(name, service) {
44
+ var _a;
45
+ if (!this.has(name)) {
46
+ throw new RangeError(`Service "${name.toString()}" is not defined in the container.`);
47
+ }
48
+ if (this._resolved.has(name)) {
49
+ const trace = [];
50
+ let current = name;
51
+ while (current !== null) {
52
+ trace.unshift(current.toString());
53
+ current = (_a = this._resolved.get(current)) !== null && _a !== void 0 ? _a : null;
54
+ }
55
+ throw new Error(`Service "${name.toString()}" has already been resolved and cannot be replaced. Resolution trace: ${trace.join(' → ')}`);
56
+ }
57
+ return this.define(name, service);
58
+ }
59
+ define(name, service) {
44
60
  this._raw[name] = service;
45
61
  this._definitions[name] = service instanceof Function ?
46
62
  (function () {
@@ -54,6 +70,7 @@ export default class Pimple {
54
70
  }()) : service;
55
71
  if (reservedProperties.indexOf(name.toString()) === -1) {
56
72
  Object.defineProperty(this, name, {
73
+ configurable: true,
57
74
  get: () => {
58
75
  return this.get(name);
59
76
  }
@@ -69,6 +86,7 @@ export default class Pimple {
69
86
  this._definitions[name] = callback;
70
87
  if (reservedProperties.indexOf(name.toString()) === -1) {
71
88
  Object.defineProperty(this, name, {
89
+ configurable: true,
72
90
  get: () => {
73
91
  return this.get(name);
74
92
  }
@@ -81,7 +99,20 @@ export default class Pimple {
81
99
  */
82
100
  get(name) {
83
101
  if (this._definitions[name] instanceof Function) {
84
- return this._definitions[name](this);
102
+ const firstResolution = !this._resolved.has(name);
103
+ if (firstResolution) {
104
+ const parent = this._resolving.length > 0 ? this._resolving[this._resolving.length - 1] : null;
105
+ this._resolved.set(name, parent);
106
+ this._resolving.push(name);
107
+ }
108
+ try {
109
+ return this._definitions[name](this);
110
+ }
111
+ finally {
112
+ if (firstResolution) {
113
+ this._resolving.pop();
114
+ }
115
+ }
85
116
  }
86
117
  return this._definitions[name];
87
118
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pimple.js","sourceRoot":"","sources":["../../src/pimple.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pimple.js","sourceRoot":"","sources":["../../src/pimple.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,23 @@
1
1
  {
2
2
  "name": "@timesplinter/pimple",
3
3
  "license": "LGPL-3.0-or-later",
4
- "version": "2.0.0",
4
+ "version": "2.1.0",
5
5
  "module": "./lib/esm/index.js",
6
6
  "main": "./lib/cjs/index.js",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/TiMESPLiNTER/pimple-js.git"
10
+ },
7
11
  "scripts": {
8
12
  "test": "jest",
9
13
  "test:cov": "jest --collect-coverage",
14
+ "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig-cjs.json",
10
15
  "transpile": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json",
11
- "prepublish": "npm run transpile"
16
+ "prepublishOnly": "npm run transpile"
12
17
  },
18
+ "files": [
19
+ "lib/"
20
+ ],
13
21
  "keywords": [],
14
22
  "author": "Pascal Münst <dev@timesplinter.ch>",
15
23
  "description": "A simple dependency-injection container written in TypeScript based on PHP's Pimple",
@@ -17,10 +25,10 @@
17
25
  "@babel/core": "^7.23.9",
18
26
  "@babel/preset-env": "^7.23.9",
19
27
  "@babel/preset-typescript": "^7.23.3",
20
- "@types/jest": "^29.5.11",
28
+ "@types/jest": "^29.5.14",
21
29
  "babel-jest": "^29.7.0",
22
30
  "jest": "^29.7.0",
23
- "typescript": "^4.9.5",
24
- "ts-node": "^10.9.2"
31
+ "ts-node": "^10.9.2",
32
+ "typescript": "^4.9.5"
25
33
  }
26
34
  }
package/.babelrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "presets": [
3
- ["@babel/preset-env", {"targets": {"node": "current"}}],
4
- "@babel/preset-typescript"
5
- ]
6
- }
@@ -1,18 +0,0 @@
1
- name: Publish Package to npmjs
2
- on:
3
- release:
4
- types: [published]
5
- jobs:
6
- build:
7
- runs-on: ubuntu-latest
8
- steps:
9
- - uses: actions/checkout@v4
10
- # Setup .npmrc file to publish to npm
11
- - uses: actions/setup-node@v3
12
- with:
13
- node-version: '20.x'
14
- registry-url: 'https://registry.npmjs.org'
15
- - run: npm ci
16
- - run: npm publish --access public
17
- env:
18
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,13 +0,0 @@
1
- name: Tests
2
-
3
- on: [push]
4
-
5
- jobs:
6
- build:
7
- runs-on: ubuntu-latest
8
- steps:
9
- - uses: actions/checkout@v2
10
- - name: Install modules
11
- run: npm install
12
- - name: Run coverage
13
- run: npm run test:cov
package/jest.config.ts DELETED
@@ -1,19 +0,0 @@
1
- import type {Config} from 'jest';
2
-
3
- const config: Config = {
4
- coverageDirectory: "./build/coverage",
5
- coverageReporters: ['text', 'html', 'lcov'],
6
- coverageThreshold: {
7
- global: {
8
- branches: 80,
9
- functions: 88,
10
- lines: 93,
11
- statements: 93
12
- }
13
- },
14
- collectCoverageFrom: [
15
- "src/**/*"
16
- ],
17
- };
18
-
19
- export default config;
package/src/container.ts DELETED
@@ -1,8 +0,0 @@
1
- export type ServiceKey<T> = keyof T;
2
-
3
- export default interface Container<T>
4
- {
5
- get<K extends ServiceKey<T>>(key: K): T[K];
6
-
7
- has<K extends ServiceKey<T>>(key: K): boolean;
8
- }
package/src/index.ts DELETED
@@ -1,8 +0,0 @@
1
- import Container from './container'
2
- import Pimple from './pimple'
3
- import ServiceProvider from './serviceProvider'
4
- export {
5
- Container,
6
- Pimple,
7
- ServiceProvider
8
- }
package/src/pimple.ts DELETED
@@ -1,171 +0,0 @@
1
- "use strict";
2
-
3
- import Container, {ServiceKey} from "./container";
4
- import ServiceProvider from "./serviceProvider";
5
-
6
- /** Declaration types */
7
- type ServiceProviderFunction<T> = (container: Pimple<T>) => void;
8
- type ProviderDeclaration<T> = ServiceProviderFunction<T>|ServiceProvider<T>;
9
- type LazyServiceDefinition<T, S> = (container: Pimple<T>) => S;
10
- type ProtectedServiceDefinition<T, S> = () => LazyServiceDefinition<T, S>;
11
- type PlainServiceDefinition<S> = S extends Function ? () => S : S; // If a function, it needs to be wrapped/protected
12
- type ServiceDefinition<T, S> = PlainServiceDefinition<S>|LazyServiceDefinition<T, S>|ProtectedServiceDefinition<T, S>|(S extends Function ? () => S : S);
13
- type ServiceMap<T> = { [key in ServiceKey<T>]: ServiceDefinition<T, T[ServiceKey<T>]> };
14
-
15
- /**
16
- * Reserved names of properties
17
- */
18
- const reservedProperties: string[] = [
19
- 'get', 'set', 'factory', 'raw',
20
- 'protect', 'share', 'toString', 'constructor',
21
- 'prototype'
22
- ];
23
-
24
- /**
25
- * Pimple dependency injection container
26
- *
27
- * @copyright 2011 M.PARAISO <mparaiso@online.fr>
28
- * @copyright 2016 SerafimArts <nesk@xakep.ru>
29
- * @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
30
- * @license LGPL
31
- * @version 3.0.0
32
- */
33
- export default class Pimple<T> implements Container<T>
34
- {
35
- /**
36
- * @type {string}
37
- */
38
- static get VERSION() { return '3.0.0'; }
39
-
40
- /**
41
- * @type {{}}
42
- * @private
43
- */
44
- private _definitions: Partial<ServiceMap<T>> = {};
45
-
46
- /**
47
- * @type {{}}
48
- * @private
49
- */
50
- private _raw: Partial<ServiceMap<T>> = {};
51
-
52
- constructor(services: Partial<ServiceMap<T>> = {}) {
53
- Object.keys(services).forEach((service) => {
54
- const serviceKey = service as ServiceKey<T>;
55
- this.set(serviceKey, services[serviceKey] as ServiceDefinition<T, T[ServiceKey<T>]>);
56
- }, this);
57
- }
58
-
59
- /**
60
- * Define a service
61
- */
62
- public set<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T,T[K]>): Pimple<T>
63
- {
64
- this._raw[name] = service;
65
-
66
- this._definitions[name] = service instanceof Function ?
67
- (function () {
68
- let cached: any;
69
- return (pimple: Pimple<T>) => {
70
- if (cached === undefined) {
71
- cached = service(pimple);
72
- }
73
- return cached;
74
- };
75
- }()) : service;
76
-
77
- if (reservedProperties.indexOf(name.toString()) === -1) {
78
- Object.defineProperty(this, name, {
79
- get: () => {
80
- return this.get(name);
81
- }
82
- });
83
- }
84
-
85
- return this;
86
- }
87
-
88
- /**
89
- * Register a factory
90
- */
91
- public factory<K extends ServiceKey<T>>(name: K, callback: ServiceDefinition<T,T[K]>): Pimple<T> {
92
- this._raw[name] = callback;
93
- this._definitions[name] = callback;
94
-
95
- if (reservedProperties.indexOf(name.toString()) === -1) {
96
- Object.defineProperty(this, name, {
97
- get: () => {
98
- return this.get(name);
99
- }
100
- });
101
- }
102
-
103
- return this;
104
- }
105
-
106
- /**
107
- * Get a service instance
108
- */
109
- public get<K extends ServiceKey<T>>(name: K): T[K] {
110
- if (this._definitions[name] instanceof Function) {
111
- return (this._definitions[name] as LazyServiceDefinition<T, T[K]>)(this);
112
- }
113
- return this._definitions[name] as T[K];
114
- }
115
-
116
- /**
117
- * Checks whether a service is registered or not
118
- */
119
- public has<K extends ServiceKey<T>>(name: K): boolean {
120
- return name in this._definitions;
121
- }
122
-
123
- /**
124
- * Register a protected function
125
- */
126
- public protect<T extends Function>(func: T): () => T {
127
- return () => func;
128
- }
129
-
130
- /**
131
- * Extend a service
132
- */
133
- public extend<K extends ServiceKey<T>>(serviceName: K, service: Function): Function {
134
- if (!this._definitions[serviceName]) {
135
- throw new RangeError(`Definition with "${serviceName.toString()}" not defined in container.`);
136
- }
137
-
138
- let def = this._definitions[serviceName];
139
-
140
- return this._definitions[serviceName] = (container: Pimple<T>) => {
141
- if (def instanceof Function) {
142
- def = def(container);
143
- }
144
- return service(def, container);
145
- };
146
- }
147
-
148
- /**
149
- * Get a service raw definition
150
- */
151
- public raw<K extends ServiceKey<T>>(name: K): ServiceDefinition<T, T[K]> {
152
- return this._raw[name] as ServiceDefinition<T, T[K]>;
153
- }
154
-
155
- /**
156
- * Register a service provider
157
- */
158
- public register(provider: ProviderDeclaration<T>): Pimple<T> {
159
- if (this.instanceOfServiceProvider(provider) && provider.register instanceof Function) {
160
- provider.register(this);
161
- } else if (provider instanceof Function) {
162
- provider(this);
163
- }
164
-
165
- return this;
166
- }
167
-
168
- private instanceOfServiceProvider(object: any): object is ServiceProvider<T> {
169
- return 'register' in object;
170
- }
171
- }
@@ -1,9 +0,0 @@
1
- import Pimple from "./pimple";
2
-
3
- /**
4
- * Service provider class for service injecting in Pimple container
5
- */
6
- export default interface ServiceProvider<T>
7
- {
8
- register(container: Pimple<T>): void;
9
- }
@@ -1,194 +0,0 @@
1
- import Pimple from '../src/pimple';
2
- import {ServiceProvider} from "../src/index.js";
3
-
4
- describe('pimple container', () => {
5
- it('returns container version', async () => {
6
- expect(Pimple.VERSION).toBe('3.0.0');
7
- });
8
-
9
- it('stores values', async () => {
10
- type ServiceMap = {
11
- 'baz': number,
12
- 'foo': string,
13
- };
14
-
15
- const container = new Pimple<ServiceMap>({baz: 42});
16
-
17
- container.set('foo', 'bar');
18
-
19
- expect(container.get('foo')).toBe('bar');
20
- expect(container.get('baz')).toBe(42);
21
- });
22
-
23
- it('resolves function', async () => {
24
- type ServiceMap = {
25
- 'baz': number,
26
- 'foo': string,
27
- };
28
-
29
- const container = new Pimple<ServiceMap>();
30
-
31
- container.set('foo', () => {
32
- return 'baz';
33
- });
34
-
35
- expect(container.get('foo')).toBe('baz');
36
- });
37
-
38
- it('resolves function only once', async () => {
39
- type ServiceMap = {
40
- 'foo': number,
41
- };
42
-
43
- const container = new Pimple<ServiceMap>();
44
-
45
- container.set('foo', () => {
46
- return Math.random();
47
- });
48
-
49
- expect(container.get('foo')).toBe(container.get('foo'));
50
- });
51
-
52
- it('returns true if service exists', async () => {
53
- type ServiceMap = {
54
- 'foo': number,
55
- };
56
-
57
- const container = new Pimple<ServiceMap>();
58
-
59
- container.set('foo', () => {
60
- return 42;
61
- });
62
-
63
- expect(container.has('foo')).toBe(true);
64
- });
65
-
66
- it('returns true if service exists', async () => {
67
- type ServiceMap = {
68
- 'foo': number,
69
- };
70
-
71
- const container = new Pimple<ServiceMap>();
72
-
73
- expect(container.has('foo')).toBe(false);
74
- });
75
-
76
- it('protects function', async () => {
77
- type ServiceMap = {
78
- foo: () => string,
79
- baz: () => string,
80
- untyped: Function,
81
- };
82
-
83
- const container = new Pimple<ServiceMap>();
84
-
85
- const typeProtectedFunction = () => 'baz';
86
- const untypedProtectedFunction = () => 42;
87
-
88
- container.set('foo', container.protect(typeProtectedFunction));
89
- container.set('baz', () => typeProtectedFunction);
90
- container.set('untyped', container.protect(untypedProtectedFunction));
91
-
92
- expect(container.get('foo')).toBe(typeProtectedFunction);
93
- expect(container.get('baz')).toBe(typeProtectedFunction);
94
- expect(container.get('untyped')).toBe(untypedProtectedFunction);
95
- });
96
-
97
- it('returns original function', async () => {
98
- type ServiceMap = {
99
- foo: string,
100
- };
101
-
102
- const container = new Pimple<ServiceMap>();
103
-
104
- const protectedFunction = () => {
105
- return 'baz';
106
- };
107
-
108
- container.set('foo', protectedFunction);
109
-
110
- expect(container.raw('foo')).toBe(protectedFunction);
111
- });
112
-
113
- it('registers services defined in service provider', async () => {
114
- type ServiceMap = {
115
- 'foo': string,
116
- }
117
-
118
- const container = new Pimple<ServiceMap>();
119
-
120
- const serviceProviderMock: ServiceProvider<ServiceMap> = {
121
- register: (container: Pimple<ServiceMap>) => {
122
- container.set('foo', () => {
123
- return 'baz'
124
- });
125
- },
126
- };
127
-
128
- container.register(serviceProviderMock);
129
-
130
- expect(container.get('foo')).toBe('baz');
131
- });
132
-
133
- it('registers services defined in function', async () => {
134
- type ServiceMap = {
135
- foo: string,
136
- }
137
-
138
- const container = new Pimple<ServiceMap>();
139
-
140
- const serviceProviderMock = (container: Pimple<ServiceMap>) => {
141
- container.set('foo', () => {
142
- return 'baz'
143
- });
144
- };
145
-
146
- container.register(serviceProviderMock);
147
-
148
- expect(container.get('foo')).toBe('baz');
149
- });
150
-
151
- it('returns new instance from factory', async () => {
152
- type ServiceMap = {
153
- foo: number,
154
- }
155
-
156
- const container = new Pimple<ServiceMap>();
157
-
158
- container.factory('foo', () => {
159
- return Math.random();
160
- });
161
-
162
- expect(container.get('foo')).not.toBe(container.get('foo'));
163
- });
164
-
165
- it('throws exception on extending an undefined service', () => {
166
- type ServiceMap = {
167
- foo: string,
168
- }
169
-
170
- const container = new Pimple<ServiceMap>();
171
-
172
- expect(() => {
173
- container.extend('foo', () => {});
174
- }).toThrow('Definition with "foo" not defined in container.');
175
- });
176
-
177
- it('extends service', () => {
178
- type ServiceMap = {
179
- foo: string,
180
- }
181
-
182
- const container = new Pimple<ServiceMap>({
183
- foo: () => {
184
- return 'baz';
185
- }
186
- });
187
-
188
- container.extend('foo', (initialService: string, container: Pimple<ServiceMap>) => {
189
- return initialService + 'bar';
190
- });
191
-
192
- expect(container.get('foo')).toBe('bazbar');
193
- });
194
- });
package/tsconfig-cjs.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "module": "CommonJS",
5
- "outDir": "./lib/cjs"
6
- },
7
- }
8
-
package/tsconfig.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2015",
4
- "module": "ES2020",
5
- "strict": true,
6
- "esModuleInterop": true,
7
- "noImplicitAny": true,
8
- "declaration": true,
9
- "sourceMap": true,
10
- "experimentalDecorators": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "moduleResolution": "node",
13
- "outDir": "./lib/esm",
14
- "baseUrl": "."
15
- },
16
- "include": [
17
- "src/"
18
- ]
19
- }