singleton-pattern 1.0.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.
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.mjs +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 kasukabe tsumugi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Singleton Pattern
|
|
2
|
+
|
|
3
|
+
🦄 Wrap your class to make it a true singleton!
|
|
4
|
+
|
|
5
|
+
> Note: Your environment must support Proxy
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`singleton-pattern` is a lightweight TypeScript/JavaScript utility that wraps a class constructor so that every `new` call returns the same instance. It uses Proxy to ensure singleton safety, and provides options for prototype handling.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Make any class a singleton with one line
|
|
14
|
+
- Optionally control prototype.constructor behavior
|
|
15
|
+
- Retrieve the original class from a singletonified class
|
|
16
|
+
- Fully type-safe
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install singleton-pattern
|
|
22
|
+
# or
|
|
23
|
+
pnpm add singleton-pattern
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { singletonify, getSingletonTarget } from 'singleton-pattern';
|
|
30
|
+
|
|
31
|
+
class MyClass {
|
|
32
|
+
value: number;
|
|
33
|
+
constructor(v: number) {
|
|
34
|
+
this.value = v;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const Singleton = singletonify(MyClass);
|
|
39
|
+
const a = new Singleton(1);
|
|
40
|
+
const b = new Singleton(2);
|
|
41
|
+
console.log(a === b); // true
|
|
42
|
+
console.log(a.value); // 1
|
|
43
|
+
|
|
44
|
+
// Option: keep original prototype.constructor
|
|
45
|
+
const Singleton2 = singletonify(MyClass, { hideProtoConstructor: false });
|
|
46
|
+
console.log(Singleton2.prototype.constructor === MyClass); // true
|
|
47
|
+
|
|
48
|
+
// Retrieve original class
|
|
49
|
+
console.log(getSingletonTarget(Singleton)); // MyClass
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API
|
|
53
|
+
|
|
54
|
+
### `singletonify<T extends Class>(target: T, options?: SingletonifyOptions): T`
|
|
55
|
+
|
|
56
|
+
Wraps a class constructor so that all `new` calls return the same instance.
|
|
57
|
+
|
|
58
|
+
- `target`: The class to wrap
|
|
59
|
+
- `options.hideProtoConstructor` (default: `true`): If not `false`, sets `prototype.constructor` to the singletonified class. If `false`, keeps the original constructor.
|
|
60
|
+
|
|
61
|
+
### `getSingletonTarget<T extends Class>(singleton: T): T | undefined`
|
|
62
|
+
|
|
63
|
+
Returns the original class for a singletonified class, or `undefined` if not singletonified.
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
MIT
|
|
68
|
+
|
|
69
|
+
## Author
|
|
70
|
+
|
|
71
|
+
Kasukabe Tsumugi <futami16237@gmail.com>
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// # from: global.d.ts
|
|
2
|
+
type Class = new (...args: any[]) => any;
|
|
3
|
+
|
|
4
|
+
interface SingletonifyOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Preventing the `.prototype.constructor` from being accessed
|
|
7
|
+
* - default is `true`
|
|
8
|
+
* - **Only** when it is `false`, will remain the original constructor unchanged
|
|
9
|
+
* - will change `Origin.prototype.constructor` to the singletonified class
|
|
10
|
+
* - this means Origin.prototype.constructor !== origin
|
|
11
|
+
*/
|
|
12
|
+
hideProtoConstructor?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// # index.d.ts
|
|
16
|
+
/**
|
|
17
|
+
* ## Usage
|
|
18
|
+
* Just wrap your class with this function to create a new class that always returns the same instance
|
|
19
|
+
* @param target The class to be wrapped
|
|
20
|
+
* @param options Advanced options
|
|
21
|
+
* - hideProtoConstructor(default: `true`) when it is **not** `false`, will set `target.prototype.constructor` to the singletonified class
|
|
22
|
+
*
|
|
23
|
+
* ## About
|
|
24
|
+
* @package SingletonPattern
|
|
25
|
+
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
26
|
+
* @version 1.0.0 (Last Update: 2025.08.15 10:00:01.902)
|
|
27
|
+
* @license MIT
|
|
28
|
+
* @link https://github.com/baendlorel/singleton-pattern
|
|
29
|
+
* @description Wrap a class with proxy to make it a safe singleton constructor. Using new Class() will return the same instance.
|
|
30
|
+
* @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
|
|
31
|
+
*/
|
|
32
|
+
declare const singletonify: <T extends Class>(target: T, options?: SingletonifyOptions) => T;
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves the original class from the singletonified class
|
|
35
|
+
* @param singleton The singletonified class
|
|
36
|
+
* @returns `undefined` if the class is not singletonified, otherwise returns the original class
|
|
37
|
+
*/
|
|
38
|
+
declare const getSingletonTarget: <T extends Class>(singleton: T) => T | undefined;
|
|
39
|
+
|
|
40
|
+
export { getSingletonTarget, singletonify };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const n=Proxy;const t=new class{map=new WeakMap;singletonify(t,e){let o;const s=new n(t,{construct:(n,t)=>(o||(o=new n(...t)),o)});return!1!==(null==e?void 0:e.hideProtoConstructor)&&(s.prototype.constructor=s),this.map.set(s,t),s}getSingletonTarget(n){return this.map.get(n)}},e=t.singletonify.bind(t),o=t.getSingletonTarget.bind(t);export{o as getSingletonTarget,e as singletonify};
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "singleton-pattern",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "Kasukabe Tsumugi",
|
|
6
|
+
"email": "futami16237@gmail.com"
|
|
7
|
+
},
|
|
8
|
+
"description": "Wrap a class with proxy to make it a safe singleton constructor. Using new Class() will return the same instance.",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"exports": {
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"default": "./dist/index.mjs",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://github.com/baendlorel/singleton-pattern#readme",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/baendlorel/singleton-pattern"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"deep",
|
|
25
|
+
"clone",
|
|
26
|
+
"reflect",
|
|
27
|
+
"property",
|
|
28
|
+
"path",
|
|
29
|
+
"object",
|
|
30
|
+
"nested",
|
|
31
|
+
"typescript",
|
|
32
|
+
"javascript"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"test": "clear & vitest",
|
|
36
|
+
"lint": "oxlint .",
|
|
37
|
+
"cover": "clear & vitest --coverage",
|
|
38
|
+
"build": "rimraf dist && rollup -c"
|
|
39
|
+
},
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@babel/plugin-proposal-decorators": "^7.28.0",
|
|
43
|
+
"@babel/preset-env": "^7.28.3",
|
|
44
|
+
"@rollup/plugin-alias": "^5.1.1",
|
|
45
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
46
|
+
"@rollup/plugin-commonjs": "^28.0.6",
|
|
47
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
48
|
+
"@rollup/plugin-replace": "^6.0.2",
|
|
49
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
50
|
+
"@rollup/plugin-typescript": "^12.1.4",
|
|
51
|
+
"@types/node": "^24.2.1",
|
|
52
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
53
|
+
"oxlint": "^1.11.2",
|
|
54
|
+
"prettier": "^3.6.2",
|
|
55
|
+
"rimraf": "^6.0.1",
|
|
56
|
+
"rollup": "^4.46.2",
|
|
57
|
+
"rollup-plugin-dts": "^6.2.1",
|
|
58
|
+
"tslib": "^2.8.1",
|
|
59
|
+
"typescript": "^5.9.2",
|
|
60
|
+
"vitest": "^3.2.4"
|
|
61
|
+
}
|
|
62
|
+
}
|