From 1a35a4a35e871e09fd4263edc43451ec27ed2abf Mon Sep 17 00:00:00 2001 From: CounterFire2023 <136581895+CounterFire2023@users.noreply.github.com> Date: Wed, 17 Jan 2024 15:51:16 +0800 Subject: [PATCH] add singleton decorators --- dist/index.cjs | 22 ++++++++++++++++++++-- dist/index.cjs.map | 2 +- dist/index.d.cts | 18 ++++++++++++++++++ dist/index.d.ts | 18 ++++++++++++++++++ dist/index.js | 18 +++++++++++++++++- dist/index.js.map | 2 +- src/decorators/singleton.ts | 29 +++++++++++++++++++++++++++++ src/index.ts | 3 ++- 8 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 src/decorators/singleton.ts diff --git a/dist/index.cjs b/dist/index.cjs index 4228fde..403de24 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -19,7 +19,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru // src/index.ts var src_exports = {}; __export(src_exports, { - ZError: () => ZError + SINGLETON_KEY: () => SINGLETON_KEY, + ZError: () => ZError, + singleton: () => singleton }); module.exports = __toCommonJS(src_exports); @@ -30,8 +32,24 @@ var ZError = class { this.message = message; } }; + +// src/decorators/singleton.ts +var SINGLETON_KEY = Symbol(); +var singleton = (classTarget) => new Proxy(classTarget, { + construct(target, argumentsList, newTarget) { + if (target.prototype !== newTarget.prototype) { + return Reflect.construct(target, argumentsList, newTarget); + } + if (!target[SINGLETON_KEY]) { + target[SINGLETON_KEY] = Reflect.construct(target, argumentsList, newTarget); + } + return target[SINGLETON_KEY]; + } +}); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { - ZError + SINGLETON_KEY, + ZError, + singleton }); //# sourceMappingURL=index.cjs.map \ No newline at end of file diff --git a/dist/index.cjs.map b/dist/index.cjs.map index 0a40385..ff90228 100644 --- a/dist/index.cjs.map +++ b/dist/index.cjs.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.ts","../src/common/ZError.ts"],"sourcesContent":["export { ZError } from './common/ZError'","\nexport class ZError implements Error {\n code: string\n statusCode?: number\n message: string\n name: string\n\n constructor(statusCode: number, message: string) {\n this.statusCode = statusCode\n this.message = message\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCO,IAAM,SAAN,MAA8B;AAAA,EAMnC,YAAY,YAAoB,SAAiB;AAC/C,SAAK,aAAa;AAClB,SAAK,UAAU;AAAA,EACjB;AACF;","names":[]} \ No newline at end of file +{"version":3,"sources":["../src/index.ts","../src/common/ZError.ts","../src/decorators/singleton.ts"],"sourcesContent":["export { ZError } from './common/ZError'\nexport * from './decorators/singleton'","\nexport class ZError implements Error {\n code: string\n statusCode?: number\n message: string\n name: string\n\n constructor(statusCode: number, message: string) {\n this.statusCode = statusCode\n this.message = message\n }\n}\n","/**\n * 单例化一个class\n * 使用方法:\n * @singleton\n * class Test {}\n * new Test() === new Test() // returns `true`\n * 也可以不使用 decorator\n * const TestSingleton = singleton(Test)\n * new TestSingleton() === new TestSingleton() //returns 'true'\n */\n\nexport const SINGLETON_KEY = Symbol()\n\nexport type Singleton any> = T & {\n [SINGLETON_KEY]: T extends new (...args: any[]) => infer I ? I : never\n}\nexport const singleton = any>(classTarget: T) =>\n new Proxy(classTarget, {\n construct(target: Singleton, argumentsList, newTarget) {\n // Skip proxy for children\n if (target.prototype !== newTarget.prototype) {\n return Reflect.construct(target, argumentsList, newTarget)\n }\n if (!target[SINGLETON_KEY]) {\n target[SINGLETON_KEY] = Reflect.construct(target, argumentsList, newTarget)\n }\n return target[SINGLETON_KEY]\n },\n })\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCO,IAAM,SAAN,MAA8B;AAAA,EAMnC,YAAY,YAAoB,SAAiB;AAC/C,SAAK,aAAa;AAClB,SAAK,UAAU;AAAA,EACjB;AACF;;;ACAO,IAAM,gBAAgB,OAAO;AAK7B,IAAM,YAAY,CAAwC,gBAC/D,IAAI,MAAM,aAAa;AAAA,EACrB,UAAU,QAAsB,eAAe,WAAW;AAExD,QAAI,OAAO,cAAc,UAAU,WAAW;AAC5C,aAAO,QAAQ,UAAU,QAAQ,eAAe,SAAS;AAAA,IAC3D;AACA,QAAI,CAAC,OAAO,aAAa,GAAG;AAC1B,aAAO,aAAa,IAAI,QAAQ,UAAU,QAAQ,eAAe,SAAS;AAAA,IAC5E;AACA,WAAO,OAAO,aAAa;AAAA,EAC7B;AACF,CAAC;","names":[]} \ No newline at end of file diff --git a/dist/index.d.cts b/dist/index.d.cts index bfd0b75..0294735 100644 --- a/dist/index.d.cts +++ b/dist/index.d.cts @@ -1 +1,19 @@ export { ZError } from './common/ZError.cjs'; + +/** + * 单例化一个class + * 使用方法: + * @singleton + * class Test {} + * new Test() === new Test() // returns `true` + * 也可以不使用 decorator + * const TestSingleton = singleton(Test) + * new TestSingleton() === new TestSingleton() //returns 'true' + */ +declare const SINGLETON_KEY: unique symbol; +type Singleton any> = T & { + [SINGLETON_KEY]: T extends new (...args: any[]) => infer I ? I : never; +}; +declare const singleton: any>(classTarget: T) => T; + +export { SINGLETON_KEY, type Singleton, singleton }; diff --git a/dist/index.d.ts b/dist/index.d.ts index 8b89e50..c2db20c 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1 +1,19 @@ export { ZError } from './common/ZError.js'; + +/** + * 单例化一个class + * 使用方法: + * @singleton + * class Test {} + * new Test() === new Test() // returns `true` + * 也可以不使用 decorator + * const TestSingleton = singleton(Test) + * new TestSingleton() === new TestSingleton() //returns 'true' + */ +declare const SINGLETON_KEY: unique symbol; +type Singleton any> = T & { + [SINGLETON_KEY]: T extends new (...args: any[]) => infer I ? I : never; +}; +declare const singleton: any>(classTarget: T) => T; + +export { SINGLETON_KEY, type Singleton, singleton }; diff --git a/dist/index.js b/dist/index.js index 916ee92..a5632d3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5,7 +5,23 @@ var ZError = class { this.message = message; } }; + +// src/decorators/singleton.ts +var SINGLETON_KEY = Symbol(); +var singleton = (classTarget) => new Proxy(classTarget, { + construct(target, argumentsList, newTarget) { + if (target.prototype !== newTarget.prototype) { + return Reflect.construct(target, argumentsList, newTarget); + } + if (!target[SINGLETON_KEY]) { + target[SINGLETON_KEY] = Reflect.construct(target, argumentsList, newTarget); + } + return target[SINGLETON_KEY]; + } +}); export { - ZError + SINGLETON_KEY, + ZError, + singleton }; //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map index 3e11aa4..951e9cc 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/common/ZError.ts"],"sourcesContent":["\nexport class ZError implements Error {\n code: string\n statusCode?: number\n message: string\n name: string\n\n constructor(statusCode: number, message: string) {\n this.statusCode = statusCode\n this.message = message\n }\n}\n"],"mappings":";AACO,IAAM,SAAN,MAA8B;AAAA,EAMnC,YAAY,YAAoB,SAAiB;AAC/C,SAAK,aAAa;AAClB,SAAK,UAAU;AAAA,EACjB;AACF;","names":[]} \ No newline at end of file +{"version":3,"sources":["../src/common/ZError.ts","../src/decorators/singleton.ts"],"sourcesContent":["\nexport class ZError implements Error {\n code: string\n statusCode?: number\n message: string\n name: string\n\n constructor(statusCode: number, message: string) {\n this.statusCode = statusCode\n this.message = message\n }\n}\n","/**\n * 单例化一个class\n * 使用方法:\n * @singleton\n * class Test {}\n * new Test() === new Test() // returns `true`\n * 也可以不使用 decorator\n * const TestSingleton = singleton(Test)\n * new TestSingleton() === new TestSingleton() //returns 'true'\n */\n\nexport const SINGLETON_KEY = Symbol()\n\nexport type Singleton any> = T & {\n [SINGLETON_KEY]: T extends new (...args: any[]) => infer I ? I : never\n}\nexport const singleton = any>(classTarget: T) =>\n new Proxy(classTarget, {\n construct(target: Singleton, argumentsList, newTarget) {\n // Skip proxy for children\n if (target.prototype !== newTarget.prototype) {\n return Reflect.construct(target, argumentsList, newTarget)\n }\n if (!target[SINGLETON_KEY]) {\n target[SINGLETON_KEY] = Reflect.construct(target, argumentsList, newTarget)\n }\n return target[SINGLETON_KEY]\n },\n })\n"],"mappings":";AACO,IAAM,SAAN,MAA8B;AAAA,EAMnC,YAAY,YAAoB,SAAiB;AAC/C,SAAK,aAAa;AAClB,SAAK,UAAU;AAAA,EACjB;AACF;;;ACAO,IAAM,gBAAgB,OAAO;AAK7B,IAAM,YAAY,CAAwC,gBAC/D,IAAI,MAAM,aAAa;AAAA,EACrB,UAAU,QAAsB,eAAe,WAAW;AAExD,QAAI,OAAO,cAAc,UAAU,WAAW;AAC5C,aAAO,QAAQ,UAAU,QAAQ,eAAe,SAAS;AAAA,IAC3D;AACA,QAAI,CAAC,OAAO,aAAa,GAAG;AAC1B,aAAO,aAAa,IAAI,QAAQ,UAAU,QAAQ,eAAe,SAAS;AAAA,IAC5E;AACA,WAAO,OAAO,aAAa;AAAA,EAC7B;AACF,CAAC;","names":[]} \ No newline at end of file diff --git a/src/decorators/singleton.ts b/src/decorators/singleton.ts new file mode 100644 index 0000000..c43327d --- /dev/null +++ b/src/decorators/singleton.ts @@ -0,0 +1,29 @@ +/** + * 单例化一个class + * 使用方法: + * @singleton + * class Test {} + * new Test() === new Test() // returns `true` + * 也可以不使用 decorator + * const TestSingleton = singleton(Test) + * new TestSingleton() === new TestSingleton() //returns 'true' + */ + +export const SINGLETON_KEY = Symbol() + +export type Singleton any> = T & { + [SINGLETON_KEY]: T extends new (...args: any[]) => infer I ? I : never +} +export const singleton = any>(classTarget: T) => + new Proxy(classTarget, { + construct(target: Singleton, argumentsList, newTarget) { + // Skip proxy for children + if (target.prototype !== newTarget.prototype) { + return Reflect.construct(target, argumentsList, newTarget) + } + if (!target[SINGLETON_KEY]) { + target[SINGLETON_KEY] = Reflect.construct(target, argumentsList, newTarget) + } + return target[SINGLETON_KEY] + }, + }) diff --git a/src/index.ts b/src/index.ts index 8021635..368d921 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,2 @@ -export { ZError } from './common/ZError' \ No newline at end of file +export { ZError } from './common/ZError' +export * from './decorators/singleton' \ No newline at end of file