@dws-std/registry 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.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dominus Web Services (DWS)
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,106 @@
1
+ # 🎯 DWS Registry
2
+
3
+ If you've ever copy-pasted a `getInstance()` pattern into yet another class, this package is for you.
4
+ It gives you a single, centralized registry to store and retrieve instances — type-safe, predictable, and easy to test.
5
+
6
+ ## Why this package?
7
+
8
+ The classic singleton pattern works, but it scatters `static instance` fields across your codebase.
9
+ Every class re-implements the same boilerplate. With `Registry`, you register instances once and retrieve them anywhere by name.
10
+ One registry, no duplication.
11
+
12
+ ## 📌 Table of Contents
13
+
14
+ - [Features](#-features)
15
+ - [Installation](#-installation)
16
+ - [Usage](#-usage)
17
+ - [API Reference](#-api-reference)
18
+ - [License](#-license)
19
+ - [Contact](#-contact)
20
+
21
+ ## ✨ Features
22
+
23
+ - 🔒 **Type-safe** — Full generics support, no `any` casting required.
24
+ - 🎯 **Centralized** — One place to manage all your instances.
25
+ - ⚡ **Lightweight** — Minimal overhead, does exactly what it says.
26
+
27
+ ## 🔧 Installation
28
+
29
+ ```bash
30
+ bun add @dws-std/registry
31
+ ```
32
+
33
+ ## ⚙️ Usage
34
+
35
+ ### Registering instances
36
+
37
+ Register your instances once at startup. They're available everywhere after that.
38
+
39
+ ```ts
40
+ import { Registry } from '@dws-std/registry';
41
+
42
+ class DatabaseConnection {
43
+ private _isConnected: boolean = false;
44
+
45
+ public constructor() {
46
+ console.log('Database connection created');
47
+ this._isConnected = true;
48
+ }
49
+
50
+ public query(sql: string): string[] {
51
+ return ['result1', 'result2'];
52
+ }
53
+ }
54
+
55
+ class ApiClient {
56
+ public constructor(
57
+ private readonly _baseUrl: string,
58
+ private readonly _apiKey: string
59
+ ) {}
60
+
61
+ public get baseUrl(): string {
62
+ return this._baseUrl;
63
+ }
64
+ }
65
+
66
+ Registry.register('DatabaseConnection', new DatabaseConnection());
67
+ Registry.register('ApiClient', new ApiClient('https://api.example.com', 'key'));
68
+ ```
69
+
70
+ ### Retrieving instances
71
+
72
+ Same instance, every time. You specify the type via the generic, and TypeScript takes care of the rest.
73
+
74
+ ```ts
75
+ const db1 = Registry.get<DatabaseConnection>('DatabaseConnection');
76
+ const db2 = Registry.get<DatabaseConnection>('DatabaseConnection');
77
+
78
+ console.log(db1 === db2); // true — same reference
79
+
80
+ db1.query('SELECT * FROM users'); // type-safe
81
+ ```
82
+
83
+ ### Checking & swapping
84
+
85
+ ```ts
86
+ if (Registry.has('ApiClient')) {
87
+ const client = Registry.get<ApiClient>('ApiClient');
88
+ console.log(client.baseUrl);
89
+ }
90
+
91
+ // Need to replace an instance? Unregister first, then register the new one.
92
+ Registry.unregister('DatabaseConnection');
93
+ Registry.register('DatabaseConnection', new DatabaseConnection());
94
+ ```
95
+
96
+ ## 📚 API Reference
97
+
98
+ Full docs: [Dominus-Web-Service.github.io/packages](https://Dominus-Web-Service.github.io/packages/)
99
+
100
+ ## ⚖️ License
101
+
102
+ MIT — Feel free to use it.
103
+
104
+ ## 📧 Contact
105
+
106
+ - GitHub: [Dominus-Web-Service](https://github.com/Dominus-Web-Service/packages)
@@ -0,0 +1,5 @@
1
+ /** Error codes thrown by the {@link Registry} class. */
2
+ export declare const REGISTRY_ERROR_KEYS: {
3
+ readonly CLASS_INSTANCE_ALREADY_REGISTERED: "registry.classInstanceAlreadyRegistered";
4
+ readonly CLASS_INSTANCE_NOT_REGISTERED: "registry.classInstanceNotRegistered";
5
+ };
@@ -0,0 +1,2 @@
1
+ export { REGISTRY_ERROR_KEYS } from './constant/registry-error-keys';
2
+ export { Registry } from './registry';
package/dist/index.js ADDED
@@ -0,0 +1,45 @@
1
+ // @bun
2
+ // src/constant/registry-error-keys.ts
3
+ var REGISTRY_ERROR_KEYS = {
4
+ CLASS_INSTANCE_ALREADY_REGISTERED: "registry.classInstanceAlreadyRegistered",
5
+ CLASS_INSTANCE_NOT_REGISTERED: "registry.classInstanceNotRegistered"
6
+ };
7
+ // src/registry.ts
8
+ import { Exception } from "@dws-std/error";
9
+ class Registry {
10
+ static _registry = new Map;
11
+ static register(name, instance) {
12
+ if (this._registry.has(name))
13
+ throw new Exception(`Instance already registered: ${name}`, {
14
+ code: REGISTRY_ERROR_KEYS.CLASS_INSTANCE_ALREADY_REGISTERED,
15
+ cause: name
16
+ });
17
+ this._registry.set(name, instance);
18
+ }
19
+ static unregister(name) {
20
+ if (!this._registry.delete(name))
21
+ throw new Exception(`Instance not registered: ${name}`, {
22
+ code: REGISTRY_ERROR_KEYS.CLASS_INSTANCE_NOT_REGISTERED,
23
+ cause: name
24
+ });
25
+ }
26
+ static get(name) {
27
+ const instance = this._registry.get(name);
28
+ if (!instance)
29
+ throw new Exception(`Instance not registered: ${name}`, {
30
+ code: REGISTRY_ERROR_KEYS.CLASS_INSTANCE_NOT_REGISTERED,
31
+ cause: name
32
+ });
33
+ return instance;
34
+ }
35
+ static has(name) {
36
+ return this._registry.has(name);
37
+ }
38
+ static clear() {
39
+ this._registry.clear();
40
+ }
41
+ }
42
+ export {
43
+ Registry,
44
+ REGISTRY_ERROR_KEYS
45
+ };
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Global, type-safe store for named instances.
3
+ *
4
+ * Register an instance once at startup, then retrieve it anywhere
5
+ * by name without passing references around.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * Registry.register('db', new DatabaseConnection());
10
+ * const db = Registry.get<DatabaseConnection>('db');
11
+ * ```
12
+ */
13
+ export declare class Registry {
14
+ private static readonly _registry;
15
+ /**
16
+ * Stores `instance` under the given `name`.
17
+ *
18
+ * Each name can only be registered once. Call {@link unregister} first
19
+ * if you need to replace an existing instance.
20
+ *
21
+ * @template TClass - The type of the instance being stored.
22
+ *
23
+ * @param name - Unique identifier for this instance.
24
+ * @param instance - The object to store.
25
+ *
26
+ * @throws ({@link Exception}) – `name` is already taken.
27
+ */
28
+ static register<TClass extends object>(name: string, instance: TClass): void;
29
+ /**
30
+ * Removes the instance stored under `name`.
31
+ *
32
+ * After this call, `name` can be registered again with a new instance.
33
+ *
34
+ * @param name - Identifier of the instance to remove.
35
+ *
36
+ * @throws ({@link Exception}) – `name` is not registered.
37
+ */
38
+ static unregister(name: string): void;
39
+ /**
40
+ * Retrieves the instance stored under `name`.
41
+ *
42
+ * The caller specifies the expected type via the generic parameter;
43
+ * no runtime type-check is performed.
44
+ *
45
+ * @template TClass - Expected type of the stored instance.
46
+ *
47
+ * @param name - Identifier of the instance to retrieve.
48
+ *
49
+ * @throws ({@link Exception}) – `name` is not registered.
50
+ */
51
+ static get<TClass>(name: string): TClass;
52
+ /**
53
+ * Checks whether an instance is stored under `name`.
54
+ *
55
+ * @param name - Identifier to look up.
56
+ */
57
+ static has(name: string): boolean;
58
+ /** Removes every stored instance — useful for test teardown. */
59
+ static clear(): void;
60
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@dws-std/registry",
3
+ "version": "1.0.0",
4
+ "description": "Centralized, type-safe registry for managing named instances.",
5
+ "keywords": [
6
+ "bun",
7
+ "dws",
8
+ "registry",
9
+ "type-safe"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Dominus Web Services (DWS)",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/Dominus-Web-Service/std",
16
+ "directory": "packages/registry"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "type": "module",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ }
27
+ },
28
+ "scripts": {
29
+ "build": "bun builder.ts",
30
+ "docs": "bunx typedoc --tsconfig tsconfig.build.json",
31
+ "fmt:check": "oxfmt --check",
32
+ "fmt": "oxfmt",
33
+ "lint:fix": "oxlint --type-aware --type-check --fix ./src",
34
+ "lint:github": "oxlint --type-aware --type-check --format=github ./src",
35
+ "lint": "oxlint --type-aware --type-check ./src",
36
+ "test": "bun test --pass-with-no-tests --coverage"
37
+ },
38
+ "dependencies": {
39
+ "@dws-std/error": "^2.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/bun": "^1.3.10",
43
+ "oxfmt": "^0.40.0",
44
+ "oxlint": "^1.55.0",
45
+ "oxlint-tsgolint": "^0.16.0",
46
+ "typescript": "^5.9.3"
47
+ },
48
+ "peerDependencies": {
49
+ "@dws-std/error": "^2.0.0"
50
+ }
51
+ }