Skip to content

Commit 2c9fcda

Browse files
authored
Add singleton helper function for lazy initialization of instances (#34)
* Add singleton helper function for lazy initialization of instances * Update version to 4.9.0 and document addition of singleton helper function in CHANGELOG.md * Refactor singleton helper function to improve instance management by using a boolean flag for instance existence, enhancing error handling for promise rejections.
1 parent 74f2b89 commit 2c9fcda

3 files changed

Lines changed: 47 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# deverything
22

3+
## 4.9.0
4+
5+
### Minor Changes
6+
7+
- singleton
8+
39
## 4.8.0
410

511
### Minor Changes

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "deverything",
3-
"version": "4.8.0",
3+
"version": "4.9.0",
44
"description": "Everything you need for Dev",
55
"main": "./dist/index.js",
66
"module": "./dist/index.mjs",

src/helpers/singleton.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { isPromise } from "../validators/isPromise";
2+
3+
/**
4+
* Creates a lazily-initialized singleton from a factory function.
5+
* Works with both sync and async factories — the return type mirrors the factory's.
6+
*
7+
* For async factories, concurrent callers during initialization share the same
8+
* in-flight promise rather than triggering multiple factory calls. If the promise
9+
* rejects, the singleton resets so the next call retries.
10+
*/
11+
export const singleton = <Result>(factory: () => Result): (() => Result) => {
12+
let hasInstance = false;
13+
let instance!: Result;
14+
15+
return () => {
16+
if (hasInstance) {
17+
return instance;
18+
}
19+
20+
const result = factory();
21+
22+
if (isPromise(result)) {
23+
hasInstance = true;
24+
instance = result.then(
25+
(value) => value,
26+
(error) => {
27+
hasInstance = false;
28+
throw error;
29+
}
30+
) as Result;
31+
32+
return instance;
33+
}
34+
35+
// not a promise
36+
hasInstance = true;
37+
instance = result;
38+
return result;
39+
};
40+
};

0 commit comments

Comments
 (0)