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 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>
@@ -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
+ }