Skip to content

Commit

Permalink
feat(singleton-proxy): add createSingletonProxy (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
nartc committed Oct 3, 2023
1 parent 715725f commit f11999e
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 0 deletions.
22 changes: 22 additions & 0 deletions docs/src/content/docs/utilities/singleton-proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: createSingletonProxy
description: ngxtension/singleton-proxy
---

`createSingletonProxy` creates a singleton instance of a given class when a property within it is accessed, not before.

:::tip[Credits]
Credits to [Poimandres](https://pmnd.rs/) for the original code in [R3F Rapier](https://github.com/pmndrs/react-three-rapier)
:::

## Usage

```ts
import { createSingletonProxy } from 'ngxtension/singleton-proxy';

const { proxy: worldProxy, reset: resetWorld } = createSingletonProxy(() => new rapier.World([0, -9.81, 0]));

worldProxy.gravity; // rapier.World() won't be created until this point

resetWorld(); // reset the instance
```
3 changes: 3 additions & 0 deletions libs/ngxtension/singleton-proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ngxtension/singleton-proxy

Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/singleton-proxy`.
5 changes: 5 additions & 0 deletions libs/ngxtension/singleton-proxy/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"lib": {
"entryFile": "src/index.ts"
}
}
33 changes: 33 additions & 0 deletions libs/ngxtension/singleton-proxy/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "ngxtension/singleton-proxy",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"sourceRoot": "libs/ngxtension/singleton-proxy/src",
"targets": {
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/ngxtension/jest.config.ts",
"testPathPattern": ["singleton-proxy"],
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"libs/ngxtension/singleton-proxy/**/*.ts",
"libs/ngxtension/singleton-proxy/**/*.html"
]
}
}
}
}
1 change: 1 addition & 0 deletions libs/ngxtension/singleton-proxy/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './singleton-proxy';
47 changes: 47 additions & 0 deletions libs/ngxtension/singleton-proxy/src/singleton-proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Original code by PMNDRS
* Source: https://github.com/pmndrs/react-three-rapier
* License: MIT License (or specify the appropriate license)
*
* Creates a proxy that will create a singleton instance of the given class
* when a property is accessed, and not before.
*
* @returns A proxy and a reset function, so that the instance can created again
*/
export function createSingletonProxy<
SingletonClass extends object,
CreationFn extends () => SingletonClass = () => SingletonClass
>(
/**
* A function that returns a new instance of the class
*/
createInstance: CreationFn
): { proxy: SingletonClass; reset: () => void } {
let instance: SingletonClass | undefined;

const handler: ProxyHandler<SingletonClass> = {
get(_, prop) {
if (!instance) {
instance = createInstance();
}
return Reflect.get(instance!, prop);
},
set(_, prop, value) {
if (!instance) {
instance = createInstance();
}
return Reflect.set(instance!, prop, value);
},
};

const proxy = new Proxy({} as SingletonClass, handler) as SingletonClass;

const reset = () => {
instance = undefined;
};

/**
* Return the proxy and a reset function
*/
return { proxy, reset };
}
3 changes: 3 additions & 0 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
],
"ngxtension/repeat": ["libs/ngxtension/repeat/src/index.ts"],
"ngxtension/resize": ["libs/ngxtension/resize/src/index.ts"],
"ngxtension/singleton-proxy": [
"libs/ngxtension/singleton-proxy/src/index.ts"
],
"ngxtension/trackby-id-prop": [
"libs/ngxtension/trackby-id-prop/src/index.ts"
],
Expand Down

0 comments on commit f11999e

Please sign in to comment.