{"_id":"tinspector","_rev":"196-f65992c5b6e698651fa605845c5684fe","name":"tinspector","dist-tags":{"canary":"3.2.3-canary.kik3wda7.0","latest":"3.2.2"},"versions":{"1.4.0-alpha.b123904d":{"name":"tinspector","version":"1.4.0-alpha.b123904d","description":"TypeScript type inspector library","main":"lib/index.js","keywords":["reflection","introspection"],"scripts":{"compile":"tsc -p tsconfig.build.json","package-prod":"node ../../.script/modify-package.js production","package-dev":"node ../../.script/modify-package.js"},"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.12"},"devDependencies":{"benalu":"^2.0.0-beta-1","edit-json-file":"^1.0.8","json":"^9.0.6"},"types":"lib/index.d.ts","_id":"tinspector@1.4.0-alpha.b123904d","dist":{"shasum":"69097d7b3d7a7ba328848090d68d5ec117aadbac","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-1.4.0-alpha.b123904d.tgz","fileCount":6,"unpackedSize":12600,"integrity":"sha512-azUFSNnYv01gwMJ4Ohcr547uU1TTlHBX/Wmsdu0efEp9GIPk1CBLdJDWNYtHH0pjHgkWVyfrqth3yhvkS7Y1Wg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDJ/kEoOVJ9Atahimnu40vqXumbIlUDVfFCGr7FP2/IaAiEA3Cw6TEX1O6K4HoccmhPUKCdHAiGudfiHaSRJRsMKXG8="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_1.4.0-alpha.b123904d_1531019334465_0.6181319035070878"},"_hasShrinkwrap":false},"1.4.0-alpha.79af24d3":{"name":"tinspector","version":"1.4.0-alpha.79af24d3","description":"TypeScript type inspector library","main":"lib/index.js","keywords":["reflection","introspection"],"scripts":{"compile":"tsc -p tsconfig.build.json","package-prod":"node ../../.script/modify-package production","package-dev":"node ../../.script/modify-package"},"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/debug":"^0.0.30","chalk":"^2.4.1","debug":"^3.1.0","reflect-metadata":"^0.1.12"},"devDependencies":{"@types/ejs":"^2.6.0","benalu":"^2.0.0-beta-1","ejs":"^2.6.1"},"types":"lib/index.d.ts","readmeFilename":"readme.md","readme":"# tinspector\nTypeScript type inspector library\n\n[![Build Status](https://travis-ci.org/ktutnik/my-own-reflect.svg?branch=master)](https://travis-ci.org/ktutnik/my-own-reflect)\n[![Coverage Status](https://coveralls.io/repos/github/ktutnik/my-own-reflect/badge.svg?branch=master)](https://coveralls.io/github/ktutnik/my-own-reflect?branch=master)\n\n## Motivation\ntinspector is a type inspector library, it can parse all exported functions and classes inside a module into Abstract Syntax Tree. \n\n## How to Use It\nExample you have a file with classes like below:\n\n```typescript\n//filename: src/mock.ts\nexport function myFun(firstPar: string, secondPar: string) { }\nexport function myOtherFun() { }\n\nexport class MyClass {\n    myMethod(firstPar: string, secondPar: string) { }\n    myOtherMethod(){}\n}\n```\nYou can retrieve AST from above module using:\n\n```typescript\n//filename: src/index.ts\nimport {reflect} from \"./reflect\"\n\nconst result = reflect(\"./mock\")\n```\n\nThe result will be like below:\n\n```javascript\n{\n    type: 'Object',\n    name: 'module',\n    members: [{\n        type: 'Function',\n        name: 'myFun',\n        parameters:\n            [{ type: 'Parameter', name: 'firstPar' },\n            { type: 'Parameter', name: 'secondPar' }]\n    },\n    { type: 'Function', name: 'myOtherFun', parameters: [] },\n    {\n        type: 'Class',\n        name: 'MyClass',\n        methods:\n            [{\n                type: 'Function',\n                name: 'myMethod',\n                parameters:\n                    [{ type: 'Parameter', name: 'firstPar' },\n                    { type: 'Parameter', name: 'secondPar' }]\n            },\n            { type: 'Function', name: 'myOtherMethod', parameters: [] }]\n    }]\n}\n```\n\nThe parameter of the `reflect` method is the path of the module that will be parsed, it is respect the JavaScript import naming such as absolute `\"./module\"`, `\"/path/of/module\"`, relative `\"../../module\"` or global `\"module\"`\n\ntinspector can handle TypeScript style decorator properly\n\n```typescript\nimport {decorateClass, decorateMethod, decorateParameter} from \"./reflect\"\n\n@decorateClass({ url: \"/animal\" })\nexport class AnimalClass {\n    @decorateMethod({ url: \"/get\" })\n    myMethod(@decorateParameter({ required: true }) firstPar: string, @decorateParameter({ required: false }) secondPar: string) { }\n    myOtherMethod(@decorateParameter({ required: true }) par1: string, par2: string) { }\n}\n```\n\nThe reflection result is like below:\n\n```javascript\n{\n    type: 'Class',\n    name: 'AnimalClass',\n    methods:\n        [{\n            type: 'Function',\n            name: 'myMethod',\n            parameters:\n                [{\n                    type: 'Parameter',\n                    name: 'firstPar',\n                    decorators:\n                        [{ required: true }]\n                },\n                {\n                    type: 'Parameter',\n                    name: 'secondPar',\n                    decorators:\n                        [{ required: false }]\n                }],\n            decorators:\n                [{ url: '/get' }]\n        },\n        {\n            type: 'Function',\n            name: 'myOtherMethod',\n            parameters:\n                [{\n                    type: 'Parameter',\n                    name: 'par1',\n                    decorators:\n                        [{ required: true }]\n                },\n                { type: 'Parameter', name: 'par2', decorators: [] }],\n            decorators: []\n        }],\n    decorators:\n        [{ url: '/animal' }]\n}\n```","_id":"tinspector@1.4.0-alpha.79af24d3","dist":{"shasum":"be07c3b5e6f9304daf554f9dee360b808b6b74a9","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-1.4.0-alpha.79af24d3.tgz","fileCount":6,"unpackedSize":13422,"integrity":"sha512-Is2uE7qmyAAc/rCK/al5vGNP1Ri4XP2MR4r78W5k7YBllGbApmZj0O1kCc5jD43OEjkoZjYpWnb8vTCZH2OJYw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBhJJ37JTEmcTbXnwUrUhai7LAV/2daFY3mCrBMOZATyAiBatxvrDNMofmnW4B45mC3hse16iJzGp3NCRbTG12WicQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_1.4.0-alpha.79af24d3_1531692153563_0.43303524232042223"},"_hasShrinkwrap":false},"1.4.0-alpha.caa0578b":{"name":"tinspector","version":"1.4.0-alpha.caa0578b","description":"TypeScript type inspector library","main":"lib/index.js","keywords":["reflection","introspection"],"scripts":{"compile":"tsc -p tsconfig.build.json","package-prod":"node ../../.script/modify-package production","package-dev":"node ../../.script/modify-package"},"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/debug":"^0.0.30","chalk":"^2.4.1","debug":"^3.1.0","reflect-metadata":"^0.1.12"},"devDependencies":{"@types/ejs":"^2.6.0","benalu":"^2.0.0-beta-1","ejs":"^2.6.1"},"types":"lib/index.d.ts","readmeFilename":"readme.md","readme":"# tinspector\nTypeScript type inspector library\n\n[![Build Status](https://travis-ci.org/ktutnik/my-own-reflect.svg?branch=master)](https://travis-ci.org/ktutnik/my-own-reflect)\n[![Coverage Status](https://coveralls.io/repos/github/ktutnik/my-own-reflect/badge.svg?branch=master)](https://coveralls.io/github/ktutnik/my-own-reflect?branch=master)\n\n## Motivation\ntinspector is a type inspector library, it can parse all exported functions and classes inside a module into Abstract Syntax Tree. \n\n## How to Use It\nExample you have a file with classes like below:\n\n```typescript\n//filename: src/mock.ts\nexport function myFun(firstPar: string, secondPar: string) { }\nexport function myOtherFun() { }\n\nexport class MyClass {\n    myMethod(firstPar: string, secondPar: string) { }\n    myOtherMethod(){}\n}\n```\nYou can retrieve AST from above module using:\n\n```typescript\n//filename: src/index.ts\nimport {reflect} from \"./reflect\"\n\nconst result = reflect(\"./mock\")\n```\n\nThe result will be like below:\n\n```javascript\n{\n    type: 'Object',\n    name: 'module',\n    members: [{\n        type: 'Function',\n        name: 'myFun',\n        parameters:\n            [{ type: 'Parameter', name: 'firstPar' },\n            { type: 'Parameter', name: 'secondPar' }]\n    },\n    { type: 'Function', name: 'myOtherFun', parameters: [] },\n    {\n        type: 'Class',\n        name: 'MyClass',\n        methods:\n            [{\n                type: 'Function',\n                name: 'myMethod',\n                parameters:\n                    [{ type: 'Parameter', name: 'firstPar' },\n                    { type: 'Parameter', name: 'secondPar' }]\n            },\n            { type: 'Function', name: 'myOtherMethod', parameters: [] }]\n    }]\n}\n```\n\nThe parameter of the `reflect` method is the path of the module that will be parsed, it is respect the JavaScript import naming such as absolute `\"./module\"`, `\"/path/of/module\"`, relative `\"../../module\"` or global `\"module\"`\n\ntinspector can handle TypeScript style decorator properly\n\n```typescript\nimport {decorateClass, decorateMethod, decorateParameter} from \"./reflect\"\n\n@decorateClass({ url: \"/animal\" })\nexport class AnimalClass {\n    @decorateMethod({ url: \"/get\" })\n    myMethod(@decorateParameter({ required: true }) firstPar: string, @decorateParameter({ required: false }) secondPar: string) { }\n    myOtherMethod(@decorateParameter({ required: true }) par1: string, par2: string) { }\n}\n```\n\nThe reflection result is like below:\n\n```javascript\n{\n    type: 'Class',\n    name: 'AnimalClass',\n    methods:\n        [{\n            type: 'Function',\n            name: 'myMethod',\n            parameters:\n                [{\n                    type: 'Parameter',\n                    name: 'firstPar',\n                    decorators:\n                        [{ required: true }]\n                },\n                {\n                    type: 'Parameter',\n                    name: 'secondPar',\n                    decorators:\n                        [{ required: false }]\n                }],\n            decorators:\n                [{ url: '/get' }]\n        },\n        {\n            type: 'Function',\n            name: 'myOtherMethod',\n            parameters:\n                [{\n                    type: 'Parameter',\n                    name: 'par1',\n                    decorators:\n                        [{ required: true }]\n                },\n                { type: 'Parameter', name: 'par2', decorators: [] }],\n            decorators: []\n        }],\n    decorators:\n        [{ url: '/animal' }]\n}\n```","_id":"tinspector@1.4.0-alpha.caa0578b","dist":{"shasum":"a3cbedc93fc31943fb2554a79637d8346fcf6bd1","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-1.4.0-alpha.caa0578b.tgz","fileCount":6,"unpackedSize":13422,"integrity":"sha512-w3KzhuVQEcysZBw/FCgwXawW7IaGeYi6u7VDdi8ZTKErLy65z3jQiDNGAbMDAQGs7dTlW462nbai0TKx1H1w0g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC8iIcWyJTxEXVw/mLccp+QCOts9M/gz49OPADijvJocAIhAOsRwfy+xhzS4mu6wdbjhhDXhr93P+vp/doLTmLqXPcf"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_1.4.0-alpha.caa0578b_1531696965515_0.7117436429172135"},"_hasShrinkwrap":false},"2.0.0-0":{"name":"tinspector","version":"2.0.0-0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"postinstall":"tsc","test":"jest","prepublish":"tsc -p tsconfig.build.json","publish":"np"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^23.3.12","@types/node":"^10.12.18","coveralls":"^3.0.2","jest":"^23.6.0","tslib":"^1.9.3","typescript":"^3.2.2"},"jest":{"collectCoverage":true,"collectCoverageFrom":["src/**/*.js"],"snapshotSerializers":["./scripts/function-snapshot-serializer.js"]},"readmeFilename":"readme.md","readme":"# tinspector\nTypeScript type inspector\n\n[![Build Status](https://travis-ci.org/ktutnik/tinspector.svg?branch=master)](https://travis-ci.org/ktutnik/tinspector)\n[![Coverage Status](https://coveralls.io/repos/github/ktutnik/tinspector/badge.svg?branch=master)](https://coveralls.io/github/ktutnik/tinspector?branch=master)\n\n## Description\ntinspector is a type inspector library used to extract metadata of a JavaScript type (Function, Class, Module)\n\n\n## Simple Reflect\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass MyAwesomeClass {\n    constructor(id:number, name:string){}\n    myAwesomeMethod(stringPar:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    constructor: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        ...\n    }]\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"stringPar\",\n            ...\n        }]\n    }]\n}\n*/\n```\n\n## Reflect With Type Information\nTypeScript provided design type information by using decorator. \nTo get a proper type information on function parameter and its return type \nyou can use noop decorator (decorator that does nothing).\n* To get type information of constructor parameter decorate the class\n* To get type information of method/property decorate the method/property itself\n\n```typescript\nimport reflect, { decorate } from \"tinspector\"\n\n@decorate({})\nclass MyAwesomeClass {\n    constructor(id:number, name:string){}\n\n    @decorate({})\n    myAwesomeMethod(stringPar:string): number { return 1 }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    constructor: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        type: Number, <--- type information\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        type: String, <--- type information\n        ...\n    }]\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        returnType: Number, <--- type information\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"stringPar\",\n            type: String, <--- type information\n            ...\n        }]\n    }]\n}\n*/\n```\n\n## Reflect With Decorator Information\nUse predefined decorator `decorate`, `decorateClass`, `decorateMethod`, `decorateProperty`, `decorateParameter` to add \ndecorator informaton that understand by `reflect`\n\n```typescript\nimport reflect, { decorateMethod } from \"tinspector\"\n\nclass MyAwesomeClass {\n    @decorateMethod({ type: \"Cache\", cache: '60s' })\n    myAwesomeMethod(stringPar:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        decorators: [{ \n            type: \"Cache\", \n            cache: '60s' \n        }] \n        ...\n    }]\n}\n*/\n```\n\n## Reflect Parameter Properties\nTypeScript parameter properties information erased after transpile, so you need to tell tinspector \nthat you have parameter properties by decorate class using `@reflect.parameterProperties()`\n\n```typescript\nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass MyAwesomeClass {\n    constructor(public id:number, public name:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    constructor: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        type: Number,\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        type: String,\n        ...\n    }]\n    properties: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        type: Number,\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        type: String,\n        ...\n    }]\n}\n*/\n```\n\n> `@reflect.parameterProperties()` assume that all of the class parameter is parameter property, \n> to exclude parameter from transformed into property use `@reflect.private()`\n\n```typescript\n@reflect.parameterProperties()\nclass MyAwesomeClass {\n    constructor(public id:number, public name:string, @reflect.private() nonProperty:string){}\n}\n```\n\n## Reflect With Inheritance\nTo get the proper metadata information tinspector will traverse through parent classes.\n\n```typescript\n\n\n```","licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.0.0-0","dist":{"shasum":"a819c2bfb89922aa4a809706d93599290cedf043","integrity":"sha512-VtaBO4auThy21dy6xSwM6LzRh8bi1bSpyEp/jKMpEIfBBMADAbQiaiQ0Uwy47gk6LmYz55DK54H+L3ZUTMBWow==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.0.0-0.tgz","fileCount":7,"unpackedSize":24198,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQO9BCRA9TVsSAnZWagAAFrkQAJCxycCrzPtI3qTOr4tq\nV86kEwe5R7m0L2KQgE8IIkkLbt4W8d+AE56I6ksdNYEJRtxCUSr6bfEMD5Ed\nuhWVTM9c109KE6IIEIY6w8YkciUZHsW1i/k0vs3f8g9tScBHGsOnvmL2ovhL\n/RlvqLFbtLAaN/oC/sXMDnSJddx0Hb88yoM16BTbm5ooiTFUG/5lXXo4+8Nu\nnZ0IRBduMLHsZMY2s3Y/8CNI4gqdMFi0cbNyCp0/L44CinlpsNwJr58c9IyT\nuLjOJbJNKBZGHe6DL6HuM3PYZ5dViCnOXR1P7adKpEoNjRh4Wq8llhYtMejY\nfMHNkX+3FXOrijq/lGHRANvbk12J+HUUeeB5pm7o8xy3Sz5XIvzVw3Bxq+0b\n27V0n/QB2WrNUgeii6OhvibUqRp3nFREzexkOicfAkSPXXNTM+nlCYeqgZd+\n6fXrhKXN+qtocr/MYYKZjMMrG2rq02IyIArAUV+qefDRbriRNrwnXV5sAaD0\nNOQcxmJYOUgQZIKbRgpO03aQASGsW87qNbJ+8ghYbSe5ivUUYJ3G69rjLnIg\n+4qzfZHEKxRP+FM4duMAwHAahK0C3IiXGHK1dM1lKclp+++s2Yf/RzpoHIOU\neIG+q74zCoYOm581Ue8/z3wstc2z0rLjiBVGGRQZzZItleLBEU01btN+JrbH\niSh3\r\n=pYnS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAFleEmQI2fo47sll8A2d09GzT/DJcsfq0xn/Dvl9GtNAiAzOioPqH35HNp3TogTBX9aCslmERFl1UcbtYmvsDLrsw=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.0.0-0_1547759424971_0.3009353463108859"},"_hasShrinkwrap":false},"2.0.0-1":{"name":"tinspector","version":"2.0.0-1","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^23.3.12","@types/node":"^10.12.18","coveralls":"^3.0.2","jest":"^23.6.0","tslib":"^1.9.3","typescript":"^3.2.2"},"jest":{"collectCoverage":true,"collectCoverageFrom":["src/**/*.js"],"snapshotSerializers":["./scripts/function-snapshot-serializer.js"]},"readmeFilename":"readme.md","readme":"# tinspector\nTypeScript type inspector\n\n[![Build Status](https://travis-ci.org/ktutnik/tinspector.svg?branch=master)](https://travis-ci.org/ktutnik/tinspector)\n[![Coverage Status](https://coveralls.io/repos/github/ktutnik/tinspector/badge.svg?branch=master)](https://coveralls.io/github/ktutnik/tinspector?branch=master)\n\n## Description\ntinspector is a type inspector library used to extract metadata of a JavaScript type (Function, Class, Module)\n\n\n## Simple Reflect\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass MyAwesomeClass {\n    constructor(id:number, name:string){}\n    myAwesomeMethod(stringPar:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    constructor: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        ...\n    }]\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"stringPar\",\n            ...\n        }]\n    }]\n}\n*/\n```\n\n## Reflect With Type Information\nTypeScript provided design type information by using decorator. \nTo get a proper type information on function parameter and its return type \nyou can use noop decorator (decorator that does nothing).\n* To get type information of constructor parameter decorate the class\n* To get type information of method/property decorate the method/property itself\n\n```typescript\nimport reflect, { decorate } from \"tinspector\"\n\n@decorate({})\nclass MyAwesomeClass {\n    constructor(id:number, name:string){}\n\n    @decorate({})\n    myAwesomeMethod(stringPar:string): number { return 1 }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    constructor: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        type: Number, <--- type information\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        type: String, <--- type information\n        ...\n    }]\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        returnType: Number, <--- type information\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"stringPar\",\n            type: String, <--- type information\n            ...\n        }]\n    }]\n}\n*/\n```\n\n## Reflect With Decorator Information\nUse predefined decorator `decorate`, `decorateClass`, `decorateMethod`, `decorateProperty`, `decorateParameter` to add \ndecorator informaton that understand by `reflect`\n\n```typescript\nimport reflect, { decorateMethod } from \"tinspector\"\n\nclass MyAwesomeClass {\n    @decorateMethod({ type: \"Cache\", cache: '60s' })\n    myAwesomeMethod(stringPar:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        decorators: [{ \n            type: \"Cache\", \n            cache: '60s' \n        }] \n        ...\n    }]\n}\n*/\n```\n\n## Reflect Parameter Properties\nTypeScript parameter properties information erased after transpile, so you need to tell tinspector \nthat you have parameter properties by decorate class using `@reflect.parameterProperties()`\n\n```typescript\nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass MyAwesomeClass {\n    constructor(public id:number, public name:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    constructor: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        type: Number,\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        type: String,\n        ...\n    }]\n    properties: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        type: Number,\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        type: String,\n        ...\n    }]\n}\n*/\n```\n\n> `@reflect.parameterProperties()` assume that all of the class parameter is parameter property, \n> to exclude parameter from transformed into property use `@reflect.private()`\n\n```typescript\n@reflect.parameterProperties()\nclass MyAwesomeClass {\n    constructor(public id:number, public name:string, @reflect.private() nonProperty:string){}\n}\n```\n\n## Reflect With Inheritance\nTo get the proper metadata information tinspector will traverse through parent classes.\n\n```typescript\n\n\n```","licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.0.0-1","dist":{"shasum":"000468b23eff9440d8eac12ce147b3b26814e2de","integrity":"sha512-28jQ8U+mYReKmcFeOWx1V+7rOyu70j/OsJT2dJCpSEu0KhtWsyvk3FLgPS11kkF8cz9zNqilYyWjlFvRdgfkvA==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.0.0-1.tgz","fileCount":7,"unpackedSize":24171,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQPcDCRA9TVsSAnZWagAA5W0P/jLT+RolkjcM1FRSiwOE\ndtCLBNxqRw6HWf0LmmxuL4l7vL4ltoNGXmgJ/KoScHW/6ohjSBEGT17nH0Mt\naJ4CrBM1wmYoEexKxDBf+xdM7AV5IAyVy7VWaXQo/zzT8yWi2s0nd8Y9cm5m\nACwSDE3+mbU19U1N1ddjOpzGX0gGNmV2L6L2okM8CCFgiEtIgVHsmMV0PwVn\no/W+ZrX/6MiIBJkdCazrV1fxajHVYTz40CoWikHc4R+JIR9QC5+3agRPZgej\nygqmHbdqQ0g8Nr6J8Vp6o0hDIWtVtxlurtbMppEEffXskQinQVN5fffpGmx3\nAnpaDhwDRCK3dyJ6PkG2JJlcuovcVlJyz7Ef9oEMUiWtoYz/+EOrqwsGtAVh\nlMvi+20WO1y24KgeC5i1HGyBvO395YqNxfOdUh1xVwwXps7O5+Q/YO9G5p69\niDn3JKjyOoDNG6krdV+GA8swXio9Xyf1FjR2LoV9ePfpr1O2Om776QmHlNDI\nQ6/iW0U4q7dhzwW6DF2ManJDTHEdOl5pknu/OKiGEugwVtUpcRYzq1sFmoQh\n1u1vqsiccIqf/5OBYKTtfOcyx2zyBegFQ0wOawAcAvNlvVRiSAHkAjBInFoc\n0MQREpZTEmbMzZRSY0HN7Ggctu38Gw0eOEFbEc1glMNCK1eFt2/WoYWYzfzz\nB1ik\r\n=EO+Q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHmcj3U4GrpQFsoDqO0Lb4fTX4N0h5fsMOEGG6OjpP8+AiA7hSc4iXKyp1Pzcuk8NRiyunYT+nE6yNjFmTDgOPi+dg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.0.0-1_1547761410580_0.5594089402392957"},"_hasShrinkwrap":false},"2.0.0-2":{"name":"tinspector","version":"2.0.0-2","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^23.3.12","@types/node":"^10.12.18","coveralls":"^3.0.2","jest":"^23.6.0","tslib":"^1.9.3","typescript":"^3.2.2"},"jest":{"collectCoverage":true,"collectCoverageFrom":["src/**/*.js"],"snapshotSerializers":["./scripts/function-snapshot-serializer.js"]},"readmeFilename":"readme.md","readme":"# tinspector\nTypeScript type inspector\n\n[![Build Status](https://travis-ci.org/ktutnik/tinspector.svg?branch=master)](https://travis-ci.org/ktutnik/tinspector)\n[![Coverage Status](https://coveralls.io/repos/github/ktutnik/tinspector/badge.svg?branch=master)](https://coveralls.io/github/ktutnik/tinspector?branch=master)\n\n## Description\ntinspector is a type inspector used to extract metadata from JavaScript (TypeScript generated) Function, Class, Module\n\n\n## Simple Reflect\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass MyAwesomeClass {\n    constructor(id:number, name:string){}\n    myAwesomeMethod(stringPar:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    ctor: {\n        kind: \"Contructor\",\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"id\",\n            ...\n        },{\n            kind: \"Parameter\",\n            name: \"name\",\n            ...\n        }]\n    },\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"stringPar\",\n            ...\n        }]\n    }]\n}\n*/\n```\n\n## Reflect With Type Information\nTypeScript provided design type information by using decorator. \nTo get a proper type information on function parameter and its return type \nyou can use noop decorator (decorator that does nothing).\n* To get type information of constructor parameter decorate the class\n* To get type information of method/property decorate the method/property itself\n\n```typescript\nimport reflect, { decorate } from \"tinspector\"\n\n@decorate({})\nclass MyAwesomeClass {\n    constructor(id:number, name:string){}\n\n    @decorate({})\n    myAwesomeMethod(stringPar:string): number { return 1 }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    ctor: {\n        kind: \"Contructor\",\n        ...\n        parameters:[{\n            kind: \"Parameter\",\n            name: \"id\",\n            type: Number, <--- type information\n            ...\n        },{\n            kind: \"Parameter\",\n            name: \"name\",\n            type: String, <--- type information\n            ...\n        }]\n    },\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        returnType: Number, <--- type information\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"stringPar\",\n            type: String, <--- type information\n            ...\n        }]\n    }]\n}\n*/\n```\n\n## Reflect With Decorator Information\nUse predefined decorator `decorate`, `decorateClass`, `decorateMethod`, `decorateProperty`, `decorateParameter` to add \ndecorator informaton that understand by `reflect`\n\n```typescript\nimport reflect, { decorateMethod } from \"tinspector\"\n\nclass MyAwesomeClass {\n    @decorateMethod({ type: \"Cache\", cache: '60s' })\n    myAwesomeMethod(stringPar:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        decorators: [{ \n            type: \"Cache\", \n            cache: '60s' \n        }] \n        ...\n    }]\n}\n*/\n```\n\n## Reflect Parameter Properties\nTypeScript parameter properties information erased after transpile, so you need to tell tinspector \nthat you have parameter properties by decorate class using `@reflect.parameterProperties()`\n\n```typescript\nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass MyAwesomeClass {\n    constructor(public id:number, public name:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    ctor: {\n        kind: \"Contructor\",\n        ...\n        parameters:[{\n            kind: \"Parameter\",\n            name: \"id\",\n            type: Number,\n            ...\n        },{\n            kind: \"Parameter\",\n            name: \"name\",\n            type: String,\n            ...\n        }]\n    },\n    properties: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        type: Number,\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        type: String,\n        ...\n    }]\n}\n*/\n```\n\n> `@reflect.parameterProperties()` assume that all of the class parameter is parameter property, \n> to exclude parameter from transformed into property use `@reflect.ignore()`\n\n```typescript\n@reflect.parameterProperties()\nclass MyAwesomeClass {\n    constructor(public id:number, public name:string, @reflect.ignore() nonProperty:string){}\n}\n```\n\n## Reflect With Inheritance\ntinspector will traverse through base classes property to get proper meta data.\n\n```typescript\nclass BaseClass {\n    @decorate({})\n    myAwesomeMethod(stringPar:string): number { return 1 }\n}\nclass MyAwesomeClass {\n    @decorate({})\n    myAwesomeMethod(stringPar:string): number { return 1 }\n}\n\n\n\n\n```\n\n\n## Ignore Member From Metadata Generated\n\n## Reflect Array Element Type\n\n## Reflect Generic Type","licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.0.0-2","dist":{"shasum":"7bc0a28c998e8114116c452540634276ee83707e","integrity":"sha512-BohDTaoJ0tbZGy5QGTB/p2s1L+4ii5/9V45QQ+FFdQ3xuyER3Pc5AhUePEI+ZlT4kttls0cJFHzIwh2st0hkJw==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.0.0-2.tgz","fileCount":7,"unpackedSize":24725,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQauFCRA9TVsSAnZWagAAJd0P/A6O7/cRiVbwW2Tturcx\neMgtJlLMoYJXPTU3njD87I2epsjTtHF1aR7GTpFSmc8La9k2/OKgTSqZFn1p\n4pOI3Z1EzntjRiEwD2tw4k82HwZ8+PNrzUZgAOKGxRPQea1shzgtAFzU3qqF\nusT/d77MWcW3TAkX5UWBv0YuNhkXKk5jO03DOZ2oLgWe4wLLQFTvjY5OZw6I\nRYgkkRT0S6fHdnleyhGjFd6lB8VmUXuXWm9cEvH/XiCJhWQfkFPMG8sLljYw\n5+jPT4qT2Q4LTQAFk4BRZtoXH47Mt8rOgajXzfzGsRSFGRmqLFN/5K7xvD1J\ntOiBnO3vmtKiGey3Nhjpn4mmD2qeIF/pYIjBuFDP5Azh+G5WznJU1qDyuNHe\nnKVsNABsys2sIeZSxSHjNbV73Lk7fhAhf4c8vqCrPYAVAROodLb1V/dkgGSH\nWG2FMolhGPlBMcqnFPZay7xrzsNhwaKLg+v/K1FY9dtMUNyrQA4r2MxRUcKv\nBuX09B/l1VI0UbHx6k8YTCgaqdX/YgZCQqPPSkzzLKf/b9aqkFm7QHwVReIQ\nyqFFF9QBtaQJ9QO5PlKG1cq2FJ6PMj/k+rjG9c1RvSbg+FH/7VkiuXhu9EVE\nMF/3xC7U91oJhMutHNgElobk/tdbzf+3MKSlvXbJG04OKuTtgQW0tAmOQ1lW\n2scF\r\n=gI7F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDHMHu+4i1o8qmaAI/1dJz4N8jB7nB7dyyNpmQAYqWoHAiBMPsACogmNZWWPNdQRqkv4pMbr/NCAyLCvXhZLiUUvpA=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.0.0-2_1547807621223_0.17429675708675463"},"_hasShrinkwrap":false},"2.0.0-3":{"name":"tinspector","version":"2.0.0-3","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^23.3.12","@types/node":"^10.12.18","coveralls":"^3.0.2","jest":"^23.6.0","tslib":"^1.9.3","typescript":"^3.2.2"},"jest":{"collectCoverage":true,"collectCoverageFrom":["src/**/*.js"],"snapshotSerializers":["./scripts/function-snapshot-serializer.js"]},"readmeFilename":"readme.md","readme":"# tinspector\nTypeScript type inspector\n\n[![Build Status](https://travis-ci.org/ktutnik/tinspector.svg?branch=master)](https://travis-ci.org/ktutnik/tinspector)\n[![Coverage Status](https://coveralls.io/repos/github/ktutnik/tinspector/badge.svg?branch=master)](https://coveralls.io/github/ktutnik/tinspector?branch=master)\n\n## Description\ntinspector is a type inspector used to extract metadata from JavaScript (TypeScript generated) Function, Class, Module\n\n\n## Simple Reflect\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass MyAwesomeClass {\n    constructor(id:number, name:string){}\n    myAwesomeMethod(stringPar:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    ctor: {\n        kind: \"Contructor\",\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"id\",\n            ...\n        },{\n            kind: \"Parameter\",\n            name: \"name\",\n            ...\n        }]\n    },\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"stringPar\",\n            ...\n        }]\n    }]\n}\n*/\n```\n\n## Reflect With Type Information\nTypeScript provided design type information by using decorator. \nTo get a proper type information on function parameter and its return type \nyou can use noop decorator (decorator that does nothing).\n* To get type information of constructor parameter decorate the class\n* To get type information of method/property decorate the method/property itself\n\n```typescript\nimport reflect, { decorate } from \"tinspector\"\n\n@decorate({})\nclass MyAwesomeClass {\n    constructor(id:number, name:string){}\n\n    @decorate({})\n    myAwesomeMethod(stringPar:string): number { return 1 }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    ctor: {\n        kind: \"Contructor\",\n        ...\n        parameters:[{\n            kind: \"Parameter\",\n            name: \"id\",\n            type: Number, <--- type information\n            ...\n        },{\n            kind: \"Parameter\",\n            name: \"name\",\n            type: String, <--- type information\n            ...\n        }]\n    },\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        returnType: Number, <--- type information\n        ...\n        parameters: [{\n            kind: \"Parameter\",\n            name: \"stringPar\",\n            type: String, <--- type information\n            ...\n        }]\n    }]\n}\n*/\n```\n\n## Reflect With Decorator Information\nUse predefined decorator `decorate`, `decorateClass`, `decorateMethod`, `decorateProperty`, `decorateParameter` to add \ndecorator informaton that understand by `reflect`\n\n```typescript\nimport reflect, { decorateMethod } from \"tinspector\"\n\nclass MyAwesomeClass {\n    @decorateMethod({ type: \"Cache\", cache: '60s' })\n    myAwesomeMethod(stringPar:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    methods: [{\n        kind: \"Function\",\n        name: \"myAwesomeMethod\",\n        decorators: [{ \n            type: \"Cache\", \n            cache: '60s' \n        }] \n        ...\n    }]\n}\n*/\n```\n\n## Reflect Parameter Properties\nTypeScript parameter properties information erased after transpile, so you need to tell tinspector \nthat you have parameter properties by decorate class using `@reflect.parameterProperties()`\n\n```typescript\nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass MyAwesomeClass {\n    constructor(public id:number, public name:string){}\n}\n\nconst metadata = reflect(MyAwesomeClass)\n\n/*\nmetadata: \n{\n    kind: \"Class\",\n    name: \"MyAwesomeClass\",\n    ...\n    ctor: {\n        kind: \"Contructor\",\n        ...\n        parameters:[{\n            kind: \"Parameter\",\n            name: \"id\",\n            type: Number,\n            ...\n        },{\n            kind: \"Parameter\",\n            name: \"name\",\n            type: String,\n            ...\n        }]\n    },\n    properties: [{\n        kind: \"Parameter\",\n        name: \"id\",\n        type: Number,\n        ...\n    },{\n        kind: \"Parameter\",\n        name: \"name\",\n        type: String,\n        ...\n    }]\n}\n*/\n```\n\n> `@reflect.parameterProperties()` assume that all of the class parameter is parameter property, \n> to exclude parameter from transformed into property use `@reflect.ignore()`\n\n```typescript\n@reflect.parameterProperties()\nclass MyAwesomeClass {\n    constructor(public id:number, public name:string, @reflect.ignore() nonProperty:string){}\n}\n```\n\n## Reflect With Inheritance\ntinspector will traverse through base classes property to get proper meta data.\n\n```typescript\nclass BaseClass {\n    @decorate({})\n    myAwesomeMethod(stringPar:string): number { return 1 }\n}\nclass MyAwesomeClass {\n    @decorate({})\n    myAwesomeMethod(stringPar:string): number { return 1 }\n}\n\n\n\n\n```\n\n## Ignore Member From Metadata Generated\n\n## Reflect Array Element Type\n\n## Reflect Generic Type\n\n## Custom Decorator \n\n## Merge Decorators","licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.0.0-3","dist":{"shasum":"2c9d570a6790de53c421f702e9a6dfd592b6cab4","integrity":"sha512-IrTZlZ4oqN7IwKMGD91xDKiILZyunvuv+/BoI2DvoQX4LXOtbHRu5I5ikzobN53qCr1vwu6jLkE8aFZnOYgI8A==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.0.0-3.tgz","fileCount":7,"unpackedSize":24998,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQcJaCRA9TVsSAnZWagAAuiQP/2K861Ri3KSBZbj8fTVr\n6jpmSirLDz4eOsIS7iBob6OlB4h4I3tbk7r0R63g3BfS+/wnOzTB+UihWXAa\ncFpILgIdEywpqSciFkRT+J6Z/DM0OJmvX1TxMY6rlP6pMpo5YTotAvEngUFJ\nz5JN+rYN506UWYAgmCYIC7OlgVPQX+ylo1GKEbwxlka8wlFAFJuH+aEyxi4s\nPsYlCtwdueriZ6pw2omtQdT5u3gzyJtF/RUXDWQ1Su80XZOSA6Og2Cu0ZZ3J\ncm7cTjpunMJqueD7f6aYa6ySxA1V+fzY5NrdGzvLR/YokGB3g79qGeIlZTIU\nqEFiChASAXlFtWrHP+ipHYAYS4bksxyQFrqjQV85G/BYFaMKTHwsWhhv5ePh\nWTRpypJhjuBkCjlWaWymUVm27WsVkqHndMQ/x2q4xnExQjcqUNZlttJ5RNnb\nG0b9Lbu8nNhrSobTtZnALzGd6fjWIklc2Ww2g3Jrqb4GXYzRkx7FRB5X9qnl\nziCIUo/DbeMk7krnME/OBMllfxxHwrlNUry4Beh6sg+5UghgRK3BQVdQStGd\n+Af/VhNFjqOhQzQ8SNZB8OUBaTGOUvcUmPTYGc6yhvmlDmWDNaqt5uJizXwy\nDM42qLJZ+EiKtDBPxRtGRUS9GRoAwygXguN2/xCKeXC3SK8e6Qzr0v2AeJ4f\nEiUq\r\n=mAfK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICneMzs6ZVlcXtS1AgMD3xEmloHmWyH/ZqWQLBAPQ9kbAiEA0WKHfsf+yztEl9KXv21Izj7u9VocFSL8n9GFpR5c6Xw="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.0.0-3_1547813465738_0.5378026949775421"},"_hasShrinkwrap":false},"2.0.0":{"name":"tinspector","version":"2.0.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^23.3.12","@types/node":"^10.12.18","coveralls":"^3.0.2","jest":"^23.6.0","tslib":"^1.9.3","typescript":"^3.2.2"},"jest":{"collectCoverage":true,"collectCoverageFrom":["src/**/*.js"],"snapshotSerializers":["./scripts/function-snapshot-serializer.js"]},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.0.0","dist":{"shasum":"65ea60668857723ce81b1f78977c4a5e31e6636a","integrity":"sha512-oqV1vOKJxAZpf5qrDc5u8PDd5jhVrI527/BcPsPsh74XH3SMadnhBGSiOGb+kOSSxdWdsYW1/L32/lXkoCjwug==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.0.0.tgz","fileCount":7,"unpackedSize":24996,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRWE6CRA9TVsSAnZWagAAJwwP/0mKDqcHA3GYeGMcKr6n\niUxx0CtUcLhjEf/RLm2ac+HSbV2SZ/qNNhJWM8KKFZqUebkhaGmE0i2h475E\nJRr3Pl4nPe7qL6ZZuSthAZkqFAGq+0N6UpLJt49gckXDuK7D1ECVl8fjnNTh\n7WxlqPXQgbnG41TB9SdP39ikT1JOP59yVZZa6VsAU3vKFsyQPFzQ/qmwpxsl\nRKlzfY2pJYDmCTQLMTCvNXYDVydOx/MsgtHouIlb72zHtAMVxFRQdDdXslbW\nH3k/lSHbromngiq5t99W4/j9F8q0RPAq+dVHuaLPQ2yWHMOj/j043UYQNT7a\nYF2/8WlePG/NPTckUHGCCpLYetmr/hd2U4QCgT8b+Dv33Mhm7JVatilOFQxD\nnU/Cs0tWsgImQqOF/0LhwogFngu9HJmg4Zy6YX5+GRC10tcMwS52NkiF7UhS\nkPpxbaItKbHZ65lzd855zdM3KFlqsn4c6yTYgp8Yk6rz0CGL9RJIq0Cl3zmB\nlNgYeEZBxGCezV0M9S/lz2kil7c7PxGePLxzT7kgSSTGn2d8rQNrPeSa1RP2\npU+i0ywhNPwf90SEMAX0wDQj/E0vslzuIU7Ktvqc5vePnk+xeRdIBYUVW1/7\n+zg6/X42qBkuUcewhqNwAwZxPY6OF2olstNEdJSga+xzgb8L9mZwxw6nd4eA\nuisU\r\n=eStB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFuhd1UUcdJ02HsXj5GsaFxtl27zWSHu3QDaF9y4BfKVAiBOndbb2YJv/CXC0sriRNG4hi/tLDtATuSdgEjixqq9mw=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.0.0_1548050746307_0.3264232754048053"},"_hasShrinkwrap":false},"2.1.0":{"name":"tinspector","version":"2.1.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^23.3.12","@types/node":"^10.12.18","coveralls":"^3.0.2","jest":"^23.6.0","tslib":"^1.9.3","typescript":"^3.2.2"},"jest":{"collectCoverage":true,"collectCoverageFrom":["src/**/*.js"],"snapshotSerializers":["./scripts/function-snapshot-serializer.js"]},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.1.0","dist":{"shasum":"fe991f0e3c26600f8f18cd3b0350feab7a8edcab","integrity":"sha512-vtHbQvOPcmeFvGBFZrIs/oXt8ZFmSU1pyjGOvfRxu6/OPuxFff6I77mpDgpClN4OKNl+7csNAN4nMSCeO1vSew==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.1.0.tgz","fileCount":7,"unpackedSize":26026,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcUVLUCRA9TVsSAnZWagAAdTIP/jSlcWFn0/IUtj+wnjPZ\nlKqBJES5J8q9XkImu2jAbEXOQCnt8DVJ7WyKqTe61bJO298zss41Uly7xKZL\nc0yAnHfestQboxCJUqTe73MOmRpDBGPDpehtnfXTNNcR5jfm76cK45iT4U7B\nxVk39R9EUKQjaQCPJ+Kr6ilRRqhZUteO5WQt1e2IDdp4Xn472xYekoQl+/2z\nulIJnRqQlMZPMHggE+YEs2xDHRUF5+QXDg+eqjUkaKMazl9eEDHdHJU+b6+6\nA/4fHvbCT85E+aCp2nXBO6/wvY64h0fJIlqY/jsEhRIrsfO4U4VGBW9W567s\neM3EqneARs8xt7tBg2BO9pBhqCpQYBTgteUpgBz/DlcFhiErHft4o5Akp/lS\nhItyDD1CUiObxWA8+BiN+Q6qtZYT/iB2erWL/e09YRj0v8Biq3h7+MXodXNV\nDT0PMMFd11Fi/jjBNabaOHFfpTJzrIbsIiYaNoQ2iCFqNPPe2ucCnPnDnDlC\nzq0FG2oy8qwC6gFkrZdYuGTK6n6VscL88N+RtaMT/a03HRKp//UyV/mxA1el\n/A3qrDtKLqHkSdOCzNeKalWK9H4KOogzo2t3Mse+hDWZl3+L7k4K37sQ5Bt8\n46RhGhlSMg8tnR1Wc11sw0ZOVNlV+prnpDiLKCvi4uAdSgR3UM9PgW5SD77h\nhRze\r\n=fhft\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTtBm6Cexm5E/rIarQmvgzAayRxPPjTGyG5uwdsFEB/QIgUFuHPRT4jFRh2ULwBM/R94rw5ttnpfe6lzqBoqSMYqs="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.1.0_1548833492278_0.056077513285266"},"_hasShrinkwrap":false},"2.1.1":{"name":"tinspector","version":"2.1.1","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^23.3.12","@types/node":"^10.12.18","coveralls":"^3.0.2","jest":"^23.6.0","tslib":"^1.9.3","typescript":"^3.2.2"},"jest":{"collectCoverage":true,"collectCoverageFrom":["src/**/*.js"],"snapshotSerializers":["./scripts/function-snapshot-serializer.js"]},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.1.1","dist":{"shasum":"46ecfedddd24342abfe9d7d39b577e356607f1a6","integrity":"sha512-LM+daWrKJuZ8nEJLB3bmpdTXVQB6E4NyJIHRU6DfLvyfvnZq2NH42jieDKeNc4ongSBo6gp5r+HmDKPTXqJNxQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.1.1.tgz","fileCount":7,"unpackedSize":26061,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcUYOPCRA9TVsSAnZWagAAJocP/2XSAz4+4eWqP4P3pQLL\nLIyZM8YRS+6BdVcfzyR3dQ07LemInb9Nh4ACi74Pa5JQ5YYObDpm1BQqPZcr\nZLufM3k+imEzYB3hDmK6NtltDSnHGbshja9CYvsIbhPYOZBiVvdVNlQE6DR1\nLpF8w6GH7UHT8K6pdbYpDnTU5VntryPWb0jej83EP7zzmeggrsGF3d50tgm2\n1uqAGHYohnOakQ0XyAJ7HBSOhMQVAoip1MpurnGZwPDxRACL93MwqPDna/eF\nK/HV0sMAK5EExhIp4xb+GojG8o/hFLdDZ0JNDHQJC4hvo9nyIEs2feins2EB\naKhEjYVQrtelUW+atrAH34qhf/9uVI7H2nanjmU4GwChRwuAwAxbQgCzNgp+\n6/BVdk1tMFq+OWe/cy1zXSeaUL+ojOP3F6JIglMkzVBiwxGq6EXzWn1pZJQx\npujZXd3l/CM0ic2+Ok+7yjpDJAnsyzlbRBcRKDpVOptqVk/JwhtXWgtbPJHd\n//LAELnNoZF40QZbDcvECt+UG4th9JrhSiWuYb3kYO5oocyMPAlFn3SmIakM\nQNJCcvgQN1lAFliKJwXnWVm7G8tG3cHMsOU36EkD70GSaUifdKdY0o1DKVyx\nYBK77i67i6D5FMLAV78Sp2BeJ6btJ2T68m0GJULPLf4Rhu6vpFK1iBrtA63V\nzW/j\r\n=0ucu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGVIyNubytLf40c3r3AyTZzGp9SDj+nV5GNI4efm2OwqAiEA+8DcDWKOY6ximWpqMzJAQ23m+bw+hgumThB+WHjAvRQ="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.1.1_1548845966578_0.3505019420049811"},"_hasShrinkwrap":false},"2.1.2":{"name":"tinspector","version":"2.1.2","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^23.3.12","@types/node":"^10.12.18","coveralls":"^3.0.2","jest":"^23.6.0","tslib":"^1.9.3","typescript":"^3.2.2"},"jest":{"collectCoverage":true,"collectCoverageFrom":["src/**/*.js"],"snapshotSerializers":["./scripts/function-snapshot-serializer.js"]},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.1.2","dist":{"shasum":"17a6b9f1b8494f5163aea2e1be1316c4d0c2848a","integrity":"sha512-FwYTqWZIQYS8SlNa29pUNlVBYxfpTn1BiYFQm7AAYf3eWFvwNtdwqWXRWGj09Nbu1hgvCbtooF1M2ou8XOvl+w==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.1.2.tgz","fileCount":7,"unpackedSize":26079,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcVUafCRA9TVsSAnZWagAAEk4P/jMTbn2HEhP/cLTHWQ7c\nZo13My2gUxTM/SJGgIVsFYMIFx6IgSvQn+kEDfuJg8GKEYq8p6BwvDlxGaW5\nWfoNuuJ0LcjNZSqnFB2dPqLtXMlDRNz++iieASTSVgiNnCWb9r/UOaWbNnGH\n42Xn77X2YAWGBvhtQfQh8UXvUuIQLFy5SsgMTL/t17+skgMz14q0gpZRG/zA\n6KWclrOWzQd9QjwJCe17fikk4bheSdAjqNqkiyp3b+U9ChDbcsPkw+BGuwRW\nhF7urmei479F66lkB3soww7id7cvliivLtyjvfT7f4Qw9fP7qr6WL7t+OcYt\ndBOK002dZticfFGKgDldf7LBb1SpDR4K0qWsYISJcLpxD/VpeDgYYi8LvwhN\nuF+UtCXgSuIe2HKIleU0bobjSQ+3Q/z3YEwbM3ouPR16gvh7bp7AOSlgq1Lq\nRRxINc0x9DjCorKWjclJ6CNf1TXuXYU4ci2W59mNe+0XSsTg9MxeTNGvtNEf\nUUT3/7dyvSwxcZiDUb/NiDi4k6E6/xvd1MiNCSJRiFGhs+8wH1Eax25uVfIi\nSexfgPKlu1CYxiXmZGPesh4iNqWUV7x8PSB1jz+GUJQroOXB0XUrq0c7MPo2\nGizVrVIPjGnRCnnLCtB2wsluMYmW6Pw4ZMp397Q0rJqbvO+e5MIu/BpCpvnQ\nBnvc\r\n=CHTt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA/A9j85q07BoDwWqgkZwXUSzP9xyedMCRZLuGCbbK2uAiEAj2SaT4yigdySvAOTjhHmNty4OWVZjbu8ggmiguBrV/Y="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.1.2_1549092510490_0.2563510966896976"},"_hasShrinkwrap":false},"2.2.0":{"name":"tinspector","version":"2.2.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^24.0.6","@types/node":"^11.9.4","coveralls":"^3.0.3","jest":"^24.5.0","tslib":"^1.9.3","typescript":"^3.3.3333"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.0","dist":{"shasum":"f981c3ab93fefb089035e985faa8925bed9a605a","integrity":"sha512-CiQIrNt1k3TZn1V3pwvPy01sK4Poz8FjMOmfy3lUKQwHghgnDAp/5M185+2w8/5Mk7JN1d4U5+J/0EUD1bplXA==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.0.tgz","fileCount":8,"unpackedSize":26860,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcjDZHCRA9TVsSAnZWagAA19wP/3vM9fIBqWrUmDq8vJEP\nlCxTZKygOBILQKujMZYgx/NFosmFFaeysGxB8q/Pg5wKEHw/Al2xwAt2Zvsc\n2HysiIWxroOjKu9RPcnLkNI/WJxwaSlF521snv9VXXzAlu+cTQLvQXPKh7kE\nL8o6LnUQSyrdjpQM1Gbv788gGBoJ+NS7JxcF9XBafx9J1cj8Ox1CZJcy3Tq/\n+UboN0tWJ+vl/nnPgX7I01R2mxV/afF/7mFBXA9PIZEPJo4BXfn9pE4mLBCs\nAO+qO12mX9Jr6q18/jqlisf2JKURA2RSrCFhbFwIFWrVfW4GOaVac66yCIuE\nFqSdS340EE7OuZllrd9xO8O3z4hfSWzX4bw4b6t5fuEArjtW/PDCCZeEImRl\nASVzKWEZdfcFA7oGQQPPSWExwTKakf75+bzd/SFZ/9dIp1r2O/iHnDhjPS0q\nYbIXkxBvNEBt6tXY3yfZg1AmvEbQ1z2/xTZycTPpyLLEIvQgxHVros8KgKBo\nYENSso1AKqyNlX6i16yGny0gj8aXN/gInp1fwQQrvzqt14YFwIThFOZR4nSh\nAtpavytyGPLDPvmi9CpgoaXUKZZ0kSoU7tLy4icVvZR64e83EZlI89Dxclko\nTFeFsvKbJImEHn/vrt6aA98ASPboYzjPp5JusplpSjrkrfU+4i1SfYk8APBc\nCdRm\r\n=90qL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCmNz2+KPurYt//2ZPada2sUzBGyrJ85POMlEvWr6vlDQIhAJySGVItry/sK0VhkV5GBN0FqQfZyBdlZZfOdxjbAws6"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.0_1552692806739_0.9513977407655736"},"_hasShrinkwrap":false},"2.2.1":{"name":"tinspector","version":"2.2.1","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^24.0.6","@types/node":"^11.9.4","coveralls":"^3.0.3","jest":"^24.5.0","tslib":"^1.9.3","typescript":"^3.3.3333"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.1","dist":{"shasum":"9ea41ab5e42d40267fa98a0f0e9a76c2ed79bd35","integrity":"sha512-K2BIQKbnW8qJK6PzBuWBrlob3gXbf5V8dgK7g1yHTodTJtQsc7ly1Yz9K52oilzGJ7OLVs71/ulIoyxAU9vkRw==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.1.tgz","fileCount":8,"unpackedSize":27231,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcobNMCRA9TVsSAnZWagAAwqIP+wffRuktY99KNlv2E9B/\nBBvb0PwvlAG9YnsaNwrMqX0O1zHUL+P+rU1sCMsNpp9oLcf/Ekgyzg2kWaG8\n+Mnqc40OoS2QxW/UKKntun44tOffxmVFyjESGiQh9cIZ4LbmozJqmNKgS4rf\nqxy/L3U6biMtHnoP7LSqOlIkYAoibLbL82EAIH0CYgo6S6Z1ZIWWxacjMmp/\nduFTSYugF+WDjydR0RaCf0eiq+YD3jL0DACKH3hHqA2xKOYFEojTP9ec6bW5\nbjGrd7nlwEaQirFEg5wlP5B+NPeMzWJLbjmr7cjNaW+DDIB3Kpz/o4KeKxUU\nV15vddqrfMQH8gpewb+KlvI0YWN767/K8mR4nuzbfA4VXG4YvSeN8CKkaz56\nlvLcEEfD97JQeLzQxjvjWzkcYIiEkMoSWrZY9RhL49IAzSwTqI5B6cU9RGfW\nag4ITGeiesV1OCYEgueV39fy7s7rK4Jba4BcuyLZ52LupEY6DBwmLfACLnqB\nOYu+vpB8Jjrr6UaoPKhcW4Wm17PFtiKPrCyZ9TaBnd4qUSuLYvQ9+MqTGFII\n+LkW/SgEpV8YR+ECKjJi74EQK09IaFLMN9yIY/NzDdPuKjkhPT1m3GJdiWjT\nud0erbc9q7NmrikR2vy3mvlHeux061L/9PdHnyFNbfNtPJTrRUZTNyUwDeWY\nwrGG\r\n=g4QI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG6/wzPVYMx4kuyy9Z4hQBXOV+j6tf6GRPnukeD14NQrAiA7xO/m5DOg/tDN1LdO6W6YU3YLoV7J5h0zUqiDdttatQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.1_1554101068136_0.9763120283645097"},"_hasShrinkwrap":false},"2.2.2":{"name":"tinspector","version":"2.2.2","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@plumier/mongoose":"^1.0.0-beta.8","@types/jest":"^24.0.6","@types/mongoose":"^5.5.6","@types/node":"^12.0.0","coveralls":"^3.0.3","jest":"^24.5.0","mongoose":"^5.6.1","tslib":"^1.9.3","typescript":"^3.3.3333"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.2","dist":{"shasum":"656483d8fc8414ab7c8ef8d0a8c371f1de6a63c8","integrity":"sha512-FiHNS6Xhnu5mpT+8W5BseAEAGfkUb3f9u1GbRqCoyuj6ysKDIQRUjRScnVRPpQCJDfM0tqpOuLIAvSxl1LLLMQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.2.tgz","fileCount":8,"unpackedSize":27368,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdEpwrCRA9TVsSAnZWagAA8fsQAKNNvfpVmu6sGLr1qNTr\n31bN/bHFgf00ZW4fzeDcL/fpKlBxqrBIkexf5Sk1trMuPQDR5H3n05AATqp/\nD2zlsyMZWi+/VyOXBPFUGcQgafjkaKJCoit16mS5maLI/LVZHGEbTiVi9fhw\nbJmOn1jfb4R7EF5jBZKi+CpCa8mSXrSJO/zqAttJotatVwKbVqWHXi5UXhtr\nPo5iTfFecDW240H/73sX4i1uqfsj7mHlEq0xl3LFAsbgMIBda7xIi5QN9spf\npKEidIT/FMpx6O5Cheef1+sK+czTecQSvHhZNNghpD7hPhGIYgL35/WNyPEd\n6gDhhtCylZoco5RKQ0ujwFrgC83hvATew9gYu08TMDtX8sn5zZsMdXUmhJM0\nuDW67pW8AqaAfEEZuMlfo86+GWWnB/2jQi/RQmN5Rr3xt3CWgJxxU0A7zjNP\nnHMl97EQEcWyXTzQCnxR5lCI8HFNSuYNzo92cbY9Ip4fMDwFLb8VSMXo5tka\nsEQ/Gxfk9IR76n9Kkjiy0lLxLj5XGinAghCqLxbdZ+fc9FF3kIO7gAg+MoR8\ncT+4UwUOZvYHF07PRleoOZduU3nTUpWw8J2kidZbIy2wh5vFjz0RQ8vC/zgw\nePu740p53r1h+fWbOO/tzHdsVlN0fO+Zj8aBpcqzarxMqtNpXu8fERKAlj4+\n6Tgs\r\n=sWkJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDo7cgS51NAhep17GNfT7N4Rb6S6CloZhUbEB0a763rtwIgXPTkV+dMAO/k5Fe5w8XxgHZS75YYGaBBLkTgT1DVG20="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.2_1561500714325_0.9453149485792851"},"_hasShrinkwrap":false},"2.2.3":{"name":"tinspector","version":"2.2.3","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","postinstall":"tsc","build":"tsc","prepublish":"tsc -p tsconfig.build.json"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@plumier/mongoose":"^1.0.0-beta.9","@types/jest":"^24.0.18","@types/mongoose":"^5.5.13","@types/node":"^12.7.2","coveralls":"^3.0.6","jest":"^24.9.0","tslib":"^1.10.0","typescript":"^3.5.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.3","dist":{"shasum":"1c8ff66eee90b7571c508371775f1e6e60483fe4","integrity":"sha512-ttcN5pr1SaliDIxNxwtzsOsusqPJUk+7LFhUMofCFSVYgsc40J26WshhMey7IKksUmTeFTE2LWM/5QZmjaWbGQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.3.tgz","fileCount":9,"unpackedSize":27825,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdfEJaCRA9TVsSAnZWagAA6noP/1Q3iUSJ6twIYDDhVy1x\nMjSwzInHKF0kxUQtKBBGSThbmI+3UhOapoSCeHcOa35e+LBX3dcKzIIE1c3q\nkC9WvTxjBceHHgIuE1S/pgOqSiL3dJU6RmDOwVUwWpRRjbhBBiyPioGide4s\nypxjYYH4BfJh6LifBhbj60sIShKuCUetBYFj9N+Wt57hYabnzKvOuR2Sqpzf\noG9fckmuKC3fXAquSsYfsPKj92zHja1A+KRvTH2T4pLFA8foRJpUS48tKjsU\n3TowsVF9x16qjeb+A0YOwwPSvXt2EMRbHIyTOMXBk2/S7KgxcgeVXGvbZcql\nDOORRIaPhnX8bbDC5KgCx5kxtlZjmUB5QkVSv8REsWPikLIyxFzYJGzf096d\nttwTKJDuKUavNbK8XD8FZV7w1Q4+oKvZx9I8waHWEdIvJ8O84VWN3Hz/EUG4\nDYSolz2uzghFxQ/JLrZoU3TRXSm803SoAiGd3+u6Vaw+m6qL9GdYvivf3+3w\n041DV5IVwzSdB98+nm8Ueo4HZCSmYo1UVvwh9VzqbsbEwCM9+GEmNOYc1Onl\n7slgUDvBA74c9/xlw5jBr3ck7MFS2HyDDJ15wVSmJppoBMx08E+oHnw+ii3p\ntiOvxvZZHdnD9wHbqsFF2X5E/rimo9rurwKSGGPnU6TjtK5lww9qjpjn+cHH\nt5pO\r\n=QZ9/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDDagKr5yiI2DHKIkWxBQiJjjP+GknqOsAwmi0Ub3dqjAiAdXWmGrkS8cNxIC5bV2aVp0IZH4NuM1aDArBldfJejSg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.3_1568424538112_0.8177914523455485"},"_hasShrinkwrap":false},"2.2.5":{"name":"tinspector","version":"2.2.5","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^24.0.18","@types/node":"^12.7.5","coveralls":"^3.0.6","jest":"^24.9.0","tslib":"^1.10.0","typescript":"^3.6.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.5","dist":{"shasum":"ed7ea74e3556f7b8d0f62409a8d0e39cfafcf0a4","integrity":"sha512-KPGq5QFcjfo6eOyJEQ6J+ViSSLKmydZr5eKFju43cc+MWDVaALNURp7I1tr88OoqiOUHJ6JcHzGMyqr7AHx6CA==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.5.tgz","fileCount":9,"unpackedSize":27792,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdiY1rCRA9TVsSAnZWagAAweYP/ig9fP9HljLHxAI/xnOr\nG+wRST8gtFDr/qI/9rfj0oMiK6IoRZ03LldPRb+GUDZJKHor0RUgsp404c+t\nt3UlEZCA8tz9tbL8eULkEx3b4KsoEjpQtCEUnA7414Ug91+amIHjNNQvJwvC\nqpLL3lvGoM2dBycfEKtwwJqDtOWkAfIGBtyF7OfGKW02KL1PXphA3cbhc05u\nE43HcN69DGShlM8El+2Vf8jx07/LZpyodFFvp9xLhfLXH4314srrV/zz40qP\ncbCbNM2noQgbvaoIOQkrQI526QXWbvbAfweUf9bslG9TRlfI/n9/MbUMWP0j\n4a45KAIBOGpFwrzX/m3I3HfRgeciJ4XV7Ded1ybQwvwRxtqNiEcW5V8bGjk8\nEZrVhEAO1jk8Tu3GmuOYnUgOfhPglaMzCnZsjTLrJF3yBWQnnHdV+zbGvQaU\nFcMQJBV3aXIDWBNE0iS8o6GidqQoRYavsZDam9bCrGInTFpaxJ3e+Cve4RBm\n6nDuKjE+HX39AbQA1zLZ3uqH41yUQ+MVdq6sgfw3mHsZ5d2/mhndwyjfw0oV\nKeeb5y/4G83gS1qGbZDm1WBERlJWR6LiVdqos3pZVuFxMDkKn/e+o6zuNTzy\nR1OlphfxY2yIM+E/z+SLCnlIq1iqGbFZfg066O2jVcE8WZo11K5BlBna8g0J\nM+KF\r\n=IgP3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFWF879Xz3KnzvSWpWAouyoIbE8QwH2SAT2RbeELCp+gAiEArCRssV5fSGrfcAMBcwF0OB+/SOApvGEAVMVcHmEpPwc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.5_1569295722540_0.8685097022025741"},"_hasShrinkwrap":false},"2.2.6":{"name":"tinspector","version":"2.2.6","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"postinstall":"tsc","test":"jest","build":"tsc","prepublish":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^24.0.18","@types/node":"^12.7.5","coveralls":"^3.0.6","jest":"^24.9.0","tslib":"^1.10.0","typescript":"^3.6.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.6","dist":{"shasum":"dfd858aa866296fafa19ce9f9a5273e52bb6d209","integrity":"sha512-WxqXm2FoUgcBcZdRQKtZsx4eDWERgZDO0DJXS7eimhWmKP3Ns34dOBeBeihxx0o/T3OlTHSn8C+eglJnHjS2mQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.6.tgz","fileCount":9,"unpackedSize":28632,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdlxTSCRA9TVsSAnZWagAAdiQP/2XGHwoH30RIqzkl83ro\n1FdlpJCyAIkJi28N/darmjKsvm9oU6ZuZCVP5zpYVD0wEM/25U6r190f1MUx\n0crVi9I4knEL98lUiLQnJicNZO3NL1dZSoxvJcuOnjgDChuzJDKrKI09hRxk\nG5Tv+701zt9g5kP9xvx2B8Y1M5S5olL3Uzni15/Bfop9TsGFPdJ718MRvF3X\nVybqSlvcJoerFh33JzswO9bVT8+K2c8o92d+0ffNrcUx/GnahWzzTrUAlAwH\nl43gkPR55Qu27qnB0seXBwZ8zSAhH8p8PZ+IIz1ODqVS9/sz/PI8GiiVwIDB\npxqxTKD4fvNB5J4DlV//gZOpYsk2aFoBhmuJhbAbXsuUidpM5hOArQM1j3R+\nsiBOZ8oVdKcxffvICDWm6p1pD+QShvMvl7qClciLjVmkYrYqSpWhXjVwBlNK\naNitBTMuEq7Zz/yvZLuZhbJI7PUN+UR59oSzJoP/zAbzm5UH7aJND1gfTQvm\nKvpXPOk3TN6UJNKTcKYw5NVPilhaOMQUXk8a1Og8VpB4WgZmG+R9v5WuqakV\n/ZGpfaqj2TcJEIUPi6bJj/K8pCEnzx1mZupdfTTgMjfWHDWP4eOhRytmHW+F\nWPs0CjwjYE4u2aKVvke+219T11nlc4B2QbHw9BT/DtQXEZC/MKn59hdPq2u5\njiUW\r\n=CKUV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCb+uLPFqs7ZWHtVlJJ8rqGBDaKJnwOyPICZSIHgiLqegIgQZLiZsfpBG4K/brX5gRF8h2rVa0hGjKKyYXxq7uld/c="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.6_1570182354336_0.03215372018279239"},"_hasShrinkwrap":false},"2.2.7":{"name":"tinspector","version":"2.2.7","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^24.0.18","@types/node":"^12.7.11","coveralls":"^3.0.6","jest":"^24.9.0","tslib":"^1.10.0","typescript":"^3.6.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.7","dist":{"shasum":"d01ea3108c87e38c4dc0fbb156d740d39f8d62cc","integrity":"sha512-OC7bbkM9XzDdD/AieTxgKmHj3Cv2c9MhHgifMeW5vHrXLS7Hl7sdhjtgotmvc2mfYvXXffnXs0VmVkFaoMmjnA==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.7.tgz","fileCount":9,"unpackedSize":28594,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdlxjmCRA9TVsSAnZWagAAEvYQAJDYY48Ew4pG+keiu2s8\nAhD8T+rp1INBR07Kc3TSZEW+MVKHmlYf17IYxivsvnJTs6YM/f3cKZLDijyd\nKMLiTBkp//yqVHIM0mgGzHygD8+0V0Yct6jk8JsmyR0NOGQm6Z2qh2cI6Icp\naqKDWSf7hwE5sJYIN1Z8IhiHZDPmlbVWMss14WNqWDTggX1OPIvnEJxCo2ij\ne2mjcauK53gT7fSXDoWBgFgSONzgt3k5YP7JK94rkrkR47bBhsWcvxYe3eSP\nyDyDkn2FP8rzWSYfYB7ScrXxsiazNdLH83Nm4v+DnNmiA0o70wqYgTEFXbbz\nUK5zOOzM8L5CObCMf4cenB0suxfv+PE6sPpKc2Fdyu56A4QW/5uahJknFKZL\nfSgg41Tj3hKpRTyn1jL0ep7FffcZNZ20XbjYK/CXgR1TgkGwUf04mxntnsL7\nzuEI4jiXT9cvd4aZn4EFzWzsn9Xy9J4AdIA+P6UMm+UBT8zFhzZPkSoERXIa\nMoizixp9XxIVOLbxmdxOC/CO2cMgwH9IfdMFplb7ojOOIAvoVFHl4YwhguYY\n/p33ASjeC666CDAqqabDZMpeqB9oV8yGsoxpXdn0aoStD4NB2rkB/PbreedN\n3oC4DMbu0hQ/WNmX+q9OUR/D9CJ5euOudZYM3RB5NJue88pv6CVqzYK5novD\n9IKf\r\n=nV75\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDTUB0+7aGCTrbbt76axxGSZOCrXq4ZYyY8vKj2/aXdAwIgMakpbxt0IpsVSkusPbVG8K+4YD8trQwSGYY1fBsT9YU="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.7_1570183398198_0.9330954188298095"},"_hasShrinkwrap":false},"2.2.8":{"name":"tinspector","version":"2.2.8","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.3","acorn":"7.1.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^24.0.23","@types/node":"^12.12.14","coveralls":"^3.0.9","jest":"^24.9.0","tslib":"^1.10.0","typescript":"^3.7.2"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.8","dist":{"shasum":"222744c50bdcebff9740bdefec78b444a816e133","integrity":"sha512-MWsawwPJxz3spe9eAvZ6D4oOVUAs4oUUZ7yM1+77tnDLvD+ii2t5kS/yzQ6wB+QSQ/VGGMjyj1PwyFijlqU4KA==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.8.tgz","fileCount":9,"unpackedSize":29804,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd41nFCRA9TVsSAnZWagAAQ7oP/0GOsZRDnUeQBjroXlmV\ncBoJ/l6YioklYkh82trl2jg6105ncL3UgB9aphueu/ibA5zvxkojSBZuUOUE\nfYHACxgjZ8Jvpsus5HtvnQHFzFbpVjB37HbgV3WzwLfBIXAyKbsmbAaPdLTs\nPSWW7TXGXss0ibLJxdD9A3foXsj7kQaOEPyMSrPeo1JT5tlMyNh946wQpL9L\nytcKqsy0v0Z1136Ir92J3pFjHSJnim/LEBptLT8b5bZRpfyriN+1JoNHAEBK\nRViZ3Rm/N7PS3NdcEC3GfELT/ZyfWU4nGj/YFqLSXLehI7XBnueB5j3AQomx\ngaESjjTuhT5TV1PYpunEqEjbcqS7+RdyZ93kTuQhqqQLU+AqBM5H7a86CThD\nfIeHO38HaRWK21eITUdUsSsV9ziDSyLuk8tCRRqHuRIAtl6n6Wg2HthxuhFx\n3an8WYL5xaWst3kBCEA0M6qCrbJXJOrstie9cede5W6fIzL/ScxnS0TZG1mz\nEZfsvXc+dedztz5b3GLN5eaghefjQk4vTa3SmZWBSh1/HCOyDdSHigamXjnO\nqkedCEgDCbrGdCohhfEMaaDoc4Buu/k9+j1w1thCKIpcxmBqBy00/oRWFcvS\nppGZx7CoyQIDWuysT8++3J0vL0lji5Rsrw1ALC2laFouOrYU7U312+5zG6rH\ngbf7\r\n=9fTp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/7g2e57cUJCHdui/zXRgmeEl02NS1ixrxijluR48ihQIhAK0NEZdJsbHMlx/fO70gLLTsDa4gBMrIrmIidY7Ck1Fd"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.8_1575180741171_0.9585173868285048"},"_hasShrinkwrap":false},"2.2.9":{"name":"tinspector","version":"2.2.9","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.3","acorn":"7.1.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^24.0.23","@types/node":"^12.12.14","coveralls":"^3.0.9","jest":"^24.9.0","tslib":"^1.10.0","typescript":"^3.7.2"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.9","dist":{"shasum":"b729f0d3402dc4ddf1609dc43275cd603a4bc8da","integrity":"sha512-N6P0ILq/HgcaO9+HCPDba7Lxr+zcRf2lRMQA83bAHNdKrDo3c+grPx996pZ9EUfOMzMj1EH7Vr8R1KhfFkpjNQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.9.tgz","fileCount":9,"unpackedSize":30160,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd5FpDCRA9TVsSAnZWagAAokEQAJ9F7OOLy1jeqFVDX0a1\nKERmLnS4Z3SyNA+8EJ95CyslYfWZWyThzI6E1B2o+rB1g7gHiyB5hIN1zLdU\no+1y6hDaSX/gllG0ia8Cu/w8KcppoSHwfGeb1BQyzGY1OlBPCsdV+dhXiwlp\nQttEZCeul+YVRabMTKEfIZiHj9bzwXisVVHAoyl8kI2I22wwkz0YBnZBM2FJ\nqMc6YksqoAK16AM2pkau7KpE7D2WBMyn45SYHYMwSfnOXoi/lIZngI2S77MX\nKtHq9Tmkd7DUsdKVYYKYOV+Xv6tD8Ak8Plf6sukVsRU9ne81YDkIJ7x80Hr4\nxfBcv7IGK5rv7WOcue0TziUwE9utEFw92TXdP49SmD+9r6DhXXy7EK16bf3o\n9oxDfco8QtUKN5gT3IGmWWWtIfoTONc36eVgsVkD0NJofwvstmscsmsNyCMz\nF3xrt2rN57h6PQ0S3hrr6dL0Wz6UTrH0rN6gAIM7bR9kzSIQxi6pCRj2+O2f\ntYaR2WOicucg/wVOQeuydtMBAvLg0ngU1HEBp/tPpPUZ0gGSaCCEMGQ6TCCV\ntAZH0hcIgLFWlt4wqZqIiU/YumW7/Vr90V5ko2DDWKSX2FtQAWMHkdA3cB7N\nQHrVcRVBqHVKRaa12TEkYHqRR/yuXDEuVyKHw4DIdRwGFbIp22IwN9NASN8v\nNOJP\r\n=4Oz0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCJKw8guqaHwikBq8h3ywusWIsD9gBOlXa7Wj1e53+rHQIgDKaOX3Uj1vdFh91pfEDzuPLSf53jgQtREqXijVMxZS8="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.9_1575246403394_0.33966557476447945"},"_hasShrinkwrap":false},"2.2.10":{"name":"tinspector","version":"2.2.10","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.1.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.1.1","@types/node":"^13.7.0","coveralls":"^3.0.9","jest":"^24.9.0","tslib":"^1.10.0","typescript":"^3.7.5"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.2.10","dist":{"shasum":"48d1cc001d006625c6a904fbff5695d5e38ac74b","integrity":"sha512-nMDEhl0LaBZG/W/Prqu/kx4b3OUoLoXjej5an+7fS22ScrordnvEu8IhjLTeu0iaj4WkryFK5Qsm1D7wpS/TTQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.2.10.tgz","fileCount":9,"unpackedSize":30212,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeOCiiCRA9TVsSAnZWagAAVJwP/iNICrjjL8rtYkH3LGKe\nNv/KRjKmfupDhWJ6rY/nwzJfaxkb5i88TFozlBnruxqmgZW/ewXPrmZvkSZu\nrCbUO8C06N7QxiqsJ9fWZtbGk1/vUfTj3Dz6VAqtNE8uy9a+aL29WXJYJ1KT\nRGoNSugasN1V7EBRZT8PyjhdCco/NFRV0ty59f3MyDzeJQsmZZzSh8GFkH/u\nALeqGTXovyGv+BgkLmfDD+Kh+TovJqfjSI0adKGvo5NiU+h9/DGYO/N087Ws\nQ/4lMIYBcbbWhgbnLa5ihTZxNhkiKLZw7BOHux/iXroJzxYgaCfLhAy/DKd3\ncFAfsD4CW1fYVgmVrpf/768TpE72AWkE9vhd2VtjRepk83TUoolMQdkHtceK\nOJ1V4NpcdEyDSG43Oo+bLR4t+PBhzv4Gr87Y44vGYLjjPXJjlYS068T84lt+\nnS7LjAqb6a8yEXEQ2RN22ifypr2GK3VdfnnhpZ/KQHHDIG5JFCKb/e8VrtI5\ng27WJpokm9gkPCcKmd/XicqVVbR8iRi0L1/+6K7rt7BV0PqGJCydHj7j8dYd\nl9NBu9LVkD4aHmJ1KRO4d13CXFrrWkJd+I02CGSm3YGCVOCaq5VKi+mRSZeT\n5x6HhO2mx7vhKsYpZBs4uNc1cfYfYXiwZraAeJwunGQfgyFRIUsCm1jTjAEE\n2090\r\n=1aWQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKmd3Cv4gmC42U4yUtZBa7RBIqLeMyb8mJgx8oHjLvOQIhAIsMxNljcDXIXOML1XvaYjBW3LzPdBRq0I+1IFLpWmud"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.2.10_1580738721932_0.10178799021014573"},"_hasShrinkwrap":false},"2.3.0":{"name":"tinspector","version":"2.3.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.1.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.1.3","@types/node":"^13.7.4","coveralls":"^3.0.9","jest":"^25.1.0","tslib":"^1.11.0","typescript":"^3.8.2"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.3.0","dist":{"shasum":"86acf16ef2a4e6a22293a7b9901e37042e1f55fa","integrity":"sha512-jPvb2hlB+fOroibkOEXoUj1JpkAclF/gnKmem6/CNMSScKXHlotoP2uCRu+JHoK1ANc/Bc6qn+HS0tda/VmL4Q==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.3.0.tgz","fileCount":9,"unpackedSize":36519,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeWekfCRA9TVsSAnZWagAAH8QP/jdwxoIzOXOqt6DPs+Zp\nQE7hhDiVU0AT87mYQ3x1Vh/Lncd5G5t4ryc+PV3qEDowlV7aT56WMjyd7qsE\nfbOQUZDF6yvBeocNtoZQGqt1opTryWrF00m1cG3b/W0RbbKFLwOSgmocvyxe\nWq5j50SOnKkS6V5v4n51NLRaJLt1766FPLHcS1/9hdReXrXbzoHxEiMVGdNd\nMpiQNpVAWr4ei4cBPNQxPyRcQIxruQfLrj97JdtrW8ML4ntCBaC/jrYh6HXX\noCUg07Y9y6ujzk8By7hqHm7UFuhlcwYUotVan+g3At3c+9jZBhRWG0ib0+n9\nP9UFwAC6aILop+qC6uGkWlloMSONu7CDMPJkKtr2/8xiaR0uzIVLvd299Wzv\nc7qdh9WKspu1UbSug7kdcaSt47qwpSfgKxf6DgR8uptPMQlnQgcTw4WQcvzl\n2nr/c7bhgWW+miWy5LLO7aRQUnqNJqdTXLRrGNrRj6A78jlcziXyUdRpJjaA\neH8uazklYlrXOPuF0ujRWbC8urYfQzy3Honrc/7jiSxB+nxVA4ZEgqE/Svjc\n32ORW9fgVJ+sEP/L8zlRiwvkyn0z4SehOoXCUuARIpechOILqviE3Bga9/uX\nrCvHC+VmGUZjQsRfWi37rsVtFKJ2Y24yDpCV507HcAF4Anyb7HiN16VTQFhk\nNDS1\r\n=T94u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDPQz+nw5wVu5xBlzaieOazAsjiwKutVFfjAKavv5lSkwIhAMjqThXutYchIjWj6KlLddC8h25EtVJPw/26vLd+mFj+"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.3.0_1582950686854_0.8944173744333019"},"_hasShrinkwrap":false},"2.3.1":{"name":"tinspector","version":"2.3.1","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.1.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.1.4","@types/node":"^13.9.1","coveralls":"^3.0.9","jest":"^25.1.0","tslib":"^1.11.1","typescript":"^3.8.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@2.3.1","dist":{"shasum":"65de61d20feb4f8df2d7a9902292793509dd0e75","integrity":"sha512-5O1m6QHcP8yA3uk4psTVe2qGvJCWuNl1hA+safJSKUdv8YWKN2jfNbXnJnjWgIcZr9nsZNMtK33yMUSLcBvUaQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-2.3.1.tgz","fileCount":9,"unpackedSize":36519,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJebdMXCRA9TVsSAnZWagAA3UEP/2dc3SKXuxNvPiIknDri\nhnnzAeTnsDSRvjOE7DPUxgfRgyBF5jh/uARtkEcMo1VNUjZ9RypUpxov7mDx\nBulULPH2CkcbS8JIY4GFpj99/2UHZNUfS9V1XlCCVBr4OsZAgfdccYL/i0G4\nhE1xCJwXg6COw3DcZQL1++UH1hehWGZeVDLLk+Q5AmSzVEAmt5GXtbApVDbD\nzZEGqwkEDs44lGtXM2xHsQm6W88vWKN7+mHLFkMmuPITPnvLu4g3K2CYnd0J\nmLjjnoQPs/efxzrXLths5RUvT//7v3VXEakYOxMq0hqQNzywpuQBxvfebnsB\nkWGegNhWEmQm9FbZg5D4pCAIM40TfJed4Jip6h2JQx2Ii40qkEElbs9i6rDO\nOmhLUT6GQLYm3yZhpc4ShxvtPliHvijh5IWbi8lZYNralSxuv/tCzDcQLhQF\nKlXR/qytJIwf4rDeT3lAfH/IU6bPuptTvO74+O3CFz38VpJJyu8u+9CZqvjA\naPDezuVrHoHYU6fEMOycweUrQrUcacxi9GEL7/ujhfJ41L6MuqJmTBAWL+mG\njvKOtxklk/sK8Tz8KMvLsNzNIlWgod/j2lFCW4aSFyVZoErdTfR3rlK3e4G3\n876SiZXqFbF0Afx0Hp7teVYzs39K0MhSFg4H1pr6gyVhAGvcdIabk7RAV1nq\n4Td9\r\n=SDYb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICBASoPk6Acq4x8hVYDoLMuuqbta1cvmTanBhMFZWLZgAiBabkT2n5BdVlHbG1qmGl3CwXUOUsWPAZCbo0eZ8QqhTA=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_2.3.1_1584255766639_0.49704870356434716"},"_hasShrinkwrap":false},"3.0.0":{"name":"tinspector","version":"3.0.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.1.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.1","@types/node":"^13.13.4","coveralls":"^3.1.0","jest":"^25.4.0","tslib":"^1.11.1","typescript":"^3.8.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.0","dist":{"shasum":"aba86f8a33b3658d4beb4b56147ad89c9f73b181","integrity":"sha512-/2HSr0Wvye/TrjhTmsijKRG5Th7sBLVCVsUXZwnvDcIVutNBonCC5zCnbvz9mb596v/P6xokYMQxaXR8HYqgAw==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.0.tgz","fileCount":24,"unpackedSize":55569,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJepe0aCRA9TVsSAnZWagAAw+IP/0xmNQ6Sfo1QUoHWErcf\nb2ve17g8XnlRvI9zsXXxSLyz+tDvblnVyTQE+Mmiysm0hrX5NZVHh4TO64ct\nOSRxlONX3WShTpU0MW7/UuMFVCYNMQeWTDqbZU6NZKPLMRo/rbie0w2cepJ2\ns30Ha0B4GCRmTg7kk7Xb/679gIBoahmLPHWoVq49NvwzX83IbDeP8es7Gzvx\nZNcE4jzjkI7wJZ5M6pUIPrfk088043Kra8L9/MVn2mnFChwUWszIR0T5aMiZ\njhouXQKEvtEYuna/nCnxQ/U8KKTCK+O8h83fYZiJYrK0ebzLlFF7R9+05SFW\nJuLUO37B0GeC9VAwdO06G/ZUeaxQQ5nVgs4++E+mfBwf1BsEevU377vMkYiS\n/Py3bHmm6bHmK2PkWeXbrZwYb2w4TtG9kF0pnLefsBmsu6tnl0PQp9CnT0ZT\nHHthH8BywvHwSm4iIwXsZEigu+wMQfUg7ManFix2ER0/c+Ka+cg13GnNP2L6\nkUfxAaKMNlbnQLJb+npW6jARHNi6PiPJcwiav5Mk0VHUuoclpClK8a9FX3oa\nC2rqU9gC7hggHD3lPxowuKcUCsP4yywN9XNlQv97YYYsZ3BZMW/tXANvu9gM\nHQb5TNotuWiMwgn8xNYpZJNUinc5cG0LCn34uewzO6MLvFb3bScjw2ZpzanF\nhYps\r\n=GdZs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCcrv4wcScJzDB6kT8teCOZGfvpW/Rwo78Wiqj4nKlAWAIgOAzhWexC+I2689BJjpwm/fGqOzwK8Iy6/qbeov4rpxQ="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.0_1587932442261_0.9918077705604222"},"_hasShrinkwrap":false},"3.0.1":{"name":"tinspector","version":"3.0.1","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.1.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.1","@types/node":"^13.13.4","coveralls":"^3.1.0","jest":"^25.4.0","tslib":"^1.11.1","typescript":"^3.8.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.1","dist":{"shasum":"9a487a20adda1c31f8365b49fa5480a89a3477e6","integrity":"sha512-x1awbNt+N9y/z/01TxzdOtNSTQ1rNPUPHmEvHK9ugk5fqoslMVJw8dRmAj3TS/ZL9U3oE3reFzpefL7Z63+DNg==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.1.tgz","fileCount":24,"unpackedSize":55777,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJep2l6CRA9TVsSAnZWagAAUwYP/0ADfruV/eaTQ40dt08C\nB13vdRTyggtx2DQgOtMOn+OTK8am8MEl5kNh9w1juviiBjs2sQXFhskcI0hp\ncB3wqsamr2rc6k17UIZ8Tc1Fzc9yvc5KiXBhR3b0J1urVL1cykmcPTDCVENQ\nF3D6/DXd6ksNHhTz6dSFPXbo58z2UjkyROzeX8f0mfWw/ItX4IU29QsvtmhI\nILElqNmIMTpL0WT2oi+W6aDwD04sQ2mS1roto3sxP9OlXrfKNrVm4aIRvvNM\nX+4sXI7mCw7cVheEBbuCB8I9GW5apvRqWBiAi4u9nNjUz+4CeUNwVY61f2Nw\n9kKw+/oItWWwwUlolcYbCX9KSPyL9UaWx4Za2V6RjYFGwlxZVIZ0n73987Xa\n6SBNIohw0d7TsacgcmvBIGg6jxTVTtZomUh5aDkZkcwmeo8J4JPpX5kKlH+e\nxXVQHm4uoODY5N6anfbFCldzX2Urm4v3T33TbmA+ObLZkm1bIoU+O7cQLmq/\nq57il/hdV3cDNArhuNwz3TN2eZDRRRT7Zf1YYh6FHDfZMpjuc7oGVVAOgVNn\nRADj++A8LwiCp8Giq9bxVFu/ThM1cs/Zze7ZcLhKR/u4Snl17GYx+WJ2T17m\nJOhT8DFmvpvu3XpKN1asumqCrLgbpsD6P1b/w1ol+HDafYgT0t02l5Ko5IlU\n1SYK\r\n=spUt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCq5unrw5WdxhsvrV3sE2RNVXUhpAQ+QjHmjk7gbDrFOwIhAMoql0M8fqXeZftNvg3qwbmg+yTiYS1XG2woLdd/P52E"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.1_1588029817747_0.962848503774048"},"_hasShrinkwrap":false},"3.0.2":{"name":"tinspector","version":"3.0.2","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.1.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.1","@types/node":"^13.13.4","coveralls":"^3.1.0","jest":"^25.4.0","tslib":"^1.11.1","typescript":"^3.8.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.2","dist":{"shasum":"696d00e575c7f231dcc874895683f060603d36c7","integrity":"sha512-73+aXfYLFtX+58yOnlVVzFBdKbK2QNHAjMwhInnX6zT6d6vYGEf1KAcVTb0xxndtcXa4V8CnUuY5CZUj/bjo1Q==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.2.tgz","fileCount":24,"unpackedSize":56608,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqfhZCRA9TVsSAnZWagAA2aAP/ii1ohr8Wi4CFFWWCGwp\nYjJv8B5olNgZlS6hEP0F82UB9KqJe2XzozCfkF2Lvjo6X9CqyOAJRiF1jxC5\n5bQ5b/GshnT1JnmoP2C8exKEdaFR9iY3Ky/MSH2vQ9P7QWpye0G+J3YEZK7l\nqgLTKCAXakdYMjMwaTrbVDZbUgOZS29mEDD3CdesPW7AJsnjV7BbUmtiYaJA\nZ93EusrUwvIV8Cym7hlRR2DlwGZ84XLhjFUTC9vfQnZ2wC1UhL0/78JEQ37F\nbOmmOPoOIOBWxKyCXxSUefz9N4JK3JF2GiELm70fcrP4HNTgBRbX3n604zXe\nKhBdD0i2jgpmCTENMmUzWFNYmn34NN2egOB7xQ5IKf6scHBbjmEELX1d/129\nKlaU4nIQ2VZOKTUFOh45of5cwa14hR8bhBs4bcSHg46EvSUjuVbtyl5AnMbs\nsFczsoN3j7XG14Z8rsjE6EQoyExOjVEzft0e3de648H320c1DulJFtafu42Y\nS2TV9TAXqIGxs8VhzNQnYDUHy/CUKsO8UQkSd4FjdLjZmkDagtxkQjo9CKXr\nZWtl9iniN1ABrN3oxdOfLec0Rp2CGr0kp2E76NIdt6vTo2Qm0E5ixgaxZX+a\na2MpbKvcq6jXBA721Vtc+FIN5ihFL8gShndMVBnjdJoWlJhjuAbqxzxQ17aB\n7gak\r\n=pqob\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH2vcgQixEa7fMgI8lb8y4ncN3DxSpkVX0eF9T17lrPpAiBFE9RIJSb+nBDfbK3R44qBAkV381teESdj8r4ynDpHDQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.2_1588197464812_0.7933816786646672"},"_hasShrinkwrap":false},"3.0.3":{"name":"tinspector","version":"3.0.3","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.1.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.1","@types/node":"^13.13.4","coveralls":"^3.1.0","jest":"^25.4.0","tslib":"^1.11.1","typescript":"^3.8.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.3","dist":{"shasum":"bd73a9ac9449e7b4c3dd0a79f23896de3269ad08","integrity":"sha512-6U8uetdZHPT7d1SWPDbsPOVMHtDdk8yB8ir+J27h1+YMsoMzZ/zXODYE8NEpkdQwbbtKIfFOxn6VjL2OSLAvJQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.3.tgz","fileCount":24,"unpackedSize":56682,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetjT1CRA9TVsSAnZWagAAGlwP+QH3SksiM7nPUaqCzx07\nrTl1m4luGay208iMmur9M+56wz/j/7XgxBg5p2rgFmYv798g+w4efgZnaKH8\n1kbo75Jl6xoq+Udznkjy8HnokwKZQZjAKzabISpRQv0D4DYENnnQZOkwMmEB\ndB8FvIB7j3qRJm34zyrzUTPpBs2cSN21wmdd1N3F0tTB7UkfSRZBjnTTf4zL\nnrlMvruBAl9lE2VVe75BpTYVmB8qmTlolvMS5nfZtpLco58MEXaTZsT4euvO\nCRtLQGZN1fGZ6TSpLv4NmlTtJQOAPyW3bj+9STWr51HWYSiRF4LwkdGxGORM\n/9pHr0kpi6vsVvvf7CnaDM56zmhKCXCwgEPbwlXBBm1D/nj3IRxsQPtuU8Se\noUMrVyncPMceMQpGRNXn/8raAJXDkUoUNl04mqCZdb9sZiPoJKS3O2qQ7ZZn\nl+/tPh2xXUAlMf8kRckB6pJqT6J9E1cjke/M1vd7rwmtfHbJePU5fbjnXDu+\nj+6B4rFFvQw1keLjiIe5afeB80SSoF6VCDigmumTXm1CQYev7wlFT4S6LftP\n3YVzx8Fd2rCSOxJH88aZqeqdsnNMZ1e22LVAx6SCOtttoCEeLxSs/xm3XIgh\nM7r+SBgMUc2+Nnu/SWeba//TxbR7U2in/zQmzIn5XmFnHfxmUm54M47GdOkQ\nAmku\r\n=REvm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFJmssjQJOmJbwGItYphkPwjmKyFqB2FINSU2eadyOtUAiEAl//k+MojzoVRTXIKvx8AN5g7cXrWsBX9FrJgCtWSC/A="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.3_1588999413257_0.40432045709522013"},"_hasShrinkwrap":false},"3.0.4":{"name":"tinspector","version":"3.0.4","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.1","@types/node":"^13.13.5","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^1.11.2","typescript":"^3.8.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.4","dist":{"shasum":"9107316b26b65ca7b85238f369f13caecc806b85","integrity":"sha512-Dyv15RhWraYu5zGZRhlsUL2OBjtImiat0VtYVJwkEVbUtzEzuqvNX76KYE8Ys2mc7Bq9gZCG96BRepZFT76smA==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.4.tgz","fileCount":24,"unpackedSize":57611,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeuiymCRA9TVsSAnZWagAAG7IP/2+wffw5/4cVx/3OM8Bp\nIPhJ/EdmWmtmnCWb5q7pffS0MWHOhITHH7AJrbSEt9AXbRJNhQFINECOa5hw\nUgsjJHOdWPkB0YnVuo/2TI+v8dtr1ezAhPXmVLbrhtrJRTf/TmvL2bLpxiUr\n9MoqHfr7pDtL8xQrVjJRmNmPpGYMZEvKghIDMqv6ZL1wND0IfAC/GEiLr+cU\n3TIZxz2qdxZ5FwKMMEZNHLBpEQpxC5b1lIJ2iubBMZ2X63afx5RLwyoM7urd\nv/oRl+zpL5umvEuA3YSA3xuU/8VycbQEsaE+tnYdZ4sF6fMoYpNgKpO5rf+F\nWR80zjN7hiV0/0JIQSfOHolExOw0OShLhrORYyQua5pPd/YAq6BeOlgxuH5D\np1Bole6SIzzyDt+LtX7SwA95SS3Pns7B5PJN+ZKwXZdkNjSXw7jMDg8FveQ9\nsntgOfnHxjbm3DxFagCfQJLjLG3Hj9Zc6xRyJGK1gw/JNUCCJGMoXRXpAfzt\n25p0AVaKkyIpR7zI+qZZCOV4qNsPULiceO2JVEe4yKbmKjOL72Xnk+4WhrbM\nQSbN5jLU03VG5PQmxL9/MS+ZZiViN0l8uJDiVnNNKaWk/MRh2jnD8u57l5Je\nCqgzFGVkoJQORgub8pVnbWol/IMZ/serWfxVVeQxwgyU5W6kAzPeaNbFXidk\nCgAb\r\n=R7ZY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICfCTVFHddV+VKFKAftdiK90fgn7RYWSl8Z/wWx850QAAiEAjHX+JnzFEI3UdCul+jZg8grF3+5XnAOB8oEWDwZ43v8="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.4_1589259429943_0.14911788047342878"},"_hasShrinkwrap":false},"3.0.5":{"name":"tinspector","version":"3.0.5","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.2","@types/node":"^14.0.1","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.2"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.5","dist":{"shasum":"7d8a64e40f8528d0ea77696dff1e03515b98d749","integrity":"sha512-hXu6n+5drq9auMrc0M5exrgMAm9WUX4WX9Tu74xEz2/m1ROBmhC2GC0mwPnby21o+co9edW1KUNMJl1hFvD2ag==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.5.tgz","fileCount":24,"unpackedSize":59895,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJev5DnCRA9TVsSAnZWagAAHKMP/1HSYL0/wY7KZTJXrR2r\nKl+L+YqCsOLUHJmf+DJ81u45unH7uvFLfTmTGggzsyKMqe4NFb9SMZbpA9vL\nhIY94fBqYSNgjLo3tHxr1/jQKWCCCWdphiyAqQ0EWRz2bJa1DV2J2648BvpY\ntVNtSgBXn9waO8IJNwQuPUjgOEVXZy1cm3zvOK09qn2kGhphKUwwEh16I6U2\nDhjFYOTAZNdD6UPOZk0JOO2lqbRz9eQM0Y14Nmfa4F0cDP8zW64UMLhdhZhN\nX+G5lG6veYF5vZxvMUIZ3UhYJt+cPgvCi2iSOZfncjFhLtKeJ/Xp+Kl0dnXi\nlkqP5BQSQS16FmlwSwrH5Rdu6ZwiNfqZJ4piIx7OFzU+Wj+s4Ch0t7rAo4Wt\nw8ut34LkZOLXC7XcMBdv35SNe79inqxHQjkLuzwEVCHV0x60gJB6ioolWuja\nOAYT+Indd8oIXJW9gBKMZcs9TC4thYAtPfSR5pfl0C8ZHGA8vm5U2dkzqh9p\nFjaokWxTBNxjmWc9FK0oFD7jfoUtUPfpuC4KYXIG8M7qYRJBZj6b0ye9aMRj\nwJE1owduX1cMhwp1yjsAcvfMON8eJN7nb9J0shdE+EJ/MsXSsoQJ4X8IPPWZ\nzPdwwLVLn/VxieGE8yIQl6ygeUZVrAkEVz7EU+nQWJ2e1xH2qGOLc49Uoc9U\n+9T9\r\n=6DDU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWgP4hSAfmXUiAfrZT28a2HGf9ILG1ZRY77zepXnKKIAIgPxUXOJWAhxJrqs7PBAFasaGK3Vc7n+T/EyCqs5MQLSY="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.5_1589612774548_0.8876984389773095"},"_hasShrinkwrap":false},"3.0.6":{"name":"tinspector","version":"3.0.6","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.2","@types/node":"^14.0.1","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.2"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.6","dist":{"shasum":"f701ba04eb5c51b3b2c2c57182cb9740bf8dba39","integrity":"sha512-/YUeVQtrHr6r6ukE14do9nLyjwBDqexjPhqv7TkI192HH59wC9PlmZk7cKRaCmdEVxkRL3ik4RcFXb5mKoZQkA==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.6.tgz","fileCount":24,"unpackedSize":59635,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewez7CRA9TVsSAnZWagAAN2YP/itinua3TIGDX5b83Rgz\nALsa/dxOjFl0Qr3Rp4Dm4mrRCunwrH/A51QFYr4BAvf+GPAVcyeov6KZWKU0\nGjf28cLJ6O6U6dvwKEYYs9V+5mwIC6jgImYQDGzdU1qs2XSQBKoP1OobJDwz\nfZyjiGf/DvA7hGPRqHcNR68nOd2iDcETESanmRg9WHDKRYlTZ5H5wzxq5/6i\n05Xm4LM1W91zB7wHdgb/ohc+Gxm7ytO0RH18/2llGrAchVJc65mXvvhTgfDs\nXod+bcQLBO7NgY7KFOm/+OR+/dCAllcYkZPkQiJ0Opz3NFB39qEp/yrYtmO2\nLRvphrATah/aajfakKebVzpbTCSMpAyZ27cRCPAuZSvpmsNilJ8I+54ctjBB\nLAq2pRpIgdCM40+wLnsSm4+AUjRYWHJ8SvUJfLZvRNq0dq0T0lfKygssYBpy\n8TCde67oUHMJiDjHp0Ibe6G6IXbzWhnNEROGQj/XGegCJKNzdF0kNPsELGXK\nQSFs6rB2N2wBzyb+zej8KgoRkT27B0L5FjSwISmqn+zpDX9OIUtHAgyjkPs1\nWl41BCdn9Zt6JOh9FOhyZsA8pTE/Kk/myIHspDoqgBATpJ8j3C28vVIVFKjK\nIcGYgZP49OVCzOVZOcL+OWISTLCLEGuiKMnhpvbyUV/5p2M5FhY8ihYFO9gL\n5IRE\r\n=F1Wh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD76ikYpz2ES2spNjyr1GndsFkopBD1BNLpMRKkoB4xNQIgYe7FsId9TcXTVstEukG981kYV/XJeu/SmagLNLK5Hnc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.6_1589767418776_0.4846185816615569"},"_hasShrinkwrap":false},"3.0.7":{"name":"tinspector","version":"3.0.7","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.3","@types/node":"^14.0.5","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.7","dist":{"shasum":"51dbd6924d98eebd7d244d5a41920ad1afb701c4","integrity":"sha512-7ZOPQz/MENyUKvmefUjw4k/WSMKyH90Iib5ZbqS1C1pZmhozhHC9BacX8hDY72SfQZMTC/0Ym9rb1NMLqXoLGg==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.7.tgz","fileCount":26,"unpackedSize":59946,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezgrsCRA9TVsSAnZWagAALxUP/iS1A5ybLYBrHLFAClat\ns3IHRxTCacZeVXCjotgFqucER5rCjnekVEdKnX323twDkPTIREYBKUTQL64C\njm5rkArfmFuToJQxZw3J/mXqkv4YCBjOWFT9+hqWul5cB/h7soEpypR47oMH\nL06mNq5z2CXAukLiqoqRANbWUUfxcl+JHpiIbQJCffHNKDC4NKHo9PP+JKYZ\n3xTGnpyFECAY+dRNwixu3uCfNcONtGO55QWHm6NrbDVaXxKoCYX0pu/PDIeH\nSxpOvgKOfP+1zXlznH7Io4eLvGmrJWELhPposkbECTrHyudChTVr9BHJeS2T\nUcilaQhC7KN6y+QfiicGpApLF4fcEuWUU/mx1qbjhj/+L+zXwZnNrrGIqwdH\n7D8gg74zaSt/gWk6wMmcr0R4qO7C9AV2DgJraFZ9ymaMpw61sXhqYsM+rQzz\nJNWl1PHpFSv91b5xjatL0rDPeiE9esW81ERjHnWCgZWRcZSBPDE1xqCF3tU5\nN5+5O1OqPLnnxXGJVm7uxVOeBrQuLcsjoNRJBG0Q++S6qGkugkXoIUyxGYPd\n9u/cwPCWv5hxgw6aU4xClQBe925Mnm+tnI91CkSvFvLAYlqirq7ZEft5wnEd\nxCz1ogPXDrwWl9UOTZL/+jAXfvg8esCyq5I9sU9C5JFQIcYfjTHOKO4mz/UJ\nFVpP\r\n=BAUw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCiWUpZkdq5b4QGQ0ERWzlqXOpm8Bb1wKwW9ydAIVWPywIgFNy3/Ee5UquW2WhtbtGHVHVNeH2MpKsxoFX/UWmSUjQ="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.7_1590561515864_0.42202572225312673"},"_hasShrinkwrap":false},"3.0.8":{"name":"tinspector","version":"3.0.8","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.3","@types/node":"^14.0.5","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.0.8","dist":{"shasum":"17dbb80649326fdc10b586d25d5d9ceba14398be","integrity":"sha512-EWizMVqkSvUOgeOBPNYyqcd7r/fy9f134npvd4qlugc+Gzp1kOlo6ZMVN9voFFoxi9Pm15IJnP3sG3sAX/fiMA==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.0.8.tgz","fileCount":26,"unpackedSize":60298,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezirgCRA9TVsSAnZWagAAKakP/AxhU23aTcbr5Hg8yZR1\nlEBh2QKeay/+fg6gf9xsufy703KmrMEsg19uU/RK3wDBvA21QUFr3dyHeW0u\ngRy6FlnxTNlSHVAGdTrmzZ3+7d6XpDEIsz0c6ZmpHSc8EViIgsgMc/hQ6+is\nYC8stHtCP4wtoXuKrwoghp+4AOBgfWgysreMuS63O4TYj0gCHXiAPYBjL3m0\n15fiukXNylfAAj3VmL7tF12ytA9acsgqHn6jYgnaMYZ0uya0kFjjnF018OTM\nRtR4iDF1AwUqOSw1ZXISMQS4MpGqm9bKf+E+L2kQi0KiDOSFKvjLpVVt48oI\n0WTkpOzPvC672lU5xC0DVysDbawqA4PXDIU7WzvlOQqjzJaqNLkoNsW/5fkj\n9gAetltFQPRj8JkhB+wsmIWGux6opgr2uOian2T1Tz4oXIXQO1UyBQMJdDB5\nO1kElvqGS06xC6vApLGBfruJAcDHlMXPnAuK5we0kNR9z07LtZGIF4YEYXFH\nq5WFGRVXvaSrKTwtxx5PoeM/9se8FxufiYCy/LlTJpgfQNfwwbaVdrGxw95c\nOY1CoLzis7g5+ceoSnzjIiDj2Ln1nbHS2ryoWYNbNGwGj6MTnUOm6nj6/JGH\nAUGj+iyI+XX75iWC6+4eUIH5wMFQ2w/bahKJR3oToYNeapyOrUhpGAn9bcez\nCkDs\r\n=l3tj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/OmIFFnPT/ZbLOctQDoN/3o4mQTxx110ZhGrRfjBhKgIgNw0TjJ2U8laQjhG6HQNKwM/5oK9aG8uHPSYjE3976Es="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.0.8_1590569695576_0.4534954343644946"},"_hasShrinkwrap":false},"3.1.0":{"name":"tinspector","version":"3.1.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.3","@types/node":"^14.0.5","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.1.0","dist":{"shasum":"05ee58e9852589f9f8563b54bff9feda722f13cd","integrity":"sha512-Lzen4sEn3TVoEh7Gncaqs4og2RQYeOtnFcaLOdMDQMM5MmYz0InN1GR9MIFnN4s8EzOVLvBqBtpSE9Z5ocA/Eg==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.1.0.tgz","fileCount":26,"unpackedSize":59327,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe0BeTCRA9TVsSAnZWagAAPEUP/2r5iQ2Td0m1B1KehpeQ\nsuoyX2Yv5m4w1d0a0pnOF3PlO8v/vro0ZAa+mELsx5l/gswgDsecsq/AfvfE\ntjsgFeLjSf2v6jacYDYONDfwXuc36L+JrjEaHGoSMrnMvplOtz63GhfoeO6p\nJ9XatAEhPNS/zS3fOSQ0UQ/odrDHamPyQs+qrGs54sc3CgVW3i6AXdRy09c5\nvoE6bMFqcpfYjgbLU2cYfjoe6sfl6RuuoioBcBeA4apYVbNACuoPt7GWIyAf\n6RRpECNfCdVrObObL1736FnOsCa2X7y4Iu94FVTDNq9YLruTO0hI+spLqgDV\nB4DsaSzvUVP1IFBkiMVOV7LQFYWfGgLj/jJe/QYNh2hO/lPIZMqHBoedMEN/\n2hB4YEZoQy+M0WRSeYFabKwME091XFMQYeJdV0k4odWI6rDp2Yoqw/wwLM7q\nLKXhcagqr34tE155VZ/8UhG8aiMbFcRZN/X61ZYTY0odnqDmWSb85zjl63Lu\n9mIo/53Fh5bKcs7A96KGMpJkVI9lkN60eU+bQvXPEBKxPpKM3MzRwNF0LN50\nBtVGxHY+5W0BRDJ4GVOXKsCjb0/74LBNx+V1ex1W+oeSlUVkWvno9veueY/u\nC4HqPXWFtYAOjiS2gTXxGlih7SfBkeXqneGvh2YP1kMx5Fq0uJ4Pmcy8Hnfi\nTVuE\r\n=CaSO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDLRvtkefizwKcvjkCwvYKT1tyauNwV93tQCHGqaikedAiBMXLy8zxf/hz9lXFgnQHYL/B2gZIMB2j1joXHio2GGqg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.1.0_1590695827509_0.6895504571409308"},"_hasShrinkwrap":false},"3.1.1":{"name":"tinspector","version":"3.1.1","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.3","@types/node":"^14.0.5","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.1.1","dist":{"shasum":"9e2309c5e3cceb082fa4b79e0cd5176aa959cb3b","integrity":"sha512-BMeGdtBneL/8Yc1Xq44PVVVha/4l1mJP6qbayxVsH8qjfSOjOWl1hP0b/0EKb5LUWNT6YwKW1bMSyvP1j4yvRQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.1.1.tgz","fileCount":27,"unpackedSize":60124,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe3BV6CRA9TVsSAnZWagAA5t8QAJwNKWy0BuIvq/R4el6x\n5l0ibl+/CVDtTdXb4nXEtpBQyePjsSPt1T2i0fEL0Tn+iXMvudf3AdZdRxQv\n+7aSAYXqhoGHKFiEMEiSVBx49RVcakaXsoYSoni1fPH/ROZrw303gNkjGb/g\nNNBjOGL1jK5TAAGH/i2Dyd/zUg70wvtOPJ+EUxgUqW50goakrXNP9gRiPwOD\nLAvzdOJZw8QIILyxcYpvK/94elX689Xz5QHuI+Y1wDt7moLB3LebRMCorSpA\ntgWcFvTs7Uw78YuC295PEbs1qGA20YnySpQS9ONGKpkZ5HryWCW+fH8+3ErL\nTy0E1p84BUv50UKdPm9TnfcS/DZXJsIFGhzKxRUlOqV+34cqnGUhr/oaDVCw\nxdDEu4UXsNa5a0WR7EnoKYlX6ApP1ke1Jl9zZp6wb1/zSdakJ24XY66fKMen\nLFBKFyw46GbsBWuVKj36j6+VI2V0SVQYYZ+X6xaf1rSYnB6znwBpSqs/BlLs\nnNDifMs/PuhsE/s7lKCnYVdkQ6qREKA4/r3koJ1ziqUgtELQ3nO8sX0qqTrh\nMAjYncT0RJCcyTUL/fUZLMIJnY3LxHkIrzKrbTsR8XhNFm3c/aKhFatKmi9N\ne8ASUsLltlusCWSFFCJ9aP7GJfpe/El5nTuC/SdZjVvFOSoXZd4cHES6iJhb\nKler\r\n=qCv0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBXgCypSJoMnT5JtGwsGxgrFFyViaU1j4lD1PsVjJibOAiEAr0dr+1MjgyZ0Z72JS1yM6sHc6zJpQxw/Xa988ZT1fCw="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.1.1_1591481722066_0.9575300703872838"},"_hasShrinkwrap":false},"3.1.2":{"name":"tinspector","version":"3.1.2","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^25.2.3","@types/node":"^14.0.5","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.3"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.1.2","dist":{"shasum":"a73065953219bbb3a5d62e32d3b658535853744c","integrity":"sha512-2M7YSMHcVX44nSUkKyclFWmVylqoLLMi9jO1+KFvvMNEWdsyLOI6PbFYPSBSa7bcGjc2AFgpGCI7RUAIBi9yFg==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.1.2.tgz","fileCount":27,"unpackedSize":60089,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe3C4JCRA9TVsSAnZWagAAEz0P/RJ71DpyOIM31GJ7JVj/\n8GYtQPVXoMWEL4ng1eUao9FcF0g0x/V6jKoTE5vTxfGBmVhLz8M09YtSwHx8\nTSBP5/EbzYAA5zw6B4YA8q1wPwBjrDbSevUPVJ1Z5odzchH9T7H5u0Wco9xz\noCk5o2j4KvG7kG/Yd3P/n/rIoN3aAOYqJqEOtlBm1u7VFCNfrMskOFwsE7RY\nR+MXj7VzqzM2N+1+cJwLdTaY0vxd0beJ38vI4b4w+99gzlYwk8bMiO8S9xxK\niv/rYXyZPk2G4/KrAoUPDrYJJ832ZZAeYjNN9W3EG33lqCDgh5fJ7q6UE/ux\nZuYH4fHrInpUt+9Kk48gb4sKRBuLqHO9VyRQ2bGh79FgK9jo7pD+zcX9TFsh\nMgKppVLRk4JfUOFiaxPlZhdjy/TeE73MBqDKWoigKjB87ZIizS8Kpvs95JrM\nM61vqgcpsU+pHVsDuuz6arrE363cFbiTAkvwBaGAMNPVfsiY3PeS2OGzvxr5\n/na5HrP6KymKJH6sujdDLDToUjJH3ainuY+W3YbQk/XTPD5WC/QPL/DlJzDD\nc0taaK9vedPu9m7VOmUQg+mfna3ykT63f8iNw7qD2pq+ZW56Nq02G9oIC+om\nCynmJlonRGgoL+VQkKcy1a44XetL/3JgkPMc/1dJDwSCwmhFh4UQz+owttJ+\nmJMF\r\n=OCbf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyshT7uDCaEnXoVhd14MEWyrCbaP72YFDmrL2LtSGGMgIgA5OcEv4u6Z+oLTJdpjvWN0uQgtXy8FKYOd/LK4HUfXw="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.1.2_1591488008986_0.1497176210495903"},"_hasShrinkwrap":false},"3.2.0":{"name":"tinspector","version":"3.2.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.5"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.2.0","dist":{"shasum":"2a5858d22f72f1e6c4b1a0595893534399a06bf8","integrity":"sha512-CHfAJsGCYYc+Ilu4faglYumFuVF8E8jehUDg2BP/Uw5oZW0bkcpQ5ZmGy8PlARdx2oFaZC8aZQcbMfRBsRCnGQ==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.0.tgz","fileCount":27,"unpackedSize":60789,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe4dEYCRA9TVsSAnZWagAAiOkP/3GRRp9m7lT3VBRB9oZm\nohuM3F8vDSFvuySOTA4qkedK5j7enU1v4E7Uj28F8l+c7wbsKNyr62ydjQVE\n/CECSXc3BnNRx7RLDmVB/11GDXrkRXcfzZldrfQw5kZLvIkn5CEA1JXc25E7\n8U19S3GG60yv0u5mUWqI+1eEP8ZBtneGMYZrHdSKJI6TXLZ7hXIqBmssvXx2\nNK+w5JELCAf4nu5Y+UMdS2BDbB/th3lDbPu6k23pI+oRN5Hs5bioIi6UG0RW\n5cy00eag9PsyYmdjzbX991ACyOcAz5UNkmw+F01+EVpaQdBSH0jGn2GQ3Ie1\n7ld+IrlfjV5QiLndQaj3eTVuLgRQXp3Lyz39uXqjQyXFfDOgREUkYXf1Kbqf\nvnux6uuq3alsrFCtnZ5QrrYeKpaqSmAPk3W7AxuvuAInkQNbtC4InbQUzv+n\n0VSW2qXFQdDIjZqqm1vBpZVxlgoWCn7krdakv9P4y4QCJnE4wkuFBGxA39CR\nfX+8Yidj7wFaW4WjiDm3JMxv4wHYvcdEPVH489SqLUASlGHzF9o69gdXJ/LY\ntI6DNB//GCE1AgzlG3LM0lK1BJmw2zIBV80Jvtmct5jIsBiel1jwcBGjPjc2\nVqguEkEcOGnycALTY430080Ktm2ZArNKCIYDI7elMYruSEppigXHkDDK1vOh\nnk3p\r\n=w7Qr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH2iJGsl8W9O62Q7soXjo8AmRPtKI2TmlxqdwbARUb+IAiEA5bpx2yhqUojwiKy5e2LYWEvoTKCtrJ/9ONi+yrEFKoU="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.0_1591857432180_0.3996377921694483"},"_hasShrinkwrap":false},"3.2.1":{"name":"tinspector","version":"3.2.1","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.2.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.5"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.2.1","dist":{"shasum":"ae3bd0323f8fddacce419dc49d0aac9800bdedf8","integrity":"sha512-P9fbHIBUqoakhXs3vPvhpEAr/x1Q0mp8qLMZHZYNsCufuM56W79Nvpp3fZLAOph5vw6heKkhmEUYTvTCi1O29g==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.1.tgz","fileCount":27,"unpackedSize":62684,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe5EuKCRA9TVsSAnZWagAAhFsP/RqknMuBN+q9E/a+t1d8\nEcLJg99aXs2iO9OMhmDYw499WpBAvZkD0pXFIgVj9gZX+jvc4n9keNt0w5BB\nSJGavNiP181ogZUFIC89i91MS6y7UpPAePko5YRxeSE9Mncp5DGm5pifrPEg\nvIu34PJPP2gW4UWowUgTSdvHH20RnydwM8z+c+TkjWbrfOoikczfZqrwVEIL\n9g4i1h44VcDbO+bSYXpnXGyb0gJ2A2di7C1p4I8aWazOJUnprzA9V6ceoDlU\n16TlSHEXTQO8goEcDRN8sDwOV+I8uQQLU0GwiVtGy6maWVt3W66lJg9yW/11\nVy7s/7DsF0hYmY7qM5mmM8oZbU5xGdOAL1cvn2yWfvxCa0+vvm0AkIBmyiFN\nVjENaiZ4q1dc2HNQH8xqp3B1SSWBJSxrVDo6NuHz9dai29PMKu4pAUWec3Wf\nIt/QF89aUjD/99wd7y5zbYe1zE1FTS8hQ5BjqGxp9n2vZYGaqudVMAl1LR4d\ntKjNyIQzgjTVWbcOLcfZOyQtKPZCJeOxOQQOuoCffwCxk4voDzrpcTfYhVlw\nudM6SR9idS2cutXjf/2x0IgvhMXxGiqX1vW5Mf4x4u2hdHLFjLAQbdiwzZc4\nO5vLgXwQ/L6aOuxvGuzppG6ILPHxLxczn7wUmBprf4zSZ6V330sQ+UAOXTbV\nohSa\r\n=TPGK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKwgKN+OrSk7mpbeIIe/NDONgUJrIUcmr8rqxPhh8CcQIgPwCTcMoBTee4whPiHYh6Z9hRNFFBWzRuHMotXR8OySI="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.1_1592019849890_0.3218819099204273"},"_hasShrinkwrap":false},"3.2.2":{"name":"tinspector","version":"3.2.2","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","prepublish":"tsc && tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","tslib":"^2.0.0","typescript":"^3.9.5"},"licenseText":"MIT License\n\nCopyright (c) 2018 Ketut Sandiarsa\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"tinspector@3.2.2","dist":{"shasum":"c161bf73a8d5c18532d959be7120ef0b2b5c8ee6","integrity":"sha512-BqBlauiAeDriiyDd1B2gXQlcZO7klCvOHBnCMGCcXGqVlYlXALtD4xHgCdhp3s/ySIdXg+Ga3kTQ/dK1DRWMzw==","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.2.tgz","fileCount":27,"unpackedSize":62853,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe7w1eCRA9TVsSAnZWagAATroP/0db8cN5yKEkoYP60Na3\nBZKJBEwUrxMdKv5HqBmVnaQOIp19ALCg87/MB6Zl5dy1hybGiiy1phhC4VWo\nGRD+DxpOji5et3Ku5HB29inipK9i8hIJ7I84KH91l4s1Yek5aUQny0xMvjuR\nwJb0UVYC9FTIjsthzOPZP6BpXxouFjmL4n2Gs6go+kcnfxNYU0KbOnsdxYUV\nlvObCszu1an2eXkgFC5G9KjM0YQawPhcu4C04luhSpUIgpHU9Kel5tQTtcTF\nGkrToNrZTrte44PIC5p/X5IzT1pwfiIoWhHxt36+64ALgdfIJWyz0dcC/+wX\n/dXe7iNbKNLwGw12jkNB7hv07MqKPnvcFBA+xAkisXVfrtgcMgvIfSmA5unI\ntp6AoYF3upLDBlpIoQnYPg/33zmr/OQwXZqVoBuUlN0ic7LwWZrQOk6k2SbK\nuGMEhrDKvaqqUHD1WCODS1hGN5Yp5Fkzc+ke5qTSJYYItGt7HnkNmGoy+Suo\nn5win8NttKlW6QZNJvixUIAZHcQZVU+YnzW/Ee2IfHGRmxQKc2S08byCFHTn\nBPI2uVcWkPGqPEy7wUPphhpWcuoaBdrbzPfFM6eD7man8r9dXgtm8xGm76uq\novuLShn6R3J1bbcgjXVlZoBAk+4CRp1UDXysE8JhYxtKGvat0hpGpWKqLK+c\nwNfd\r\n=Eh5L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEinMThi3mMyVjNHyF5m1iO37LdATvJjG/s9il6Ya8UEAiA75i2Dq5KtKs4JMUN/6zVPzFWK9D4E1tNiS461fMsiOQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.2_1592724829476_0.6693826593988876"},"_hasShrinkwrap":false},"3.2.3-canary1592806142.0":{"name":"tinspector","version":"3.2.3-canary1592806142.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.0.0","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"06cb125750ec650428ad9dd81e1646264673dfeb","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary1592806142.0","_nodeVersion":"12.18.0","_npmVersion":"lerna/3.22.0/node@v12.18.0+x64 (linux)","dist":{"integrity":"sha512-x6Sd5N1RxsYt2KsUzT+tuLR1+U18nHqlTMyJxm98o7pJfKFTSmeeUOf1/9oliEcWsYq7KS6kYtJl/Wi8ZrwtWw==","shasum":"b0c067a7448979b313f76209b3762cec43252b1f","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary1592806142.0.tgz","fileCount":23,"unpackedSize":62949,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8EsACRA9TVsSAnZWagAAsu8QAKTyCrEH+FqbmsHnNyUZ\nwoIkuIn/8a1XAX4G/SlI8HZpca7fXltATU5Wy7pf0Y0c17I1eUjlxmNTYTbe\nw/Ugk0O5Axud/4w4fqdNJp9XA4Sh0Ud39BpOJ23ZCaXyOyMVhS1KLC+cZXsG\njuvlGrXEK5VoOvkSeG6+UBzKUr89lFic1cxjZSH0X1S26Ch5UyxLuZEP+UIe\ndt57oJLW5jPQ3klK2ZEnhrDcInkWDtqI65Ti7QTGXIbQ6nTp6jXfyb3mff9o\nNlcnxvkJo2889WaH/ydgQmEE0xS8SRfoIyELS/jY4gnGOJfPDAvoQueNnVc7\nl1yu4LOsxC5y7SD5+6Mn3zLo/C7l1jhPdjkfNJofcF8t3aaBYp6Qv+sON5UN\nedD/+NnuVhDUqrg0GtHXzY9sQC40GbuX8FsdINnGQ1e/40ynqTOOGL/G0yQl\nn1QpIXA0VKU70UTomrE0cyoXst3BwBBV8mQOJetCPqjMbaxOCoYv9ejCbu5e\n4Asjb9QttaWe7Geo5qFXc6rnCTSsCRS8BHXizOIULqA3O1g1r9m5cRJPRrt6\ngw5abwGw08ECA1TaBWmyQnWpCiVJDiqoJ4fLtZq8MQwrjWiR3v1k9rH5Vstc\nbh8AZf4Xf7+DEb4EHe3nQEeQYd89r9T4XVWhF+PzeRDn22FKDdntJEMQ+Lsp\nJU7g\r\n=IcRp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICxDF0EuTgXoWVRpblRNEmqg5TKw9wKHqwH4Gb86iXxWAiBIOMWSWUZiIQxcrvGURUd7whKluZLRH8VeXTzLwAShGQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary1592806142.0_1592806144446_0.6232933678319514"},"_hasShrinkwrap":false},"3.2.3-canary1592877058.0":{"name":"tinspector","version":"3.2.3-canary1592877058.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"786bef1c6466ad189ccf28e811ba21b4732bd9f5","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary1592877058.0","_nodeVersion":"12.18.0","_npmVersion":"lerna/3.22.1/node@v12.18.0+x64 (linux)","dist":{"integrity":"sha512-GmP2IbwjCPvTaYofeFQTpr6CMHCplXVts4KBgaUkWWxALTgHb06b2zZStBOkvappansuRiIF+jTJ6YpMW0Hlrw==","shasum":"86cbe965a66877375ad90732dde316bcbbc19a53","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary1592877058.0.tgz","fileCount":23,"unpackedSize":62949,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8WAFCRA9TVsSAnZWagAA4GgP/3D74EzcSQ8AwgNyfRy9\njkssfwidvd+1fDpxg6OLbJkB1XxHNmponzxZCWUldneENyJ5c4sph8CqcFHx\nzO71dru84RZQAwzZtmOOUPhfknxRTxKVXujwwAqluhQXwI3xwvb3lQf4m0tZ\nfgSFl3eyYvdxDHmZtb71A16ZEMLAWax6lJZ2mETDnDua/WrUdKQj8x1Ha5SS\nILMc0xoxY62sQp6PR2MvG7JBa4ft89w1Gq57MUo3FyK5mGtztvEY4h8Dg6Fh\n33g5jVcM4i4ZAC+sWpk/MVUN6hrQGVDcFi8pbO4QxUfptvJVFgKAEsWOp2YR\nhTQbr1emqx9bjGljOGpWlNczV+UcdBNaiJoQXPbHk8cGxKz+06O33XYnZM3N\nCPc46Muc2Q5eYMl6l4sT+4KMG6LnZwe/y2U/PH52s1TscnoBrIIq2djSep/r\n9AN3GP7ES8mMw6OTb9a4eOMlc41YZEPWu9ib9LDYZqVJ5Evjs8tkBQfcIRzx\n8PyXrzHhFdiZpiCLIj2IbnGBOiEFHEvVlTQrutbPFXw6vy5C6QXNACIuL8Yj\nBSICkRwzyUeFHSbaaFFkMEFZCypllUDK8BnmwTlSzHhVqsGZlAegmkGtpHff\n+3G9Xi0qLpJwiwjiBcpuh307/s64FVejAbUve80lHsQpOPOKS+8kw8KFMQ6c\nne6A\r\n=vMIL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZnXOo9cYIM7vTYgyzaTdk+s1IC6PIVJt41IxwX6JycAIhAO5RSH8evBOrvTyv3mYwRtl319xXMfMNLvSK163YddPd"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary1592877058.0_1592877061290_0.7289600483786591"},"_hasShrinkwrap":false},"3.2.3-canary1592886862.0":{"name":"tinspector","version":"3.2.3-canary1592886862.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"438c2de2249305176eaf2c2e6e526924781edd48","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary1592886862.0","_nodeVersion":"12.18.0","_npmVersion":"lerna/3.22.1/node@v12.18.0+x64 (linux)","dist":{"integrity":"sha512-j0BV8/BtgJC+In1LCtoePuVeLotQNuLv+0zN0J5IhZXVTT+sRY2RI6jCklDBxFu8oDFxX4YOiMlHGSmJt+zT/w==","shasum":"5aa4a41e877b59f3f14044fc155dc77e57cad94d","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary1592886862.0.tgz","fileCount":23,"unpackedSize":63006,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8YZRCRA9TVsSAnZWagAADfsQAIzgtOHbADpfNocI+5vO\n5wAb9BVZbKpIAobtT0gRW9vJADOFXQtkJlJ09qZcNN4L17cPVl8jdCng+jJu\nKM7f4xAYlhEo7kMX9cicMjV3ga8j8+2xZ49bs27XkoxrxdjhTzffCEfwk6In\nMOaRtUXiI8cIL/GI3eIv3sHe9VTWsCBtrR5rb1F4g9Ex5tWvsKwAOGFbcYf9\nttfH/Igm3aJztU04CA1w44wu91uGlkRb0yMqCiCqOnNSpK/cUB0npqHbiu6S\nVKGjmd5/eHlEj2jIgyCcX7A4jXxGG7PiU2FubIMwd1abXcM3CZVHAXxXdIO8\nygxlhoO0Vx9RoLTvEVaZguq48TQm6ikXPqDvxCl2O4c9Y6IJfaq5PL002Xti\nuPSrBF+SV7xRNops7Du23JHK91K9k4hb9lSMJ1e7f60nYP/yty02uKGPKmzf\nmf3qirw9CLaunLHNRTe5SaJnzq9nvxiVztUveL10n1ETatWo4bSWUR6Yj48l\nT8LLeFha2Hxtovd4WQLwsfhYiYHRTamb/KGIUM5lB5bNXHPgHfpIToCZV6de\nIIrV7YK9tre2vvF3cAuSGwY9HsPrvNy73GjLTtIPLvwtZH78EwGOhNIfviVU\nKKOC+qo4i6rmmC1QcLOt7kKHftqc3T1yUgn119Cx2v/KJ8Y6e+Cae9fr4Ch/\n9YSG\r\n=nXBY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+SXr6QVDat2mlOTssTrPuxnBJlYtjOeknSt6BeRqBGwIgPDIBWj+o6V8e7atCHX8gDnZ5aYIwB4UxJP3FwwrtFIc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary1592886862.0_1592886864915_0.22942564895210982"},"_hasShrinkwrap":false},"3.2.3-canary1593026645.0":{"name":"tinspector","version":"3.2.3-canary1593026645.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"7c5b7808e61a5c8bb3fa768a3083f47a2cc28426","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary1593026645.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-4qtpkTcpRo8iQIMM8F1KCD2zBJpajvg7M02xm4GY0fdSSnXsKP8t2brq5YU6aHeJjvBAj8vqz6QqZmamqbmhDw==","shasum":"55fb3ab3f8929b870ad70011eabb757a9272c8bc","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary1593026645.0.tgz","fileCount":23,"unpackedSize":63006,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe86hYCRA9TVsSAnZWagAAgasP/2s7hHh1wZ3dPJDm6h2u\ntxr4mG5HKND4f78XdpuU67Krj9VtFe0yK7PI22izdzuK3aenEQB66Z9jAEXU\ndpAKNCNmFYg0Xyd0ch5tm7qGaGhAj8Bo3cP2Vkfz3kmeVU12hWGuxod9E6iA\n1JDyVf2ZX+WyURSa+kKnab2Iw/7mWEaWIJJu4z5j+kH6i+Pc/4PRmGYhycam\nJN+cMPMAS2jlMkyVsNZnNrG2zrKKnaFOE5cejTJTNcmNUBNaoYHMxd1dmvdJ\n4+WzM5c7QrElr+JCm+ZStds8bz/C83R+MGhH1DkhIKQBcb9n4m68bAd2fHze\n+e/ohTJBHqFY0UCbgcGyyHAqUTy+UGQm86xgSc2zT6P2JY3PnjZtFNg/N3YM\nGfEv/F/pGWwt9bwrHLkyBdyBeJkT61FQtq21IzCPw1OSzjGHnqxxYaFp5PWv\nK3Apn2m2p+iBEbLanCmNB7hd6BfZ/DYZixptzocqthMTt7s26oEeK44VSXrs\nMlCfzFeAp4w0qzzlYCoG2nfszyUcLkabhyi3ApWoJMRZOgH3NXogFK+h5fmn\nIyMzdWlbrG9YsspVadzHrxs3Dr3Zxc3Ey08ymp7MxqhrIXSCpvj4qYKMSqjo\nR/hapoHZxDLGF1HS/+98NLZGOWlurjk0gK4rAxv1qVqj60WyaEQr+lR9o+fK\nd94L\r\n=asjk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAzsqFWmZcLWbCH9ZqYtaM00gCZi7U1YtN2pU+/jD4kVAiBIhyszcYE/QKzg6QJsrTvTUNzfvHR7n178+9KYKyYyGQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary1593026645.0_1593026647852_0.6196305172826766"},"_hasShrinkwrap":false},"3.2.3-canary1593069049.0":{"name":"tinspector","version":"3.2.3-canary1593069049.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"0d2edd1c9bd4933a5afb0fbdfe8ffa53cf43ff31","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary1593069049.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-8uF4l7GVU2xxvPRiAT22CeQTvtp8cbEhy4KfZbCHb1h9vZGDjOo+1il5e2XZ+wNAmHJLznVHYaYG4mk7BAU11g==","shasum":"b6fbbccabb5989352189ee77d8f551ee3a2f6f16","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary1593069049.0.tgz","fileCount":23,"unpackedSize":63006,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9E4BCRA9TVsSAnZWagAA3yoP/20/j8Cqdqs0Can1e58O\nkuKPjqUTVjz3+HM0//4huY6dZFINsdy1kC6BRk6CpAuZ5+GWi37g0xdkiN07\nTfJvMgk74DRN1xCU6PaNmwlnGBN2/Jm6r2Hmu6F95QxeLRcVfqGs0fyUpUat\nrP10xye8jRoIAeywIUa63ttcG6QimXaJkRVzZ5av7RjFCpQIUA86vyn1YlNs\n9liYUBrf6SifM8XSmjpXQhPsX8Ns/bpuTvLP10gvTkMS6315khQMn2IJ/ypx\nOOOL0SaQrG5etiOw8gEmKMVarn//N88aHdlvWmFO1atEPiG8nhAdsccybQ4q\nx+BH+qWlsNPbQecDJo8UZKy79qDi28POnhBVscxBD9pgU/2ztYo+hPtZmxVZ\n3WbxpINFzEpa+XKOSDzXVjcz5hthQjzo1dvf+X4uAs0eoz9nyuE0HDVyScXt\nwA8/M/Bwn+hvuqgrtfMOj/Oq9bKzIuJEDYJ298Iq0GvEVdc2GZPbrBMuFDiB\nXZ1VB3tkiDHPxacZSfyVtuurCYaCj+XO6y8Y7KISdUHp1PLRSrW1Z5gewWU3\nL4og+C6IJtUsC5ixTWg+QP+JT4xZ7GFy2x3HE/nOgsIdgGMTstmEUhAKGwN5\nR4kmZlpScLJSETlHIrD8zd7HC/vKcyPovb/Tv7CSihoxIOglMbPDL38NOw4z\nfsbT\r\n=SC3N\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLumXN5t/eomqfKCEV5rnh2MENzWivJ8F05fW11bHzGwIhAMauGP62QbbDmiJ+7NLftelWrgk0rdR9D7gTBNW+6Bar"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary1593069049.0_1593069052933_0.027655937891369664"},"_hasShrinkwrap":false},"3.2.3-canary1593125083.0":{"name":"tinspector","version":"3.2.3-canary1593125083.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"fd9f134964f69f03a1aeba6b8ee3f8385cd9f5f9","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary1593125083.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-E4QoaTiKvliIperAux9/mOE+FdL2ectOTuJM46zA635G2at++fsDr9NwXEdud5Nd200N96uTa5Im7JEUzU62UQ==","shasum":"6ae2f87435cf7eddc68f1cdca2ecadeaae0cf8e9","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary1593125083.0.tgz","fileCount":23,"unpackedSize":63006,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9SjeCRA9TVsSAnZWagAAcZAP/jijrjv9bg9Bmtiq5eVG\n83Kv89MIpW4/toOpg1GpKJv7OhNoeND7nhUQR5Ow5cYRYBNQpjzTSNTOOCRK\njVfcOPFRdvc+X6EZurc6zJVOaCEnGf/izBsCRW4nTGuCtLUnrw6V2tkIa2m8\nqUUmNxlND5EgIcl8chlWUN4uKD8Sv8WITqprM+w83UO0aTYK5LSDrz6RsRar\nMeRDwf3goD9qpK+FEZq3YEjFDHmXRGr6yAUjcnbY9QTmWpZ0te8p/gYnNmz0\nqJqhCceVZ6rA2tOSo9s+lvS7fs1AiHLVIPuQyeY609mdKFhAEqaOV1TUIgQo\necbj7v5hB4VZ9x93uW72xKGa30NtSTkO3vU/KC0C1eBUkhMMyzPb4BIay2KB\nUUB7ns3GGsGlU6ZAn+oNKcTAIpUV5xJE9Yr8SGcqyLZBRA1d5FaR+/85cl9W\nEqFNnjo6HkWHva01C972cjQT66x7/WwurQHcmk2TZzOV6ixASekjrUYIPTzX\nBgFRw3gSxQ1BprzJBEw568pWUxm56gtH/jZfGrnhTn+FFU+lx9M54wdves1Y\nPxWD6arNNUKZA7oWW40nRS4tHKpnVIUSdlv95skvlATbdPkRokEu3ATStQWc\nkNrJJq7uELfzsgYcgADT9vDEzzG1FQBDEjbq493yGuY5Isqed+fI/Gtg6+O2\nSvso\r\n=6beS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC6syeGMbJGliNJ5rGWqagH2LpRPBzZjr7dBWtL174GrgIhAJXD6BVkP9rmZ9NKmrKgj0dRqe5zkkcsTVmAkQ0D8zU6"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary1593125083.0_1593125086398_0.9348811797398608"},"_hasShrinkwrap":false},"3.2.3-canary.kbwv88am.0":{"name":"tinspector","version":"3.2.3-canary.kbwv88am.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"078d37d1ba9e002ea2272403880fab107a8c1817","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kbwv88am.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-TSbtfsqiJD1vmgbPeaelJYulPGEovNpmr9zPwmFo1WHgwn24qWpP8/gFp4Ttl+si+W3zyG61A18HUNRFE0VmJw==","shasum":"9f2c1adea925aca3de355d71df92b25b7b2d3e48","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kbwv88am.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9okbCRA9TVsSAnZWagAA0esP/2IV2cx/i4BB7iNtXfjj\nLMfn1aIY1EQoRsTfrcNs56UBTaORfPWH4+URjq5ham7nZgY+2CcTjGCZC0gM\nf75g1RLToZJ6ljMOz4LL8scP493QQocM1zRA29Jk2Wd6rCR4hEn5EqsAVyUz\n54ar1Ck+S2D6VY03ls/jAYnPD8Jqup6bf5j2YIiV0ezGTRM/1p0JtLKiyOEu\n8ocbTLEHlgVh/yEQ/JZOe5xYLO7uPNc8XhqpRg9n9YgB+zYwD6Lrebtnx+uw\nMt6qnC3t6z4TTzugO9tpXqmMNJaf7NktKE787mKWqweIf1VkdG+k+5JsfhYZ\nx+eNd4X4KCpaNV1ozjDpXnduwsOF0YWIoY01UtbNuXhk1oJPuugTlh/svDbf\nD62lDAKHOEO6+iMk3lspJ3RTlbAtaL5UqkEVJv+W3GTec34KiWVd7D4d/Xsc\nC9Qh+RekDgcMcJQyfKTR/YFBQFtSk+GezzWMvIH1MyR/wrOWyjKJttXcjNKr\nOdBvlKSeMpm6zzpvNHkQWSbdhiE95BTGrzHWiNNEJNkGwGy1qwgrWnC4CbQq\nux/5QB7E9Yh9YPLMxXaNbqCKqDLv4LgB+bvk6SXDeOubmrPhCH33fnqITz8w\n87TP20m+bx9wOL6f1z6b2CoD+9eXheU2T6j1hkVyM2yFoPrKyv1iNZqL1UYQ\n/V05\r\n=JCgZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIApIlYcXupmUA+yClYEoLsqiGSAjhKuqjOM3fI7SJDdlAiAdlMzT1Crxctg0/jqOaZs0lZcqM4qZ3b7xm0AMwJ9j9g=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kbwv88am.0_1593215259458_0.6071670374698397"},"_hasShrinkwrap":false},"3.2.3-canary.kbwxgwmn.0":{"name":"tinspector","version":"3.2.3-canary.kbwxgwmn.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"9e5872096730b4ada056db7bd448b509f7950c67","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kbwxgwmn.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-yA109fL/g3LaWc++5B0MPQ0mSZi7W3MVhyMdIdIEqVVurwiFRlqI0DHlbPP0Codt2BxEVEEk0Es6Vigb0xhcWQ==","shasum":"3c3c348d33f8bd25a9d7883ad4127883ad34211d","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kbwxgwmn.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9pfQCRA9TVsSAnZWagAAOJUP/2y+xrUzxKytT12KV+i/\nnSn8nUPzygQkK7wbj1C7c3szWb5ukfzS48uNyYe7Y0HCAKmzg0Q94o8MUqmV\nKmTmiCA5Z0aovj7/oIDmK/PQAV0gXfDyyYv+b3PQmSQtgr1GSeIn1io35IOJ\nrwl0ggUhW0RzCBF5IaPIkxEY0O10bTfECYq9QBx9uIMzK9uagB56mHnUfNAd\nu/Xa6MBV7JHLpGUyDvoVyAeH/A8UOqT3Qwzd1oTUXXp34Rnd2SCRqzzBvAV0\nJOabGpNjhHMpahsqSDHpOMKYqea7PiFGpqjHxtdSzvBd3fRL7E3QpfqaGiZ2\n83fxoukpL+smZ88ttXdjyEdQTgGmhoA1Xos5N3Klcu1h70zVrOM8TR6WS1yN\nIcKnYbv4q7M3iQmpLRiLwq7XzUFeYvQDwSmEH/r96/VIxjnd5nzZmbmtrWj6\nFmpy/72E2Dw9CXOskDEZhqbzb5cJ6VMJ5u8lXevo4LtYI0bUnT82fuzug9eE\no77bV7CDNrfvjRqSz3aYVq15JU5nEuIToxORaXkeJbEZmrcpAp7pLXv9Yzk4\nh3KM/nNCcenNDtLsCHgDE5VWFwLTK+N74zdPYVtivd89D0EJwxoDh92UxieI\n/pfIBeZapru5FOdfuIWyTaerI1926sK1BiWQtNu1udvJpNeTe3D5xze/gALb\nhUP6\r\n=u1F8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID1byMxfJDEsSdlTWmHgY6fu/ZoHIH0kWYFCFi6mruj7AiAAuvy5JH2R1c3au2MvftVORe+OXN8DzSMRD55GREyzkw=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kbwxgwmn.0_1593219023983_0.6673130747580984"},"_hasShrinkwrap":false},"3.2.3-canary.kbwy7dnv.0":{"name":"tinspector","version":"3.2.3-canary.kbwy7dnv.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"8340ceac4818b017b05164ff69bcc243f950e96d","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kbwy7dnv.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-jhW7TpB+V18M0JUqPLO/8EV2x7ldZ1JhiwSd1OQd4C8fzijfc0Kge7fOa2e4yVQ++94PY6wB2M/01VHorM044g==","shasum":"727f3d3f34b910e6833011b1b1bb6d62584c3d44","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kbwy7dnv.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9pyjCRA9TVsSAnZWagAAgUQP/0WVMlVaw7OgzDesVtY+\n/fFFjkpNKGb6jhccQC4H1pdqag0won7d/CSMlPL3Xti7Gkq/Sj/KcCBjg+nY\nnYOyWsaZxE+KXWE1TRVaUTZcXCk+VkxZaeabycCYwZ82dZrtH5TktWPlx/RI\nmdrbWwrS89uircT+f80728JePF4mtroXr3bnZCq4+MFWqdrYPl69rWYnROrU\npDx/V3DMHznUtss//yfL/AwGOiEkdWwMFtsyWcw+pN7n793Jlh80IMoQeFO5\nzAJshGQM3HMNXNVVXGR1MojxoWorzfJO1S2CteTa5PmZwfe/iySwYRENWy4+\n69QgwIaEOh6FNG1zD93NykCg5OYBnwprZ3EnPlY7a3A4H6S2xv8lUFG78Xr1\nVy6KTI3eW/epaI4nnGCOwV/1aCzJLj0yScZK4kjqmiy1HieZ0xiENJEYH/lM\nwkWmNfjluQVSo73eI6exnmqpA3BgGsp5GnuYt3l5mBzxws1XZylLkeBExYMA\nhV+qSnxeJ3JT+xVQYsPBwp15QU77zXy+a+w4D1CqcW1rky/KI+LbmIri3t1I\nBveGd/+xzaD27zmrNFOJswCG6e/0FGU96e8+nV3+NPVak/gAly9FUXaDAcUz\npQRw5scud0Wn5aiWwZ56HH2F/EsvdqSD55npPBLfZN7WZqLxFWXw9MNTHQPv\nUAvq\r\n=DfaK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHNftfQ3T6xRusSKiqkZgmTXI36h8wt9Ge+vtWHulQJeAiAmLyqCphZwAEweK10sSLkE2IbjS4OGdBAHZtFIsLPTWQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kbwy7dnv.0_1593220258804_0.15862410317174436"},"_hasShrinkwrap":false},"3.2.3-canary.kbx8uhbt.0":{"name":"tinspector","version":"3.2.3-canary.kbx8uhbt.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"5c9fb4bbcee4097ea4518f571c46b874f022c260","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kbx8uhbt.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-W+VoLm5AfEVBkim8UUtU3j2ZWwCQ65g04H5ZLhXoe3PIsdhQZhcK/pemkpfUl/WT63gyuRNe41tbCuJbTl/57g==","shasum":"e8f5062aff3c880f710ab7c1a2bbc8f67c62580a","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kbx8uhbt.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9uJ1CRA9TVsSAnZWagAAT0YP/RM4EwDPA9KZm+Yy8nfR\n6Djm8etQQ2oVuBLd2pRHqE43AYZ5WckOxuZ29lcVEtgbSDSHW8rVKCOopF2/\nvSjBCmpAttvbmtDf7VR3P+4ZNF4jWvNLaaDRhOMiU0rO7FQzFuNIvXIg7QqP\noMC297ZbPppdYVBlA321rE1pMgX0+kOBlRh/+SAgrZVRA2o8tRoqLU55TACP\n/G+I6DwbKm74w7sWmnDDoqeXz4tIz/5g3Q+xB7S1f4hpneULsCJhN8I1DtFR\nLWxdD0JKx9EN9b+tWYtKReibp6b9FTq/Tmup2OzBmnjTIecew3T7EK+35/9n\nwTzhbwbvHrXFbshZvtB3GKB2brgArrMvdH797dohnyvjunVrmDc+DGy7P1mo\n27NEVV5OgaMevJ8ywBZVz5tUq9KdXoFPxHs8kv9skZHSaO+UiNl2QoZHsvrT\nqqhHI0EIPTHUirLwZCpd4CPAljyF26o7JQ5/X7QQW8Rrzi+MtRvo4SXrofYS\n4WP4o28fvKF8IfdV6uEDuRfMxml0FvepSAI7YElzc/3ERjlLwl5lab2MNTU9\nywVO0gvFwO0dUhV93UtiHGqR30mr4a5f1n+alGDenRxuUDHBrPmyhpq+ZhpB\nHurSczp3Uu31jKQaaB+4BLUcoOQnIItokJ+OS4mLLEh7UtfFLfBY8z56f9Wq\nzH8B\r\n=XAwL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDA5MalsdiDSkRtXNLTzeBKB0XWH6dHUO4iq/jihxixVwIgC6DKQOfjKn3vcrrCxqWkgIpsJrEEJab6jr1kKni4tN4="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kbx8uhbt.0_1593238132913_0.2153157942619628"},"_hasShrinkwrap":false},"3.2.3-canary.kby6baek.0":{"name":"tinspector","version":"3.2.3-canary.kby6baek.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"3dcf2e82f9270aa8077c641dba77ee30d287b0d5","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kby6baek.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-9XYSSfrbBo+bZc1gH5siLCzOrS/Y5/p0FoxRngE69MRgRxWJ2VabW0rOdJB5wAipLRZbx5Q2RSxz4ZaQuiVJ6Q==","shasum":"15a304662b51646160cbe8e25af8a85e74566d8d","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kby6baek.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe974JCRA9TVsSAnZWagAAmCIP/1luEkGKZw+4wzOK9dJq\n8zYemybvXH6hpRM09kMq+WC2zbr0l2WoCN4QsDqYVYUwGA0h/uv49z23/fkN\n19HsSdMIIJ6GSWYDiBIzQtoP35Uyso2fpB4+qQrjHBTNne1uGvHHK/o2spKB\nsChV0PCUgZ78MnlBPlN8fPN5CK7w+tH8DmbEjHX2a87L3HRlCBck0vm98GLT\nfGl+FDwk1e4srMUs0Z0O2BGzGG1bJJ6+FrS6zzfuOMBrAUKZzD1THgbZwQlk\n2u2lvAgtHzgNC/mF3sOEmunmdZc6a/qo5fssRoYaNqGz56X72DuPY7xQL5dX\nBz7wvQOl9XS8nPmSn/CLzNxhkHXDt5TB5csDj+FbKMS3x1thYwu0z7eVF+k6\nTc1boofnJEmTrRZSLJvA8uDodNFBlEB5V4TT4JREJ5gWNT4xN/npy+Z+IW+r\n1AAaMD0HsYWWMeqTiZEbqt/4VD4INxayR8MLN+pwiKAzkbsDRGstioJ8IfMd\n2Iv6wSUki6KOGjOPvjbUsPUs9QID0eZJxa6AsDva3FDmdxIl5sAjkp3us1hZ\noRewvNotTG52yU+4Q5meXsgCNlfZM6OqITae8pft6POZ3rMEu7hlbGFgYFIS\nfdRF/IMVwLIIC6b57AGGLzUIVQ/89oV5CPq6wol081UFSjddGz0YgFmP3ZFA\nefS/\r\n=YquE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCbVefoEXxLCSdmuyCarmFgfcQICJP8G2w1puXD5p31PgIhAKFOQUoAVQjRLXTkk+XWaLxYBd7yMQG3d0kbhRnXmK9V"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kby6baek.0_1593294344578_0.5438512409959364"},"_hasShrinkwrap":false},"3.2.3-canary.kbyejgob.0":{"name":"tinspector","version":"3.2.3-canary.kbyejgob.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"cdf586edf2c62ed689f8b7bdfed8605d6802908f","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kbyejgob.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-ocN1L0hV9IdUph6aiQPNGvEBaFotgLv+LeUSZS++2Z6V97leKSty3lIYdAZwS0r0uKlC4PZwtGmzc7OftjinSA==","shasum":"5f09e05581d8aa1e53166a1664444f17a3a7ec31","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kbyejgob.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9/QDCRA9TVsSAnZWagAAnykP/2qHwEcoqu629WRZ/z0y\n9ZnCVgcS2qxJn6JHLvA4unLDmFwwpYVHkbQv++i5oYmCrt9rw3JZZoyTAGXC\nRGMS/KISsqZRdMlAM11Hh1gmkCDgu/m214o1z3E+AN7haaX+k+cWjIJISl3z\n9atF8BIXZfpcQ129KU68vGw7Yagsknflt0hBcryzCpiIg7oVmqv0iVwqsoY5\nMSuNseLwDgTDhCL+pa4h3GlBwTPQqPOL2rBX6hiFI3IfEN28XhK5dEdUzqCs\nArhwFPrr2ckcjOc5xyg2xGtqAj/UvxDBXfRl0V+FLz8GLh9Y/2D+Y63VBYbZ\n9oJq50mxmAjVS2VbvtbvJl4glZjxikskAJtWv54zTAW6Uy4rv/ZY1+uZCxEM\nre5MYrYDoNtcWlw/cr6IqXOInvU7xknbySpw2BtvpGAkWv+SLM4fc0YXT21j\nzYgcgxb1lw5N15q9VQ6nnsAhThG+2HqVvfCnwSRzM0E+sJGhLvTs7SNLrfoO\no1LxxieXkp3/uLvmWs+wbiykYddsc1BVy3BjItOCtAGGEkgsD/73cQe8kBNJ\nSVPol/P5Po6e7mjNPO4KiQtfHTiETytce1lVNGCoG18cbUSFhEcGfbnjzOc4\nkkxGyOHE+WU4wZyd+tHQXH3JXakYQ7QD7N4GKk67hwaX9Q8WrozeMK9IiRFB\nOgQa\r\n=7jzM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCWCI+pnSdexe228ENedMZrniANN8UyV6wlQZQ1k15OEwIgTyNMqRcCgyeYNSM1dcaDF4e2Wwp4h/bEIbTTfe2YwHw="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kbyejgob.0_1593308162889_0.7362919408814448"},"_hasShrinkwrap":false},"3.2.3-canary.kbyvfeer.0":{"name":"tinspector","version":"3.2.3-canary.kbyvfeer.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"c34b65684d8325dfdff30fe799cbfdc5583d06de","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kbyvfeer.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-IMQtEG3dvhAx8QWOilMHdkkpkB33t+l7jazzi7Sa7dvtI+Udz879J2Zbz8NZw0yO4h3fMgKs6yGROVts2kzODA==","shasum":"9a0d6aea9e5e8cc9330f5b040e9ac50ceaf0f9cc","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kbyvfeer.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe+GLQCRA9TVsSAnZWagAAK8gP/1zVkCePFfQnxrPVHT/X\nDjztB0rHqjuQRhSlEXgrvko0UNBrs6os3BaNLPwacMGSOCcAMTqMOO8UeiYY\nx8qSNkq99V4OXuTOJoMX49Q5ayJZMJlZF5czAa8PaT5mWdO2abGqYx/pfULe\nEKACW7TELvuVepH7Ja+tcRh6oTgSEa/vYEN9igef0DdBGztmL3T6S2LAuBNF\nHZknmcGpD8rlLzcFJ39vg77Vlq5edzjy+hAyqR2P4JqpvgTPwwHYmcQ8EA3x\nvkblrnzka2XlNhTtUvNZH1FBOrkGWEwvHfncxYdPxJF/wdKaohptbDVQ5aEo\nJMMyGdJ36Ou5QYjQHD7IXQT//yiXUGbRL0g0jcriYj3KqgdHrE5QybJgrAID\nlSp2DZIiFNDB1eH0RovXh3br/8UDd/k8JMmJLlCaYIYtzueWW5iExHdpNm9N\nPX/kRB3ANg2nZ19HcC+caq5edhfNl43VqOdI/0hnaXIXG52FKXGH0Mr5alH9\n5nGQcasC2EYr4der5Dqx9xRvSG9HkhQIguMsjo0+djXHKuVd/TvUm6b5L52t\nNrcBSrG3RE2X6tV0nSM0Frj0aMypp/FwZS1iqo5E7jefcdotxklDZswyr3a4\nyjf+Uzfwqim5JOhDNPUeuLPm5RPpl8rZhh0za5rlYFeWIZbn7dCQelPRXw9w\nFeTr\r\n=XMVF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAhNY7P08Gqagw2UYOKBcIXI6/bLKrlUKi0vYubLHuJFAiEA4ETohbQzy0xMhPAUMQQM3nxVtPIPJngk8y8+PLWSwSg="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kbyvfeer.0_1593336527509_0.4829157686785872"},"_hasShrinkwrap":false},"3.2.3-canary.kc1bv7t9.0":{"name":"tinspector","version":"3.2.3-canary.kc1bv7t9.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"8b07711f7c88b02d9a92012c50917c7bbf3f47a0","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kc1bv7t9.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-smzm38CMrYL4zSguOrG4y3E6Y+wKT4Uscjqporxkht4tS6b6jRkmfXJM7fevAkExEG/NemXxTe00kejYS+KsJw==","shasum":"52da4d66d1ae60a07411951c5632e0a2b502c557","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kc1bv7t9.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe+qcPCRA9TVsSAnZWagAAMncQAKSW4zrw8fDRi8w4SbK9\nO1CDiMHrYUmTu2ynlbuDfnPXU/8wsyA6/S4YN6f7IoQg2fQBcALB4EUCVP/C\njcG2W2SlwtOATErNQAq/gHb8W/uun6XC1Barwrq/kFlA1GAVX1ApRuElKfOO\ndhW2bonwlL/1JBLj4NdifM0wqouGueRET3fIkNClRHGP3bTdh4giQcbvyRRC\nuAkmQ6oLzV7haXkDHSer4VUdcWfqxyGqqcanYLTBjpc8cCzCEaZAoUcGMAse\nheliXhW/Ak4rpzQsBT2VNjdo2Zrm6d3vq6v7ZSXHQ6ZklHW60DEJWE46go75\nn7H9M+pLX062hlBpMYq0sVu7LV62CADSwe8bND7cpPeEiLnD/V0GSldSFo+C\nthgC5+lT02JCSSkAHF65GRVybYu7zZgH6UbKSPkRLKsVmN6t+ipGF6A1eHTW\nHnzFmeMWGWaoDX4VLadNZgI27EUjzYTpD/KyTcSqenZsoPZ76WhdR/kwm230\nqIiJIz3f+5KJBRtE045Sf6e88OfEkBqrBUYkB6AUrWPynjqY0l8RnNmw2kYP\nS1DSvEqa7oEY2UK+HToYM0GRnLMAWJ+VAggph55fG/uLC8TPizfDlEACxrRk\nt3t+2M3pSKiN2JPUuUdnV913LRherx7usBjci8aVPc+Mc7QHU+lmVyAqeUrV\nLfiO\r\n=BGA8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIArhDo2YJae6XIcbAFgiw6g4v7KRviM7/Eg8Z20eKnsEAiAkxTWQ6F3RwbmZFiIAirNuIqn9bHoO6jZP+cokHX3YDg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kc1bv7t9.0_1593485070597_0.6051686299509262"},"_hasShrinkwrap":false},"3.2.3-canary.kc1j62zf.0":{"name":"tinspector","version":"3.2.3-canary.kc1j62zf.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"2f98d379811b8883be0add0184d0394e516d4099","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kc1j62zf.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-QSMpcwy+DG9ms79woLsiYr/aKDuLbkAqoKFJd9xhwKYWGKb7tGUS9SoUUVcuEK96j9F/99tJI13dbIPcU/iYjQ==","shasum":"15ca06aa3b39b7ec4d1a3813a0e8185563a117b7","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kc1j62zf.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe+tb3CRA9TVsSAnZWagAApRcQAI2+qTYweporUV7oov+b\nydJN2YNyZXu308Wf3tCnPnra2/GjEAEIuxdJlWXvdtFXBZH56nF5AyyTx7Rx\nfST5S0UqMKO2YpZahz1rMIanVWkGD/m3kiOuoBn6zgulCudLcrH5d1nFP9CN\nUctSg8xS8vndpTw/2AjCR21gNOW5oRrc8Ao6OE/jRAduIH6GGCYrfikJmXV2\ntdrCfOXkDO0mbKXWXBVZWJP/L2R9uVrfsH+bfsfCdTlMxABBF73blvxM/beh\nsKZqs484cyA10vMTASRaPgzDXJJT6tNRWoTMGwfpwC4Ga4p9VVmIPMeLJ6PM\n7Zfub5ONJs+5ZdHk/oFKLuu3WXDyzcmFrYQ6cshFSKf5kylcdzLHlQpDPHmu\n01s+g0Fi+UVdLCA39Ro1mD/wbW6NMqkAFN2HpsP6z3H35OVMKvRu+BfuDL1N\nUxHM3g8DCmm2q8lisxh+f1nk/VWoO9tgKygVDR7mnROC7xOlcwGophlPiqWH\niKYdZtqq35uuP/27WzsIkDMDermlYhY2DWaSFKhYPOPjii88jL7aVWcW8G1r\nUbscsTMO07zYH5bieg7aEpNOLkl5nq2uuehraPatTV1T372jSDHuJX3GCMWt\nKWldGkhXZzBpcVkBbSfW+v8RM2YXhQltlUEhg1qL3eZoM3tPdgnQSRqEgVAx\nIlhd\r\n=eFLD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBbnGqrhi22fTN1H9eldlbbcYy5yJOJbypQdPHkLuhUAAiEArJ2Jm4KkisSE/fWvN1gjknxc2+v6ocpgZYwvsJKhxBc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kc1j62zf.0_1593497335242_0.25604458201169233"},"_hasShrinkwrap":false},"3.2.3-canary.kc1pwqwc.0":{"name":"tinspector","version":"3.2.3-canary.kc1pwqwc.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"5a00072e784b732caa800ce0ceb07e6264de1384","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kc1pwqwc.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-tXYIRENuy1oTbdFk7NCnIx55BwYRQLOk+k+aXT46LFWkg8Kz5yJq+Ozt0cPToCPWuYuT+hlJuB91WCH2JDvRuA==","shasum":"2fd94d752a5f373648ef90fa3fcef6261bcb43ee","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kc1pwqwc.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe+wMyCRA9TVsSAnZWagAAC+QP/ioxcL35b8KY052EAbqx\nuJVobgqYEE+aa5f9ORhNSgdjw3exY1Gn/63xmOYj4fqNWKPVwdphl8nBkceS\nszYyRABFjPpNcQm+mEgPQYabAIhcRGCVS6sZK/EZJ4WxKCRYz3Tcslg68JvM\ncRDo15QJxk7X7NQvr8Rsmjbn5WaN4AyGGBZODIHj+EcmP2zMB9xQ2TRSAxd5\nZNnSEblO4JL14sVANCtO2pFWc2p4Cnxu9SpN2qit1/XM86RYx6kItK4y23iI\ncZ8zCZgttngze96fISDw6sTLPlM7398zN0HHrGBTEAQ48g68ZFSEizXB67t1\nw9QbK/uTEsZHyin7d6ckK2X/1ILBO7uu3BTWVa1DkLflp8Pg0CFeBK8AsWTX\ntPcv81WKbwa/u+YXsKoAINd8AKmxVpZV6uSjv5Fk5l4qTxPsz5dVEDc5RlWl\nTuZKVfe/JBDpKNFA30BFu6p0cxjfZqqd8DG2O8UbsnCCHcX5m8vUQhtJ74SB\nKeHJxipAFo+ekHnVeK+MO/fvX5ghDB13pZ59/IcsMgMZWk+rYtANjiXdLYHy\npf34pC5ziB1AzyyXs4m4jwVtveIrnwboKTfog8UVazcORdLQRJJf4Th8vaGw\nNQwZ62qoY1lev22H9u+RWqdRBo9o/KEPB3CzK3xy2lXPCPRVQfVoPUbIvKgi\nRAP4\r\n=mu5s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDGm1Yts7npzao14GPTheXePzjfL4vzBTjZWjY4pkfvVwIgSPX1uWaSF7X6RoFotmlDZay4X1yKS308OJzU4o1W7nc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kc1pwqwc.0_1593508657845_0.9284182420914309"},"_hasShrinkwrap":false},"3.2.3-canary.kc6u1s8b.0":{"name":"tinspector","version":"3.2.3-canary.kc6u1s8b.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"adec22f2ad69278c901d066b154114d5e0b6d1fe","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kc6u1s8b.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-9yTYhH/wbMAYcCAbtQq4BBhIEZRXRUxIs+wc2Cy1PqoVdHGMwM7p+PJVJ16w6QlQ4m/9rsQC9kGDvc1fVcG98A==","shasum":"2ec5eb9ed1c73067a1967eec54c7dd8249419249","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kc6u1s8b.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/7tVCRA9TVsSAnZWagAAqioP/RwqQz+iy6bPL5mlNk1t\nOLLehczpFVhbwaKomGYXy2oF1bRM0aWRkizJxNmsO+/PGie/PPEM8/FvpMJG\n+qIyhFOa0Q7BGuZyKqDKOFBb+ECBVnQ/8MYfsXShV5/SIL1gnZbBcRRY8A62\nle+raWXBpFQhvSXrxMnWoY++gSzRbQKwmwqqxW270ZLh4tepvbUNs22O9WRs\nOfMaJoKb1eN1yFf6Z2rssAka0+0j4svJoaO6xBgcpKP/8OTVMZLr5sGGpHHi\nqR5CS43Zs5+raZVFyQD7t4uBc689pcZVpLD2E6mcs371W+JiqZfarpvTwccm\nkUOx22pDLb8e4rvE0Q3wDlA4cnwV1tazj9gmXeKcLdmgutZCmFpRbW4u24K/\nOB5l323Ujic8t8QnJiRaRrU3X4hY5BGoZrN6evaEHN3OoRvJ370qeSEk98vw\nztYoWgPSvXq5aJ0kVs46JJ52KMcW+Mc6ZabhHrEtTql9gOAKQ1M9MohEK4Fh\nZ6be0o1UrMqTSi9BXzzb6XCbt5P+8atT7bybsftHFC4zvRMHqCzDknqwiURS\nh6a86AMGQ5KLqW01WXJyLKkMpKxgI8a9FFbr+8LFg92qgdPEQk1/FEk6AK1A\nhMU8PoELXAWwdWE1QprnQssvF9qhJfb5IsWU6s0PiT3oUl8Ov1D0kzL/5NQ0\nDJ1p\r\n=Grhz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDW8sZgxCoNY0EzEdjDuxmRIhiBkhiegPBgyB2+gKbMZAIhAMcrDKN2iH9e/WyMj9GmLab/8PaVk6gxUz2Z7J4WCgAE"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kc6u1s8b.0_1593817941326_0.6168494929313417"},"_hasShrinkwrap":false},"3.2.3-canary.kc6zqei2.0":{"name":"tinspector","version":"3.2.3-canary.kc6zqei2.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"5053ec1594498080b795e4c92800a3b4aa5cf601","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kc6zqei2.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-/Xzs11J6VYi4Bkzh31f+l/1AgnDYR9Z7MWvjIjIEpuYhPhX01HeYiis7kNZbrB7wffap7nQ4wrPpXqUGeYZaeQ==","shasum":"43742df01bc1a4d6cac35bf615b26a09e002865b","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kc6zqei2.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/+CgCRA9TVsSAnZWagAA1V4P/3aQ69n7oiaE/5nRaatG\naVMn65lk/Z/YPWjbjI4wcT6koaTlG0lZD9qXhDWm2V4j+7nET2Y7bqIQ7Q29\nja8pBonyiby+EX8WEvD0msL2O1JeZIN+xmruvpR3Dw+H161XiOrbGRGnBQ1v\nxcDqeG5IHs6QlDRb/Vlv0ktHKtiAPJDKXFyvVZ3zkiUsl6GzEYqk24uG17qK\njoGxIReH8LKY8TkmHKxByTjTneeZvAW7yfMqvQ2Hl31kT7VC7L7VXIXXKIKn\nhKlKqbhF0RLiT44fRKpfdiXRfASI018RbPqThZkC+qBsp0cd97otyVSqwsh+\ns+Z94mnxvMkbdxixnl1PNCASYR5NOYJBgeDu9k6zd/pvs1NEJSBOFhu7sy6A\nisg0rDHE0A/mrwlc3i0HCqwZjMV6V8obe1lXom901ZC8vyqY9snvEAoY6Le3\n0pUokQScJrAZD86CMijFdCtaSPqnZp2hb3SKGW38loeOeaakJDvaOYIG/pRO\nURkSA/mMxc/iAfdjWFZ87HaoPq9tlmKIqpm0cefxF2PKOSkaDozLEPAmGUaC\nFViUcF/vmvunolqn9BlKp6QkeXfCYTJwjPzEqhaTtVmBB1zldarI4P+Yun90\nWHRx51sn0RCv9V5sDCtlJ0UMrQvaTiUDVt3CJZc/CjTEDytUxgz+1ACoJaCX\nLQGx\r\n=rg0b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQClyvX+W1N38al9WxOjpcdqelo8Ly55+TqzQJXjswubMgIgWJ4W2HZgHMBrvL4uiVWJUBW7FKV7FcPdM+U8vQYlGwQ="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kc6zqei2.0_1593827487922_0.5605018879221624"},"_hasShrinkwrap":false},"3.2.3-canary.kc7ailpb.0":{"name":"tinspector","version":"3.2.3-canary.kc7ailpb.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"05f574952f8f5ca131844e05d992fa7a2698f3e2","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kc7ailpb.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-ebwjRAsTqn9raWZ+dlz+Vy/Xu3nMJfjAhKsGwcgSdHkfvg+ufcLOU5ZlKpvovxlDmiR6cDEdThleV0H1BmoE4Q==","shasum":"31f9e88036272b7f4799bfb45155b257cdf65609","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kc7ailpb.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfACdgCRA9TVsSAnZWagAAgf4P/26rWmcvC6l0WxNOzBff\nsjtG3jeGqClzE9xxINahFbyofmuRPKGYWeoP5DqNv4pAh9Bvpb8+EGrr6bgP\n54EWzipaS519yAicYcutMqUtqnh9kJUchV6I7TFnYObXRO8n1KxR1tlKSSma\nedqnJvtthKd9sQUH8fsgvnyVcDl+b6fDCdgZzP2cGqp1jRbyB2U9pHP2PMWd\nyYYMqlvhEcj7Rw7MXJ/an8mZ0u6ljSljjYa9TDy9AHBUctRyVO/efEmG63Va\n90k3NPMDTAugt7L/yFYygIyJfPofa+bqOaV9Z0Er+3Ut152rbJ0dxLV7tX2M\nTntVCLbWKK186QMVm/+x1sm9zzWJnrhodgyzqy5BGRF7sBvU6pRzungST/tu\nWVA8BHVugtnbigRNm2wgy5NLQAn/o7X+vVZx5VimMAtHiukwrLZGxIcP3B9D\nJoNlcFhE3dtfvM/npcAPT9y8ZWut3vPeBSG/7t0iFU5PpNbBi1tgp7nF55An\nAKIRa10HWDEXxO64hKshYx0xUkrAcxiDwqtQBr/IUdEhmZHVY302S4TEs3Bc\nOOMjqKhj1doiIG1vLopufw9NYOSsWXGzFVwt4uYZn1VCkGBAFXhdL/pZ45xT\n3eVu1MLs7KPaItAyNWKQA1e1zuPj3PuOVot4uiAbGjUC+s2/lZWn/54oRLH4\nG6In\r\n=qzMb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCR5Hz4FnhUssHR6bswde6xRqDL98TP2ETXAGLu88ZZkwIhAKgppdfVSWsJw2PqjvnVkZe2Sw/cpdcJNaWfGUPgRfst"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kc7ailpb.0_1593845599617_0.13400759365738635"},"_hasShrinkwrap":false},"3.2.3-canary.kciolr74.0":{"name":"tinspector","version":"3.2.3-canary.kciolr74.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"f1d046a0797df68f93a1a502270d0ed075d25736","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kciolr74.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-B6z2q5fsKN8ciJkj1yTijhjZQ5Z1dUwU6O4adou3w4Xb9kxQ0lOFeJ+otY/+3gSMKDzNmFAhBJPatw9IHTVPiw==","shasum":"55c91e410fdb55fbb848cdae1e9753b6f3904270","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kciolr74.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfCqn2CRA9TVsSAnZWagAAFrUP/3QunYH5IMF2QPxHKFcf\n/gV4WZeS0d/lMTrU5iAaTEdwPWizr9jdgoajPxydnyTJFAxOuEApQ7LUPaZL\naYiU2OOe/JtIehEDSAFudVUg7ljReT13wdb75mnb/nfDRbbK5zvqotlUcYZX\n3IINfBmVgrlDsbRHlu8m+78FUTtBU15gk1tdE1IUAmSA5rkuooh5Cx9HeYZu\nBO7sGlGaZPWygqo0CoLq/tbZzjY6qsLdFbvAOAdP6xygvMtrYxhGd21UXsOw\n6EZFp61N783Nc1iQ+E9TAaoK9Z95R745+qdLu0sqnUjX0+1GVzkxn8klyGg7\n2BZ0rxCqLhxlKWjowuihVc95D2+TxS4OVZ4Z/GO2ckPs2klhTMVUoyqp7rs7\n5VPdbCw3dkq0XM+9Wy+dfXsv3cfUvPCm+p9yeRV3zqhVau2NRAotcYqJfNzr\nR2vk+Yfm2WFXFfNXJ0hXcKl8TdWHg9Km9ByueUW+JxygJwdaA97qlBLeCunH\nVUvl8L7NAPHUFNtVjVnMZHQ6Xnr053FH6JtiMRq7AkOxf/m5+V5HfisJwuPQ\n3C7Adx+wOUiYXc9tPIQMR39kkhuoX/TOCDfvDj0+tk5Ly9nL8kj+1SdHcdaK\n1mlL/9KReWRWg+nQwaBzVRMv4hFSBZXokBZdS57Aw/O62HBnXgGgj0T65XHs\navsl\r\n=Stqu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICEkpHTHuVQRDTHZQnk9+VsOeh3rjijeqpsf6j5OKo3KAiAfEJRb9FGGZ7zW4qg6G2bBdnXmfmWBcZ0385VbQ/3gHQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kciolr74.0_1594534389723_0.24289639120248596"},"_hasShrinkwrap":false},"3.2.3-canary.kckaf5hv.0":{"name":"tinspector","version":"3.2.3-canary.kckaf5hv.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"d4e0415ee441087f122f131b925d59190a0d95df","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kckaf5hv.0","_nodeVersion":"12.18.1","_npmVersion":"lerna/3.22.1/node@v12.18.1+x64 (linux)","dist":{"integrity":"sha512-Mx8ElMDum6fbNfvuqMOwJzH+Y1XYFRs3c9QwqGfpHDlODPMQA7Y/+yreaBryd7ccOx2M/gJxIUIVhG3ceLOjNw==","shasum":"5231dccee5555f1cb8cc3b63169df0b1ddeb6a80","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kckaf5hv.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfDCVLCRA9TVsSAnZWagAAXhcP/i9d926ZH0XAEAC24OMC\nCaLt8oVDk43IPUwzagaOw6UWXAV6EvOnkzgbuuSKwT7QtuCcSmibK2asrwTU\nV+HNwxY1lwbQsykuIlQhCP9Ph7RlG3V4OyYC7+CsuAyonoVaChq7ErV18h69\nrJOD+/8JeveJrevqaSkr3JTU6JUUFHpot160yqi/joxgBCX2OXxvHJgNr+qp\n056H4HQDfcy8guC3gKK3soiRAKF8v2GoleZDmIDNwj24LZE/KuQE2DGbYJ1L\nR70+yeviCznXdWcnCrsOHsrqfA9sS0oADysOreXY6U7Q+bg3xda7qx0O5Ai1\nexQ/OUvXX4a80qb/EL4nSBvqEGj7TI4dpg0ZLGKeXnpRUOoiA7SPirxQb2X1\n2zgFsZJ9zTMAH9AWa1TolDvGq0sUaV3Zr+Q0vCiuPL9XuyYo/QsLodcNiVG5\nAGGHuxmC3qmnrjjSkUK2NvHhSeHvCIDNCu17YXf/H6keavd8ENoMf6VySXeR\nFfbE2WUoRvaRxk+qe56yUNqxdnbJKPXWltAytRJ0Zdiq4Gg/i/klvOQWUIVs\n4H5uBjnUBUESTs8TBJrXL+lFLQrb+ySHMMzP3M8O0i/+jaiZ3wZXLd5hxAm1\n9YlxAxfDgxpRiZcUCtCcqmxgQWm6/vrthpIFIwyeRkP4XkVettJtc56jkwG/\nwrGb\r\n=/bPo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/pTKx+CuQjBqBdBFr6i+3yCXHTmtsnHuUvQmf8UaUjwIgLIXlZLjrKItaPSP6jfsFk2V0I0zpF/8uDo1r3MXjux0="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kckaf5hv.0_1594631498937_0.1719915623778645"},"_hasShrinkwrap":false},"3.2.3-canary.kcras9pq.0":{"name":"tinspector","version":"3.2.3-canary.kcras9pq.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"fdc190f87cf801025bd41495ef0ba37c018690ad","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kcras9pq.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-uHtmYosuWLh9kFITqZYzcMC+MqCPqNaQo7z/Kt3JYbObCguLbUc+OOQfAiTSMxnDve7gC1wlffERC2nIUqeTeQ==","shasum":"5d9c7301cc8410d092f75ec5d98a3339cc3bf1ec","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kcras9pq.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfEp0OCRA9TVsSAnZWagAAIQsP+gOJEQuoZvvyLyXpULGR\n4cYAdrr9QjXUjZnycfeCH2dPy6Hmtiu0Dc2SfFDk2b17IyPnWaKcrXtBu0uk\nZcX8Mhjbll5JLE9JCz+X8jBZYHwmpu5Suh0pxgm+ie4qh1NFDwS74I69VSQj\nBgbOhPZZPxgrNQ0edREdgf0necMBgVIRR4kASrUuNCpeiBtpNsvBnf8ewfTH\nOYAu/h1SD0ld+0+jeAVG2rWz68ZlcbtM54pA1CJmz7dtAZkn0kb7GOHGak4t\n6ELbunGh4xxlzsx2wPt0/xqrPXz7xcJfUJ3/W6GRjhbO01sSI3wjpo3k/anh\nr9B5UZtKpwADcGLtdIrSn8JV8tZQRe1sn+a0xMBy4t6/rkaDnrhUW9pW57oZ\nWhpVmfs6sQbhidzBaB4CjYDRglK7H/mPM8Bsf43blnLa+2zObS9SbpmtHuAq\n3dXfUt9S11S6oJ69fs0Qvgko1p4HKMBEPcdM1IKiWKe4nINPt56XYRqUkKKC\n/fKSy3Qro+E1xQxQXc9ewSvtc54H112jy4hNvb+mxUKbwuPJK61019g3SpKo\nSV3mt/cvhYnV3yaDsoO0ub2KmyBN7+YiBG7OtF7lbJTCnZ1misQQiISl81Md\n2q2hOUl4fZ9sRtZmy6TFujsW/OJsTOnFda/mTD13Uey9FvULyH7j+BtuXsIc\nZdLu\r\n=fssf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFkExoyt9SIvZa4snyJMb/mXq0zvPU6guFv3+9mw2JGQAiEA1gPOv9ufbsFRuVMg7ao4B4Y+i7HMhqxfuac4Vy+8Yjk="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kcras9pq.0_1595055374265_0.957411478524586"},"_hasShrinkwrap":false},"3.2.3-canary.kcrinrbo.0":{"name":"tinspector","version":"3.2.3-canary.kcrinrbo.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.0","@types/node":"^14.0.13","coveralls":"^3.1.0","jest":"^26.0.1","ts-jest":"^26.1.1","tslib":"^2.0.0","typescript":"^3.9.5"},"gitHead":"8cf3108f2cbf5cd2a9ddf7da1fb02feacb1aec5b","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kcrinrbo.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-aeuW7OmBAwLFFUPTYoU2X3iJX5XUZj81+Rrgxo7Q5NIaq72qJ/apPoopITKWOBLytqsYe3UIl/vFX80HXzUUKg==","shasum":"b464d16105ed963d8af1876baceb7abf86971b2f","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kcrinrbo.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfEtC5CRA9TVsSAnZWagAAIsAQAJQ8YPOCF7HAwKMx14ST\nvabKu/o2PAqNH4ZIKMd/CVOAd0as8ZuDnBxPKY6euoWLKpgjAYvz2Ohph+uC\n/tg2ozlIpQSkupc61SkYBW6JRfPWS1Lw8216zNaedVy+3dnP9QgbtlJZzRHK\nb+ihXwjjIF7Qy0BxESCShnT+AdprvGnrI3erMYKWnQmvuflfThMTti5j3Nad\nLzBiWr53URBsVzyyjxeL6p9McWM5Gk1/qpGHYFnLnd2Awm2rF2Tlr+4skcTv\nP2Aj7w2rQTm9ABl0Tu1dqPZl17nH7QwPQTUJyJOtb9DJ/HYrYdbg4Q8OOPOD\n9zF3tWe+VrYsiyCj7aR3Ta1s43EAEerFVQUiE2HIa0VgRTaIqoq5qHayWk0a\n7+HOOtDXMAQ7QXFGaJRyOPe+zGDPugbS2PxzKyR1llTGBAfaQtatrC+xD2YK\nTr2/UKBSNlOdZ7T5wB/qylQkMPoW8fRToEmOrQAA1sNm8D9t2Xg2h7ThUjqP\nrpp0Q8hmd8uDQqotqLHtXjdhJOR9KJ0LZYK2gJFWyx6jEGWgSMm+TLYZevw6\nV3T3Tn2bEAUGLCbW9Y8w67rdrbZyppvJzbgpZJ6XysyM9453wc66D4nnKP2i\nB+VPS5XFegc9SNg8KBPTw/Yao/9oO73pZgMALcsZfHP3PJemMNqLlCfr+1Q3\nk559\r\n=DfMj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA/sGs7uFlpXzQulTeXu9CUzDE94sX3DjvGbPpFTE4KjAiEAxRdxp5EYhPqgDExWrGcjNLnSw9sulS8ED4FNzQIZVFE="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kcrinrbo.0_1595068601041_0.4494252352167021"},"_hasShrinkwrap":false},"3.2.3-canary.kcs5b8ny.0":{"name":"tinspector","version":"3.2.3-canary.kcs5b8ny.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"5930d385ab838c3952a6a06fedda2417d803e49a","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kcs5b8ny.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-NCGUwn71rKZweMSE/DO4elD0EWolriZnxKPuVzhg7LHz5+gO3vuHZGW3pH8oAX3GfwpInsfvgc0TvSejNNsB3A==","shasum":"0c6d091350370bc917db8dcecccd6fd4e90ab1ed","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kcs5b8ny.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfE2VYCRA9TVsSAnZWagAAM5QQAIvcCZrVo8csp9zflC5O\nyhUbxilxSYZXbJeD1vFBi1qRQOG+kRvk3MJl5zco04b0xuviPtR4QkppFSN+\nfzyjgQOUGpp1jf6bpeWKfwZ+NPRDM3CnLtosykBAmz28TY89QBFOgu8alGOb\ndLcc0f61qLv9JJUJ7Zz8h3SjIWSvVL+XH0yox4eywXEdyrph+nObPnsprx3n\nVuCPtVshi4+sTOA/R5T5HgsC+TRUpSP8xKLctmdV+4Ie6no49uiekR1U3+QT\nwPViC6Iz2h4WwH9kRAQvg2AobpYw+tUdty3HvIbZdlpk5xqzLDICdCfhcbN+\nB/S1DbBgQ8y9HSAoC8B+93Fnub7NYob1xkInocjpfLkSxoHoG68SpP2fIKxu\nnt6rdx13ykQZbjBgsYMCJPJAP/Ox5xtaUUSLN3ueFnb6YmRBTO166V7URl1b\nlu3vN1TZdF8GzGmZD3JSt0f1iG0K858pvz2MyFp1GmEmDsBZadDYKKC8vtEI\nlV4mlQ1OMa1Zv81dC0NWcKbXB4AO0ldppz0juYucUNrvlvTw7Rb3R/iAE+mz\n0xFQtbbqnDoKvXnz6sxeL0cI/E0tJBupWGxG5leiRdH7jgNWLCLy5zzXJc5n\nscaLaEEQ9wZEYWVBnXYBjCtua1Uf/LePt//ZWtEm4h5+nE78WghVY62b4Dc2\n31da\r\n=QHBP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4LKGA9JXNvevF8oxNjFPpfdon41u08O7PRdKhPcFn+gIgJ2+Hyx+SdDNBpfkbJbtz4ofiKvuipQXmLG6+i8pXVk8="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kcs5b8ny.0_1595106647708_0.5785885895997807"},"_hasShrinkwrap":false},"3.2.3-canary.kcs8mlx5.0":{"name":"tinspector","version":"3.2.3-canary.kcs8mlx5.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"d2ecdf665d13b659b67fc5c360c7e68dc67ef5a7","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kcs8mlx5.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-KoUnxqsCmuppUAg27q133nB3Q5FitpnCM2EkK/eKllILz17FKRkpR9xcUOn2Ehj6ecoINe7punpLuh5wabtdIQ==","shasum":"42dbb8998be3d8702fb19f5ca6e735334fdc7279","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kcs8mlx5.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfE3sZCRA9TVsSAnZWagAAt1QP/2R2Zae713Sef/HuOG/e\nFwqA9G2IkkEu+h2xDso5QiTQhh5sMTF8kZ0IZ2Y2AAbjweR2EAN3kH7Mc8/C\nAB7TELtmp9tvJN4NhBWeWRkafY3c7tEJAcXDFBljeg1ju65U5CX9NfD2eCNo\nMmtlzG6STu1aXUMaEt6nEDbg4Xq39baSaipyej3xaqG5m0PT23Xck2z/uRYF\nA0Xo2qBDVuRqWD+/AX1HJr7lY2kB6x6sgdhi71ML6HUTWwftPPrdIFisW0O6\nug3Kp4noJ0dHBlrYUmccDtZK5BwnK4F+FXD+p0qRj8q024PuT5pQ5W4yiaM7\ncZg8eX2Z7vh7t1nEKavIBTA98YwQYe8RmDylJAvHe23oh1DjroQOgVFRGlU1\nOWfrmULDKQq+p71ilf8vju7PGPpXGwuXY01vuc7O+y8bjkYw7pJy4BGQqPRd\neu/WSXNV6oOs2ueq7hv9iVUzvKROHN9NGUtfYvgpHRJBJdNTFG7bSJuP6nFS\nfM5CVB/pybbcB1HpOJCn0954DvSDCybASW6sfungwcc2/fs8eiBubfcVCNxE\nss+aYlh1Tv45LflV/mwXJ61dsVJq3C1e/gPaQ+qmjRaTE9Z9FyEViorVEmg4\nBtTqN7MhwaoM6EDYt20PuWZ+IN4xiPlU9r8DubsKAfx9rAdBUJSzOJGrd60S\nIkqn\r\n=XOgh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRIQIpQZlS/ZEfbWtxqsdJiGmMQf/Xv3DXRv0K4b+LVQIhAJ7JoKnJ2xCpymoDjYc0gBPSEt9k7+f25z711A4PQB+n"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kcs8mlx5.0_1595112217046_0.3320055014056833"},"_hasShrinkwrap":false},"3.2.3-canary.kctvam2m.0":{"name":"tinspector","version":"3.2.3-canary.kctvam2m.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"d32dc0490fd4ced6378d0981ee5395cbd741a174","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kctvam2m.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-ICebGSBU7DZhYbLLw/9I8UaPgGnMFZSXmlKSQErlJwFSm00+jyYb52m0kQ5AZhJoJOH8OGQniccPPzjwuTVWDg==","shasum":"1a72459c3481473c46e82f606f3795d20de428a6","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kctvam2m.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfFPwDCRA9TVsSAnZWagAAMv8P/RBXGgzM0jwVC4ACZLdh\nk7YK9GJb0Mxt+IRjZjRiYtEog4gOX4exY4IblGxZ0TLMw2gM6mj9A56Rwjo9\n/dfctO+eypyKMPtnmq1/R78Cft4tLu6ERF4sZStk7sDdSK2faVLVF4SLk585\n+Rr6DOuVYPOoPU1bRQ/gCmKFvRLBRtrrkvYfuouIqBvt0EvEhshdQ7s3dGav\n7+dBXQg8ZcXbWcWO/I3p3saYyK6IH/zo+sDOQkgS728XKr6EvK+HGFNkZYhD\ngjuaH5S6yPGFieV6Uso9Kkg7NIqPSyu283cuAjVEbJAbuHuu5HTOQoNE6Mf2\nfHHRUBHCgB0CuQkFxUjiOBeHTe9KKwdtorDIvHyoyEoHrCBtsPsshj6Qx2Qz\nw4MdCcfBCYdHCEkW88D56SrJPHDkR+DoHkcL8EEZU/ilqvsfuCTISznJBBnk\n4nmOKHVg2vhacqf/D8hcdafBxWjErVY+plqgcwH6ImceixjlB5vk4JRGTqq1\ndffMB98HbZdERzMOCECjSZy3+YDbykXnmedZRr+Ne1mDRkPbLnR9krjWu2xi\naDOGqXSUx4V5eBeJu+Wzb4FZIhS9Hyw0m/crJZslq5LcUC7UCygYAUOmy8f3\nWcL38irb8ksOjPCpzU/dKUbPsXjcEapdVvyS09X3wWmzEDD/g5ibpMr3ptSs\nA9cT\r\n=yN0Z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCjYCxUEBpGp1qQEDeckXydMpGsd9eBCwS4RgvCpiruMQIhAMbg2QkOWTXLjPuOBd/yjTp0hDEpXo7MTl0OKqXUo3br"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kctvam2m.0_1595210755015_0.47128407346764223"},"_hasShrinkwrap":false},"3.2.3-canary.kcvksj6x.0":{"name":"tinspector","version":"3.2.3-canary.kcvksj6x.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"e5684abbe1be7ebcfd212bdbb483341ed3036ca5","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kcvksj6x.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-XnzZdoBKYqTQM22HzADjPhPvMf8g5f9BSYanGzjMym5XZa7b3y90GbVZ/yIM9LLsUcYHCz1lEIA0QSbKTXqs2A==","shasum":"3f322fbe96440137455ef96976ea3c9135570c30","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kcvksj6x.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfFo9/CRA9TVsSAnZWagAAV0sP/3Z3T4zTNxDBpJRBdUlB\nBcTsyOX+laeIbz9+JyMQlCESwUqFvvkffdjpleKc/1MWqD6MU7fEA4iCqvP8\nCPpqLwoQWxd64kVtAGEI5f1/extBDoW9ql882M5AM3B/2j3HwQQBJ1wcuWeS\nk4vqvnfQ5YyoZoUPSHu3D9L+jqbrLjzbx7fUQXE84tDwZhiHbWHSwKBBOenk\nsLMKxH6O+EJznLTmCk9HvxWHSWX141Rtuj4y/BlKapgrYcb1ShBVqpj4p5W/\nLR64mQxC2sdMRFBu+bBIvwj4uNpxjJ5uggUErsWCgnswAPnXvftRnQvtE5U3\nyOLDF1KSP71vsY5fGAj4McxZzHmRJ96AB+yTLnYB1yW0MUolk/CM+lOeuxO9\nvIGOUYLyK3+jFzCEid4A0PfMhIiUjK6iM3nvlUWkEpeV1paN0fQ75JpMTXkK\nyqL13F6m5iktNauWTAAVlG1BDL/JIVFvx7D6LcN+f7I272HRgmB7qjo3OAKN\nUhdj0mdUBkntzZ6+XyzRstwOu8jiJQy9uYUf79UDONDbC8Hs+AnodwVmWCMt\nS2OeTKDYri0reV1QjPoxOoonNfNlg2dXhP+WUu8mdjjTB6glUBKHY88wT9Km\nSslk8pmeE0olNsH0mL5qeLH0HpBea9eY4JmzsBQloUCcKMRkdtLxkmptOo6v\nWMZy\r\n=4n6l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDEvZU1WbATB8rWXOU++yN2DpPLEu5B2DsBiKpKW6xKTQIhAOtzcoaISwlH1NU8j4Ize/rpOXWd4GdASx+wkpUxwdg2"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kcvksj6x.0_1595314047429_0.9795381458981591"},"_hasShrinkwrap":false},"3.2.3-canary.kcwgd771.0":{"name":"tinspector","version":"3.2.3-canary.kcwgd771.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"a07cf1f3a27f19abe304ff482210ae9b31d4a222","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kcwgd771.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-eDWUEoJRwb3DYy2MY4tsdQ6AHJZj3LVZMHTbkllQimup3UPEHvMp56qzoJrtKFEREpLmz5vouM5eneTeZ8n2DA==","shasum":"b09a1a67143b509c3777583ec8fd4cb91580e9c7","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kcwgd771.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfF16oCRA9TVsSAnZWagAAXf0P/j7Blq8jkuWJ+pY1ANyv\nzFn2XCOC2Lj+14vnwpMvnRxcX0Itju2poikkLqh9pgpnxpQCWEf5PJ6SyYVh\ngjNXIAKpWQ4/H8D5JA6vl0YTnTOlWgVn6itrZLCmaNUkuB4YfGw+Kp6T1nwD\nu9loPhD/y3QpLTn9Ln/4HftMwH0VC2ND2mtHkvfCv+Cy4geHyn7a8aM1d+26\nHzB9yC2W6vMNa8p6l1COm4yC2L8CywFVcx6gZrYY1Rjf3d2uEifYaME8G/JT\nMRDzx2gEUNecwOY7sp42rop9/oLR+AhH4EEhXC9o9I0p8SAYpdLygI88qwPV\nGRA0bBhu081dS108VcWYoFSQz3X4HM3QRC+nsy0j5gFnCL/5LxzTHl+dY0VV\nZxYBVH0ra0v9JWb+bAAXMZiIB4R9mtQ3ODTp/JqF9Tj44KGm23CgGsmNhdeS\nsAWHxh/wyCGiB6mAVJk82z+XIqS8kjAzI8vDXNZxcT2AgWCp4NX8OySE3L0V\n1mpNsls1mrmuTXLRTXvS9pRIywIgRCyEdYpQZ1LsZcqZMW6qAtizYJT9CkvP\nFYztAPrWEEwIWA7qLUpQwTuNXMmRowN8smCVLKa421WYtimylVRDVAMvGWeY\n6oICE3dUJR5rbeKyfHNnu6w6QRHiGzTLjj/kmkwkZiOVt0S38GBe205QXTb1\nxlgW\r\n=d0vl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCUiBxNuU0LJsWlZ6aUu7INpKJSeU/6W8d/oFdNrHGxFQIgTQhr6LDFiIjKraxfF8YDPR4pweJBORLTrIPZsg62Mp4="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kcwgd771.0_1595367079619_0.7611766571873302"},"_hasShrinkwrap":false},"3.2.3-canary.kd1392pj.0":{"name":"tinspector","version":"3.2.3-canary.kd1392pj.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"3b0462189ced23324018c1d01723940299a6c77c","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kd1392pj.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-d8d9WXFWdeVY2100vesWvZa/8YGP2o5vlYpb/npwYWgDBhnqOyyLUinZzdhpoxojEPRD+V9/r/69GYnHX85tXg==","shasum":"373ccd1281a0b94b1d868a8425a2263cf0e76e6c","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kd1392pj.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfG6WXCRA9TVsSAnZWagAATA8P/iKzjhkgJEOMAEbEC1dI\nmpgkBDhb6WOvn9sQdimQPO75gK9nZgavO30nwNuoYB+Kx0A7nYZG9T2sJLot\nWAUHPk11FPCSjSqWlq1yTDYc8YONz6h30mY+cKcSqcEuK7X3jUK+mFITLEOl\n/RfKEjf9gFNZyRfD604J2mCM9Nd5T9yFIn7n1U2xAEXYjXbZGdOVqcr7Vfss\nYAskvpiyRAbtdhI2Wdio691ux0/lvX8pkS6Wd7SxVTPWZlQq237d82eKechd\nRcu9Kg8IDhZbqinoK9mGyvpRZ714VyL/gS6cVif6KCpeQUMvk3dx6IKJdH6F\n/BIpMnroSH25tQ7cmmK0AFTnetG/EpiNKsfNpyj8Uj4VkcwmAAdHTm8KRfOL\njj5iFr7Dd6LVxmzXWHwTGuDguAecVx2/OkKYRAQy+0jnsqPeSteb6odnELef\nuNkdo39gf2SMxeld2roqVvEDqjHVySr2yUlybHcXWpDV+CeO3dsYgnCwahCJ\nuxjyKH/dAjIA9cLlcUOSrDAfaxhwKLCgQbOsZ9YJO3szPz5Z4lJZvj9rcroq\n/h0xHOSTPIW2qAkhCNEaGIrhrSbBdWdt8XyjyILRbhosEgos++os4/Rmk73H\nQssnjM0QwpA1qqNJ5uvf21tPUTAFtM+qgX9eC3ZPmv6EQKGmJTjBHHHxYg0Z\nThFh\r\n=2o4c\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCA+4ZpLccNXwsXcUeCJBc8WHwdxSQTBdAIRhm/r9SwtQIhAOo1d5yWbdiI0e2Ft6LvfibiEb6trkXTZrRC++r3WNBc"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kd1392pj.0_1595647383303_0.6716396820319397"},"_hasShrinkwrap":false},"3.2.3-canary.kd13oe59.0":{"name":"tinspector","version":"3.2.3-canary.kd13oe59.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"25feb797777dbf094590690812eb01976354fefa","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kd13oe59.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-34kGkQutEf5byqImGbMYzFjVxns7CnnQ+sWgo9cjsm+E3jGnKOtwfhx98Z7+nLOkUy4VA28gQ0sCElWm1NEBMQ==","shasum":"e3947577f497f3c5ee74e66a17645aeac052700b","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kd13oe59.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfG6hiCRA9TVsSAnZWagAA6ngP/39txk+c8F8X27Xq8LMx\nrOEG5cX4Fgs7LoKuxLvdyobrIiMv3A1oh/wuwwjtGGO20j5eDQICop6LRzJw\nCN7iJfLMNCjwhPmr775hwiQhiX9zx+WR0c0k23nd/j3gVue85aF/N8I+xFHK\n+y5m/q92Z3bfq6GpTqKjAz+n3nm47rGm1uiq0VZl3IyXzQKhTvqXJTx+e4m1\nZ/5jXn6naKCzBOMlP0CCXWkAE+rryOcQeH4DvSCTxch7AqeBYjRV5Zc4xjeO\nbOvJ1+rqgNq9DH/pXbRomq99mdqkHBG3yisCKVcR9joImfdP2d26B+oBlUjW\nWuS4g4xemudQCdFtKFuxvLpMJhAj1tDt8eV6vgnYEOWEQnFb5bgrSLBhKtuO\n5AbFJSK+5e8v4+JH01CjU6DjzOI1Pet3s7N3Lq3A3cZBfMh8B/sVSX279N46\nUR42q6p+Bj2+nuujMFajmKu0sGqowmBT9gNufwEyPHTgP9zEYsx76nZqid/8\nWm+yFErREfiAWgPAY6475SjckhIpC+zlw6oDIIbHNs5lExDmd7Za5qQ3mPPr\n3bivnB9e+J96lkDuBvQG4HM6yYWN/AkwIs7go82cMRIcRidjvsvj4gHe58LC\nT7IK5sl5F0ZyrlGVgsRCMms0nMn2D2aNdPlHxEk9vZ5OcyX7rnsBKan8MqI1\nQngM\r\n=UYaL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFrz0kLNKZh0aoUjafQSBJQfC9pROqMScbpEYmUw3putAiB8tmSEYQnZ1pRXIZK/PWc2fQEst0Lj7WuRtdaU2DV2JA=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kd13oe59.0_1595648097734_0.017300029383047866"},"_hasShrinkwrap":false},"3.2.3-canary.kd18a18n.0":{"name":"tinspector","version":"3.2.3-canary.kd18a18n.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"10ae92fec6d9aca11ad78a96578b7473c8a50af7","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kd18a18n.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-Tv8oyykE6BMyFfgEgsb2TrXPjEa+vRR5kIuZZ66c/FO/N16X96ANjFCIuDupKkHz4GfTtUPI9cvO6pNt1WH72g==","shasum":"0d507bae0f9ef22eaf3485730564741bea22f158","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kd18a18n.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfG8aSCRA9TVsSAnZWagAADGcP/jZylmA6Udzn1ExLSKvY\nLr1vjyFUEIzqgY5jD6YdpZZRU9NvRCB5hcsgXTK62IXD9LcC6xqD1UN5zYvP\nexM5YLbBQsAqXDnm1sKxYFFVs3ZCF6CvF/SK6vYLP4AbtMXuQUXwpSena2j1\nSO1U3ITRPBbqmi8GGM3cVrtGCRDf+YOyjqEwNkKu0R8i7FSTRDlXmnny189j\nVg7mA5v/qtA31hQRp7du8QAG/8MzuFDGWja6BK9CFIPHeiN7gudEibReCRc+\ne+kV5zJGByhvbq30GAIyaON2VZP1/73r/ULDwIrgKWNbH3L9cEhBPwfG1X0P\nT++jSQ5uqk7IBzRNT9PdMSJDUTGlNmrooyW6DmGmxO4Lqp5ewoJE+JKTtrDn\nFC5IA9fFphJi53j/EkG7hgAk+QYGBuPJZDuD2F5G78PKWkPooy0WdS0iHJwN\nue2rK+tDNcjMy+iFQJunKLnRnyiK0kZRCM03PTmkhu29JXUOhRvBRbrA54J3\nAqirXdAYRZFmehn8hAkaThKFt3T/92upSwKyLAHA9PE3E0rWyzhTGx6eRLTf\n+CK2h5T74BqsOptVF16NVP1fTb/jG25oEKbH5TYDW26adekgjQdUvW/nO++f\nR9u7blTC4g62yjLd6VaiEZz4m1ZEdTQXUlHtN+fKsz0RQ+QvlQKnkoZ0cul0\n3UBf\r\n=vU/h\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkbBw/q8D3kl8l/X4h789AtSrscQgohVv1fdwynniqCwIgYQ5abJJaQ1MDzj4P2szsSV2XAmY1BjpFnABw136fot0="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kd18a18n.0_1595655825957_0.296111680823157"},"_hasShrinkwrap":false},"3.2.3-canary.kd1i13g6.0":{"name":"tinspector","version":"3.2.3-canary.kd1i13g6.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"9140106b1b8e5b6a1c586c6fe7280cfabbcf1d7e","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kd1i13g6.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-o/rSjQYexSjIDnrt8YewTABX8TL4n1oSOrz3bd5w40BC3iiiXTZOBV8F9tn2RoLHnHG6onArZGwTk0UhNF5W9Q==","shasum":"5d0072696e01d185cb3aeebd054a123d4788ad71","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kd1i13g6.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfHAaNCRA9TVsSAnZWagAAz+gQAIbll/ra7koZtAC5gFV7\n2ukh/tDvA0ZczE3kI2mg608QsAh6PkKqimZCcFwQiDNC+lhsnPI5Xyle0W5j\noMs7WCieOxHPBa1kNpyPe0BNRBIAMdo+T3KExRe3YeTjxjveOOJStqaZshjZ\nD6UZXJ436rQ+hmhT/jUBItXVVPP5Qkn0HbMxNk2JX1vMHxHulxZXJdE5nOrc\nNeQGg4Rxls+i52tTp+Hidd1kWec7wBKmw+YUp9fUtBzM1W9m0xLNNwpwTUKS\nEPNaAaD7sj13XLKqhSHmOthqpHzZy9h658lSgl03f6LV9rpy/1/gh9P+njcM\n+0m01xhxKOATzvZbwN6Vg7uORSUz7B5eqj7078HcojvSQfb8aA7lbt7Ges1a\nPKmZxe9ukpFtav/6YZ7VJAPSmR3mxsORfVlJpBODYyCBnuCihPiKM3MsPcOi\n6DU3gMoV/sdVZ6CJfw5AgmBVEoIYl/YZE8Suq0t8z3SGOYWbuO7uD8QlkOyE\nMSEKHGylEDfMnMFNx1Dolxy+jwlhRQBlh7Cbgigy/ufrC9Xi3DDedJSOjagD\niDICOkv9xs9DzOYXxtnOU3Un7yFrH5U9LP7RRHV94V3/tTnW0YdnjR2kr3Lh\nyvTxGzm4IapEkt75UkytW+d0UXB/pxBX9Hvd38oLxGAtZ6MEX2J6U8UZRy3M\nCa5+\r\n=3bWe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCtK3ojZLWBTKza2W1zwXC7dvMyM6AqBGcWw8VlZaZgBAIhAMlJ/XHSRPG/qb6fYmK6bkE5NVhfqCKkOghGI770otcO"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kd1i13g6.0_1595672205287_0.08208577426023633"},"_hasShrinkwrap":false},"3.2.3-canary.kd2p0nhi.0":{"name":"tinspector","version":"3.2.3-canary.kd2p0nhi.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"d2b386d786d56818c61c31939a53f24de7d33906","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kd2p0nhi.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-Ex3rGgJqY2pybjCtdnyQw+sxjziulfLvfe4QBYa2JG2aEn+tG2CHNvoB3vzoJYYe7zShZdMyAbDOgPNCnUuawA==","shasum":"52935c766996bb78a3391a611a827a73cfed71d0","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kd2p0nhi.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfHSCYCRA9TVsSAnZWagAAQe4QAI3q+5qjye4lQABWwt3m\n5VUx0yslBr7be7s9cKCldXTyH/o6TwKZptgAkVQOrsElbPTNGkPGpaAuUOl6\nxiGQ+rD0euLSPdZnbY24TNPQ9ZGsd7fqvnBYjIA+NHOfoYrfoBIyeEUv6w3n\n9VO64kpPbpjMXusMaCJhfSD+Yfvwgh9mL7kDawi/8MvbbRWUkBJhjIO3oURj\nuPLT2pUbjngYHsAADcjm5B4970nENkdlZ2WRAiRT1qA0xx8qhO/aOtYPJd2a\nfbzAmV4ZnGiHOBMCZnnYTc0t1X+9RPSfi2vcr1TjYvQqfPlCcOxtfINgIFN8\nkm9HORF+E9bwBSNrw3gUHdgHeZggtnkgoCVgBszPBWGxdUkOErA86CbTghcP\nNlX+MGEVQVeXjrYLzLVeEhY6WxIdv4niUXg82otgWBElnr8yeuat2pEopJJ+\nPQq326Wkyfvq8iEj1opyUC31KxPHFR/4D0N4ODlme7kaixEPji9WFH6/aRud\nlOZWs1rw5YZchuhnyok1ZHhtIa0Ua4f+4NFoBNAQBfHRUrhLMwx6g23ML6Qq\n7VJjr7sq2XGOHJ1G0IyhWr3VXPhXhICRS5Bgttu0mR0fbYVlRDQskAj8pTmy\nAsIEaO54TbdSR/zArf0EPWtgwfrYHFArvYxAUraujnzRq+xhcECHZaDEdduA\ngLVC\r\n=wOD3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDjaBt3OgvlpYm66i1D/LYVNcfP/y2s99TMq9U6ERE02AiB4nfQvD9DDJsodlp6ZVwQNuL9BPqcaWYLISX0qMp3IyA=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kd2p0nhi.0_1595744407849_0.533521309027768"},"_hasShrinkwrap":false},"3.2.3-canary.kd3mpv1u.0":{"name":"tinspector","version":"3.2.3-canary.kd3mpv1u.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"24bb431acdcec517c3dafb55812e9b6014134ed8","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kd3mpv1u.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-qx8OJzM91tiFD9g8pHAQ6ICnkwY9lvNEMhB8eLTcFm4PQ8BG+s6cOTVFAJto6RkdIJltMamhIUfGiGVHfKLOxA==","shasum":"35767eb831324f463e55f05ce38bcdfe57345837","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kd3mpv1u.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfHf2zCRA9TVsSAnZWagAAzg4P/2CtoSdk84cYgvxGejPe\nWwBB0WCya9UzBBRvXeXdtA1n97ZGhxWjN49ZEE8q1qNJkaJb7MO43W/gIztP\nPrvz5knqv+E+Miq8AVOXXmj+Tuc6ZpbBkKXbmeKuOaTTlz9E7uWUdgJVWZO3\n+7QpNeQqLTT5eZ5y5tcCB1xnGPAftH/4Y+kmVhhw3A4FWr5kH/EupqFIYtkH\niHEC0sLoTbg4Al2y/ANUUqnfbzAUVgxPJ4joRMM76leB/UKdX/aRAHkLfqiE\nMhAsj3QQYjz58xoqd3nVuDYMCTVKUWjFKlIq7rayTMKn/XhGV0/CbcfMFkEl\nF3QuR5DAolIUqHH9M4Ll6hQDFcU/IVTGPpGEWL91JYhz9Oq5nhcQRq2yyBE7\nhZ8wRBebB9ovE+ZblkliKdlga0hJaDIBLqr9XKALFc0yaVlYHMT1sIOZ/iS7\nndb3+JF47HUvl5BaJfUicSrex8CkGCNnYsfbqWFc3LMCw4ZVj+SpaqhzDzaA\ntZ3Bu0TMcWUVYJRFRiHwQjSGNi5PjWHElcHXleq9n/SeVemhTu1QBsJxhG4H\nvv2bKtYl8Q0DggnJT35oxeiwzGWHwco/TOqOvNSIFv0DiRl3A4B+xbCuMdJu\nW/NuSWp1982rIR0Sc7FEtnKWUlOImgCEE41fEMlfUGZrXSmLgfY9wP055Fze\njg2E\r\n=Df5+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID0mezHpYs6QjCLr7nd047aqjQ5Nf5QoYc8hanVRE99tAiAO8U7vinam8Ie7nSz5rrLTyeNwxwYH/FJ+AsgBC4gVwg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kd3mpv1u.0_1595801011375_0.5424045356003386"},"_hasShrinkwrap":false},"3.2.3-canary.kd3rqvd4.0":{"name":"tinspector","version":"3.2.3-canary.kd3rqvd4.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"ae9b8e103ae6be253ab3cebf401a0e34689da1c8","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kd3rqvd4.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-WvXAd0bGZp72Tf9liLuRXKlT7DMGl8Uk2fSLtv79JE8RvdNyDefe+81K/mFKFUHFFo07hLDoI9R4hqpCk+CHXQ==","shasum":"2e919ece9af879faef6bc59adff10d680cea8f96","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kd3rqvd4.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfHh6xCRA9TVsSAnZWagAAn18P/3Sy3yMPbNdDgZe2y9pK\n4qlF8xGAYcGJQEpZEq/fSkM/1kzU94QRDHj/mz5ele272X9Rkzwix4YOhPs5\nctvo8Vfnkie5HJ9Y7/t5XM9dQH4hdOunIahYOHCJi1dUixq0vQW/pkXdpHJs\n3TTJVdO2l18LAWw//C1bbztSHr0VRidjnOaSOO3r38o+kyTEwYSghVgXh8wv\noao4o670kd8h0Sjy8isWTrCP99WTXPK5pOx+1f8fwwE8pX0np0uYgRXxaZn7\nKDI7b7zbeUpd59L4kgSAEcKCO1lSxCGjHvCyOVpoT3eTxQ8S3e1PV7izhjBV\nVu/OSbUdESEginQWVFRMUcT51xpsYDwMIKbkmg2MMHBoIe266j6kak6c9PUr\nxFZOZwnAjeyHfFtDZXLJ6uKp6Iv1mQ9lq4qehqGeInqeoAuKYdbcTdTfaYlM\ncAYeiWbc8NCxCrXYJD3jZPsDxFpWKXPC90h2qe4g5uqzQUOCoq31QxO1w7L+\nrLzyuh9fz6fom+vIWMJpBYumLjaj+y97BpCkHRrHrk+1c4skdu/mCHuLJYPp\nMOPRrBP8xb8ID/Vm0VHa22pmC8NCDSfDlYTUGxVtmT1QVu9dZ53IbdLMU1R4\nSdmPYzrHQiAKnZnc0Y3lGb6L4vqZ2fkZYWXdY0Ne+Xjp0HK5KDCZq3gxi04E\nPhvP\r\n=lOhZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH1lQZ/Uf3nDxlOh6gPwTUHVjmaFAAITtBk51+2uWMXuAiEAk+4lSqtsGjjftcI1jDpGSjeyeVh0s+EyH7p1hGiKBsk="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kd3rqvd4.0_1595809456708_0.13349620707203758"},"_hasShrinkwrap":false},"3.2.3-canary.kd6wewq6.0":{"name":"tinspector","version":"3.2.3-canary.kd6wewq6.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"3251487851196165e3ab62144161d3329811b4de","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nconst metadata = reflect(MyAwesomeClass, { flushCache: true })\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kd6wewq6.0","_nodeVersion":"12.18.2","_npmVersion":"lerna/3.22.1/node@v12.18.2+x64 (linux)","dist":{"integrity":"sha512-nsqP8Fb3fpC4F/gftsXCaWc4nVFdcaM9ic1MwXEZGnuQ82sjnr8RiCNU3uh+w8N+xcpwUvjdGa76NlfWS3w2YA==","shasum":"a804d46db3bf5195fb053e9486547a2b8312f253","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kd6wewq6.0.tgz","fileCount":23,"unpackedSize":63005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIQHnCRA9TVsSAnZWagAAzlQQAIvbamkK32LgpNP1OLVa\n9X6Ta3KqcIzlf8WO7nbd9/huBfa39rtbtXN2gRig2jzmPT2eOEr/7SK8bGLS\nnEWhFRbDr5bjiDOROLco5iEPpAyYVYhkkobb+K+GO11FcdzL5NLCb/qym/Pq\nci35Kw5NDiKkqDE0WyXut0DxW1cVhkFwDSFnFwwqfcs5JMOlYZ5ZA1LRTNM/\nUio9H55l6sg74lbry0VdqfC0FM9sEsgA9+KyafYKK6jRqa7FXkNb1+qz8s0o\nRtmGFV609bAe2wCGPkEU4SbgNMHI2KmDGd6n73ove7NLPes/S7dUN42sQXB8\n9w+2u8N2b9lCleDgLeEE8UMzCnI+oA/vOgcOu7FE+Hcjj30QiGQcvx9ksext\nn3nL5us/+vtp2k7ALXKMiaWAQA+qtaECQvRdpsOtQeC/wyvdvf3B7lLtMPNV\nbS5rTFPxhwlZjcmLb4DGKKnTR93/7u4cr3vGZe+t9DWI09q/IUCAUIQ8Y0h4\nRZBfPz39ZNHkSYv5olwiPZrStn0RX0NXKs/kK0upFr3pfRvJPU90a9XxLc51\n1gSljCbPyXX5HspT5ZXKauZYBtzGoXJ72EnKo3DsJV/GhZXHcMCM0fmbX8gs\n0omR5dEEWCx2XbySZ3FiNjlH3zLesSlFoXtuJjJFsTvFwu5SswBlKXhr7leb\nOxYs\r\n=afei\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCw+fJBcODgx2l/h5+Bwqym4mTzVoEra5rAkQAzVwOetQIhAN99uLdweVcfnCld1wihhdQNinlvnZm8JSV0P1n7ZmX+"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kd6wewq6.0_1595998695336_0.2864288411853524"},"_hasShrinkwrap":false},"3.2.3-canary.kdf0lwtn.0":{"name":"tinspector","version":"3.2.3-canary.kdf0lwtn.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"b159de7becd3e5b54dd97b796be4cd7715f9d3e7","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdf0lwtn.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-lSk4I3LqclwJD3TzG9T6dwmxUYR11mlrYRyHJbIx5KqPTWjP5NZqHLwtj/41R6/C8MbPnjClAf+7I9CE+NN+DQ==","shasum":"bf39248ad8fe60fd1928a6810f4ae0036fec9340","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdf0lwtn.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfKH7+CRA9TVsSAnZWagAAamQP/RfS3Lp6r9y2ZoXS372t\ndnCA5TDrURU4jVcuMsV7sTl1U2TYbMcVPuo9vzBkt9agl1ZbXyCn87Ho/tLO\nn9cF1sUEpgEinZvUjMRtQ5NCW8HLaMovVkpUhK8SmC9GbLSjb5I0zozU41Ih\nCLnPMLK3/2dlbLW0BMj07c8fIh50I5prfD5G4I0kvDGnQPkwEIxnlchbqzAF\nNI534Sv0pty4uT8MPsbQThG3tYlJXwLn1i16vgAWqrCBmcEyZ5kWro2XdVMZ\nmtgryaeWpR+h2U3rU+n2NscaINO5A5ReZjh1ZPJY5qV+BqxdSH8cQiriyVJ9\nohmj5LasDZjm2K0/k/wVcHZIe6lkxa3IrQY/TEWuMsFbdwb0e6A8N9i9Ul7H\n0S0rgFYC6qvEzXn2qEqPJz8bXrvfteuOnrmiR6A4kxeN4MS77GdIVImFCg5+\nw7c9hKGm2++ZG8c805ibmvEbBEz+sijkINB343Qgsv716je0NMCRxa/7W6Z1\nC1E/YWzDboxUWTwLBs4NxGD+7L/KBNROuLlECDLCT0viU7qwGdqREC6Yz8Hx\nTo9Rrjy8BVjVGBJGF6QDAiR1kXIMKuBrQS5Ui+/lvmaCJqiiD4F+1yv3+8Gq\nAfDaaQi5JNNjNt012VkkOqSJ2IqS2ZdbgSZKNkDXBHm0AfimDgZXxt2hErA8\njwul\r\n=uSIw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDhdSUd2ZiR29jcFnIHJkVuXreNmvqiXoZmmNVBiiVrcAIgD6OoKTODmA9U+dJXtleIdPm910Rcds6RYMC3EyTmH+M="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdf0lwtn.0_1596489469717_0.05671126303632534"},"_hasShrinkwrap":false},"3.2.3-canary.kdgfdc3a.0":{"name":"tinspector","version":"3.2.3-canary.kdgfdc3a.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"6bc1254bce8dfd78d1803f98e24ae995540c4907","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdgfdc3a.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-7jwLLrxNCARu3aIJX7hgNCzc+rc2fUl9bIgPdXzkPQkeRWS4pHIjrb0PFUAYsc4urX7B9Uect5opHkCk8viZjA==","shasum":"9929cacf8f896c457ba18afda20a141429222d45","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdgfdc3a.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfKcwKCRA9TVsSAnZWagAABqsP/AnQLiiaJfP1Fj3/gcT+\nvtSwDmzlx1inVFvn7qh5lxk5MYmAtrH9owIbPQa1k0wWCCErj7qdlR+67sHd\nxhn8CE8TKZyHfx7RDTnrqz5yKywljtVpXbO6a6pzcoGRTpNH8f7nEBZsQRhT\nnrjK7wI8JIO+JCJPs5E82g56Uy4f6d+KP8LOvgqRXyb3KHx7Gb9sHWectyid\nw49V4cq+38o64BQxfm7gsJOLSFRXuv44pBFkp0vqJnIvX3rEIrRSHwOD7mEC\np1LWKWfDJfHVgCGm+AohKhiTCVQKO44vN5ZshEC33r1tAsU1aI84TolPjnZu\nDskiiqeQSj6sc+zt8usLwDm6t2aWAW8Tsmkv0iTDas5VnsTlr0J+Bt5p+HXG\ngM0snowfi7sxaku6T2ztB5OlH8nDZweSmvNj94afmDMw1kEDIRv5MIWBdJj1\n+o580GJb/iSrg9XV3lwMeftzpTBYvysBmTOr+z2BMY6ECXopow4KoGS0DkLo\nulf74VWJsX+AnNcovqAnSdcrfmJa0w5Uh1nhXHCXvGMt9i4E1hXkzOMVYtAG\nnj/KYsoURyzNE7EruzNc5j8ve5GNROCeRASfUcIXuRLN9tLCa8eHP7iMiT0q\ny5ycV/fMrERmHT8Kh3riPTBkUhhYFKr8k+nb+u/wxVk5SrUfw48+cxU4mGVL\nUHAK\r\n=ps7T\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBLxdvlCgohBE9eOO0ml8gEBg8/k67A7+banYq9t+G23AiAgOINGrLy+zSMTmPQB6G7tKy1o4wWKYeyGnmm0tIYTow=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdgfdc3a.0_1596574730022_0.2283592271540913"},"_hasShrinkwrap":false},"3.2.3-canary.kdi5mwkd.0":{"name":"tinspector","version":"3.2.3-canary.kdi5mwkd.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.3.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.5","@types/node":"^14.0.23","coveralls":"^3.1.0","jest":"^26.1.0","ts-jest":"^26.1.3","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"059fb90cf50f0674e8bba366fe055f0e8294e477","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdi5mwkd.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-qH1tCoN6anVRDEjhQGwIPWlGkLAmpM39dhvKKjLXdtClbURFR3sVp+r+LfFnEnkff5uUUSerUoWtAOn0pTBn6g==","shasum":"7a2317f59b88c209ac0791c732f581307c4c39c1","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdi5mwkd.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfK2SRCRA9TVsSAnZWagAAxPsQAJwrjIcDT8NNe3dZeu6U\noXhLJhGb8tlur3U70FX4HZJRWp9ieu9jZJUy231WRt0goi0a7JS0ZpgL0rPe\n9YddtEAiR7GJpYHT6qhJ7uEans4q5P+SdSt3xdu8FPcZtmHspiY5WOtH/b+R\nyd0EcwD+DF9V5QvBGyutYc5wsnuZ6GiDR35AjQLJn0S/Elgd/QBVKo/lmvty\nmHJgEIAwL8rhdGSFsxMd96IfBc30CU28LstkVClfiSkSFJyRPZdiI49NP/BP\nI9onkR8ny1pSxuroYj5eMYKBmKndi5AdjYJ1YarfXKp4YLATVdPyNQmp5WRj\n22oxlhsiRo+MrXqU9rx3fsMpZNLx4mJlFdfhqpPMPvVfqtdPvOF5Lg5smp3H\n4xMWQpN6Had4vP4cpyB0zYhV6V9lVtLV6n2cW08xUsHH3FTlKO3787x5cMj4\nQYrn0UMvvsLEULaDZhNRGn5flOLGpOvIG4zCAaDw2hWhAr4IMxkSI41Zw2BT\nYvU2F3fOah0GDaYFqyjkASLWAXH0wYrjc0vE8KS3cuLuJyHbjjG1wYZaxDLQ\nuCXVLj9g573GtJfP1jbkz7rfLLbkKF3A4OkbP8KEEE32tcmE7spLGNomQ8Sw\naLXAtBjoP0l8/+O7KShJtKXhS+afScZ0Y3LLWheJZtroddCK4zibelWhHFaj\nLuO/\r\n=WsfI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQjRFXO1LV2Jf6l/jw2VbVsGQ1ZtjRjR4Q1EIoj/5CAwIgbgEZfEgsomODa0yBq5rEVpLak054DOo7CF/Xfb2zuaQ="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdi5mwkd.0_1596679312683_0.235750645459462"},"_hasShrinkwrap":false},"3.2.3-canary.kdi9bq15.0":{"name":"tinspector","version":"3.2.3-canary.kdi9bq15.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"c62c8dc2dda71d63bdb6e80a3d51157b8cbd45a4","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdi9bq15.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-G+0kiwOzYNz83a1RNvcsfzJwfC1buiIbep2xXND2H/jMXYLv7qGE8sUxfXKTshmXxUiy+2nIDp1QgNxA/rWY5A==","shasum":"3d56d8ec88d50860ffc6368172b48ef3565a9d73","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdi9bq15.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfK3zGCRA9TVsSAnZWagAA3xEP/1jXKqRO97ObQ0lN549a\n5CYsTWYEjLl64gdr8bF0XxDD0UDwemgyJyHGYaqUJ4MaQZjES442n1wQ1xxl\nMhHdUx703vGhtXHqkbBW4qtIj817slN2Z82kImjEMqISvGMg6iF/UAfSMxP0\n1jMdrnxNLWSC/tPnTx2mfKpYchAqK617weh8bZToQGjnLiQ9s/lcjCwkk6tF\neqlMROI666i6mvKEvX4uEHeBuNpwArf249TwWKlumalqAsonBzzt6/BDQabU\nCR7i8kIIAdk6198TGr2/+lnfM92qS4eiXiXEoXOLDWGDtFNREpbDc/ve304a\nYupOkZGJkPcW2M/vZtBT6OuzQmG979lI3K4aYvjvowXEv7H7TeDhpi4xONdI\nTa1vwBeCebz4PKJObUc7yYsn4kjCQ692R5CHPZqTk2iHBvLS9l0Ya+iV7k3E\nMhdyXQojKwpgCOyQIVhU1eBObNgzv+Mmem43f/Ke6wAclv4PVaj8UQorjZzx\nhhr8UDSHkeTqFxFYDN9iiGbXC9Yx9x0YUsyYUPIcrditeiEo0sw2EwekwrlI\nFufPfCvJO0JTDY4e7nhDkyp4LoF0pwaKpPsT0PALHspV5CWvNkBooSfb4sZo\njbs4ifs5l1c2UoC2nGbYv0l2VyU3Stmncai/OrlGQYwrmDV46KsdT+Y9KrMa\nfvZd\r\n=p+pA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEdpL4PTRYRXV/pAgxG0Al3tNPHG+0gQK1c/a4gVUT5XAiBOB49ZBuUYGlNCu2dsQA2zf0heaMXEy6Sxt8XZGvzUTQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdi9bq15.0_1596685509709_0.7170341698774734"},"_hasShrinkwrap":false},"3.2.3-canary.kdid6yqc.0":{"name":"tinspector","version":"3.2.3-canary.kdid6yqc.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"1a2937448a8288fa11bafe68f3368841cf95b16f","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdid6yqc.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-nwEDbyt+bZHV/EWvHjtpzsh1nnbng3p5NMkFVX/J9R+XP4zU2L855lyGAPlSzQxPyfPtVhE55J//Iqkf63FGJA==","shasum":"61e7873d8380e325721ba9b7dc2bdc3b3d95bf6e","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdid6yqc.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfK5YmCRA9TVsSAnZWagAAFfIP/0dr222UgIyG1Vfm0fKo\nnF6wsaRbBLYuIVtJb/HKLdbrnAI3Y9lroa7xJ8dIIhhTBef546tVXffVZ1dM\nHljqk8o2Cu+NLpT1Ft/l71nBbow8IIwaRuPjympqfJUVnR2xW7kKUd7wbEVN\nd5e1DjcjvPNLB4DpYEP+KTd6jXP/Iuf5H89oLs4QDL8AQoCazU2kgXnuKKz8\njkUEqAvL2WtdbyUH+LW8fs1dP03eDsizpeaeQDJkijqLsPeOvIaRNCa+P3X/\nB+bG4wdSzPIfU6APh1SbDgkPJsFDKfZkzKdla8FgZefV3QLFrvTMTkeHOOKw\nPr6nVcBKhLm8j78vdVMZ5v2aOFDTKMacM+wSMgQob2jPcaHZEEcgbTCcnbhe\nDNMsmAlJfpjxhF4jecaEXn6rMwnRufvfzMnvEyrMSbfq4DFxYwlgewHxn7II\n0o7d23ag+cKddglZLCbkiMLILpxHBlJTMhJEEjvVox3uEA7rLGoDXzy2xOfC\nbs1VPnmyZhbLp4sADBxeVyPPX1zSDNbj8n+HD1ile4VqmuG2zXLpt7tqZxqE\nFVyTXos6B5sGtRQRzjXdYGg8uvsm9JQCoNpWlgR3cm+Ablj6aMm7r6KqIFwE\nWlbJdvOutS1rpt0qs9C8T4WJShTNLmP3STrGbXXlXtQeD6IaXgxqa3d2oEUF\nC6Rl\r\n=+TNX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAKUH0KtulNEkgVJBtWMgigvHC4FZLy5UU+q5Aeal132AiEA46AUMKcZgD0pKdYmHV+PpvSXoAMT42RHPNl5zgVs6vU="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdid6yqc.0_1596692005912_0.6721531486252925"},"_hasShrinkwrap":false},"3.2.3-canary.kdjdfg7t.0":{"name":"tinspector","version":"3.2.3-canary.kdjdfg7t.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"44b6b52be66103214c84ecb1d9966f3f48e3c0f1","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdjdfg7t.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-oGczl/dmGfqEjQ45ZhtVR4B1fjA6OceYtLONQw6sQ6/AXsPoFjB2b/Pb0dDVnTCuSj84SFMRdl6n+i8iRXCLGg==","shasum":"d00ec395af379a23fba47fd636361eb3e90e6363","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdjdfg7t.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfLIPkCRA9TVsSAnZWagAAQvIP/10Xoa7DuswneVju2o3e\nTHWGsRvvqF+l1oDERWkl/NM4RGmtvVCh0eL2+SNIYJ8Vu1U24jXXxWIMPLW3\ngwa2xCfR1fq0x9lV2E4aWew5bqUZyq5sI4wYb2t8Pd49ScRfEHBivandpyaK\nO00NChgVZ3/5a1DL5OsgcnccZm7D0HoPxqfpN9BEFIV57r+gzN7TgYeMRWkQ\n9DsV4LjyEhrTmZvl4YdN/ikX75sbv5SnwVBeh/xyMXLlNIde/K5HbpSF3rEJ\nAUc4MJRuOCNlwIKF9If7ZafdP4DNnWmjkaouWl6iQ1J6BppvhGWVU21Rhvh8\n2xHqQh6plZTIgpET5A8jugpmHilB/fUQcmzlR7PfcBdXXEXrmumdi4Xk8Pls\nwbDB5LlIyRjWmwxXRyXoCBiaC5KuMDspHRCuwANw8PozMT2BWe8ltQDANrk0\nqDvH+jtr152kYZslpglpOwxE3kJ1fgKKCfHz47V2xnbmAsPJ0nkAVHJDVxc8\nd3mebcR3LdLFeRLfwn7VbIh5pFag/xzgD5cHIGh/U+u+yGXjNtZoODkaU1hp\nj7B3vMrVHyzphG4Nhttin3Igc8sQEROlDSowZUDAMGeekik4+Puv2Akj3kYT\nEe+RRsL44FZ2tedAU6++9PP5SXXqK5G1rlR8JlnIE1xm6rEJIl40qmwIs+Yr\n9NMO\r\n=o7t0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD7uOhHstE8vsMrsXWmGvbOENP6/hNkVvXOhqkw7KKdMAIhAMeC4gVH0RhpAv+KnupY8rezv1bJKjoJvabKOzFT/Y8U"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdjdfg7t.0_1596752868281_0.829562821795703"},"_hasShrinkwrap":false},"3.2.3-canary.kdjj7hrf.0":{"name":"tinspector","version":"3.2.3-canary.kdjj7hrf.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"3fccd923c599e57b5a0efd466d288dcc948c1ef1","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdjj7hrf.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-flkV3JDxM6YeFDl4jUCSD4iM8SA9UbqXLdyQnUoGcDgJUYLGAfWFiy1di134IVr3FU9G0UrqJh1h9S06OnVf+w==","shasum":"010bf4d74d4446112357d345d5ef42db8b6829ee","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdjj7hrf.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfLKnOCRA9TVsSAnZWagAA5i0P/2EkKIxjb4mvqjokw2AA\n2M2JhzTA3Mt2Ww0fasD5Pfxi+GMfihaRWdwRo3acA8n7X4P8UYsp9WB2egij\n9RU/kjQjF6UZunSYfaPooeTI9d3U7iSFeGpS8dkAn6PpO+EjuRMuJXozIi4k\njskRDhn2rALpPF+iymWqju2r2y0cQxvGJ7bKJ6gwqbQdIRqP9zBU9DtWinNx\nfZ/mbbPr6lymqBtj+WP7ZYNSAPUkmbPhjGNRkJhLHW+foWi2EO2VUGk95ugp\n/DHm6ja6CfZWM1GULGr1oZ42k9cQ6I6CDPO92nvZij/rQGLTWob6d6VV3GfU\nFhvHCDeCqE8LfHW2/bAu+W1EZe1r1p+bMMiKzfeiuElVEqNN8G9f+uRZ9Fup\nvEn3/xpoqFnSKclv1+DkDC5sEQckyVbISlDve3gE6wVC20eZL34jQEhuko3k\nKGeY7p8TPQSh+gsprJMBssWBK3VYVN86l/4piaQL9Hw1rGqa15Z8MjY1g1q/\nNeawPXNKN5cLtvp2+IUG0oioxN/Ui0uR8qV2uAhxVRAmivTXb3GqclydZelf\ny9UJ61RJYNDuxJLKhYsl+CF2w17qblQg7c7zF/EfMRm4FZj5nGmcC9IVPJbV\n0qidGLbJlN2r2a/YzUInGAonzZfqdG7taVRX7xySXkTdG3Bgt63046BOM39w\ns9LQ\r\n=cOMV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDx72lKgz4CqzB5lKMsKjMmfFB6muCTtspjr/UxEJoipQIgdIPWoWVQoUqvVfdwx63lzF3ZcjFLuxAcHQvJS4tLESc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdjj7hrf.0_1596762574284_0.22900617546019886"},"_hasShrinkwrap":false},"3.2.3-canary.kdkqxkys.0":{"name":"tinspector","version":"3.2.3-canary.kdkqxkys.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"f21c49f710f91bca701fd71a736769b90094108b","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdkqxkys.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-Xp6MyHYxeAekQBAtz4GzVLurvUo4PjT3+A8IOI9d7J48PiSUra7wY5fNl7nrH0Oz8YpjiENKkZ9jUnCvS3ompg==","shasum":"d1318e7f4a9859554ffb496b37ca40be1e5b2847","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdkqxkys.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfLcivCRA9TVsSAnZWagAAZaYP/jAi0rYJ6COYNy3fgBZ6\nVfD1E9qkSKc+KSajx/RFoxPc3cCl5JIE5B+ypbTM9mfaBNAbyiAPy5RD16fo\neaME0T6wPsxzMo7tBO3+P0t6Bw8BITGPYpZjKXGOxTYVIxkYFM5OVvJGyWQ9\nH/PDp7upkHRR0G1S/3Ypvrr2ymrxY0XDGkTCUB8q79P+eIT+4ww8SqTK5vLT\nVHSXbOzOADueTmueUGjp/sL7FAo2VR2NQsI+klRhAXuItSR0H4ew2bh+t0SB\neFAgixU5DrAWunqINRKVmddC6Ll2Pvv6f2fKtPaE5d7akn2pjUD+mCnPY1h8\nx+XH196zXkIo50a623IoTwUVHIEIh8/1JIAUmmCyrUBms+XYIFIjtS0XJT0Y\nDi7mJlReDPELRscJ077z1t2HIm3wrEs/ay9j6suaipk0vwW/COXj+IX3BLfW\nXZsScKdk9aNylpxhP7NdqpDPURebnIhaXJNsBIuVyjsNjZCjjKWS8651aW7D\nvSiIHElrmN818fsrkcTGl0PMc06Yh+dfUTeaEGCpiYpJIzYjIFOS9lPYqqld\nr9kg67Asf/UKHRqiuA7OLBfrbKisuCKtHz4p7GUPWN2Uj5BhtuOHOHD4DhdR\nGprWbj5CTEwd4UEom5rLx7qhdHJ98LamMbvM6qGeDPfZ63gK0lqJJmOvpxLx\nF5IL\r\n=Avwc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF9t8rX5e0QESWIyMjJ0VaWWFE6LET6pajGqB3cCmH9nAiEAtAeKwgQAPeMisU6uFTgLIasUy5MGTd5Ux/bPHjtc2AM="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdkqxkys.0_1596836015171_0.22553015983951297"},"_hasShrinkwrap":false},"3.2.3-canary.kdqpr7yp.0":{"name":"tinspector","version":"3.2.3-canary.kdqpr7yp.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"790722952d9fb62b0cc63c8f987cfec27f59b677","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdqpr7yp.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-KIEXmC1ZI93SQqh+KbiEx7nm3iihIN1PkvflrRL2Bp+1Dd3QUd3FVTCnCasF3xZ4cQcFMqP8hLYpqVi5SMMpUg==","shasum":"c256c63ca21095263ff6fe995ea5d078bb8b5103","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdqpr7yp.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfM0okCRA9TVsSAnZWagAAPIkP/iVzDj/a9VXJQgPWHF80\n0nfQ4+IE1cO8Ln+35siegkOm+jRLr2uOqVZQvPnDnc4q1IufBFeOgyFN7i+i\nSQrToiptnJxf5ffopJrSCGfBqJ+wMjxC8TB+Hy6VNoNXE7qV1vNckYHksNOO\nU33QBUl6Hs62OPnG0vd3BTLLrTD0g++d7nQv2ohGYBFLxDTMtLtjLK8BOpGp\n4jDwqfN9UtDECGJYQl8k8mO4BYzca3BvytnpsHgoFxx1K38Y84nTvUf/Bezq\nXlB/e3HyAQgQoKh1EErXxmU3BY/FpTv31q/DuDtJX2jd8zg5jI9JDeS7M2be\n+VWulAlsvEfoJHcUYAd/oeKxZThJMNuBmX8/HilTtLZtZOpK5mCHHS4OAFDb\nPmE8rMWQyKENfCTOfDf1qCJ0dHKRKLu4EcoUenjxuayZ84Beo/CMKOcttLbf\nUlzL7UYghwxuCeb7vO/lxsWSW1W0Nv1fquNg0C5LHhbQ5MMJrL/D9E8UYQ2e\neQb8cwWH3/YByw4akcZs5dLvEnfhICdi9MB57nf0dpEzNZZs0OyrQPI0evXI\ny/rN+EAd9uwPWVYZXOI7xIC3F/QJ+pRJd3aS3EidxAl2L+qSi6Zyc6VcgW49\n9YDoRjWRS3qe/SifrIWlwrr9Ud39Twwgox95D6Kbh6+DtgCTahRYVuVt+AqI\n+cg+\r\n=x5cY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB8+Re861868wE2e/8rvz9bVlZnYHnHU1uJH2EIaP61TAiAi6o7bjQrWcOHVHUX8Cy72rOfBIjPbHX+JRVXotoU2tw=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdqpr7yp.0_1597196835889_0.007728283423052762"},"_hasShrinkwrap":false},"3.2.3-canary.kdtej428.0":{"name":"tinspector","version":"3.2.3-canary.kdtej428.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"5e8868a92147d2ae5ed53e4c7f47965db5b23fe5","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdtej428.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-RMVDJqC1GnxX6YsqbmRjEl40F9KTQDzcBo9z2YCojBUudurbqPbDWZbJ1lrwrXsoLQQoe23uq1amI5ilcil5zQ==","shasum":"d3228b6808953bce828b0d097e1c4ed08bcd803d","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdtej428.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfNcUUCRA9TVsSAnZWagAA1QEP/AppElTUaAZoSHbl9P6t\nKZUXjkdQUDhFk8akuGyVq+qfK4ku942jwJTLi2xF42y4aVBkyJ2PgMwxdvXT\nIJKZYF5Jxa565+fmdji4zg+bNHnbvlLs2nluGF/f4T4VURwdEGoffKQWIPum\not1pHa98NOmZwakITAlNmNl0kbyFV//ZSZ73F6XjOzh8zZ9GZl073Ak3yhl0\nfvyc+6a+x3x+xzsAxIYJCZjmK5/cezDG1DeLDVSpmAAiCIFe9H3lYvaDuLXu\n+8SoZQm+YB6W86IejY7PbVOL3Ti1btculgVNIW8J2h4KiBrHR5hCZe2XwNyT\nRTF/v6nIJymHVrxIkBYpraREmKBzTwzMYZx35uKg1djAImmrycMSLhH/Rq1o\nCz5JHXW7Ekdf6KHpiFtFhLpgP6KCxP3RtCIcq8YZyfFe3BwNm0nvZIGppwcS\nu0s8VoxQ8NsIfHmb9xujO16d2dzYkaNiTrzy/TjKwrLnvyYT7rLSVSL1ecyq\ndmh5qA/d6Srd79ZGJvxus4vEdl0ugL4s9OUSO/AADOVEpHGmAOLGjtaVMWhQ\nKL68QVjkBXy4tRZeQrRgLPCFud5VSPFsPxu9z0uTPmlk97qTw7og7zTCco4c\nCbJRb9L4rVPrdGWZv/vCe9Z5HiLrfVLUmpp6hk6E5+gzQJ/XZgRMSJJ/lciA\nG6gH\r\n=xvy3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF4V57RwwIFqQKzu1AkGo3S3dS1J2yoJowRQMRl84F7NAiEAgpqLGbHKfu4i0bpZOHBb5dScA658sPQh027P3ICamIY="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdtej428.0_1597359380092_0.48887889095682846"},"_hasShrinkwrap":false},"3.2.3-canary.kdtibqoo.0":{"name":"tinspector","version":"3.2.3-canary.kdtibqoo.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"14d35dcc5ad081bc853124a3cfdcecfb924b7973","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdtibqoo.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-F91/LFFsCp46jIiKvMcMnmjQ6/kbB4SeY4S0u/DdOqLLI/dUM0SNI0BoC2iVXiH/FraHYDyCKHi1DTi6trJusg==","shasum":"f77ddd5ccdba8274aca8965f920881d0c9f5680f","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdtibqoo.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfNd37CRA9TVsSAnZWagAAHx4P/jXDTAQxpPkIipNYjuho\n41mmxdCNWrMjoAqAbM8WKC+ZITTyn2KrNLjgce9MZgozG3ywfMs0ytUt3bNk\nqG2Ehd/fqJthxBZjjQEb41s/LjbfEDBvhGEN+TDSmGXJ/CU7vroo1vOZIg/d\nE8lTOonqZkI3CF5b8A8YMK9oEjwfn8YHSG7rDL2MbmCaxLDXcMhNtb0nf1Ce\n4VlKRt2DT4UBbLE88UuOnDSk5mULV7coStVBtKpVWrFO2vkw+x5cUl1KeR6N\nLlEGT3kqY9lH3730d8arvKfFwU8zVdt5MbHAaYYYiyo3iAZrecttz3dlf5Kb\nxGznrSCLTKMzak9gZ0HKU8gvWblg7sAW4Ptwru5hMjrvNa3mF6A/SpoAJBGz\n28q4N9guy6iMYhAwCcQAW1sYgIqxIi1rS4jHj+QqgttGBqCywpBj5srKUjYl\npJ2ZfJ3i8F8CQU+bYDXVR/sI87T8cE3J9l2dKIqTxQMpqaJyQlhDlpoIq1ll\nAGFqGohTQslJa2JIExaTN9M2MK+SigXW+v4MyNTtXLuDjHnO07DFGh9Qh5Bs\n9zl6KvVWgJzubDFoHfe340BsERpaD9X8kD9UbQ8iBkwjx8SIeWZjgs+4wXUM\nAxDlzP9FQEjnB7BTcGT0svhMD5Y+u/RJNim0YqsYihCksfGLbNwnkCqtbmMt\nFg8w\r\n=ftjw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDaVSM2MlHna2Xy1oCADxt5aPZFi3uiIoKbpbR4zKJ+GAIhAM4MfwAoWGAZaHT9POOVOV5g4cNi7D7uwCMZWIydPghv"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdtibqoo.0_1597365754687_0.960622061240475"},"_hasShrinkwrap":false},"3.2.3-canary.kdvw2za0.0":{"name":"tinspector","version":"3.2.3-canary.kdvw2za0.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"3ffadbc90a8f7b14a6127874df90c13237778480","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kdvw2za0.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-kaLtk7ObZLz3EKobQd5C5AhiJCVu83Zt30qTn/wn+rjKMr05F9GCU02HIxhetXHpZ27jml/2Xp7LzK3VMyiYOA==","shasum":"81ac8d81902d328d032b4bb0478b9054e6d84895","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kdvw2za0.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfOBChCRA9TVsSAnZWagAAtgAP/R13zmUhYwm+wse/9NXx\npx5zcppfQVwEA19g0ojS2EfU7Cq5GzRFupY0EknHrqGtxBAIqDq7u3Sj0hP9\n5jlux0PSAuOdCeWhpB46hIbeQeCvLsWQYacyqik81hpDdAmoFWGNV6y7Ep+B\nqtKOxeM3iwJLL9ycrDeH1t+Ag76ShbtspmdJNe03advsISbSBcsXvddMslfs\nj7UP398nVhEfEjZPyt9NdPmnY4p2BIyuNn5Ai6e+xwHYmv0dYwSzfn06Z0aw\nHtG5XTLyMi+qjR94ii5wUdihYbuYvuyioWwEs7dQQv4ZryuBSgnyG2NCxHfS\nLgW/gLcLz6UcPXDGvJIWt7OOGhlrT9Mq3k2p/0erAE8JPVyiL7ifnEC1DMQp\n8I/lprixlOVZQqMKk+M4n06KlTvIR4qP/Z5NlMxJ6byRW5EtXsHeN7vq+Okp\nqu7jucMZW1DCeis/ri7sRFeIhSaqFZVgpxgaEBzlQSKE1iYrr9ClvEl4qOz2\n4kDgjzgbEKonIDdfNzCn7Xg/QXtN+cSX56jznbqHO04Wx5z+8GOdR1wdeQ4A\nBspIVVCOuddaiR73bKbtk8lknZBU65fYRL0bIKFklRiDqjAYNk9MfVRKKCOw\n1A5g6qJvexNhaHji3AZSrvGj3aKOXcc3FUKlFte2HIj7Eoo6RpT+Em+ffM6q\n6ZTE\r\n=NSuV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCrv99KeIgJ40riRuhPAHigmjBZ9MU7QLWcLkhO2RM3sgIgG416Yc0dSSUMr4IrJHiBbY7clHiwDUZJk9lTe0lAhzk="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kdvw2za0.0_1597509793033_0.5229256995127787"},"_hasShrinkwrap":false},"3.2.3-canary.ke8zqwdv.0":{"name":"tinspector","version":"3.2.3-canary.ke8zqwdv.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"adc4afba59c808b862403bc0325063302cb05b3b","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ke8zqwdv.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-UIeIL6ZX8bSUlsikjdWlwc0vLeiKSMbVRO1F+GDpgP8dUWz1bzvyu5xCmXtLZnMIwY8lxlI752oR2iV6FbytmQ==","shasum":"07fee4bc9e894d68d5250233876e794176bbc4df","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ke8zqwdv.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfRCc4CRA9TVsSAnZWagAA2wIP/127j9pwQmg2rdMJu8Sm\nYjMB1+YDxUgTE3vCEXQEihHHR1fgrsDasm2O2br+JALyoO7nikuP5bDSdyzE\ngwRhJQellvvlNqjVxnQnpAuojPIQp8/X9lfFsy91D0pHMuTd3t0r2lYa7/3B\nGSWIm+9zNiKdFpp2M5COT9EY8o4PHEJNot8WL1sFi83JgEomkPieIWnqVB84\ngTNlZb1Mbm6KBp0sSMz8IUgiJck0Z15FO2uZAnSxMA+dUIhbkdnYOMIKb6uA\nmq5do3vwfur6EjDsbfFeYqGkTa045Uf1nou/eV2WDY57Hm94kk2/iuFjcm/2\nWUC+bSiDbDwcP7sZISKYYmizpVCXkYycQjDH8rmNAcTiKrhRTKdI8WivXEbM\ng19rDe10bfq06HGTw85Es05zg5Yn+sUBqmB5wClnWc3Vph3U7AEthHF9rA8s\n0nbDEjxaGj7oW66HvLvejLsMc7Y/Djkyj3n5AueRypopT8RzBr3SGREy8LS6\nSdf7EQoZQXgkzFepFuAkI68Qh+NGbbtRzZ02cHbU0cec9hJWHr88KVIXGdTl\nIhFAFvfT+34ERVvAaJfioKBsuRIoyczO0PoicHNOenWerLHNVOWUnjtLYqq4\nxHfEcZr+9yA5B4FM7NuDfRKdcFeA2ImggdGJnAGKRNXFAaakWPC6JybP6feq\n+l9A\r\n=L+Ke\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDsk0/0ygYcLCHcKZR9rM7rPFJl9IfiDg9434SYzAlQUAIhAI7ZhAx2kfmAfuPXnFqU72d9lkBFIzaZAX9fr31KSvxj"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ke8zqwdv.0_1598302007957_0.20304305079572904"},"_hasShrinkwrap":false},"3.2.3-canary.ke91wrl1.0":{"name":"tinspector","version":"3.2.3-canary.ke91wrl1.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"e2c6cbd83b5c0ded22f2795b1b8dc0876c9b7941","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ke91wrl1.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-WxObKvpSupHLBQKtdDrX0UZx9ycw/PZYLDPH5Wt8xcHFDGw+uKoZMegPY1dTdqlaXwtKNdMmv8H4F167xY8yFQ==","shasum":"1da24df9299760dc1744666384bb8bc7453998d3","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ke91wrl1.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfRDVpCRA9TVsSAnZWagAAwQgP/0gtd46JhlrQ6Jj3bIGO\nCgM/YANpy8rEck5zqamiXO8Tg0RFefgeOBfTA9lXAcwPDiz6W+oDQoKZmun+\nuVciS5n7mkvUwX1hs+0Af9LZwSEG1hSO8c5xuMmvHwPwZ9brGHKgpgVYZ1oI\nmMAsqbItexZh/Prv7dy9F5vN7H3z7695r2dqQjxvhxrbjmH/ftGlgwJzc8kr\nONDKsqaBJ315IRuCbZISKxeIl0oOG3cAuzbCwf8MrhspuaQNNlcakNJMHkqt\ne1hdop1cdXTC4HR76kG6VMrfCctvXuwKJc8Bh1t/H2XVBBFkOROEVREbnBih\nLG9fg7B1WsRLVbDeParJEUWm0JTIzvTrCf68WyaMzN2PietvGy5lPM/4+s2l\n7pLtRItcr+g7PykOQ7mav0EkjnrZP+x0b/mVXMo8h8F0jzgWRzW1g9J/kXHU\nrPChs0wqqd2049sqa0XpKmX/F8SqZV+tPiNZ4Asi2EWGTCZymMcYxYM2J5gY\njaFI7S3ZSszts9WMR1mcV+1enEhK/j7BGPZNj6tdfUveRVb2qUbquwc7DEhY\nqDfCoSekAP7wXEerdaW7nSkTQ5FtQKcKG4RQQdrfSidOKBAMxFqgcv0RJn4v\nZaC7OSz83QiH8S2wlpFVx9dRuXet+NxONRqvGfm96sfrmboqUmZjTjOLXlP5\nnJ2O\r\n=gLEC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDglOyumsuFFD1ooJjK0KQwCWmQdFjoK65a4qjXLzJJjAiBx2fp+Zi16bEAIYRsnuSXLNhLnRDm9CMJpLAF0Dy0QWg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ke91wrl1.0_1598305641027_0.21824990175977876"},"_hasShrinkwrap":false},"3.2.3-canary.ke93q61k.0":{"name":"tinspector","version":"3.2.3-canary.ke93q61k.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"15b2cf636a45111107cf6c2579e1d72cd105b4ed","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ke93q61k.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-hNJjmSchusl0WoTwfPUFW05LmQopClIqDqDibfaSTpsdAgUig3CiolsOhGEbpbh/t6+bMTL3va+9sVrpwqaXYA==","shasum":"9d78ac64532eef6c9a9555afdc36a9e3e4487b36","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ke93q61k.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfREFVCRA9TVsSAnZWagAAq4sP/i0rzgX8ZGyGWw8Qvr+U\nnxU76z2tukzElMd5/itwXbf1C7fWJ57rubmj6RnkX76X8iYxV1vDcCbvT1lO\nvQdpdwHypLWXaSDXF4LwLpSnKRNXwMClTJC1RxnNMXFdbFWXHKcuqHFDsphq\nAVW7ZtG2v7M3PF5pwt9nUqs46wd4EqyTQK5cHff8Hd0ro7YsVV5bW+RdhfGZ\nOyYQf8Ltm6C2kWDvgK3O8V0g3bVKI4CO8jhTVrvhg4nEqq7X6jWMyc5yOkP4\ntUrw6/D9fhTVwzk5TP1VqQfB1fyo+8JQ/+svDuDfTmN6Y9NEFMo9jeCxxhe/\n9Dc3TV3rffAk9h+luUl+J9tIkWcXY6HLLZ/KDB3emu1T4F9JCnBorEmM8+Dy\nT1md9zQRYkes3CDZJVzQBn9XhHoQs1Unb879j0u9i/mX9KnCTpsJ828LS383\nT6yeangypwqXz1BkP+i/e+hIJ2qX9RfaSLE4grNr2DSv10SC9PPqmgonimIc\ndCyVQ/BKc7kL7qTNjsJqzgmlOqf638Wo22ab8pmcpjgJzKUSJxYJ1KymDkbV\nkpzI2SQGBrILckrai3vlRdTJ8Xy05JD+mz28ixqjrPrHa7ubrc2vMGCAG82a\n9/sETFmsWdQ7Os2KNDCzYAO/G6ffrm4NHqxi0/A1fL8yZO1mGhnXnQm91fXU\n8rQT\r\n=Xeub\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGZYjHOHrIJxv+TINzy5Y+rDXoEYDCSRN4KvO2p9uFdQAiEA/8KCVkzfBfvxiLJaROoUlfEZ4kueCzZ0BZQmGJ2TEZk="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ke93q61k.0_1598308692593_0.8159373402257211"},"_hasShrinkwrap":false},"3.2.3-canary.keao8m4o.0":{"name":"tinspector","version":"3.2.3-canary.keao8m4o.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"7a9b68b6b6f55cab312754dabf0d2ac52d8acf50","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.keao8m4o.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-2H1TGdzMryf6H3NVNVF7pI+v4pWgDMDJL9jLexzY8tUsK6ZEigAN/WlAZKduKZokGYtJs1EDFN0MGDT2cXjI1A==","shasum":"0a409dd4ebe99c6a7935a7a39f5fa86e3a37ad0a","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.keao8m4o.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfRbQcCRA9TVsSAnZWagAABbkP/Ai7CGFU+kpsicUkcFsA\nd7HkmpxfeKXsvil8rTDiHTfkPN89eyjJEB/ZnldSWUQd7kpFTozpRFOXPKmi\ndUkqHRCvJpWH2PGh/rCulWsTMv5ZeosXTPQHwOLdapmsC7JgWWHbHqYHAN3i\nYxXMwmkc3eNRHVQed7BYoZVAlsBlyEs2TQQkpOpJJOxSTqKyHNmcLHrkbp95\npmqcwF5Uo4og36Jzjc6MBMRVSg4G9OdENzdVHPdpmyiJAKEG/iQ84UBS6BQo\nkSlaAQYGIA0JSDVChCBCdG4Ba6/DNy0AsuneZFKAD9HPOslUpTFrh9F9RWfA\nGH1XbpgoIIv3ZfP50j6osXDJEYRFbp3Ry3K2QB0Rww9SUKSEmL+p4PYqW9eu\nzjjC6gLL2Xf5U+BB7rXJiIsBdXlpyyKcHxZqmLuE6AkHNReN1D8Z6rLkfeMK\nZ1ddIB2ghxN5LqX0s2Q9PD6QlLKCXCVdqKeRTcduTrHVFgDFI+T8gPgrn2zH\n6TM+t8Nef1gOpq2Y5quBzoMVTdxUTBJ3UsMCsTXBuGlpQe+1EaAfxIore1QI\nHXfyCrV6s1tKfkw6MII4jlnxt4mhQpDQQPr4zE+guV7Sv6zyXPRaVSPYqVUt\nqQujq6Lgk4Vr6/9x3Xh75stkY1YUtOldQCXx3C53bIFbNKPyyKqAAvafMVx8\nub5h\r\n=JwMJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZQC34EY/GzBe4/uh+9fJY07E+bLr64S41zoxjkSxapwIgTHDUPsmVH3hRNuSsjFMAWxfgUkT0KIdNotGhV4l0DEw="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.keao8m4o.0_1598403611663_0.9500449722956998"},"_hasShrinkwrap":false},"3.2.3-canary.keaththw.0":{"name":"tinspector","version":"3.2.3-canary.keaththw.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"194d725bab3a2f0096610bb9cce506fd2116ecce","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.keaththw.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-8zkPOm9iDx5L6LmGX7B7JJXMe1Cb5e6FUq+hNBJjWyQB2tGw+4SLrOoi19hZFusg1HEOQIDRfyN/zpwKBaoROQ==","shasum":"3afd2551c00dcbf475172201414c7e9a82c2e433","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.keaththw.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfRdaYCRA9TVsSAnZWagAAc9wP/2qtHo2vEpMF10HPP7kF\n41CeJXLE2SAUY7vfDZD2ry5PJUuTmWdvgh8Be8QJay+CMVtdkkOuJiiN+fg5\nq9phbfbODEZYYFoDlhTIIGxq+FZoPi/XXqunj7mJYYKHEL0JCu9xHkNBCgZb\nQQSDX4Apl7Ipicyjj7Bi1PDMzz6cFfUodPudoy8mu1AQuovQGwbn5w/mTpgJ\n1WmsyrxyYHJGaNU18sSi+/90PLDnejXmgleuJXb2CfEBV9j5CPq9TkGTczxx\nPoHcNCw5KgIU5kUWsu4QgE/1brAEE3HQm23L2LEQ+FzG0vdUUrELeozxRupn\nnG3nmpR1MOmrf0GQCDNOR/hsDwJvCryZQDKWQuuf7KERLj0TB1VJQ0W+qd+r\nlmcHtjvQDDHPHACAhNyLhBYDDq4lEp7hBqhPoTFqti1xc8StPNyKAYkXuF+G\nPhXcukQ7+puTR14YN2DrHB+haaWjl8S3ecZAHtXMbNjbuPN15sljt6Mut/S/\nfpL+R/koqyhxjLdpA4qxwrwkduS7ftGH4kxzrOmtRlmPv9Nhui6qn2Wbgn1T\nUwWMA7Zj9LLYzs6dUaHFuyHFb07BqPqqSxzLBRg1stmw64yKO8OFT4ogiWX2\nzTUjLtfhANoXgOom1/Oa/60f1KP0SrPwGvoShE2KTs0xYblPq1aCJQL9OTBW\nMQmL\r\n=yfKZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDK/a39P7AY8MtAOGJaNjOjzJToxr9Z3dTS/SKq97yA+AiA9tNF9vJjfIRMjMMwhsVPWzvx9crIPCs00gSxAQJ9R2Q=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.keaththw.0_1598412439762_0.7154347241126118"},"_hasShrinkwrap":false},"3.2.3-canary.kebz3sj5.0":{"name":"tinspector","version":"3.2.3-canary.kebz3sj5.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"60e26b5a715ee021412ed3c2a6d1620932877091","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kebz3sj5.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-K4Sq5DPvjYgge/p6SDfUzV5RMh9AHxLth08aJ3WlAV+8WQAftmRqDWOmz5XWyyADEoskgCi7XPXmR6g14mQNnA==","shasum":"7c1d2ad6589d2ab5acbeeb117344d080acb312b4","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kebz3sj5.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfRueZCRA9TVsSAnZWagAAyPEP/jg18nFEkVUtlof1TFMI\nmcw0uqL9Uqhm/K5l2+n2btSatksCVAZSir6zTcVBd7h+etqPDW+dROgLjtfY\nx3FDoRg2TsHXCfoxAw7rUrrrD7ubXrMurFKNGEK2RcCL2QtSEmh/54/xzV0u\nc9SVulPfTHsfc0xAnqP9FV+Ic+DdDeoiYmClx/je5TPCz9bvLb2J2D9KIwiE\nOaqO5nJJo5VsefsTfaBQrBOB9H8yNt34T9kQGH1+4rs6iA1FTFhpOskPTOPa\n6HQbvkNQ9v6QPnIo52loMxhYettsk3glx0HpK8VuzKIVCXkaZJ3Tki7pUmBQ\nSg1DU37BpnZKkJgptZxJkDNd9wrM5sFmisQfSBL/P7ziLIRUFgrFcNXQR9Qg\nLW7ls+3yB03gIp3F3YmqJxJslP2b9TbZ6vHhoBY5iSDLd9WH6bMuC/7ORKXM\nXJPZ58JLsW8Rde01jGA/sOVASAU6G33LOLBi1/pbp1sssgXlX3COBfTydnvw\nsNi3N2cBjdIigyM46hl9t2SkzuE8BkSudFAIxUB4sRfEB0Q3A7GtRi8Z3I22\nMBFFU3PZKA+qYgMckKOsQ1DYhfy82dA0bcvffNT0zqK3UBs+9hX47znpQg2l\nMIbbLe3rXD/HZGryXaVMt1oBFDFF1kGXuRh0qbxrusB/Abm3e0SUC5jTAnSb\n2C55\r\n=mdNG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDD1mE2ztUyG+7YnCsfzQ73jSeKDK36inEEfbacwUMEtQIhAPd3BUDI4P58n+tD+jJ/kfOjA9TT2Z35/XL1Gdu5mlJk"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kebz3sj5.0_1598482328528_0.8820875323009518"},"_hasShrinkwrap":false},"3.2.3-canary.kedxkqhh.0":{"name":"tinspector","version":"3.2.3-canary.kedxkqhh.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"fb78126d2a9243dd16903d18d7583d36e3a7cc7f","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kedxkqhh.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-biHZCfzhoeNEbeVTJFwSy410tPKkeY0Y+cRZGI6LkGl1hOR5JsPiW5OJM/q+1tSr0U7gVjM9Er0P5sS6RQqh9Q==","shasum":"c2383a58d3e98c29b69c2fc78bda5b1c4ea693ab","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kedxkqhh.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfSLX1CRA9TVsSAnZWagAAwf8P/RMf6Ue+iHcobTk3nwJ+\nBKSYFcE0lP2gmNTId3rZillnQZd9sRbDcEkftIRxt3dLr7L8BW/5mVNTV3y1\nEiMCk4Mg/Jqel5eYZ5/oavtnbMYQg03jN6sP8FLTJ0iL/WX6xaw1l1RinlZl\nFo4bavyqWDP9LD19e/JXEB6/561vFNLrnQ1+IaCc98G95tfRzFNOmUKfdReJ\nI++OrjT63eCS7Fl/WJfPj+d6vwRaSGIDElhTotip3MixT63+oOmx3zEo5IQa\np5NFRzU3mPUKTf55EJMIXjg4DpQar4PIHSGCmihduDYYYUaGjLinTKxat2BG\nmZrjsV4mC9ByGsxyv39YN8CHcWRoQ3ac3jHlvVaWmkqbFFi6yMB9PBtFDeKq\nZ+d6rW5KDWo8QhnPIqXMj7dEeID3CEOObhxZCP4NM4ijaie7yG3yxg7qcv+W\nx+AqmFYR9x70Im5McoRykd49GKLVsrBdxJdOcuE54RkISauhDPN4u90c5Gqn\nEH44+yQ8fnwOD3HEw9ZDB7NphJCye0BhteHKPgF11dqlAUR2S8PasnAY4La8\ntbNOZ9qXiNBOboT/wCyVIisUeFYxgAOc+355rwr7LmxwML7GuAhux+fmUs77\n0K6M62PQrqdthUPH79PVO/8GBW8dmLn0dCwI4y8JLJu28uDvsAZfTxfqeMql\nEIN1\r\n=e0KS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDieOxsu7KQlmrClIDBqvepvpbIFEzKtkhfHMVnb1fJmAiEA/rPsmKe/dpySJDZyFWPkC1VfnedLnBRevEm+bT5yFAg="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kedxkqhh.0_1598600692397_0.588072299713613"},"_hasShrinkwrap":false},"3.2.3-canary.keeqwum9.0":{"name":"tinspector","version":"3.2.3-canary.keeqwum9.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"045aa514dc4a632e41224220ce089e25a3c78da2","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.keeqwum9.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-SdWjwSAHU9Ui73XOhPG00Wew3/osZmCKs7F5S8ghggJnAXgWarsPvpV4BvUSvYhS4P5+Yd29vu9Wl4pbGaS0mA==","shasum":"022cc2ac95acea97e8fd535120f39b8b8cfcd3a5","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.keeqwum9.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfSXZvCRA9TVsSAnZWagAAx5oP+QDxQfSc4omtVBSwkzFg\n6lfal78Wa40zElVcajwwzUo3WizHJdtKs3HAycuJNGWd6cHoLWAmWKvQifld\nqHi4dfVgvroKW2HI9Sc3619QIFheH+aaf837h6uHtUn/axpPMbo07J7xZKmx\n9XCnahOPbD95gy6A+qKgv1yEQY2sbeNjeQHyMf0xOZTYiqfxuv7DveIOWmKr\niZlAuZEe60otPjVIo4UoJNu+ZqUmURQnrovfpwjIKW1laJBowhB5zx5ppMGu\nJ5EOoNn8L0vG1UPkUzLrHmJdcijDTMzUbbEP4bdLMxNwAupKEHezE13Gdagn\nv47Z1D/RnylOPqxoaGyNoc2SRqIbf8HDrWXxGIVifYeMFekzLJwp/ec+pnEz\nrPhLbGM4I62pxGY/Mi41picjSPkyXawTUG43mnSdrUoZy7xrLmCfXBUKUQGR\nc0t1uXRc3P8SBaUx/02pviuCjpmITO1N230vuw+9uoFO81ExWrlPRXU5rIgo\nxLTi7FMNrImYwBcSKSJch01r+cKVI/OFUhk+kj8sLXaw46RX7jGybhktmBtr\nlYVgAeT9DL3+gJxnjWTZne1xOXC+h5rJ/co75JD+J3M1uWK7nPnIQcEBZde2\n4n/EWmy5AhHHmYnFUQAwiOHWmK6S/iUYzuKRbkKPwvageM7hzgUYY8wPvx5+\nMaiz\r\n=Gykg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGOKA21od91xmApVVPbX10TtMV2p5TomSo43qpRQfe6/AiEA1wo6aaxCwolGPUonIZMHBf87CAtRwhnCFv2OpCrLcX0="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.keeqwum9.0_1598649966319_0.9496761415536836"},"_hasShrinkwrap":false},"3.2.3-canary.keexw8ts.0":{"name":"tinspector","version":"3.2.3-canary.keexw8ts.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"2a3ba8009ae6fa7633a126d65bd4749acac36015","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.keexw8ts.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-xHx9bQs0nJAwELKD0ko1HddSsgPvuhdmgg0RJwc4atUs5oxcExTxrrzSh+4aeqZyPSZxUYiwLsei/3c4bntCEw==","shasum":"654bd0829141c2624b153cf828021d6fe8000c92","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.keexw8ts.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfSaRACRA9TVsSAnZWagAABz4P/3pc+k/OgFQ6Txk01yte\neWStFgHqooplzH7oFRhdIxXqqh9BTbw0jnz9qQYZLFPxpDIowTAxi/iTgVpI\nGKtCisLRZRAzXHKYXSy8hJRSB0mjQD2u1IOvqm2xgNivaADNxjPnWO5twl/R\npGh9FjtWRA0avoC5W9W2MzpefnURk5SszGYl7Yj9/I18evPlfkYOdawEjCKL\nd3S05YCV6oPxCK/bnuo2iGac4tymf6IbgmbYa5+cay/cTMemLtjgKkHlEDoC\nVnl+wMoLhz4Asx9xGTZ3+7PMC2jB5N7WLUfJ2+uS2UUC1K+gwIqzf4pR64XL\n+7QfyvayjgXjDu7lIXEjPcQRs2GHMa3dYZbj8DgN8Cm6DKIroMWErxSxWM7E\naPHbhPMS2CzXSu7WLYj4quTPeHYotB+l+AYbDJ1AzWOvuA9kfvQE8UyB922t\nkOiuZz//NJ4IC9HrlWQyco+9XYEFa5pQ7EI5/TOiEknZp/YKwNGngBnn1DiA\n9iPar/XcTwybm/52V3ol2XhYpGEqBuCC8D5GqzZpkc2ixX/A2r4WkYHLz6C9\nJFPJQUhlUU+wBfmKvDABEQtaqwvIOp35E73yci9D6vYc1Ao7MKc6feAKAmHy\nl42YrDjR1PWrjXGVsOgwidKh2IPqMIdQtWqwdO8d2VKrZre1Omm92xDNcLkr\nKe9A\r\n=D7qp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQcS/CbVntMx8VOh62scm7A13jdBNuvnhhgqliLmpXVQIgYeZfy+PPc6POVLEbhzLp0HJKc9keOWZ80OEUI+DDaBI="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.keexw8ts.0_1598661695582_0.8283719101487665"},"_hasShrinkwrap":false},"3.2.3-canary.kef2e3lg.0":{"name":"tinspector","version":"3.2.3-canary.kef2e3lg.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"10eba1274e8e553ef3cfe19f131ae213ac9f752e","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kef2e3lg.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-E5gZvZby5YKjBUGoLtHhIjhAdqxNWw4lmsvpxGUZhb2xoQ4GczkNjLTzpinJN86MEdtGsxMGzDI7xiW6832hRA==","shasum":"1bde527659c31c61cac6281a0552049be99b64b5","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kef2e3lg.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfScG/CRA9TVsSAnZWagAA91oP/1j3akiQ1o7GSdsfwjxY\nn76AmeMbaVbiwfRFi7tAo/3cDysx4qnVvvR0aYy7KOVSaOWGCnjQUIxOE/OV\nG7C0SehJ7gfG3ChZncE4ush1oDLW+ud4LT8wPcZ2W2fejUnefiZzAQNSCBjB\nQu74VG7t5A7dKAQQ8+3kKENe1X33AjtWm6xmlxgxOOy6HrjKRSkI5gxlQZk7\nMAgqjDJ8aBoAXorRf3odeP9HB0FNcq4aerhRWa0sfAXmTQmQ8vGT35kHprtV\nQmw6a7evgUWabhMJIdhT8TYxOY2kTo8yLSUkGrdHWke/+yKznATq0xGk7SIt\nnPEvtYjDRd4PbPR/fXPl69ZnTz6G4OSZ/Q1oo1OK0NUHJXIqSgX003KcNJ4X\nuShP1TQx+PuTvZ3a6LdJlkWqHWN724TafSBN7BfMt4YT0Ixjav9LaDL5k7ej\nQzR0wQGoP3r4tUo5NBrwDtxXXuBobeDCZWMD5loZhOZVDak2U4Md/Jb6NN+h\ntV8eVOwR801WMrJPk2EBYrcIoPyB3Dgt0ohreeObjPom12LqVpLCyufhiPz0\nKQVzpCC/6oB3wAS0J84/zOXVIcw/ikvOxImxxw7Zn9p+36b3SQcCe9zeV7xV\nROsDoUxx6Qez4oWGxr8JMdFG4lmH9Zerd+PvwkmA8PRlU8yvMxNBTjMPRFsh\nV87q\r\n=cukh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHHtdwGaNANwtV+YFMphDdTe5kOipKoR/Itujg+hEJv4AiEAxFBdNyVh6tvXujy64LI9F5kxdAATKndeHHFAj2z/wYY="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kef2e3lg.0_1598669246829_0.2569688793043359"},"_hasShrinkwrap":false},"3.2.3-canary.kef5312a.0":{"name":"tinspector","version":"3.2.3-canary.kef5312a.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"fe66d981d48900752b10ee5d052ad62b37a455af","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kef5312a.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-ZY0fA56TtMcxb5MfYpOCUgikRULS7chzlR6FN6YEgC2qsNhSQqMhCTZe/HyTuNQlyrKwiHAucWqtv7Mu8SX8Sg==","shasum":"74b089e513ac3488ff1b89b7b97197cf5901bed8","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kef5312a.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfSdNpCRA9TVsSAnZWagAAcvQP+wbhPe5AvzLKCrWcp597\nKm0VyWyV0h9WH8M3irgv//DFJw7lmC7416MJM2o/4cShn7fZxLCCRnkvATDU\nuF8Ijt+kbjyFFngE/SFGbqh1xMexzJqf2BsbPhQr3SLtznFOysf6xmeINEDf\nyGuhktqLCIr2xjpAJwmZKq+WKZP5UGlosDycbQfv9rIQduGLbRwFydcfxPf9\nPtRO6g4S4myV/k1yVrVPO+QblBD5rV+wQ/sJnV67nXH+X65X+3ap4yIq7Q/A\nXOL2yuXxRTvCb2xkjppLTCOr42Q/gjFd5ubcxhSiuWtxGWMcMRTaeS5jk2RI\naGdHLyvHEl9mRnMcCEEqzW8+iodJyVGtmY5R7feNsl192gwQzby4QDh0ASrV\n7HyqbM66QV6gsNVexMaXWNqKj4jWxRFYcNyxWQ3l+0kpdzD/NJasopZPDdC7\nhHECBCqfR7nglgSXSpeUuokb+0e6iIxmBmqCpKo4ViuAL03OKumZb5yAD7I8\nsFfycVIbQGQocKYMYqeseDfzm0ducNnMyLgzrO+0VejZMyOda9xoAHp8gfGE\nXDCtzHVopzYjsYUh2ynA8hywEiZLcMJWhJnqWeRr8QItIO+DMuA1GlG5gM4+\nL0JPFTSUbkiJZhnW2PmDLuLLTPBnV2h4bfUkHAMwMoKslPvU2CdhroU9XHc4\n36up\r\n=ZVPD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHwWEtFKvWYV7H+30ymJ5JD6iZKBMHzzXslGbbh8mMc6AiByPmB9qHn7taMzManUo2Sx7LmG26UrOZ5rU44Ll7yq3Q=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kef5312a.0_1598673769324_0.10709798751067545"},"_hasShrinkwrap":false},"3.2.3-canary.kefh7qik.0":{"name":"tinspector","version":"3.2.3-canary.kefh7qik.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"a769d424261128adfe9a66360104b83e9dd44277","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kefh7qik.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-JwMS98PO3145zXzkGfrMAzSKDAVLhmzIiXN03whG/NGAIwpC8EppZ65w4chzJEIBa+Y/YUeDEcljrGLJueSR2g==","shasum":"9eb633bbacd4d6da4a45fb1ec0b7ea65a906053a","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kefh7qik.0.tgz","fileCount":23,"unpackedSize":63328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfSiMACRA9TVsSAnZWagAAs/cP/AmTyenV0rRPbfPpghkt\n1G5evKI5C1nP0ctH5XE7yQCOvh2/RSM5fx7BM33zPxkzODidQyPllnw/CxBy\nVPCvYdc5vhz0iGfyZRQQkVNscqCZZ6p/qbCktAF21kWe8pSg7dj+vERq0NX4\nh/z1NhB6QnXcavTAtkxs2EC2xpd4qWXtFGdI1dYCZ/sIT9wLnX0YXYQaqPl7\nZV4qwvdssEI+fjrwNm1BleQkxgJad1Pa5FklZSsL9RUdGTB5NZVBwbgEcPMo\nsk9zNAxLbX1PqHrAFG6ZL9KfbVczLVKN5UnFr3qMAUwK6twB7mBbGO56oXIB\n8uJL1YiDQOKwI9Bw1lR83iyQ7zSG9IwcKzGUGsRBCIIu4Vcn9xKKSQryWiOi\nzNjEL6u4q/hGeZUTSF30E1oiop8mTqmYEfWkQ8l0PqXvMVpzyZdz6TZnUQUB\nE1G+smHzjHjg/bAAgVRNIw1RlIrytDjyjNh404sdciZEKoy30xtJQlKTEpNp\nzCWfEGW4A1k7A0L+Ad9z9AMm1ogekkvIQbKUiqkgL8qq2eY6R1jygupRmEEX\n2hYGFv8fQ0ndffpey3IIhNnGBBxhjiTFyZwt3S3640FcHC5ZFcv/0kEzxDca\n6k5uzWrLBy4nd8Y9SpakUiFZTTymv8fG7khQB8qOEcu1c8QkdFom09JZjq2Q\nEO8R\r\n=lpc9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG8ijtqGvbemqLkndu4Qvm7IOQVxR6ykPQcljnpV/45dAiEAyNP7rZ2kbeUFtz9ULIQh25mvxI0g5GNdcgADWE6lojs="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kefh7qik.0_1598694144188_0.29411212018515864"},"_hasShrinkwrap":false},"3.2.3-canary.kejh0j48.0":{"name":"tinspector","version":"3.2.3-canary.kejh0j48.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"b8fcf00deb21acb8713074efb1b84414d992a97f","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kejh0j48.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-ZRFlypEo9o3595hZjd1pNmInPKSmu6FVnE+kUhnlYgV+t1XoDev4yG4XOcLbATwew7Cg0bS8jH6DzDY+WdOSoQ==","shasum":"efe392fd0b9a9a710c5e56c0f4ffc47ca6c25741","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kejh0j48.0.tgz","fileCount":23,"unpackedSize":67553,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfTdJ5CRA9TVsSAnZWagAACnsP/ikNa6n2cKjAfas1fHRQ\nxkTeDSAggQOglXvobYC7aST5SBIWZZZ0KhOAqz6zDbzv/9GJgUoYyIHd1dSA\n5N6A5eH8TVb0Eg8fjUE/REvkmd3oLZWvqHrkcNKMg7XSuTUpylmhcL1BYwCx\n74+04aAjtXhwrtrpEP5M3blXEjdR+diazRu/uEzhh+zyld/ryUQ/RF9mhydd\nn4QWr0Z1jCwi2Br7of+nfQsW0BQs8v2ZTAVUU5CLYVSlhGPCh0uuvtBFHxcT\ng78i+XMQ2OzOQEobpVAktsoDfpaciowVQSajTnIXTev1an3ArjefPMxVR35Q\nv1TnsfRnFuYk+sEag1g5M5C66Cx2RaXcLSCc5HKOLAI2FpYeLTlXv6H37Bh5\ni4o5uJZza4Rk75Rt0l37cqiYH7c3OQjWxR9CtSD6v7skAl+8nEeRw8TyUDUN\nseJtJVFIG5E0V3HSLE7jHpARnR7sRhZOsDlF9/CkO0U3sWNInY8JWbfK8TRR\nrG5QNt5D/ncDr1qIP6CwZLslRRqhiDiy9Bdqu9jrjciYQdmezdFg1zRLMfVx\nrwzZXlkPCMh65SAzSxotMvc1YJkUs6H0AgI51kvQow7Gbz1KyFYHAVhJ6Z3z\nBJJ3g097cDFuQHpfol1/cGO8F1dqjtWWmaFElCBpTBMNuGhfxZg8ZryeSp/z\nEK/q\r\n=uBaX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCSC1kFYNiq4hs5jmaHBV8JoL6a1+DmyNqNDXJrpwC16gIhAKbTC3/Mc/E1WTzYgfTbeCGmR3XCZ5tRuI/IaICGEUU9"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kejh0j48.0_1598935672715_0.49544431153048984"},"_hasShrinkwrap":false},"3.2.3-canary.kel7fsyz.0":{"name":"tinspector","version":"3.2.3-canary.kel7fsyz.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"0c1ba796324d9de0fac8b8a9ae055fde7308aa74","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kel7fsyz.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-NsBWwGOMCO/JofSTn/Vwr2UIMEzxyK4Hm2zeAvnuLoDArHQufvKYjGdRLjZ97nvrnV83b0b72dnYrYgq2S2uGQ==","shasum":"a71243660aa5b3c0b45089b749e0385566d5b266","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kel7fsyz.0.tgz","fileCount":23,"unpackedSize":67553,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfT2wJCRA9TVsSAnZWagAAWjYP/jSd//CZj7S1u30RV8sz\noDwI7CGwVkuGJvkp8lz5Konfl8MBaYgfIl07S4fvDs45ZHJTuU7fNyhCT1N5\nVclBFx+sr3oxuv9+8CdC26OgcMbWRJqDR3059C25dIpMc91P0IgVGPXHdvAf\n0kcsGF7WvgDw3fMXXGJHuyqHy75QJ/p/kUyR4VGkD3JhUYSxACcOa8RPad2k\neEi3GoJOuI8yjElsBr1/tGQMqwUieaE6qwBKzi1SkXNz0LNDrsSvy9XzcuiN\n5NcQlNh1hwMDWrJewzOFguVvtrtxSDVspfLoqW/B0XCKctjyaP7XaZ1K5Ur9\nAjPfMNI6T7CY36aAd/5Gf1dEkVsoyNShq44i98F/e9gv1djNCWUa4fFF93S6\nK8Jqea0+RVP11FabBNIcqWMhuaKHTBVsOXo0KwxAd0421hJuwgrPEcrEnE/Q\ndwfKlchjvmIFarAfLtnCI8buScwHEAgxWWJ9tyFPoliUTU6/3v4DOe6VW/2I\njiYplar5yMIcH3kMh0p2iLj0+il48GCufXqr0R+KJS6gOBiZ9Ipcp82gqpWd\nTFmY3pMtUEEu3aGWbhRgFTCdsJWq4dMJddwIKy+5LrwOQZVKWgxzO9f5TcgX\noiSJjDlIja7j49wjsEWcQLvj9zT1j4nOHlY8iMo9bJeqvGRSMMedbxQBJenP\nv49X\r\n=drBe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEAkUL8et+gPAsuOp3HFjXUpjObdYOB0fdmL0q3heamsAiAGzREEaCnNVPMVRK0VN4Jj7aFLXMB1u/PKxCXM/N5LgQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kel7fsyz.0_1599040521226_0.5264712291214131"},"_hasShrinkwrap":false},"3.2.3-canary.kela2rem.0":{"name":"tinspector","version":"3.2.3-canary.kela2rem.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"7.4.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.9","@types/node":"^14.0.27","coveralls":"^3.1.0","jest":"^26.2.2","ts-jest":"^26.1.4","tslib":"^2.0.0","typescript":"^3.9.7"},"gitHead":"6fbee487ad1bc9a90a297ea4049ead025aca6a21","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kela2rem.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-ReaUgm7ZZKZ67DgvlGFSW1aE/B6TSY+FO8hlOvDMzhogpkYv0a0/6Q0FkkHWZqX/2teasCvYBZ9nx8xlzA9Nvw==","shasum":"1446139e278918b6fb8f51aeba11d401e11a74e7","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kela2rem.0.tgz","fileCount":23,"unpackedSize":67553,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfT31YCRA9TVsSAnZWagAA/G4P/16XoGAszeZTV+7uKTDV\nnhjq+3Zev1gi26EjzIQLLqs1MNsPN5RXJXY3YsJdgEFpJZa3b4t2E+ya4pTA\nUqPv8mGm3MOQ86+AGbfO3dUf1mGveUjnjpzJ0ZeNG9utEi77YL8C27NKeyVv\nANkogf9n64h4Ns4aHywWemVKM5r0ihCTq0+8V+kX6MTbWUzp5v0jykBc9eBP\npNYuV96bjrcwLLGcAXwyCIuEQUeYVQY+Pk4pOxv9PBs2KLoO7UZt2P29oj4C\nNv8S4DY5pZYhjiI8kAO1ncdzgD6uxV/UoAfEUbCtF/VcBeE+Eqbs17ScOB/s\nn+nkdOu84i2wIO3TYqhJfKoDNeTR4Pp+oRUmhz73PeW/CnsviW7qCfrPQU9/\nf9SH1cncyWCjQFku1h6UdOdG8HHOgTuyJrQvM4huSnQcy3QL53BDRrtpuCbl\nib2hEONnJ98uwNkSZKu3VuLbsrszl1KTPYjGq3zY1ozYzRs2xATNtsSscnBj\nZnuE+3XsmTdIRhA0c9K8Zkso0N1ZJunjaoU26J5b285/xgRkZeVPTnHm5AVQ\nM+1T84WAGn56+UJgujuoDaQ2tcecnN3PzxLxhQcVxvELVRzBzCrGimOW7/bc\nHemoQT8uZNtC6L4H5NFh/HBSbB9G9Vtjsv0n/e5dIYTo+j9n8ZLpky3XDdTa\nHZ1s\r\n=d5p3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEXKVX8dpA67Gm0txeHvd1LMaV8kd4JPdV8O40K39rewAiBzp7tYlJlL0bvtYrUhKuD81IFs4rZ++MRFnBxBMWpJig=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kela2rem.0_1599044951778_0.11835086639527903"},"_hasShrinkwrap":false},"3.2.3-canary.kenou8nl.0":{"name":"tinspector","version":"3.2.3-canary.kenou8nl.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"aa90073420085a8f055370aeb09815c6083d8b86","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kenou8nl.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-7djT+23E9pjTBWRU32RrxCrTHwe3xNBqVmRJePySdGlvuTIPaB0+YnCeQL+xezG2xOFMhyFt7e+gKK8FiEKyJw==","shasum":"8d7e25484bcc293655d4634ffe80b22836a192ab","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kenou8nl.0.tgz","fileCount":23,"unpackedSize":67655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfUbaaCRA9TVsSAnZWagAAIGAP/ijuT4TIWY2pslo9unaL\nLrVgpVLVf5oEhEcUs8jsa0LeVVyDzxIqbjzaZsbmzxcxtNtkbjf4qalPq/qS\na7PxX0jEf85sqLZU1KEh7Dp+G339fwfcIFtBp35PLzBXxKz5vPMQNHPMyj4V\nrIpPJf99GLHAh84xdKiCU0VhEb7JEygzoI2gXe9fHaC/nltrw76weRoFb/Py\nkiUnC88XDn2rVPbQm7lDu0sJW5LzytpyfrzO6nkwn2S2jqupC1i8BMGEuLvr\nf+UfMthMQfYz/hFFAs3q2WQlo3cyQiUK5yBrPczGc7KKyy0qlISbBuctgjii\nXrCQkJ5Rh5AwrmetwC0I29QxDKoz7EYZJQsHzaFQRPWoUARWaKMkP3t+pfeX\n7Raof7lu6ce1LO1ihj+rN1Yo4BJ8neGUPO5nER8W8K/S3+Bj1sr2EISF+Eoz\nPp/Q6A0Zerjdllq+NSvmibJk1HBpvQCyCirmnSHwiYGOk2D71mYmscxlh6x0\nW2VxOff4dCFwtUB5EFNcg4qj4lNSfh6zJqEIcga3tOA8nwisQ8ikUM3zQds7\na7Ti3xbCNB/QJ4fl3kiNvVTlzlUqdJIehURRcWLp2LfhAS58lVpRZrw2yp5g\nM+OlDOlFD9K4nsj3zdR1DzCSBcPfoOhNO4xXodVjb6iEBEM70usgnnLK5gTg\nPMXQ\r\n=piqh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCoN9qQZpyH50kHHVIJSm0KVXfcl0tVYBT0iuHY4vpPfAIhAPRLvA086lS7apPkJ+Oo3ei3gCaZw44dFM9HSm8x+bDF"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kenou8nl.0_1599190682208_0.9284382632199224"},"_hasShrinkwrap":false},"3.2.3-canary.keoswy6l.0":{"name":"tinspector","version":"3.2.3-canary.keoswy6l.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"99f1de1bc01750c4470f356ad5994ba5baddb6ff","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.keoswy6l.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-gbtlKLLKhyR8jML+bOl04dWV+t76aUIiUgNIRd2S4Pqip8Rydq/5MXixKuQpF9sGlXrMJc6wwaRSAteX/kFE4A==","shasum":"b7879c39300f6700c74732dd83eaf0fecb0f983d","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.keoswy6l.0.tgz","fileCount":23,"unpackedSize":67655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfUr2ICRA9TVsSAnZWagAAACgQAI/Sb0hiDBkjXngXeDM+\nwV9fVIFoghi2Zu+V6gGdaSxzfEzJAGVjrhIYrbyz2yKbG9e+O0f0XJelCfgI\nq1kZixf6W+FwhgojD1Kdxyls0LZxd3Vqj6cOOl+E5EyN2nSHFISNjsu2hnqQ\niUpmRJUT3YBWyqZWMsGPGnAVCOV6li6IU1vuJ8PX7ARcS1I63lumSCAKLehk\n3tUJBd6k/su6BIWBji7Rpj5a7HHY0UobZgA0RWfl3COkA5vuoqDOXIM1fZt0\nhKjhZNugufYW+2U5XvUR3Xkh9bxwC9XPBR7kiK1ojUY7SI0wmVgS2CXSAqYj\nojmMaMzYGYP8P+j+aTB9BMCqqdeSdJHu+E94vHx1qc08VTUaqagZ+ML6XW26\nhl/XHNXqKYsK0mcv4uQ368kvmBPsqwBC5pcwcfuCDpBskQ1/o3DrTkBzGq9l\nnKYPRoAf7BaG63yih8vJEj1F+Y5eWNxARswunI5UYmBSHxzZc3DvGsk8pX34\n3A/Oqxd1+ivwxROF/hlAEzl5Zeh3p7DGSUTdK+juKFwuYyRVRe5YTnSfnrHa\nTaXc6mUoa7jDssxP5mf0pXRk+z3nE5FXs246qRTDiDED2mL9cFF2p6tlBy4V\n9KfLu3/+L1qJ+6LEAJRXVWL9anGup/1zmdvEj6JXsbEikB6He9FmijRhR0W+\np2lQ\r\n=hwpu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHrfNkuziDkiu7Qz7w8JdsCjQPVFl3gOm6K5BC2erm84AiEA7rBkoSLsLFgKEizMe5+LpPdLn6L0siGMG0oh6af0/Rs="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.keoswy6l.0_1599257991578_0.7883978183642488"},"_hasShrinkwrap":false},"3.2.3-canary.kepjwxp9.0":{"name":"tinspector","version":"3.2.3-canary.kepjwxp9.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"d3bb046a67fa3eb0fe43976b1a2272f081293720","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kepjwxp9.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-9G63NVgRf6gnIn+fA8OhU1LAGF7lxgA34X+bkhzOQaJ+yLWkj6BYjjDthOjfZJ82BffcfduEnmpWwvB2SbjIzQ==","shasum":"79fcd84074ce55231ecc72caf8be96c4cfce5fb5","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kepjwxp9.0.tgz","fileCount":23,"unpackedSize":67655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfU26tCRA9TVsSAnZWagAASAcQAIX1cUX3OXa9djiSjimO\niU/ybMW6beuAIIKOgLKaV7sQeTW9kfbB1+UyG18bUQdSQ/wnf+rSKn88wakG\n6g+J4SHtooJmDhf06fhbB2xI1vtHUTiA1xrxq+IVD1zTUS5ErwhBEXJxRRTp\nsAWQPyJlrUNnv9erYTzO2vrd9hr4e7SSW+Y6BnUhaOpecxwAaiD4V5zk0zC2\n1SYIlJS6HGxDaIB/VIDSQ2Y1RvUtQZPvU+7dx/lIMvTmr9I6FrtPyXBP6Ia8\nflDIGmTZDCw+8jLRjY5czKc6ZbUNaMe+G++z1WwKCdh1HR9AOdEKJ5uOtcgc\nAiKYY2BoyegWmcsM6a2AplynifmpOtKqPWJD91opbMtU2nA5CHwGb7NsUy+P\nBgOiyN7wQJjGiXH+H4WyEw06C2kHxcL0mpdKKjhusRCeuDC4wrP1n4N7ZdXD\nLQqxM/CZcu4Hrk9JI+EPM3tcJwZ8N11c5QNDit2EMUwcPxNRC6uJjDj4wMhU\n/FPYTIxkGswBPgZtK/TR0VlHVNGVoeFCeJa9xte0bBCkQZSUEXhspP2uchiI\n1CpL9KhnYnxRSXJmAxzwQEwkdTSowxQj7diTcEuJzU5L/3dUf5F7bo9u5tF8\nmMaf0gaJTTPnSvjwrl30Yzpxdr6V8I01f5KsXM1RDIgi9VuquDwgHyKRAkUH\nr2+a\r\n=EQJV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWOhcflJrRzBhT8FKgc2CaiLZFq71KInDc15WEA2EM3QIhAJOydgjYIWZXgZNMxdRtBkc66UAWNq4kPFNYcpxMYYqk"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kepjwxp9.0_1599303340824_0.06695165144998749"},"_hasShrinkwrap":false},"3.2.3-canary.keqn8ee3.0":{"name":"tinspector","version":"3.2.3-canary.keqn8ee3.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"5749a773d86fa866817a79390cc5e6972151a97a","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.keqn8ee3.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-97SiS6Cznv6gR4RXVpXPq/E98AcWzpPtLLpa/r/Mi5pz1ovR5eA9IfspAyCjGq290KybwaLGIw21tY3thx51JA==","shasum":"018aa62f2ad0a36d87b02a1bcfee4db9dd1fdfaf","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.keqn8ee3.0.tgz","fileCount":23,"unpackedSize":67655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfVHClCRA9TVsSAnZWagAAgTsP/RaU3MS7TgWa3XQlgO2I\nokuDLo1R5nAX+71hjn/bSKIVXYk1hGSmiRJ61vczHKCkKty5KgG0P+e+bbQf\nf7YVyIYd0BEgU2LjpOcR7UJJQzJ3RBQif9sfw3y3TEMwO7AOfL3NTcJSEa2B\naIFE2FLXigNwh541fSR90f2tRcW2WJvxWpjLJbFDi6Y2pNJTP9gy3CDrEv15\nIo+WSSBmyRpTbmtxAnN+rISsQyl0aSgQ+pEyjjARMFnE53kGJTYhwOLkmq87\n8mIMR5ijZBqzeq6NAM8Q4j4deOWqX8Ebeb8+na9j96ZgV50o/eFT2xmeSE5N\noLDhB5DMHmhiZuoU1NlvzmAbSkPKsX7fnaNAkZaqRh/vJVi1qHA24PfDrfBt\n8kOUTVHNbaVMU+hNPfjsH9GJMS6r9oIGPMq1zcIJe7eJc0MiOaussQ52ZirE\n9HgQPnSDNCq6CQzxwZ+54PBEtQFQVzh2Llfs0dxq0R/k1IwSs/C1sLM47zlG\nNQmniujKgu2fyNE5l6edNbxV1RdiQq+hXz6DlujCGKut8VvgTyFBAWRJvLd4\n49ahzx1dk7uN9l3fHpHZhHEnrv1Gdm33hVd71c2jfl0B4qmF0bTVGbyLYPFT\n55qGnmwg4B0u9uGOmxnBZBeQr/d7TC+pn8YzrJ3H08e2u/re78o03oJ2fqYe\nAHd9\r\n=2FT/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIALo0lCCLRz/Sj+45Y75b9zOoIgMAutlzo9jLBDVGcbpAiBI1Qr70yY5NL6kn/h0LoPX3opQBXQLLjwTqsZQTaUbJQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.keqn8ee3.0_1599369380654_0.7983581998024172"},"_hasShrinkwrap":false},"3.2.3-canary.kerx6yap.0":{"name":"tinspector","version":"3.2.3-canary.kerx6yap.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"dec0c5a7ad06cd6f42cefb6799bacbed4cf97095","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kerx6yap.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-on/Xg/EqFBVCEbSqVWBApzi8UyPkFyMAXPsX4Z3hhrGM5z4r7dwk+tMW6W90mfAefv9Vsi6S3biJeYLkqOUwsw==","shasum":"1a6d480cc8b36e89c4c7db86733192e12a5b4dc5","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kerx6yap.0.tgz","fileCount":23,"unpackedSize":67655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfVZ4wCRA9TVsSAnZWagAAAeoQAKPUhWX6hQCuitSXSJPz\nf10TAvfxFPF609bCMCVueDDdSY4P0mTxFFBiWmZsZ7qaKYsmt+lO7Yojj9bZ\n1x64iUXVPNakpasjXEF55TOi23agcKJBo/9J0ZJdgjcCLwu4NBaJ1Vy6EIWT\npu418oMUaUtj5rzbIbCa0HijAQPhO7mSXNr+B6X47G+o+YilLK3/MNKaBrBR\nnOCdLIzGfwLNzhGALGw8qjuchTSFij/NqiH1ucS9PWhIcAKRH1vkJbzKaz1E\nqf02fmNFtUO2SEVNIL8oFFNFogdNWcDQaMq6zD2GiGqJDpjO5PGEsVlv3a47\nmJdZJFr+kSMPCxr33n0k3nTj6/JrG6LQvhHQSmB4eEksVw71qfFVZ1xOps62\nSePv4JW5e0bK0CW1XJyeTLdH4lalh4pGP9aw9zmLYTu4rGkwJCGP0AkORe3G\nrh+EuBBzJzRF4Fwb7qzW6kY3nD1eYKvgkvyGuJEokGLyCiVQq11sV5hjUSxE\nPbbpgX17g6fiRXap7Rmflf2E2JaVGsGT0G8p+bkSGqEDmjJsVHJf0iqfz3Oj\nV5Jicx1zqD/Q35CjIXod8sY8Hs814xiIHjkC4ofl0WScXtaiBdJ2N0ONaROS\nLB7Ve8OOIj8mqwy1j5veqf3TR4R6PsxLdJ56Ow+uLpTLZ2oNacLlUtZ26zKV\nxcY9\r\n=00u5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBkA/fqOHbgvn+3vLxr7xV3w/O1bFUcHQbJiJ5W8liu+AiAnZ/gz0PYYLA4If1ygsh89IzuSccMwAoaGpYXZeyfltA=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kerx6yap.0_1599446575595_0.15617403304485955"},"_hasShrinkwrap":false},"3.2.3-canary.key2i6eu.0":{"name":"tinspector","version":"3.2.3-canary.key2i6eu.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"81359dd00f41443a1772929ce7b73e9ff85bae9a","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.key2i6eu.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-xtmlo4Ade+HYFtYiE+ktrwqaGL8okv8agMWbAxuFfSq5P7daPvSAkcDgEW12i72/xbH4rE7Puxs3bkGj8MVbyg==","shasum":"db3da9905656adc7287ad4b3aaccf6e14d7bf9b2","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.key2i6eu.0.tgz","fileCount":23,"unpackedSize":67655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfW0o3CRA9TVsSAnZWagAAQKYP/0X5hY7mOQqdNNwxBwPu\n71LOw0DMMHpUW7sOp6JAyl5/URd0KgyOp3mbiWyNShWjmjKHrVYPAdhpBl3A\nyPkGeYIyetVNjNrDGDNDOAY/ZTQINqxXSpa+yk+50kpqF5OXbylESvYZlydr\nmRokq9NqWraX8hXEpCtiVx4SbLdmKu1GksAttsrZpZ68M4GjyKrffEsu0SG/\nipJy5Ij5SIxSNOPi+rGpM8hL52+DEBqQkFjYQOPu3lugbtFOXxLtf2MyAPYg\nflvN2SYU10KHBLGdhZY6atS1qtdXmowUR9OZOtPZs0BSAswV+UI2QUg61szC\nALZ/h9YL3R5oiRMtlbdfWqE2NY1Yb6BZuinmhDd0RT93zrjJYOsvIz/llD/0\nbwA5QnMYseN9cKn698UsXDrpmmP1dJhhbmvlZmU7ADjBcXO9O76kC7CVDlUt\n5LoZTROjvLbeOlmJbae33cgJPGTknHtrex91kDr1wROOPmyrqbmy+Or6B0SS\nbZuVcKkfq1zmP+Cr1fmdQb93Fr5h1pebwVj/7CfccEaHPMsWwfKE9ukNLnPk\naZtG99ONhy3XyWZJp6fZcUnvYd1z7+ve6CViG/9WSr4kpI03rOgqcmhkfoFM\nYUmCHe5v8EAklyrpdSPGf0UPLTof4DejWuA/VlIFgdHIXbKi5CuHqb8uCWqK\nqM0Z\r\n=cu+A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD2ZHFhntt/7o+uEvpG/AUjKFloMkrXGX4CHApkG2dgbgIgNuu4aODaDitKZ014waywAAF5S7/sVt5jFt6dkGPtz5c="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.key2i6eu.0_1599818295061_0.5198598452140784"},"_hasShrinkwrap":false},"3.2.3-canary.keyz518l.0":{"name":"tinspector","version":"3.2.3-canary.keyz518l.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"a6712d2ff49cd1ce4893ae2e2e72ce386f4d7af0","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.keyz518l.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-fHYnQ6iD4mcPO4tQVd7CGPuLKAd/9nfmwNVIgPBMYG9YlysGINgim3YGxWSrfq6KadwGkKKzjQfi+CdLVQ7NBg==","shasum":"472e5bee7f050e79f3b2cb695cc62c73d0ba26cf","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.keyz518l.0.tgz","fileCount":23,"unpackedSize":67655,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXCBWCRA9TVsSAnZWagAA0QEP/jalZK70CEutBqS2r0ck\nqATjsGH+SfuMwdNMgJtmovu0SXCKX15DF6Q7TbsCZ78aUsAp0fI+KDkd2ei3\nUG/V4e8xv5oUzYXw9nTJ7vNLdboeADQ4e/KSc9V52VZOUAPXCDNAKA0vWtEq\ngHQjbF4tbpqYngRWU13xRUOHSPuj+4hNBGam6fdFfyupyyjV5aiXvQIPbRL3\nOKqcrfGpUpkxX6XHIeQNU6ZUyux84XKrOhPJZ4DScKzpPb4KZ71e6jeT0Y0V\n7XrcmWWtM4x0MvUn891lgOISUX12ZUgF0BB4E1/eE+c6khjZxsYMAlpG4buJ\nHybEPGTqi+nPd5t1VaddStTH4Mxz75iXC1BoLnA5d247rXjL7L5TDeof443T\nbXCs1k7ZqsYqtB9EX+wEGEq3vl2J0vSxrWjSBPEhYDnCrZa3mc3ViqM/4/c6\no4mYRClDsUhxr+DgrcP/ura4yEfws9U6LMSO8sUMP+yksJRKXs5UWod7nCsF\ndWIswdpPyNazyyu4AdFlNorjmZZ58zV6jgAkLxaOOobkqmA3/1gsRktuf3hu\nsWxCF0/TYhVQHjmcvGDdmmsfAGsPMUEa4UtHqC3htDAPqctHM+v5fCluwaR9\nJd62MQvqmuzXGBIVl+qafzObe1t09Y7oFzu+hog7Cn8yfE1EvKxD9+wtQuMZ\nicAK\r\n=vX0e\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBYnLGKHpV/CONiMVTUY9htiC5qSDP30PTAdfzYS4WVxAiAj3FPNBhg2VsLUnuqY2LAiYV6kYS9fqga1qhgMSuGehg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.keyz518l.0_1599873109808_0.7725023618659057"},"_hasShrinkwrap":false},"3.2.3-canary.kezbpkd4.0":{"name":"tinspector","version":"3.2.3-canary.kezbpkd4.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"e02e6c64767a66656edd8fb13d9a687a9f757a0f","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kezbpkd4.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-KwXWgTqJ5lCRqNUgen8kxieVsKhtYARD9TTq6asWkrgcs0iDlVzXEQ67+DSup498bOx+GCozMo1i+xnT6zqt5g==","shasum":"c0153389ecdcec51cf7eb6818defaaa357909776","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kezbpkd4.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXHLOCRA9TVsSAnZWagAAI8EP/i0ru3rsJxqZtZ7nJpKN\nLdJTQXqwl6ECur7YcPoeAwoapaQQPchFo7bhaHVcAiBfoFrfCew21OFCYeKe\nrzRtRvqpskuzGsCu2mRw4VMck44RSWYy0Zj+hFSAyFgnvhSEJmtITb+jqxK7\n1j04N6knOSGoCaBNtESXbTTnFsI9JWt7Fraox+e+Svrz3urgfUuXlvMTV5aA\nEzWUoLjGcqxQOYvORPADoDo8sUa9HS8Ocqw0inMeh8wLv9n3ImvC4W5yC4kB\nIFO40JBi3aZ3bQIDozH9WP8WNIXdEy2zz5zX3nayTeQ3PtTUsOV7GqeW4D6p\noWdrnrjCwrUI4Zwr778Kj4UuJMjN0t27Gi7IvkyC5DDfCpufZhZo9d6blWFW\nxmG58XaZvlLtlPzVlYAOjbUlPCbP/DeBCtktCYz8L3I8RLpIeOZb8CX4jkg+\nQrNmdTaHCqoxNscMP+b3i8J0i7QCRe6YrrH2xDQHFgqzWwW91gRyM/Fa9riq\nJ2pEg0m+NYoEJ5Xg8VGx8DIlSErSSZ6ufz3Qkc1thzAbtYwM1emE6kpL2pjj\nkgeomevIRBtVYiiO+Ozqcd9muVv/i/gJEjodNSAuRuQSjmOekN+bKKfmtCwt\ngE5r675Sq9tAO9w8CgODy1fW0M6N7N2+R6J220jKYdcayq0Vn7feVSLLbhfL\nGNHO\r\n=rkEs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCRpejS976VJJ4PDrR2yyNng6sRBE0dWdmtBcYWbfpfeQIgHqy3jBxDEbh3CqsjM5SCCEzuUaPDoYgkqwYQDlK002Q="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kezbpkd4.0_1599894221911_0.33267925970010936"},"_hasShrinkwrap":false},"3.2.3-canary.kezj7wpq.0":{"name":"tinspector","version":"3.2.3-canary.kezj7wpq.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"23eb46463fa91516e3dc94383ad1076d56dc6cd5","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kezj7wpq.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-hRwCvPd3TpoLrOPBetAhX5dS02HZCBRMvfpy4qZtGEUiEueYj9cPm2U2sAVIiVMO/jj0bSF5G65kdfwd1WauMw==","shasum":"2c664cc78efa04a09a2d204f32e2c0acde669936","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kezj7wpq.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXKQTCRA9TVsSAnZWagAAGcQP/A8KeJk9lAdncBhrhH7Z\nC54yQBJ5iq/yjWoETEYfoXVqo7gEKPKz7lJtseKPbe4CLt+VZ71VLG3Cj+PX\nKC4Oj0+W8xWoUwxFkdQR1+f+AxtYs0nrk7yr6M2UqtuACBo6/RA3vMJd6L1E\nggqZOfXonEVaZx1JSCFJuXL1HFu2F+jT2ADQ4tTJREJGbydbx1Q+kZo3klXL\n/bxNGsbBNQRAY6IIt+m3Os07P7YAHTp0tRDF0atkPi47LAseFgPAdFP4wF8x\ndu4BtUD1w1TwBp7owQbmKrr8LK4AqVoweFzYz5ytQo8yBMV1atB2p0/UU7QW\n7ZPLtNPsbdSCcAysreMBlcV3z+7lljLuD8gu13PSquiMZbVrMhNvG70nSAmo\niHuxKsyjMp3ByDNvkCxFbQDG08W2vRhelFj4ofWz//1SSZcbU/1w1Q1EenW+\nEo3uV/Vm8X1qia5BmEndO9ND8zBAAOGQDO7z8wk0P+xDhu32BXAHh1QIqtWO\nqBeYQDWU4GdC/JsHiJbQMZUusPDNlfu5d6Y1B9Lwqax1HbCdBXKRsxBDgjov\n/PpDVH0bFln58SONaH602dDa/ON2MImSEf9qGaw8OAOz9LN0dWFn5GXACYP3\ndvPOy6gvwCFu+DXjfrqYUVdxFd4FJOietg2J4P0JMypPW4ZOYrwKR7fa0piP\nNncR\r\n=m/Au\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7GNpSsj+ZvYwUsVrQ9sodTPkFk8taSo79FUAZJ6hMNQIgA2D/5MfVemiQOJ79nMBnW8QD5cXMIiTSgm6HZQt5hdA="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kezj7wpq.0_1599906835296_0.9178898735680938"},"_hasShrinkwrap":false},"3.2.3-canary.kf1ngfd8.0":{"name":"tinspector","version":"3.2.3-canary.kf1ngfd8.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"27fbaeb8471fb1ea8009bb02a9248cd13416f58d","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf1ngfd8.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-dW9g9zF4tyRYqxdvsSEHxf6Ldy5vkfNBtHcRKv8JJg2zqWq3wJEdKNmm08qNJlFhiOUyvcBRHpqw9WVclgcYeQ==","shasum":"c18dfea92ec3cc86ef96de642f011bd4fb253e60","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf1ngfd8.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfXphDCRA9TVsSAnZWagAA+XgQAJ329gGN/0gQRozOCe8y\n+hdGPvvX6hv0AaVF+aOmGSyqJ9Qqr3YxtdODqAGYjZ6kqyQgrhj/0Kg8UfDz\nvVjXueuiMZCJQLPVplg72W3V/p/uoih06pjJ4TfXmU50r1vh8kdENp6Mm6cJ\niIV/xIcw6XJgBCKGwZAyWeIqA17I8fMJmCGE6k8jGmPTqGg26NpJoXmUeN1c\nIkPBIBY9HngX8J1XHb3P47WWHrLLT8f/a7BwZK8tWdDk7zk85XfpuPltf6Gi\noPitDi0yAMDiCRsSXeJwtl8Cru//XsSzrE6V7NFDGhqoxc8EwPuMuagIPLAl\ntMViX/pBc9CGeUOjCULoWwBL04F798aWFqNUDLCV2GLbdXn6uQWpcafgjbPt\npc2ePIi7tER6mNOmtjIcZw0LhJOvQKkSfYfoQw95mZtx3oO74CPQ9V6xgJ7k\nkk/CI+kDrCwP3ckKyn7b/s/f55rHBTMRSxwHkF4gzG4UVRefMAhCOnuWA1uK\nDJfRLuusLpbO00qAaLbplGQAdl/KpjOAAhZBuOTl5SH6GYJ/C0sYD67l3y9A\nfs5rXr4yRaaJtMXLWdsTLuVTCDvJZbsNK1wZJpE8s7HgiBtUwZDW63B4mDhr\nakUKsPUxdH3VDQYKfsuGR2L89fxkI3Z7o1skuXzi62/B17UoafqHe737NReu\ntWbu\r\n=yVYT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9enC3Ws50xnp3hgbe7hrkmL8wzGvt7ddaxCKca83QFwIgE5KIzyibMH3oosdkC3JU8WOPvhXJWhCZY3gglv7xBUE="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf1ngfd8.0_1600034883354_0.8742848055143351"},"_hasShrinkwrap":false},"3.2.3-canary.kf32nfdw.0":{"name":"tinspector","version":"3.2.3-canary.kf32nfdw.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"cf3025d29ae34818da55dfafd81f4d1290aa8379","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf32nfdw.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-P8gpTywvtFeq7/DwuxfeJEKJzJi8PrXz/xGwUSzrOf4JTB4Tk+ygHhTKZkCVrEf5VBpB5snF59LZ5jT/61jwUw==","shasum":"37ff411fabafbca243f521c2abb7e9f9e215c850","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf32nfdw.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfX+gnCRA9TVsSAnZWagAAcXcP+QFQDn1CU9ncmEYcUGwl\nYm6CJxggJ++caMsdQ/+FdAwPjq7m1qQCiga5sFquzPKn11wG6DnEbZbiQ7Hw\nFeeH73Yz7UlA1RUKR8YCsIfiRgVeYSZIEvXQQDgY7B+Urt2LCbrp4uT4/0s1\nAFp9OWE+pIMfhT6ZDXmx3CLBGvFoiy5PyWjQ6MB7vBGDtmeRhtp1oShRbep1\nflE1zHvCKxE9wNNLQXb32BYKRlqkjfw1voNfHy7q5r+rNJ3Fp15ZD8z63m3c\nwIJaipWO3r6tLlzAXwHJLzFD0W0qlIfKgVRWKxV9Jj4Nly2lqQWjxVzJiUB6\ngdPzf6vAg0JricJ2tTzXJ73o10DkVTXXVhLtAflV1HBbzK1G9LFf2ikQo0Mi\n/oUWJp0HN4jZ7kukhUpwJjViBETIPhJMVdann0aqJmCtzEPd9ChXgQZVpVPe\neMhEm/Ajgqdhws1p/aWCtC3BY/OPv0gItJ+FAkaj/XyYQT387yAGAQdD5YnN\nMY03NaKMpMHcwJb1E4h77uGfNCzbDXsiYgU5/fPQZsiLwKCy8jFL7aidn2JV\n64+Oxv8D0jFzAtikhf3dVT5GQadxh7FUyzgSuflMECy9ySNICYQfyP6EMZwc\nVNVrhZgUiqFWWU0ha05CaPxOPRa/6QFSm63I3hu3m3JTgFuPe6yaq5oTLf4Z\nkkWQ\r\n=DrUZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCk6MlEZIlfeNYFy4QwjJC3im+QIw7Inv2WyOqCIcuNnwIhAOfiTLda9hqk80y1AViXv1WUbyH/HnsLmzFjEoNun9tj"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf32nfdw.0_1600120871054_0.026338466262870952"},"_hasShrinkwrap":false},"3.2.3-canary.kf3gt31v.0":{"name":"tinspector","version":"3.2.3-canary.kf3gt31v.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"ec6bedea41b8078b31f16157ae1d909390979029","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf3gt31v.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-UOmGMo3b5Ih/qtsmni+XBPD+jIjE6KF0sduRQY8vQDVM7KOrZXGGLMrEUl5/HRkgNpjYWGCJoTxMiTKMRl9yhg==","shasum":"e725e03ab14fe920b17d5044cce85a0c663a095e","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf3gt31v.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYEUJCRA9TVsSAnZWagAArSwP/Rc+TwPfB0ofGdq+pXjO\nkCy/mq8f1szmAfFPVELjJKZ8Z9txbjHuCTvQRXyT0I5+sWUMqXvUqrxpFuMJ\nve3wE+FOmtvGFnvZJj+M9hmLaN4l9+8psuj+BSknwUmzm5Dp4BBpQIWVSb7+\nOMa37D8kZJfSMQWLVEqXxpXp4D6SuGeutAIlz91uJ6VVMt8mLblOyfprY1Ak\nm7mOH+zgG+PVB13MZ9Qvd9cS5K/I7UKoDU5aMzHjjHys2rH4MpvriIAuBZM7\nlv98/2ktbZXO50If5nMjaTUzB8HNVSY9JVEiTa0PZ7hQ3Us9ziwq/GMTtkmy\nLf4GXT9Dj30Tjsd0zklvPXbPjjpsH6b4sjJLvIqhOEOYm15iNY/cBZBpeZco\nhhD1A2ZrHzo40OQN47lrDZ3TG0H9asMDDJ94xV27XT1a/JMLXSOn0NpUoMbY\nZ8sZNbbmwwyLmdEy76y6Y7zpdzZawsi/C2OcTY9L/OpMuGEdF/bJWeyC/PXs\n2yn5P+Ttu/TXEKcFRbVr7WZyfguJB+igM8omWDEgjN4lhoPdsV0IvoXZMDLS\n0WYEkWXrNnSCJdjYd/JzNr1DSPzJESn2wbkIpcnI28aGyJEjtVL1k6V3/s2C\nBme8Y+HLZJ3hCY8VKD7i9dUqneJiXYgWXNW0JEc6Rh0EFvGsgyWYsNdGhf92\nVCxk\r\n=soY+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnOfuU4OGeKItN0+OiRQ0xBFS+lS82CBFJv6TDOLRcjwIhAP0KOhe+2jjbdev4K7h8q5TsuSMJsg6KpqEX8Xkn4LA9"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf3gt31v.0_1600144648817_0.7795020560410659"},"_hasShrinkwrap":false},"3.2.3-canary.kf6gpx8m.0":{"name":"tinspector","version":"3.2.3-canary.kf6gpx8m.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"9bd4c79ae6c47ce2aafc2015d95a1cbb7e4b0ffd","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf6gpx8m.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-Tx6TvilHtUn2JBN5IimOLHAzooldNpSBHVFd0UvYvOS8sfbFP1yOJ3XxRHNf29rPA3CwTSLNf/JO5g4Gcl/iOw==","shasum":"6c152c502afeed6498d59f252d4b3face0a5dbe2","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf6gpx8m.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYwkOCRA9TVsSAnZWagAA3DYP/RtwkZ0U3f4cdTRzT0Fq\nPnF0p+kvtQM537291DNCCo/cnkhEQv3bhAFTFxeKUf+4G5O6QFYB5U0xjdxS\nirgKSAhk8tnTPmktnTpR9e8fWh+RHItBL5cYXvZn93EugqbFVTsz4b3mcDW4\n1Xx/efjSLa5c2HfiM/wPU2D05Qy6JX+w/7XRyhh7dXJyxRtcai1TGWoeAMXK\n5moHj9jzmBWw5W5/qlQtUCpThCIjpK5FvZLLCF5YrrR1qQmTypAvOShPKg9s\nRqS3xXuuA7tJ92tp6DoQPKEq+ohY+jQTYW+/6tUlc6+ltEa1RqU2bI+wiFX/\nnOgB3kVv4yb2Kq7rwU+A7f6zNQ5BDmdHarX/tQ+2vBZzSg/pLPWBumGRiStz\n6sBOIlXf7O2Evx27ZIBRJwFzV1N/0g7eu+KAtywvn1xeOEZB3IjU+tW10IqX\nJSKR1z/1DbOicQAQSa+a/aVLeFIvBpCTt7VrFXleFJkl1CPiL35+HjeNAux8\nCm1zFCUuKWM8fdz9ScUhrHjRtr8QOHrGnBguYK5GYdXRjkoc6OVlfomsIq1B\naggGmkWlj0JXhartNg8Mf7OoewPiitHyfNBwJNSxGimEo8CRg6BSddfkPXba\nAbrHG7gVs5x8DzPJ19g09/7O55BI8cvtQs1xYRZc6Z9h2tZy/EhbVG9YzHki\nWLGm\r\n=Ix8j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZzlZuay0J2u4DfUXlzZdYvJnUkP9i5kbPfILnxcI5mAIhAK4n3S5MzUWr0HLiPYpR882FkRCfSYhQZ50P10iagnYD"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf6gpx8m.0_1600325902432_0.5599466175423111"},"_hasShrinkwrap":false},"3.2.3-canary.kf6lwncy.0":{"name":"tinspector","version":"3.2.3-canary.kf6lwncy.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"51fb2384c3abffe1de4104e776e49400c8b287af","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf6lwncy.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-Q0gqnVIhzO6u7ylfm4jMnkb6lHDdGVCVGwAm//BuW1d1Azuot5IcQi2Yb8pAnsU4BgH/qD/QneGzT1nTjQEWyQ==","shasum":"c98ade30702c6de118914f92defe613342e6c64b","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf6lwncy.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYysUCRA9TVsSAnZWagAAgJ8P/RPlhavgX9E9lnf/7biU\nc9EDxDm7ByiH2kRjzxHP4y4dmBmt+6UVA2bcnI+JCLIZY0xD5wcrd/mred55\na+6GZZzu1NMmRX7iU9zV5LFL6RJPMz2Gp1kS5Do5JxGWEcT1Q4QUB45Hs8BZ\nbLCBxz2F0He+in6TvuZF1RuHZjux2/FzFBhMx5qrkIa+XQ2ZAibCanJe6riC\n2PuP2KiKjMdmSi78bwGjaJ/VtvNyJR3NBAHeXbZov4Lnrc4FjSKuMz+mxeTq\nUsGfIXer5srkg1fP92TbiSwgCym19bTHzH10e0lcWZKHM87BZa1PA69a3xXP\nou8oTFnVppZwhqtduxOxkyC8mcgPdf4bTic1ETKYUD8xQJSe6qNWLuPGK0FX\nRR58fYZib8tiuSGg0S+OsSLkVewFdMNCxVWe3m8plfl7gb7G+OUbeT+f/J/Q\nNDeAhZZtn9lnQy4E8pOCdSs0qjytea/hcRo0KG2RONwahzlCKKCHyT2cPVQq\nTQEGKIsO/tkT0QGWmQMNhdEFepe+CIWQN6IJdsSuFQm7Efya/WjviK7E7D2a\nMc+XAujrNexne/668QK1gk4Ex5+45CLXUnTAKAvJwfGA6UDzpUniPTXZFH82\nAmmGjEsqFcMJ2TxasPG0qcLKnUZqfGtNgOthksIunBR8mxlXOss1XK/CdjIG\nAcAk\r\n=hDZh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEktI9sqE7QhKwsu8M8zYm4M2rf7iY7DPF05yGAi8a4EAiBYMB3kVdjNRKC/HFnvfbPsMvj8gM9kPYxLCjLPk+ktEQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf6lwncy.0_1600334611639_0.5622577638735478"},"_hasShrinkwrap":false},"3.2.3-canary.kf6ox8zq.0":{"name":"tinspector","version":"3.2.3-canary.kf6ox8zq.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"9230abb52eb0a4000eadabc0160a513ac17f67ab","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf6ox8zq.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-4N8fV3psq0mq1eKS37hsRT6HkIKlCiO+lHtKqt9dEGARDtD4BwfIjqERTSIIgeavYVsH/YaYz1Rl/TByFOya5g==","shasum":"eade52078ef645855de4a5a0fcabb79815c2cd7f","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf6ox8zq.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYz7fCRA9TVsSAnZWagAAig8P/jiErtEJbVLS8fqGZfHj\nQlK9SrfLpt7mtgX9419SYyIHe/SVebYzYqgc8lJUElEwaMIFAM8/AZr4RrQy\ngPG5ZQFQP4zOWr7+5epcGoeCoMuQuHIUGD9iEpiSsdcwbIqsbzw6V8az5KqZ\n468TiwVr8UUZZpnyFJxcB//YZJhYlusTkNMJouCsrtvOAL7XS1lhm/0I52bU\nSukKQLH9CWL1JHs6KP5tCs6s6/Xz2j/WACsQrIfsuz8FCamkt9CAN0sgO+We\nPfji5rWmWIfb+lyZe/B8Dx+9AwMZQ/HzuXeUuSUh2vH3ptbIEuLx4tyAPOK1\niFgyFg756PFplKDQDgtcPWNHhOOuSNgA2rkQmGPr7SlBfyzmfQ8SM4Aun3/q\nDrLQRH6POCBdE6yxuTYm1hf/MGx/Add1deS7TkHrVO2yJbCeA7pcMagb/buW\nsi5A+398Be8RRNPIO2OclFbCUjP33O0Hg6o2gc282AAQcU3oYzLnJGgvk6uM\nRNxFw8mHUo0XTD4ZAiE2+xvJu1GcgEAEHjYf4OgshhJYqICakz0tYzdXkkFe\nZuFabxAfYP0Xw7ENu2LNUrdr8F+z7t3AhSbscZiRas7sAEYh1uhWMWY2m2Kf\nbM1Sx4CZZmZaNUfjJq63VO94cjdPG89bou6AMzmggA+Vun2ov43KwHv2MYck\nlFYr\r\n=u4jw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID8Xs02GulTY8TfMLvl6yFt3aXPfotb0BEAu7CAAfmxmAiAOLB8Ou2ZbxLJb/auBYzPmjtW/1Nk9zzqTlzMn5wv99Q=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf6ox8zq.0_1600339678472_0.0999297159908843"},"_hasShrinkwrap":false},"3.2.3-canary.kf83flsl.0":{"name":"tinspector","version":"3.2.3-canary.kf83flsl.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"07c2c89cbb0cd55577359e45a3d3aad20eec1827","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf83flsl.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-xwwlnLmBk9oZ1+tkZNFdlxZPT8Vz98SRg4TOdr+evEMFUU4VBRMpzV7KyhkIeskUs/LjE1oqKgeRcY2K7hTV2Q==","shasum":"3f762388b4a030e75af970d3a15d28cb94aced69","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf83flsl.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfZIpECRA9TVsSAnZWagAAyL4P/1bL/IwLl417OZ9zWWF1\nVMEaJnAYBEfAnHJ9cwaJ+cAXJUbO7OMISNjiV4VRlWCc6ZeVDHUgWMqL0HJd\n+FFCm3L9RklK2edS0hMDGRZQHdMrmG6TN0B3MBMReTcp4KlQxI0bA27UDWr8\nnWLrwiyHneTURri6x07xjfeDII3KycmT6gyveKmtQDE4RVFs4zeHTFhUrfof\nToBj9u02he9KJEtaMS938ZYdQ0t5xMRSkltl+D1/WnGLW1B5jrpgFVGjXpZZ\n++/iKMy2S+4339VnToGw2iLubV7AJhc8qLIiLEdg7LNjNK7l+lgsNY4Ux8wy\nd4KtB51GbUu6SCNRmwyo9skJA5CritS74cGOWcVANjnYv6vHx3WIVvNFKa5m\nJ29SaBoeesHHrKptKP6inCgIglmV9G2bAFb3KSE0Vgw1uY1C1ihGD5wFqKQU\nYB1Z/HkMvP9y9XQoD+fbNveE6775fybx8VUOrKp9SnMeGbD6WdQ6iYJwXP/O\nX6tUR6BiBbAmvqLBrfZN0Aenk5YxssBzwXoZUmF86iublfE7EIYVwr6cxgUZ\nbIAwoHgoVBcPQK4uuHS3V8JW0CXdq2C6KVUs0oHaGk1cwoqxLsNEWl0bnk9z\n5NH0Yx2zau7BQC33758ix4Bfuw1FiJQh+KVSvgielCy/oJ//lAWitf0Q7Qr2\n68km\r\n=c1CG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCL0beFx/tkkRjgRi8cDeAVpEDAWdVqzN1fL1j+4SrufAIgREQFwREEodnzhIw/mIbr7uVOEbQpYi6ex4/Tq/SmLaI="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf83flsl.0_1600424516113_0.4715019550576547"},"_hasShrinkwrap":false},"3.2.3-canary.kf8yuiqx.0":{"name":"tinspector","version":"3.2.3-canary.kf8yuiqx.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"01dd8c01eb466efcfa3cc3db5b8ccfbd863c947b","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf8yuiqx.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-qpVv1srXzd6pPg3vJz069/s5vy/N6uCiKB+IL9NN4Hru6qzg+YbOjD7Raj4R0ui79aE1MyZS+krD4XfudPUMsg==","shasum":"0aaba1b1d3ee7dad331663786b6c76473faed39c","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf8yuiqx.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfZVhgCRA9TVsSAnZWagAAH20P/jH++Y6eCS07HD2ogqHp\nU4Xm70GZrvh/W5tVg6q6aolLpAiIdnvmsF/eOfYM15aP9Ez0B0lhxy0+Zrcg\nid5+JGCxqB6wZf5DcoXmilqbwyyxnCLLYsrXavvygewUfrhdeXn4cODQkxB6\ne9BSrQroYRnkQ+WGj5VbL0QHos9Nc/eUpxy+XCuEnSipPYlWbzyiySdFCWZo\nJ9ilA6mgQ16+Zukw+va1tkC8h8LVg+O0wIL5P2wmBfSqPULnNSA5ZZXdS2xQ\nqCllr5nFqTZCD2z2KSDwilPBm2u9yyy7DQzuRLWavm/w/ZYqon24vwvUAW4Q\njCuKFWonlgJ0ZpEs1qGXmMdjqTr03IGbTd0t2Al4sACx0m+oidTzTWWS9H40\nl4yK/c3IeglPwfY2+qv3a3E38xEdf0I9ABwvFMQRuHfeEvsIuenoLSRBXbq4\nZHW7fLyEl1lXyrHNwfaShxhlLkqmekH0UqhjDV3UHQqbi5iLX73cCLttAKqf\nS/OF5+RWtLsClsYuva/8w6gUuUCTmu/l7/zn/7DpYhvTSC97VX8wJLHyPKXH\ncdyDk5kfd8GbYpACy+2v2413BzFhSZwN/Q3RI6uhdSfKOGqZ/tqGh5W4NVjt\nGI8Jvt0dhyqoDC/aFnP/iq/SCA9msjDmiACnBM4Xj4cQIbMkYAQtlmG8crzu\n9huu\r\n=mAgs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDJZVdrYYrOczVzfoP4fJG7YdUBF8sznoX1Dp+jepkARAIgTjdVrtFx7/DfQ4gH7Pl8iVhTyWcll3673toEWZXKQWY="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf8yuiqx.0_1600477279706_0.13780730623560578"},"_hasShrinkwrap":false},"3.2.3-canary.kf9he5u8.0":{"name":"tinspector","version":"3.2.3-canary.kf9he5u8.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"c84a00f979910fffc06931b2d5c54917f302742f","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kf9he5u8.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-KZ+l/bKJ4pq7StQJTEiGIS1GP4hre/kXNBUQJMnSFi8I+EJYqXm8PwhfFiijuTDs1HYeFCFsKgI6U93WwBRmtQ==","shasum":"8a6cdff8f2ecffcac0e56e9b1f6237348b971455","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kf9he5u8.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfZdINCRA9TVsSAnZWagAAbpYP/A6RANZPtMx4k/ewPP76\nTJoaA7PoTPlYvRNJwSc1gH3OkKQXyDZsZegmJT9JJ/5nS+GgEp2SQ3kO20N7\nbnaL2mZhuEmrstQAVkwxaw+a6oC9G283i+TfcHMu6h7TzggbFQPrn6uAUMI7\nvQFf+GX2niGlPnqOu3rw4lercinI4A+GY21K+byW0KRmrA6onshi40r4dajX\nmgyTzeeXlNTU4u+Xr7TkuJlPxrLW+G76aUAEJJ/0tSDr+vLIZi7O3r9+sfOw\nn1feoSxh30k2QYolIr1tsQci7ZljQ8G+pf0H+8+P25j/x5gueA1TVgZs4FW6\nKY+vsrAgZtfzk6FkiQD/WfrQnyr3h7K+pq+51LEXPH4y/zWChPfnDbJbTCCw\n6vnpZG4oYwqJHMP2ngihGFdw/yrrqxkkfTvogG2owe+SzbEr8bDg2YwA2IJ+\nLaXnAnqUGQq+AdiOo+l8S9cfTUWgmPveIt/MXD3vO+Q0TS3TZEPf2dPNHSa7\npDnbTfTj8W0Hdxg6EJPGfxplUx8dhMk0AU5phdfnB99YAHeTS0/LdVk6zopR\nFmgXFjx4htjSMbC8ksQYbqMYAIIgXV2GMJTTdRV2+dKhZuJIu9X5VckZDHn4\niydmJINW5SLJw6WCPCk7oWg14o2+qGKRe+edpLwyXo243uzQJ/YxvOCVnt4V\nCjku\r\n=VX6n\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG+qvA+tdwXHG1Tgf9NHp2YsBkNN+AX3FmJCvGsiSKVLAiAn6lxbU2dxjzrRu7iFq/OrUTLD4VAJshMxntjh16wcdw=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kf9he5u8.0_1600508429183_0.4220503873817967"},"_hasShrinkwrap":false},"3.2.3-canary.kfdk5pvu.0":{"name":"tinspector","version":"3.2.3-canary.kfdk5pvu.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"aafe89d8a496ae6c09c5d950645b9cc3bf05b8fb","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kfdk5pvu.0","_nodeVersion":"12.18.3","_npmVersion":"lerna/3.22.1/node@v12.18.3+x64 (linux)","dist":{"integrity":"sha512-FGNc4xH5emTnBv9PlOzYiekP3EVm98LSgGtgpm3hujS+pfo3Bonm0Ig0hj/D15yc+9DbAc5fSLAk8J1JaTCTRw==","shasum":"e9fc4b2934ed58452ed088f9911c5095ecb39f4e","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kfdk5pvu.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfaZT7CRA9TVsSAnZWagAAqtUP/0CoVhuzfkvus/l05R16\nNYWebUaoP8oOzOPpJWnX5xDJIKlHRC6t50ohXsHHpuqyZmABtpOoZgjPMXq7\nEVLydeU5duf3Jm8di/zPRjgCYBcI/igFLFWzM2YKJlUnG3DfydDcD/o0VAQI\nMLksmnYGWyLUXPHdeXU4pvQIQ7+9u6MCbV4n8m9czncZBvgPNRg2Hj2uhUEt\nuDFn/D74HScYzB1vhCnUr3gLAlrYDWibSl721mknCP6djEwlalYmuf6dlZZ9\n/wj+UA9faZ7KHfcg6ki68TzQ6a2jPgcB9nB1Qs4b8879c7/pSRXt72Jr11dV\n3TbqE3seydAE18L8+ARunDP23blX9ZLKOs0f9M9bfmk0rVK1dqkuXOV+SNHb\n8F/epiWiAUj2mkMjCaKDS3QAG7U3K86nQsmvxDo0ge8OI0fxd4HDiH7XIwOJ\nCRKOHsI4CrHqxD9eMF0IH/7JjOg1hpSp6R7ICU9b1lYNAUklBTK97jdlHCF2\n4bz2j+DppcTfwrN9iXeL2xEp0nHSQR1Yly+PXbhM7h6aw4wpVCcXp7juwBTC\noMeSIcZjRqnul+Vq3BgHBSFboCV79aFaLJ9RMygFxksIlKUI+icdBA0Frzr0\n4GXokwT+ZM6johm6qy7GIuxB8w80A3D5LFbKcnYSCysANnIQ8wFwFlfH5+98\nyxe3\r\n=pxAI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBODoYveeh/JWLEqFcQx6lYyYoQLt+ylVWNf1RcImyoTAiAx+Mw3wCwDwoeRXRs32lnbiLHby7t/Ma7QcokTTzE6dg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kfdk5pvu.0_1600754939073_0.8284429401745663"},"_hasShrinkwrap":false},"3.2.3-canary.kfg7x8ie.0":{"name":"tinspector","version":"3.2.3-canary.kfg7x8ie.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"4f8af9b20b3a850cd7aa7e8453faa7519978e1bc","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kfg7x8ie.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-nb4YmhUa1G/Ijn62obJwokCCy6byiE+oMprOlmS+Eo9HHm6w/s9JY6xL9eou/gBeWYbpJZKS9hDzJ50BvE/d7w==","shasum":"067e176fc822cf4ab61cb04b097b60d29594aed8","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kfg7x8ie.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfbAlKCRA9TVsSAnZWagAAGV8P/1fckV/GOkKX4KO4UtAy\nZsS/OUwxappmUjswRL1cQOKv5pWCLSx4eFDsOhtUQ3XMWxw7DhvlL7yPaeUJ\nu2Y3KvCSWlAUPm7bshyc8zrBImcDo4rrcGe0IGAiB/gljyknYfQ82Es6OtaL\np8T5etHRJYIURmPNGdMyVUOij4Ja9lkZ3dtbhqyC4vcwf6qaS1mmjgWucVba\nD/kcFMTg7MD1uMLHtTInLdUyJRcy4GLVmDPM+3sjWTvSN0tSW7WD0JmvMWuh\nVVFeLHbh8U/lfJ/kq8okuW+oOpiuJ7QJe9PNyf+tTCN/vuPgygh6vPIFdtdj\nsXMyk0UnxpG9B/OexbWUaybJuNUGu658I9rCXpJz/WfnrZb9+YPrOrCeY5v5\nkvxGaC9P61tsoNAlazU46dq0djjQWp7AXcAmGpFp3DVuRbAX3jrOzBKUfsdj\nEeLq+ruHWdm8eizr6K3lU5/s+4dtN58SLxn7kk7MvBLiyPIt0t/G2+Bf/jPj\nU7h06od0QOEHenkdvL95NnQpQo+aA2zcUPBEdfEF8ImedT3g6hjAhlj1xKdB\nuTE/tDBv6VUvQR+GuQTX3o7sTRAu77oWKwKHYImLxoF3pvyzacgQdgv/8Udx\ntt7mVvbQHOA2kazzKg0REzrJII+cDxyZfNfHDILyEC0Z57i+go5UouOm0YB8\nSEaL\r\n=Z2u8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICbeg2crpN763mRUMKgD3d+m8QKTp5r6Qw0N13DwrOQjAiEA1AAJ4eODz7R0/u00Ph3ao5zYUL35y0UTO74xCESdtOw="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kfg7x8ie.0_1600915786140_0.47808744664879077"},"_hasShrinkwrap":false},"3.2.3-canary.kfku9xyl.0":{"name":"tinspector","version":"3.2.3-canary.kfku9xyl.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"4a1b1e8599873b1f24c7f30ef0efb9e5d2294afc","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kfku9xyl.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-b9QTcYidJAf2TFNcEQHLwAtcQBm07wewJB7IZ5z1w9txbm5hK9zioEIpABh3gTiOpyfMHDzs5o6ZEjKWVLsymg==","shasum":"36f06d153e1f7f7272f3802419c97dc2e2a5c47a","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kfku9xyl.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfcEy8CRA9TVsSAnZWagAAxGQP/26qaQm0l8dJgNRxjr9t\neBzrMfCzR43iUHp6iJOwcCbRpeLYCyGle90fQq1IDEWp0pfy5EpIQBci3f7/\nAzjVsN6NFNZXCD/cbRwKAO3p91bMVBjnGs55WrqOFGH16ItBbUAQ3689m0wz\nukH8O8Sv7RyZ7lXrP8tIEC0gwjRu002vwyDrnCbkuEwBNtfppFXSA9Piq1qi\nzFp2l51hUcQwOAMGTpJlhdzEAAIKMksLzSSPDKUsQzOfSy6PwwPJdtd3hy+w\nRzilT2881No4BOSU+QEkgy6Hn3g8Ih6jCb5GMupP+lFyduQZsJgKLzSjhKXG\nwkVUbisFhdnLrqq8ZjzI6GOLvfN+G455dAz2osCDuaA4/C/Pa2H+FrnAt8TU\nSjMQf5diLSnMcrj7UMvwKuX1v6/CZAxDmiqwKtmPuIIMSIukzna3SWtCyQpd\nAdtqqCLQUWEz6sJgKX9D3qPI72/FSizL/FH/Cpf0aPufwVQlJknY1GqZNiZv\n7DBEidSr9/nXY9P9XcFUQvC9VXRgabQQlJywhz9ZT3NNacd5ndZJf4tKCLTe\nPUNAgySND+XkOyN2AZyNDwRNmcsBnFTuzw9+DTHlyhK0b1liXiP+TG5oAxWW\ngHtA46Kvv9SzyG5tsmEzrl1SOB0gV4oqJlQ6VSyRuD48416e2hAdy5nkC5xQ\nAMBP\r\n=G1Eu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCfwigXGeud3azupbGTIfFxICfVkJ8jnHzpB/OGanm7GQIhALXctMLzC/Sl9YDKw9RqtTWuIr64In3PPczibaTkN7Bp"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kfku9xyl.0_1601195195506_0.9624479735737892"},"_hasShrinkwrap":false},"3.2.3-canary.kflwpa3o.0":{"name":"tinspector","version":"3.2.3-canary.kflwpa3o.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"4a9a5d33f35a426f2e44c0f2b1dc2006bc61b0dd","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kflwpa3o.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-subMcAjjJzWwrq2XEsIEkNNFabiAIWoL0U8WDpyGTSfgX2pS6f4HvKG9yHUNdfXioksdi6nnF/+EvokS99frgw==","shasum":"4c5e06d57b4bde52f35babbf05a44ae75ff73166","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kflwpa3o.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfcUjZCRA9TVsSAnZWagAALicQAIBZn5Cz0sO6Pvc164kF\nVu5Gtp/qnlfkF7+3I4Wnt6/Odp8yKyvdstJcBO5zjlsGXeUSNjciqtmL5jXW\n9XSDl5PymxmE/a7SkoIEQiSXt8B9E1WSRKSaUvnXt2YwZ8dvDU+mSUn3JEv9\nnIs3zyHGnp933xayyB6xzxlEc5MExbMjqOjEins1F3bLIb3sseY5Tsph8uXC\ncPhlsS8H19p9F8xhiT9v9iT1cvYSVrm/UlS3b6e0NFJjZwU7Hb42jIgkA0MX\nT0EZEIQBv/kaYuV4hk50UyNJyxihhHIYgDcZHlesFo0je5cRqJje1wGAiUL4\namDX0pjsXr7clyn8/iI8Tf0VFJcIUKtWhOZEHLguyj0iBg+Y4oOHuIER3gUO\nnSM13Pb9sQ2Y5pMWfy7DkxinNP5vp2s4H3i2YV03Hc6zZ2Hw7S4EzgwnYLwE\n9G8xt54/0qlP/MEY9/AQTMoDrA0m3wtBRTH6mVhS1cwWU4XiE27KfmwZ7ldH\ndh3N7ssPbZHQletAWycR+qGGGjPPxdmKszKcBQNGsbb1ApWlWyy2H+g4bmt0\n5k0XeM/lm2DIuUPi9TBkWdM8cEcW4EVOoGv8xjPQcIgjspUxWYAF2VmAulnl\nWQNy0ZzxCx8LJMCR/VaQnnhnetpdbIcj5ijrQZTCJj5K7NiVoPhK3jxhoC41\nrE8z\r\n=PAwJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKpW+DQzRNejPu2kOGBnq+nJ7+M0H/aGLWLJ2QzwkB3QIhAPB9B0wHq/TntdWTHoRB/Ax2LtAf//cS14YYe1ri/Ew6"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kflwpa3o.0_1601259736678_0.04898462401330361"},"_hasShrinkwrap":false},"3.2.3-canary.kfm9pqez.0":{"name":"tinspector","version":"3.2.3-canary.kfm9pqez.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"6767528b01ef9de421b5390049cd0b3125f812cb","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kfm9pqez.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-ZM7qnT5e7avpd4BuUBOdf8GpT6xUBAgJkAfpPyhdD+qQaPaCDJ+Rguj0RCotVE3CUiF7J454IYK/jVnSfhQ9/w==","shasum":"2e8074270aa1ae725c30f643984c19670f351112","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kfm9pqez.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfcZ45CRA9TVsSAnZWagAAHNcP/32XhFUQGSqkd31Wvvtk\npTls6JGU3yhGwB9LfoHrb6u/QCUsE8pDT9kVrx2fbt7Kifw6yhND4Sqe+FpP\nYgyKa2Db2mYSAsgEiyGCKspOQ293nvYAiqFZ+cBiVO5tAuXfbTC8dC3RMhmX\n4/s8NwKSEq8A/e8n2fBPgGJ3oV+jdZ9abNe966slm3I6+qYxKiF2YNzt2PsV\n3JAEygTaOM9xwGdmnY0Jv8u53GGO/flARksP6vTZqnlkgmChznP4ppHMcX4g\nJvmWpzSJD2AIlH9ptuwGqiFy+UsV0w5pb9XpeQJtlb6S/eBZ3+BMWEsNAZUv\ngwv4wUvSED5AcQCSYuEpC4msZrPraFABm7QygvG8gzrdiZaEGBe74wqKGyY+\nj6zEyW0NA9ZesArqctv/Rm3zxSlEOX74odyiD4yDWdAPdSw3bdgVUJXIrhPh\nc+g38ATAF0DDz9dnwKnJTPju+LpKJVPM209VMQovY3CcCbYAjmY0dVgjppXv\nOb1xZrB1n36M6BRto1T34fR6o7ZtWGvsbDQRbvOZW1OMb+RMBNokROfi3aa3\nSfOft5Pbz9aQD3aDgk/Fp8URctK9EmxweKBd8AGZ2lp9KcVY4qkoohfKMR1y\neAv0K36OUTsNT22a2ZjnhUsBWvtGwMjclpaqsE9KbkB+2IpDDIzXQwAz2yMV\noGNO\r\n=/J4d\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD5pMFlyo/8tS12ak0LV1zwmvxRvfkygL6s+YJdZX3L1gIgeI6qGwKRtil8UBTJftAIJ3TIM7f6GZ7/pVB95orRN8U="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kfm9pqez.0_1601281592537_0.4353730819128976"},"_hasShrinkwrap":false},"3.2.3-canary.kfnbyb01.0":{"name":"tinspector","version":"3.2.3-canary.kfnbyb01.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.13","@types/node":"^14.6.4","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.3.0","tslib":"^2.0.1","typescript":"^4.0.2"},"gitHead":"f902a9d0f305d5ab3569f38d5f5c9ee05cf29da1","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kfnbyb01.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-9gDHMPqfZ2DBHp4OLyY338OcyDsSWAzW0DKcw84o+9u/cpXqcN82QRwbbjtMoFyY/mCLhidQlCmg4cBczLGqeA==","shasum":"d06a42da68c3486539eca3209b411f39ad3cd303","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kfnbyb01.0.tgz","fileCount":23,"unpackedSize":68540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfcpkaCRA9TVsSAnZWagAAgrcP/3FQTZ+/KKAXrDzR487R\nOzrqrAvm8dAUCdjXVrC1gQpkkeljqr49CPRQy2Mv+aSw7T9WBsO0Djrd9pP+\nEbj3tRJxYJcNl9NAjeDu3axgKUazG4Z8Uq115Vv2pKvFcrTvqdywKOCuvAtJ\nQzhcRnO3Ry+x0TWF6GuBPfq3qnE7ckmt9oIsaH2OyzqjIUNHurIhLpBMv1WS\nPU/zJiyvNYY9GqC2gbHgf6dJORsAx2xapFLMNwGXoaGS1E7PBB8K/J0I8Rex\nfOPREXnAw4RH5geGOc71ZbI2wjX4Vn/G9e4kWb+XHdZkxrp1n2WdmGLst9JT\nuNpWo3eHLnwntPqu3O9/GMqvyTgk7AlDXeOSWgVoiz6jvk+Klv5IcJsoqODT\nByTdenINUMge94nU+ExfJn3ZCAWh88MamMS3/7ZQ5bo6hJ8NNTtJRKDczlwr\nN0J0a70lOpbolyh7F4JVagnYe/QVej1BQ7jXLVFHp3Ozvqa8/2jXBsHPJiZw\ntzXr1YsvtLSzVti9Qkyev6gOLzcGQJRjqFJZAZ+GvN4K9xCd4kJbFIAr3Ego\ntWeB2gGiJrRE25ol1gPWajlQhcPGhtBnwEJYq4wmPRtgd/gFrlFfcVqiZPQ8\nC3iZ7u0N/NmwKcC9xBw9jUzHbeiq3/z23vYyCnoz+ADKkJUMXFzqraRvNmda\nMW9M\r\n=fcid\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDG26pe9c2Sxh9qMU2TZ3jm17bR1IOweFnbtWD/b9krwAiEA+YP1Lva5T8DVH5agdY4tbtYEVFkhhkhKol6jVlYG6lQ="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kfnbyb01.0_1601345818224_0.2829361810892981"},"_hasShrinkwrap":false},"3.2.3-canary.kfndaw7c.0":{"name":"tinspector","version":"3.2.3-canary.kfndaw7c.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"28c72a5feda16a8eb65a3a7416b03e28ca95db8d","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kfndaw7c.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-lP0olb8KfTeffwWHEQDQuFzuDplUH2Dp0zTqK5TUO1AkcxBFm/zctldPRHr62rFVZ6LC90MCwYjjaRUXpAEiWg==","shasum":"5fb1aebb32ceceef37b12536d56755bf4f01edc2","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kfndaw7c.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfcqH1CRA9TVsSAnZWagAAVdQP/2SRsQbenwQBJ6hFevHX\nNA1bhJba66+Sj1B+YAtgax0fqqVl6g55QW9AfxRq/gSBoFWWkMMwoT3NQhYb\npDGhejyeT1hkpGfCgt8NKpsjlwYTPt0kkfRNDeiRv2XCUcU7vAcXwT0ZeVRf\n9MMXdnPdwSoua8QmItHa3UiyeGcWga0bPZz5rqKnu6tjGO6rVOJquT2Ysa/G\nMoqjO4zRKqJugjD7hyJLTbM2lm87no29laK8KTWj/ZG3wboAcHkbQf2qJO2m\nxvKezFpvxCazBroCt7AjXVLfG1QZD6eiopPvQGcPhMzgqQyxnXyC7C+zXqxM\ncqWvXXRPJoLzK5jN90qEUZrTfzervm8vbrLFaKQD4FZ4MIj++p+I18klFQPR\nx24L0GsQQWFRRO6cqvrfErLS4j9EIyGmLonlw+5rDLJPJQAbmFmJIVT9hPYr\nOfO9HfaN4oJf1vl+PNJNpYGT+hoj3ZkJiNKAS5gmqQl3ZAOcl1mn4oLCj1wh\niHgcHIHHkbFwgs9rihPY7Dred/s8oYVi/f9T310twvLMIdWM6/FdDrQhYdRu\no/VlaAoKd0Dt61QV3KTb7k86iVZDFvsVM5oLRdfEAOqafYkmSyFhOg6WI/xY\nCZnrgJF0WQNEO5W0i2kOEcFMtk7jzxAB83+IzjajLwX6vRQQkZ/nSgG+cBq8\n51Fa\r\n=l59f\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHxVGZSxJO6ID3DLfzjgXivpNPW6CrSsEY1UYUI+VX83AiEAmntAaT3GYcrK2VEkSpdPDulNm5hHQltcGfbTWpYq+aU="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kfndaw7c.0_1601348085176_0.24933427172112244"},"_hasShrinkwrap":false},"3.2.3-canary.kfok0ubn.0":{"name":"tinspector","version":"3.2.3-canary.kfok0ubn.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"3dc703277c8514fd632501716b20cef2b2db67e9","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kfok0ubn.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-5sv4nkGwwJaClAu8azX/AuW6wK1Bbz6nSG8twMMvg1duNg+dYN2eubN5TjQ3TN66FY/3GVoEgB4rJmwBDlbCeA==","shasum":"399448892ba1fb52ef12fe3d99a1305a1fd77b18","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kfok0ubn.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfc7pACRA9TVsSAnZWagAAfIEP/RDaP/611pdrb5E8kNtN\nSNY/Ou17euhD4gB2ZBNviMqN8dC+xooCDs7CUNv3mRynRHi3PnQRXCo5Glfw\nlj2iCvZl8QVvlT1+FVeTVlFb2RIOzLgsdyKtZ8NOyc1Sk1D/BuwYZhcHnk+e\n5XqrDFkrw8dizR0m1y4V2FpKDRDN1zWQnjLufXTSknq0kDxYeOoUGQPoPb5D\nyALQncmWWqpvEDJERiuFSCZ2VnjWLYjbjp6otjUi76Cu3ToHyS3pwtBWyXMq\nxRmek3CgWDPa9EQoDyStroSUsaJaT3FJmOK2NLSc3YzRDxfwLfe59e1uEb/y\nbxh+56Hqfqaq0/JF0i4noxhGTHN4pwR/bTemh4t7RTFoitVXKGBb/61PLKRK\nstQx0OojOaBmNmVDmpKkFOccrnmJyw6Rdla/amJGVDZZc71IqfUVkJ/+DNvY\nxhSF2Ko8YUJzISDQk3Uj4WmDVeixOHSBo8n93I31l6G+R3H4zXZS03U5yzf/\nknixDYXoAOrYVXSI7fWyqVx4Zz5SP/B0Ef8nJz5DRqAd8Ui50SQNpZ+60AbT\n4zt53D2ITgjEYGGj6mrkMdhXEznoHggM4d6lOb2HR8r01yn1mJIYeusI0+WR\nfl2/PB3OioVY+obxc9Cw42NOcXgwYHtHVppHNzp6ikTj4fXo9F87Ubp5S3tK\nCdj4\r\n=G0ls\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDp7jaufBGu6BXceZ1vqGvbJzjKXQC01r9CbsqZlQeNawIgRe0jt+DNLgUvERVsfDey2eSkrW1ruP9+2as4sHRrfJ0="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kfok0ubn.0_1601419839591_0.6813756610733881"},"_hasShrinkwrap":false},"3.2.3-canary.kg3h9ub9.0":{"name":"tinspector","version":"3.2.3-canary.kg3h9ub9.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"157a87cf9a09d2ddaa868ac63256f3b7fe9cc82e","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg3h9ub9.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-uHMYhMQYytiBAxbtYQPu/OzWRxP6KtLCVzR1zWEyY8HBuuAsKb5Zy/oCIZtqhszjhlMiB2TSCSO4vZn22m1iXg==","shasum":"0e7ae33fbaa16682f87b6988691bb48b3adbef31","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg3h9ub9.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfgX8lCRA9TVsSAnZWagAAnGAP/ijT+8asEP+ot4evNILD\nkmBO9qpUudhnEV2KMjPlXHIptkk+TE1ZH5gir+hxaWCqKjkXr/bZ/UfyVxzW\nZsF5V3GI/CJ5IBWu+NE6HuBa5w05DcCgdqfkeg2+VX751WhzWO/iZkkbCNQh\npr+fCwePz8mdSYeIEdEOuePjdePVu94v1MXfTuqjtfDuUrnOHkT8zmlgWvSu\nAwxefjBIo8aZMdEBwFAblKDrslWmczVe6h8/j44gU5ryGG+RsD7Ny+ALTpiD\n59iU0ykSxbIxIzYB7MV1nGsUC3nK4e+n2FbVwjm6u844p/xRBrob10kLDLQP\nb4Z9Y8aSxtwvL49K1llJcQv2w8U3jQ0NmlTzZeRGzTzV9tf8/0vWGmBQnb5g\n/BxNjoabdTOwL45GdTu4+KTRTCdXjuece/PajXtrqXttjlIGxDRqdSjQG+eI\n7UCU22NJU/XvDyDo5ot5SA+vhLLNnwNSwq4kd9adrKFbnUU57wqOH/pX6MpK\nFALGlQdOrkxDpdT0Hdn1NKJHiUzcwTDeDgt8z9UOHkqUZSmUVvWndknM/nqC\nINgHxVI0FnnNdEAQHv3zEhUTbRc+j0WugxxJEd9Wxyp0yA1HlhBbLCFw5PAx\n5NWckpDkqHgAnwex1rQzRhccTTgs+9ODMTpNezwTb3mLtMJGriN0BqpyWkFa\nrp44\r\n=QoTz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGtzMW8B7hFaOVIfrVpFdkXYX5QpXC7g8WaGAkzfqNK6AiEA475wGK6KgYmTRN21T26RQbWL9he/0y2n6XF/x1yyRxE="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg3h9ub9.0_1602322213010_0.26525232129285414"},"_hasShrinkwrap":false},"3.2.3-canary.kg3j85u4.0":{"name":"tinspector","version":"3.2.3-canary.kg3j85u4.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"8f056ceb2b697c65f3d9b56477544088323e3618","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg3j85u4.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-hOxC/Q8Jb4NmtK/U6SXkbuANyClrVUlvtdUlb9qCHKgVMe1kaO1d7jb30hNnJbSmcVsTSJZB3s85XkXmGsV/Ww==","shasum":"1d01386a7d55d600ec24574f0abca78066e991ca","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg3j85u4.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfgYv2CRA9TVsSAnZWagAASBwP/1lCuFIoFh3mK6IjZU6d\nsVjKVvp+mN/OK1IqCQx7wWuQ+b9KcG+AirSdGAdDYy3Xh1AWrhYGBBVgwsZZ\n9nFHR9wMHED7Vx///i3cjlLb8ZwRiFxYeS5OfZC33dcxBDJx3LZZ0mvzxarp\nqufsXrBiFx/WWw8LodR/IUQbww9Ehek11HIwmS4Ib/rcmLFTW+QbFKmBr/FZ\nDiEy6h3zPeoW8GwsWumqfKzq+fut8aGKNotSKohGez5WfWqSN1LdSGxFvDeg\niRvluXSSJphx7AA+3HUoVS39pj9j+WybRXWLtLhI7E3ANeHfEccvhouD1yCM\nksPj8LqISocGcJ6FG+VGkcVlrvJ5/ne5RnSaIb/r79aIX6hUnk4BeDjjiwtv\nPYiSN0Cx36aSh6yGkFPVTqvlu1v6sQ6dGPt5eWIBeMaNZRz6cYtBrgqT4+Ww\nDr5weCsmC81VegMgdjeAVmkcM9kfRVkhmK0KFoqgeMMtJbPComkyMj+nOrvJ\nbOa0V985bT8Xp3PXX+4m0ebRL5Psv7O+dtcINVO1FxYftvL20m67IJQ8Tu91\nD8ZpvHP4DFWgXFtPv046WhKZeVisgoSkrxtC7BGJ9ofY3+RXWAqMf4sn8OBr\nMdw5wvz1nH+Xy/fSgHp4eAONACwEhhj3HgSuXSLppLlBim0EXs4zIwBuzWRr\nvk4/\r\n=2Ig5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDnc5J0kh6CHSNOmX2U7hmE9kXTmJ247QwtRE78KHmbPAIgVBpfHvY8K8MRC8SRfLCmTT/ch81hiWu6oPIf1ZFWelc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg3j85u4.0_1602325493961_0.970516441897523"},"_hasShrinkwrap":false},"3.2.3-canary.kg45m6uw.0":{"name":"tinspector","version":"3.2.3-canary.kg45m6uw.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"bb14deb88524bd847bc57a13c5fa5dc58ca590f8","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg45m6uw.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-f/fYEAlrwRk990DFHpSUjAYzBQ+RcfzXUHs768KPxdyV2oMMS2Ci2n39dYbWGFTD76xauI3/EjeNyIqL0kLMdw==","shasum":"823edef0be7ebaab81fa5d7ebbf4ab40d7a8e967","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg45m6uw.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfgh7cCRA9TVsSAnZWagAAtKcP/2Bh4lAbhctSqSaq89m7\nCQp/pKczIXsA8rclHXNs4rCw3+1OYWALRa089Yrho8At//+lbg5z8LQ+q4pz\nS+Ub4Ini2FZg1vHJ7K2ZbOhDjxmZyTVwrF+dHW5XC+koEZp5ONf5vbOQVQSM\n2aVdfLukTkjkbsYwjCQvfdiadM2Qv19t48OpK3GCEbOfqvP/bUc5jeRKH0m2\nhApmSZixNiuqxHXMd/ewq7f7JdDHiEYG1DNqlNts/nG79V+MNqnuyVGXhjWV\neji5lEU1eDcjeTbjnnlMTz+6cOQqDjdB8ts2OVnJWe/nbCS7B2zQ90W+ps/b\nRhsi3qntq7I1VaqVPu37KHU3I3ftuI+6sOVjBLE/nQfW8ZRNfjbC9nUW4Qjj\nayNWLLWsa80d77jwCPmBFJdqwYa9YIVoQUuXob87c6k0AFW6M137iMAKNj0+\n1rTMLS8/MkeyzlEF3xANrPvvFmAvbibIxN6NGDSAs1FOtJqWPA9V945B07cG\npHXbEYbqaWxDyQzVtR3fRF0pO8S871ZygZNhoQSc1/902BgEeX/rrb++t72n\nZqSlYQGWseXSwfI2OKDNcm5/3Lum0JjlVC8TWaDb4FFXtbdD0FiTi39SxqpG\ni3ed23Twu3uIM7sTqzXtnikh8Vap3q0Jk8/XYnlrROl4OzhBpquWXRsUCdMA\nHfjZ\r\n=mF6V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3X2hmQF/Fb72xMsUGs18M/I9LoOkurCsY6C+RxN7fXQIhAM/LA53uFO0q5YRlhhfIttFGvfdy+pxDR7BrkPGiqKMO"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg45m6uw.0_1602363099839_0.8806939496185062"},"_hasShrinkwrap":false},"3.2.3-canary.kg4vj92q.0":{"name":"tinspector","version":"3.2.3-canary.kg4vj92q.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"78229684158ca745ff625183465494fd13dced2d","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg4vj92q.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-x0OnawDJjgyTVmVI3RZtrAEZOvjy34ChNs1D9D9YpNfhdTvTb+k/XkGlaB7OMkI0fzpLiTGadAmpcSaK5Cz4ag==","shasum":"8782cc0beb5a745de8a0aa0889f4ee9e303c59b0","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg4vj92q.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfgsjpCRA9TVsSAnZWagAAnHcP/j3j63ckhGmHBdgr7edP\nvUY8dixHI5LKKfsQDvsvYlip2S8sQBdpGd66jkB42/5xHvPXCLRbMkXD1uwO\n16TZTkrcWffI75HU6nDRyNpkYlYv7h3KttkT5lW3ItdLwWUGSWDmJqIucwPb\n2lQqVDvE8mCFCYMSJFpoe33mbIj+yYvJwhonO+cuvZWuI1Ub052huj65zriN\nnKIvb8ZvwOIS+tyEvrLr/su7CZIl4cs5D9htsphxPVDnZOWViHUQY3FAVc76\ncJxlCBRRlfmF5PtBK0Khz51CAA0zZn3NX9hnmQSSs2ODszZeT9fgaNUt9yiO\nW5G3JHJ8EoV0ny/MoS56WTuaazXvB70IcYSA7v8ycfDRqlF1XKKtsYrpy1O7\nL+kuVFn0bxB1t2uVbJhWzY6ZwF1Sjy+YZpu3RLvpU4ti0kQNr3TxAUGP6Bz0\nKx7dd69kUx4PeVUBYBJcofgaojVeSuCQMnnUdfJDKeEVfGuHqU3m/Cl6gdeT\nBXI7w3q6F6nz66yYpIKEloHwYR0/cRUQLrOvobBsk9AzD4rso4ZJeCLcf8Jt\nNP5vJ0QFaXsbfDcFHbgAgy0kkD/VZmI8QHxdFvJSOUdBCEaTcXct+cGw2R1L\n69El0hxcdQs+FamgJ+PUme7boaX1P5gtE93ggoEScKl+cy4pZyTVjmVE0B8V\nsMkz\r\n=fEUr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDVMVwCRE6XbfjyTKBBB/HbhOj9OzalBTV5pdfimc+y5QIhANToAFtFF49rQFlLuPxMyuZBEv1yoVK6c+0q5ivR3FXe"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg4vj92q.0_1602406632707_0.2354392744405771"},"_hasShrinkwrap":false},"3.2.3-canary.kg68uhyf.0":{"name":"tinspector","version":"3.2.3-canary.kg68uhyf.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"de5850d5f868bc934531d942a0972fa4a1e1f445","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg68uhyf.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-diua3xMasr4fsnNOJPtyB/RGoe/w796xB+yFhGWdoJzEzPlxeG0Y8lL1WcvKvHys54WMQKjm48pZm6gYwT61sw==","shasum":"dda7f5899911e38ca8d1fd10335167ca8a60907c","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg68uhyf.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfhAxzCRA9TVsSAnZWagAAGesP/RCqzyx0z1th60ji0kdQ\n942fj4/wahjcDy2FZIq7NuMdU07QtRandaZRnoGRJCaMuDxzFErMeBNMqxDC\nGMryJD1SsJKepXs9vIAY90/2bBGofPj2AhOo3uMU4CswWy/5VCJDjeZt5TPQ\nQ2RiGFkPliq+BbJmdUDCbPkFy5iqF17Bryg5y1O1E5ppGx0Eo8EsWfR1jLwa\nj2QOngc+MC6YpRSW8gF8SOAJ2CUcHlIWfPdt+IsjdX40lUokdgJ2l6pT1D34\niG2n5YQ8sI6EJ0fBGxJX/qMe/v6xuF1jE1bpJd6TUY/Xz5YO6PqqsLvd5CfJ\nLlpioe+C//DiiGN/KNpo8+fgN/SMKWuHLnOG2QF6B4H/GFwntBUD64GwJZ/x\naN3Qd2Zm4cVd7rcgisr/0XGNS3Dt7oXBocxFuf5VLPBn1gdgf7dC+dfNHFt8\njN7/DlGo/ufW0vYI/AUUt4Jt70+RH4R2N9RUb9k51ZiEJedd9PywiMfaqw3P\nF5OCb0Owlcec4CRuuyijqPM5XGnlMO1vDWHxmlPXv9faUnrRfb4yz6MLOGCW\nZLNY1K58T/wktX0Yp2cvFnkRAM0/qY42eqY4haTu6VxRTjww0ohsgPI2R5RI\nByucEZ8bLbondAaLRT2FGFncLjyQfrCdpGUmrxBuhMzJj1fGU07uGyI5ERO7\nybzD\r\n=oWry\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDnWdD1I0DbrV12zBHX9cedEKSFv0RO3kr0xeOM3XlQtAIgfoVqhcYFGb2Nu3zcpUd7vKcpfTZXGlu68vayfTntDHg="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg68uhyf.0_1602489458455_0.8415655163633782"},"_hasShrinkwrap":false},"3.2.3-canary.kg6g8g5u.0":{"name":"tinspector","version":"3.2.3-canary.kg6g8g5u.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"f036b6002d1e6be78ed717bc328045f2df92c821","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg6g8g5u.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-ewbun2aYbkG7zf9V5g+J2k/83oJZCrVLzuVzqcYQNFY95NGRt57orUeBahrKzmpa9uWWhcexiGad7ivklFdoCg==","shasum":"81b40e891dbcbf195c8f060c5da1c8bad242a0e4","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg6g8g5u.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfhDzwCRA9TVsSAnZWagAAo5gQAJ31ozyEbcvlUYSPYN4P\nFzk0M99kR80+HuABlDA8CdoZLjG/9uXVRX8v5qG+uywD6LCO6VpSNuVy2XtH\npQ0nCTPOnNNEYHPYZZ1qTsX4qIjbIXqeXUGrHx1WCePdYz0BMfy9yUNTX1OV\nRWAw/xS8HCJr+20pR+d5henGGXldbtIWDlwd2amMwlRBLc0ghjnYLHyPlFC5\nieqXkxdfY5SRqA4tfLDRYruiL00SQ2CzVlzr+u4k8fCO6Z7O4rJa8m2L9lVE\n2zhqlxeL92vFej6h81yeLSARXXoKE6XtmD2iXnDs2IP1pFOx5fugabd5u2B5\nnKAJIVkjOt5MvaM/Z7XrH0yMxUsLIopR/bxCUxr6hdSx3DR2F4iWk+O2YcT4\nkHBIo1UaxYygmfkTewb25dJ/QzvoaY7YLt8VQn2kP+/N3IsdwdTmursOhfcI\nSGTRCxcTT0HQ7csC3qmxU+TOeuzVyP8a4cSrA0iXoUcthelr6b5CDXiHyS8m\nGuPK0t4Gbjh9sGbDQHz8fA8SL2uduxykXkfhLQ3UAFVmMUcQcTIOaceoLvyh\n5ef4ByaMc+eqQtDREmiSogIQbtfxQovCDroW0OYlCbwNJJaHFnv4nahVGDHz\nLpXjxBEuzcbGco4jYAhy/WQWa+7qLp7hOB25aQBq8oNRAvYMQFgNuFm6mzI8\nydDh\r\n=HdwV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFu2F545Z0XvxJ8hrH1j7aDc76qzzDU4lDskdpl3POXpAiEAmqTWzTQSYNpGcqKevsmiwvVw9WvGHLjgu7oSmiG+JTg="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg6g8g5u.0_1602501871587_0.21376286633832553"},"_hasShrinkwrap":false},"3.2.3-canary.kg736xd2.0":{"name":"tinspector","version":"3.2.3-canary.kg736xd2.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"cc3f7d85532c68b98b1ffbf5757c8bae2acb6115","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg736xd2.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-QljzEzLSmNbOEtGiD5Cc5mp4Vv4bpUwKfvzwAPjE/AByZBcWygX3NIs1mzTwKlcdBfLw662KVmCP/cuZjLGTRA==","shasum":"f58c3f5d2ad2a9be202540ac637398a3c21ad807","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg736xd2.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfhNOLCRA9TVsSAnZWagAAYWEP/icYaL11XP9BEcUaHpuo\n/FESVlMjgCWjh6BfThuXFc0Vzw+IaCrqB1R4mREWQZOc0aSFE/q+P1PgiRDg\npd35A09WxueFwg0y3vxCdnnejFpf7TjwCy+5Zup6JZje3bqdlYhW4abvsIW4\nPUqox2QQf/UWx7XbpvCw8iNYqXlTLbFyDwQKOBK6GpW6gZfarXDTgu7ZMR2d\nEg2MS1HcXNa6SgdqTxBckrn3p8jVtqTP6yBX6fZXCx7kRp5VvNhcaKr5qI0G\nGk6Q2BLGoFT05+97ON2FBs7Pn5gVC47dqNTs+jo4kItDoLzYi+L9qgS8Hgcd\n8S7aVYAHT2ogKGGETi2IVMrDL8UebgDBP9XnRWo1Ko6b4bfAJqiphrNqeuve\n8g1V7q6uIHB+BHzRdtlq+JWRPqIDjIQTkIJPUh/6YqMCDp+0IlJgx0D6nfrr\nQNOHPpLwr7NJxtT1+ShblSvw18jZArS2gwfcUYtZxTuipPUkd6/zNzVMjiFD\n4dTRAyxvDb6ouif4bZLHWwf08x7fGi23Nq0qeBnIpJJ3fATY7ZhqLdrZ4Q2u\nHaacGzqM56FsRFXnquy5HNkfrxOAaI30XT1hvV8Uqbab4qDo+nE3miEYARE/\nlKL2EVrphfdZ7VZBuL6fqKyepPMfGgUyeLC2z8O+mxVeh7RI9/3srpbgXiXR\nBOyL\r\n=iEbu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBprwu4qWOt/B134YI+srKGMUOUHWPcCULjR05SB2V4XAiEA3GaAZ9xX1x2ExX0FNKEfMqZRe8sNV4P+HsItKF7iIRU="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg736xd2.0_1602540427112_0.9452676332537682"},"_hasShrinkwrap":false},"3.2.3-canary.kg8ugq0v.0":{"name":"tinspector","version":"3.2.3-canary.kg8ugq0v.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"46ba1efa9aae70684307289d23f79feff595d553","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg8ugq0v.0","_nodeVersion":"12.18.4","_npmVersion":"lerna/3.22.1/node@v12.18.4+x64 (linux)","dist":{"integrity":"sha512-zo43iSosPSbVMwfompCoIrrm4biulu0aZGLfMUghBoW8fd7w9+LeMKFmI7gf2F8Dnf5C31pTqemb+1nhKxhK3g==","shasum":"88a068826542ec927593e59d744883281bbef90d","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg8ugq0v.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfhnKsCRA9TVsSAnZWagAAoLYP/3UwckzFoNsgE6dizi9J\nMa14WzODcA6Svj5jZBlc8m0FQeRVshXVE0dJAfgqWE0itCZEIGekMAguB9BM\n7+F8OM0wnNj9Z7NLn3o7IzpR4IMiBPiHxTFgs16R0QFUiZxa+nQcjit8Y8ny\nU3a4PHRPa9swMFBmnWZKbInJuGeEwRpRvCq4g2OJ4+rmIchdEELQZQgdIaTO\nygA2qWLI3jFFbgHTqp2R/5LDPNPi0wI7TyYDKfBTGPlSMfheDBF0ujeZI02s\ncs3JH+5Ly3o+Jt2Fhs6HfkFcxg4OLVMOqMB3LJejwXaLvV9nDyswF3V6snV1\n6rMtVPHrg9Bal/lU5fOK0h8ofusuRpIwQYAMNm2vIb3yaz+LpOwM/klZwTpy\nEDxIXr2HwmVO1apJQZP7eweSoKcZBYxPZOqJuJy+cNzUvQynqRoheq5HtwiX\nmwhxRYoqcn1di1iLEUFUl95fzs4MjoM/q06+Mx2wa6hbyke5L+cHjg3t34xZ\nf4X+n2PiL7FXvABTpRgM+PtTN4D9TRkbrkV6kha2VSMdksDxx+yEDcG/Tdg1\nvlohniXHBvbXMbi+kCxfznbmCoILX956Cq0tCHZHgAJmy/SKSafPMpAVQFKs\nfpfgH4q1+SsEJ3B+vVmrj5hcnKW3QjI9TRUXSDb2TFkxBUbdEFuVQvva74KN\nxD8/\r\n=cvul\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcyvVjP2AOls5O0j/UpTXBvjOkdOOO5GLurbA/ZtPVKQIhANk7LGqjO48jeTNpNKQR2jbJPbTkMAO32WyZypqH8aJf"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg8ugq0v.0_1602646699987_0.7202723901199839"},"_hasShrinkwrap":false},"3.2.3-canary.kg9x6kqr.0":{"name":"tinspector","version":"3.2.3-canary.kg9x6kqr.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"08df8648788e5ae4113f0294d27f9e33fccda37b","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kg9x6kqr.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-O1zVjKQOtLfGEVpk4phw6UYSd8dwrl1EG67N1GbvcO/EP4T2N/Q40AxmxJUplP06J2/4+EZ9MlYK22vCRyee/A==","shasum":"1f4d6b30a78c6f5f4406f31ea897694d8e9fac38","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kg9x6kqr.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfh3C0CRA9TVsSAnZWagAAkuAP/0Js+qLdEjSOwtJIgl9N\n/w8hTZqNeAeW1jcJEibnGUkcz8v8bl3djYdkwiIpwOnaay2sVFyLrNvhemAh\numgNvYBTbICBXkFjZjzl2JA0x690Ehk9G9F0hE5QZ9MsJe2oTudZrndcfeax\n8K5mqHj9wjAPjwToIhazazrpHl4r3g8sSwiN4aKxB2Kgw71hjGkat//0pWRk\nRshwWlwGQKKS4gg53qMHhBq424x6uUNd6yhim1OwJ+T9csND8Cn0SR5QzTTk\n4XHMxgjAAcq4/GYj8kAUvRS55f3d5FEETnNty4M717lvyAwIVGFbULcQ+85u\ncQYfHuScrF2C1zTnV38O9yzT0eS31dVqYM80ktlCdTw+2wo4AlLPelNRyYZs\nSMJb8AhHdH8MizCUpiUEY5D+igi4OXjMYEb5l03ZdJB1APUSkFiZA3Wkcvet\nc6y83uFV8JAsmMpcvb25Yc+RfthkJ7wUFlW+xDd3MKBYEynYNDIyLvge1UZA\nDP2n1zirCAmAk0H5kE6eoDGb0Rr5/VyIpuD4u5dn/LplU0avKaS3hf0GPC2K\n4wrA2G4ALOhW4tKOg5PLRY18HmM8w1hNcFx93dzmqiSNayEHqjTtg0WxPHc2\ncZpVpLuuP8lRj/3Z71dLCZYgHW1U80nx6JyzaJACb5hFJV3wioxytUiCij3f\n4nfE\r\n=sLrR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHvahxi6TcUDOg2s3bumY8wEB8WdZJrWlb9vDinvnFftAiEAqD9mwzwr+CzereQoFwQG9mh/5egLdpHtYQw47TTOosQ="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kg9x6kqr.0_1602711731509_0.6110856203244208"},"_hasShrinkwrap":false},"3.2.3-canary.kgbtqzo0.0":{"name":"tinspector","version":"3.2.3-canary.kgbtqzo0.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"debc056cc43e23ba9f37f80a7e84efa268ff5440","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgbtqzo0.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-pDDe3QcF6ljeOBjynGpVCCtAFv2lSSY7euLBHvdNNb3zyJ1U1S6jgqjcQl5Be8rFmXDeHFTXEs1Yo/vPHn83jg==","shasum":"004f926e65857756805209983622cc6114958bb9","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgbtqzo0.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfiTKSCRA9TVsSAnZWagAAiL0P/Rer6y1Iabd4Vfu0EZ3n\nib3Gcfk8teaJtCdA+7YbkaZXW9MubF4EuFRm8hyA8KyafoCmuWnvko2iaDsG\nTDwSWhQ9tn1IZD1R0OFdgLobBVzEgBY7B9pVWfJBp9bcxWzfa/Kxd6C0DETw\ngheYs+P/Rfraq5fC/OeyL3awCgzhAap9M4CUJRCx9iYpgZ7h2RSASFudxaVP\no2t7DUdDujs50biQTC6VXMIXIJizwo/NVVI+SOpYWliq+NhgDdw2E1GWpUK6\nG7nEpjdGf0G1dtYNyKg3MHwTTbcrkweIPdzy6I3dSVgdQkkdJNu/Tt7W3+G2\nM8pDoriVJ9yPScvoZ4VeIPEzQOQjVMDrOXLxGfF7+yxGG28AwOVBgaRQjflJ\n93//xpNyYZqGQUO3utAC8CsneaXMQC+rDGH7VtHlfZL+veeNiKZmvYIeF7vJ\nR12Ow90wofICIoezPkeLvMAIcgDvHfQw3x19bz23K2/xbujYzy80FN7pY9vJ\npIWbP2lqtek+yoRXhMt7GkbKzB7cJfZcpeMDQtU2KDrBBDvvqve/0FaqunnL\nAnmUpERpDvtybMPI7WMg8d158EKFKWba2j7QqEUT8JhOW6bWIdOuuxPEt+V+\n6ccGA8RdpvSUXE1F+/hRhbwIBn0TSm/kaXljkbYaxgs8t2nvQJFNOL3y+Pjw\nCACD\r\n=PoGj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnAbKXljvQ4btqeFmm7St+3o0vQ5H3xk+/j7e40Vhb8gIhANiFDh74P/2inhEiCD48JhYn7UBpFN2fprKCGGI7rfW+"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgbtqzo0.0_1602826897789_0.2808891707339336"},"_hasShrinkwrap":false},"3.2.3-canary.kgc219pd.0":{"name":"tinspector","version":"3.2.3-canary.kgc219pd.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"661952884ca1d89be1d1227c7b3a71ebcd5bd1e3","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgc219pd.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-kafhiDpfzlyc9fkiocRIT9M+meqWAGBL55+XU0yoBNAuz4iKSIXb+5gHs4qKJkwrBjNDAm6mIRhuPGYchBpJjA==","shasum":"c10d4fd104ffe58c01e3966d10617a4a4b630f58","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgc219pd.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfiWjuCRA9TVsSAnZWagAAI9oP/3BSiPRLaUnyH4efSSo1\n3K5Dpcd8hym97fIBMr3rx1mpYA8EBCKQbmL+0cA+sizY4d2l4STBfmRwsSkJ\n8wzudKphyLmdNgZvpEZS6awE88Wd2cN4ZcYMi9eMhhUirAxFU3vifhlIhdYD\nbAfTE2sSqVFoQksl8mqJocMyleBgqhVVaOlIJE02w9XxdxRnagv+J0l/14kY\n2ApoMnobjwmw5B68tXQs63TnaIE1nwcLdBxrs+VlvqJ6PxdJwdxWNdNh4yiK\nk9YYG8eo+MKlv5VfCTEXy/y5cadg7B5DNwl3B9LMH5JCSM+p49WeznaJ9P1e\nLGgdiiGPHIRLRyvRcA9qnqwhihaZIy9wZVmGrIs/tmjJwzL/2hPEP9NTnSsN\naI1x4d9VUaSQ66LwDPhmmm1/P/s0VoGfOUMjl0dU6tMsi6RJBO/5gSjuooAz\nDDhRg8Gyo4THuONZG0aGrYet8tynlmUMY0BYA2icU0fpyFXAUUNv8Dih0UO1\n2CbJzWJTH+DbeIMz/0ZR80D64gIRSvMVFl9Z5rTn6zoxlwAeOunGTVBbvGTS\nLSQSsN2yKkwViJ9LEFtehy0HzmUZCf42v/BQr1Xq1c04rqLSPIWWW39FRjVx\natqZyt3dDaNCWt2NpIMoYGrzi1ZrZem+M7qKIbYVYEL3Hk6jzeBKylOQcCGN\nbxI6\r\n=kxiP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDZAjP8+YpCmV6zGbxo4OptiGHPP3JZyy2a+f0eIpm0ZgIhAL9asTjb/mqD3qPv+jAdoAgZj8uXr8q7KlGI+bI9hKnF"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgc219pd.0_1602840814140_0.8718327831397152"},"_hasShrinkwrap":false},"3.2.3-canary.kgd3ozpo.0":{"name":"tinspector","version":"3.2.3-canary.kgd3ozpo.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"aea6d6f23b3af8191372b9619c411bcccd2f1809","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgd3ozpo.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-9f+J3d9IsuXmkxv/B5z7bQ6v0p64KLqwaP6GJ3rVaqueOxfhGFKEiW7nLl5u4rryMbe+bim22axuzdPtuunfUw==","shasum":"1fb804a30f670c01cf573c6680609e5199a581fe","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgd3ozpo.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfimADCRA9TVsSAnZWagAA4ecP/2t+x35t6ecZH1/NaGU+\nek+9RysR5rbZwrj+Wqq55crkDlV2ES/VxCCK4+z7fZPu5wMCu2bhjlrlgOmC\nrEwatI6dAwuolpeymZPZp7wtCKuE3e/jjz5jmSo/yvwaUAcaIz471m2CRH27\n63/2AWNRQMSTcarenBYybKfMLDnXbvSMj77h4Qy1cB+i/U0JrDxBT3YGZoHe\n66U7USH+h6g3A6ycuNih7lz8WiKjdQkNwZRVSiZLvuniWRprJTSq7GAlG/xI\nihZclTlSh9it4Di9jusrJEGh7hpXyt8jG1L4f31HoqPK34ORS7X+L/UAN8dt\nxmoTuSzCOwH2OGAknHoIPz7LhvWDXeA2BP/VpL7iBxc3iEnYEndOgp7kCA8c\n5MR3G+tYTtbBgOYG8xQK9z5066rRK+mEA+52tYfXrxQ5koRqMo6vf+SRmvl8\nfEmmPDBE5lsWLmn9SfqWVbuFd/T6rMbrUlBkBC+pZoq9VaOiVTrD7TjECKuO\npAAKAXYv+P/mT3pmvzE2W3z8nZsc7Q7s/1Qa6cWw8PbRKoavWmxRmdfLUG5l\nGKvT/Sd16vWN9MmquPaWwhQEhUbYf6cDnQs/VIJ1+QpU6yx48dXMRMb1Rufa\nC24lHQ8CoGg9yc83MohUQmrb69UmfT1NXmsiZWNEb8Q1A/MfMSyHqpyY47Qj\nsZvA\r\n=KmPV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDpH7icYSTxCYzadFjKNtFZLkYxKJSp3SrveFysNKtN0AiEAo05pdEAN4Mj8sH7qKTua64ypgh7eLgNVNq/dJLeoLzI="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgd3ozpo.0_1602904066665_0.3597670446165224"},"_hasShrinkwrap":false},"3.2.3-canary.kgdlm368.0":{"name":"tinspector","version":"3.2.3-canary.kgdlm368.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"72d65100fb29d00266799061375ed45b33ee2bc6","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgdlm368.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-CcYs34Py9BX4KBg868B8VU+nkP/1pGHc5d2nD9i3lzuc3uLA/arUl2nO0a8SIieLQIp2XVbE/j27HsCVmqQCRg==","shasum":"8faaeb52cec3da5351850b6c96ddb791d2e9d32e","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgdlm368.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfitWVCRA9TVsSAnZWagAA1XoP/2Zvk/ch4xiSq2Qs2xM/\n1eWhN9zAaRcFTyWOiHyBStgIfDUcPY6Iv983JeswevMKw2PUGMtUvgLOWvj+\nUu+zF9zXrqBANxf/xLqpTgCcKITFDSRhCISQ12rIz1DGlpIHIBiKNrcjyS4Y\nLBiHSesr5p9G2kXS8RH96DGJ5RAt6vUCr1xocjWeF5ICvQX+ro6f474PY4At\nDt+2eD0x3kfG7EyAmCodqjaC42f+1GxbmjVxmOJEPxq6VnZWnXil+D7DUIE4\nihioDKSY3soNoaGbhij2TOgrlFiaT65www8vbSAk5in3LsPv5cZKn6vUEA7n\nPJWC9B+5vB+bOh9Bb1tjh9+jR5ELXiAEsi8DzhushFz5H3s1MhzV1q+qchCR\nYtArTtGvfvWBDAAja2VkjT2eT08mmUWMz1eHAo5a/czBaCOcftlF7mLjoAe7\nIJDkfn8+gfn4r7ixF/c2aKKcaLTVhnFx0MPStMXV72wiKpZNPDFUhsCIQgh/\nwfSksBaGv+y2Fv+a0zKuNgQ6g1y0+opjqgghEFkZvNUSWi1wOjqz1u153+cd\nAf0QzzdTs6lguAv38zR/qEedpdv58lIQQjTAw1sedzQGYALywnNRy0Wdk2ZH\nW7+rubuiGGEWIJN7g93e1JVX3TxY2zvHLrED38Gxk3IMIsAlEH/Wlfw7sile\nosXX\r\n=YK0f\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBwC+ly9B5ZpxY4gyfPUChTFnoh3Q3BH1FEcOgTE+WyEAiEA0MUZqG+Dbo42FFSGKc3PK9ay0lRMq8WH18Kvn053Wio="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgdlm368.0_1602934164718_0.13206472393707447"},"_hasShrinkwrap":false},"3.2.3-canary.kgdmgzlm.0":{"name":"tinspector","version":"3.2.3-canary.kgdmgzlm.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"513188e5794c339ac9eb66c4b2b4063070dbc420","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgdmgzlm.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-WhAhZhFDazogFT7cd8k69oA57bBhQP8qYto0jiIa+PBcvSqK5ZAc/aRa1QuD+brDwLynfuITIuSdLTOmyPg3lQ==","shasum":"836125c5f6bf6782ff957baca9ae9b3a81ae0b02","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgdmgzlm.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfits2CRA9TVsSAnZWagAAlB8P/1EvsDXdKg6h17Ceo7Bb\nUgYCA0bAlITZlpiO1m1WVtz+SDTZJRrSeIRVHeyFDUoVY0v5cKbQgB0lB5ZE\ntaUzB0RiSKmmQq0DmJGZpiArl6IVnsGZmfOYlsX7zPUnqt3JTXPBbeDPWpba\nUsyb2aBTH1Y89tfyErpm4uu9ohAI23PNqUujEjEl52nFmXd7uNJ7y3HRBubt\n1xlV7W+LKouTgpBe/B2dDKUhzzNtqOpnHCX8O43aLZeXND0uAO2JlNsWD6Dv\nHYvm3CeHlLGpFTCESSYGLRM/HPeKF1o6d10pQa9t4pFq6qf5pWVW7EGX0MJf\nmQsB20Mk4PHYlj5hprPs+4AutLbWJfqGM440+YNKs7WgGMjagrUMel0orNOn\nJHehxMVfg3/TDVh4Q9BIqDu7AuLT/UdSRrtgGccyc+lTcAagCuvaEt7nNPo5\nx8VmKEwrE1Hrl5bZ4qpHrS/nGaDqI1RO/j7Wkjck9Avfvpw1xGAjkOB/Vh0d\nzu/RHVYzFGWYXMC8vJbMZrVBZwbWiEb3dfT2qfiQL2701vQcplBvPamlcELA\nrXsFH51CZ8vtQ6EkNqdruFYdkykDJ5nJtbRjwrc9K7nldh3O2KgRTJU34npM\n1SqdX1olBzM6WePyMCRFgM0k+/PPNtnsDbTXk2C7EjTbF+T45miKGVkmsLE6\nHG5Y\r\n=W9o0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+s0H3rutw0UXaTc12UXfuirKWi0Ltfti8ANmx2yKKWAIgWKVXt6B7V4ocUyEsmPvuV+x+GxxrmUzHjY0t+VX5bfA="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgdmgzlm.0_1602935606091_0.8789758234016687"},"_hasShrinkwrap":false},"3.2.3-canary.kgea9t96.0":{"name":"tinspector","version":"3.2.3-canary.kgea9t96.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"96353e359f27f36466ca1b10150e1d03915d2bad","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgea9t96.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-0yBL28dWr++B/pjz6PU1l/VjZdDoZgEMpfUodW3X66wtHMe7T/T3/h0fHhRCe6yI95MpS3PjNG8/iB6me8hvjg==","shasum":"3a8145704d5a86d09b918f747aa7aa2ca9d9134c","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgea9t96.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfi3deCRA9TVsSAnZWagAAFYUP/j6XNk1JSR+yJLWtwD7J\nOI71UJgwMSs7jICBVLuxwC0WBAV2l3Jp+0SMTXx6YkaXnilhbjf4TRYbmxgV\nrODnpp3duH7Tq7y561cPtOS4Z2Mp6OvQTH4O060nQVlp9iF3YpRmZCPwa7Yq\nwA5mZbQigG2su2NAPO/mnHrM1ZkNEJedk8QNGay4ekE07mpyFVKK1EOdqILz\nygSU4F9zN0xs+lC8Kgb7gEGsT+EUXhfv5+4srL0m2yclUcZE48NpuUJUG5WR\nIzgsojd+azzmgsLSaJ/nwsKQWjd0o9jsvZx+JmI72PYuaUjVOQ2yBHxtjDSX\np+FRdQVR9+jLhPsVyreDBl94xEThYRNi2vkpaLnhYvHSQD2K6DrIf2nbmZyc\nHnd0ksjemSPhmeQmvymt9B1sSgjxrUkTH/CxgVJzM53PTeqFkNjmvvleGWs6\naQzrxYBTK+ZEwCOE2bM0jp2sIBVk7x3JpFrPJbb+FtU1iIW5Pxj39PdkEwm6\nxeMsL4koGJP4EZI9F523B4cNqdNr2P7jMLWReMFhiuPZHo/6OXScFR0ieEIN\nmh2RbXAxMoIIy5jUIwQlWUcBaO1PnrQjl0sQzJ8wg2bZMP090AVVrSjRWuce\n6vs1L9c6G9i1+SMs8jdCRvi7ItZyzO/4Hneh/KhxV6U7M5tlBKeiGsAzty6d\nMSy/\r\n=n3/l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBy1HMfbqCX3fA03/GImuyoIvF6zhRyDh3k/YuEd/ui6AiEAuSWbSV7AusnPAAR5/7RwgAT2GaEVVuyOl1RPhdRrgMU="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgea9t96.0_1602975582385_0.6882807107843998"},"_hasShrinkwrap":false},"3.2.3-canary.kgelgslo.0":{"name":"tinspector","version":"3.2.3-canary.kgelgslo.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"bfddc699bc980dda689b67df01af464c828c8df3","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgelgslo.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-Y0xby2XOWjRNh55vTtBcRPt53WdOLWojvtjl0XYA8TiByrRwKSXhamLTkYyCYJCSWSAPqVtOlaOZioQjOrvJ6Q==","shasum":"509d9529a25a5f1e4c4cc6a36788e0989d65f511","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgelgslo.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfi8DQCRA9TVsSAnZWagAAwSEQAIN9ogPfcBsCngfHcH8y\nThh9BU7+2A2oXc/gUkT2yh//AmimcK4Cim9XSFN6YLMnYtFo3/6koUfzDoFm\n55R9WthTk/X/wMY8OLXnRNaiG4fVYoma7bRHvx3AL40D+NHbIBvwOCegP+yL\nF67sae/WW81d8HUxBEWbKRjDxC4e3jK1z/s60qWDJDx5NrVFMq7a1jOQpUlm\nV4bs9V04QnU5caIMungA1qu9WYAiZYIRHLQm1+3iMMj5QhSg6SnBUVxeFW7D\ngPwQTsVJ1MLqTFbPZ0P3042m7zfViZYCVQ6UrONQcYcT//bBUUqRNvfi2fyH\nGAt6vHj1PmkOBzvm3JBs2auywOF4mP72OzlI9fTttnoKT1XK7uwzqcCCctcu\n3SxBuB9ofUeQnxCYkRM5giEmLcjmMY1vHzogLIiEhArlcB59Qn2BDBZDKqdP\nZpWXXbRmBtFYbVybvVur+HwbZQlUAMzLr4I114WW+s6uIKT8Q7VjV8rEU6Vu\nUL2Irjvms5Wca4nQujEyO5OicKB19zNnJKb/UXO7hskH6WDbflKhZ29xvuXK\nueg5LJCB3rFy/HlbrHog1ZhUGkGUTQ70H2gOiXzszRU4h7x27sHUCpH/exmx\nJcdDAzX2ywTYtJb0zcytkVTLhYb/FWLN4GPca+dT4C0ORPZ92WtChETgjEd5\nrjTy\r\n=V6Mm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDzk4oRDDJybjTmU2Rq8Uq36vlcn94a+LeZdxP7MHpelAiEA0A5CY99DJHpg+meHnXOvj23PLXDv8YDjALPZ7+aU+OA="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgelgslo.0_1602994383716_0.4059985838088329"},"_hasShrinkwrap":false},"3.2.3-canary.kgevjcoc.0":{"name":"tinspector","version":"3.2.3-canary.kgevjcoc.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"1178af1cc765c0d5f0976e9b676636e243b8cf87","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgevjcoc.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-NNNk5DUwW52XCX8M4lxVqiZlhNyOr/i2LBKxpEvcg1kRWv9K08K7wdfd/YA7QrsfdD5jIzraJwaF6DBm9amz9Q==","shasum":"4108984738df0b29ddc0c656207c65a5245ede44","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgevjcoc.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfjALjCRA9TVsSAnZWagAAFlkP/i6uIyVVVVpPB0pg0JrQ\nhL37Crt6JsVPqH7O3QluVd3DB727MfgY1ci7z19hZvJ5v+7JhrQGMfOgvuri\nsKp61Mx66UcsvENdssU4z+kgVa4JKKfNiuID0uXULcg8FD7cy++1JGWdvqbI\nMMKxoEHdvPoGBXTFe1BCOZ0xe3FMsHpwlrq/xP8/ueEWgY3wU9PkapxsMFcE\n1Jk4bojcrNfLUotWMUW7psoSs2rpJFZFVeVVwEv4xIWrhdPc0VtMI1/BTImP\nHQTfNwK2BKiJkEFroEMV0sHJ93Y21qmOpPfNUshPbBLUMwEhGMiYDemTtteO\nU5V9EzC/eY8FnTg9ZG0ufN/kxTYSe5THiqZKhwtlcS7vAsCcOv5pRoqJ0rGt\nZAu2CAMzIKpPWyAQMa954yKyBKS0m5KjtAMmeEAAGAj9Ea6L1gclKGrlRQu9\nSYR/Gh86kdvdFQQX006dFjYGRZYG5tg2ZKA2wIEKrk4axsotBhZamIse+i+J\n2P5Evh64CUgpx5a22DEHdA4pprzPRfo6owA5LxfaddzKV/BN+VZkpyPNRwQL\nyX4ngDL3J+0P4WdEAB2spR6h1JSJt412boeNbAADfXlfOfZPZHBaG9S4NfuE\nFLREtA6tiCUYWbvX3NKl4uww6NRDjQhKJT7tpO7t3FIlTPG6yt4bMa2OzDMQ\nzx3M\r\n=kYTY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDpmMuRVNqEvKSIP/unR2virTDE+4V/OQnXNz8g7uW+RAiEA1MbInWxYsguWXBQBPTm1pQt37Av3ZGx0kxw2z9+pObM="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgevjcoc.0_1603011298838_0.07500110658385051"},"_hasShrinkwrap":false},"3.2.3-canary.kgg7oarz.0":{"name":"tinspector","version":"3.2.3-canary.kgg7oarz.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"a1d939c5b0bb73a715396ebfba1be722b491e667","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgg7oarz.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-y3Y9UynUNWmJxeS9ovrzgUr+cxwmTRwhwQGaSyp9oJ4niTjA1lB9+KMQlms/ViqdHXbUMZhToZCIKWCck6WHYA==","shasum":"ccf8a643e3399f387140447fd52a92f0f25ef62b","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgg7oarz.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfjT64CRA9TVsSAnZWagAAvL4QAICjTv0VRkWRs1NSnZZe\nc/XTqe28hw3cK41FP4JAOm/aWPiUgzEaoRXw22vObRS8JrCdjdZ+eZjx6jwY\ncWDvU5RiCAamVZV55XspoChNYUmU2Ul6LzIxPfrY27Vgz0yHMMBNnhQOlHO4\nt52zO52TBPFkib8Grn0indzfRd2Pkq0zMt8DnA7Fmt500gn+BUtoVLl6lXJ9\n63C6DzKCLBmEPcZdpitXmy0LzseELBSCuBOb3s+OLvbdYPLIH5JDYbru32gu\n+hn1a1X3m917A2Ya4yXauLAStLLGtoA2geSEx57iEFVGHBu/e5PwSYwqD8gd\n5+wXwfxV1bnE8aWeKbUeFj4qXwd6a6eZ+rxSSYMaLEUws+2+6XtWQvR01VWq\np5yBwLn82mG6xlpb0M9Jt/hbBRHGhmgwt0P2wROb8ZbXKE25cpCcWWj+W7nn\nJ7qneeL7Ng4fjszXV7OH5cjWT1KEeDbVUgqqaAU+b7Jc00c1P7tT+VjDK+YI\nG/bP1bzLhyIEskk8jvQ1FGyqnjkbHiNoehZzxY+4zncGzOtF8rgBcG96ARLT\n3PsdZ3+frxZK6piT9fTME/CtK996b0EjjXZl7RXAY8IsBytU6Lq8sB3MCcwM\nn0YzfF69zFt4sdFdrXCe8c7F7o1FqFozEVbwoI3vyZsi0YAJU7kz3JJIODP+\nWDW7\r\n=cYJT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZ50twltWZb6EbI5QKhgiso62UiLml7UiCMfk2Z5H1OgIhAKydM5cikd3XbUZor8Ba9vTnk3u56QuPmjd9odF+gzfT"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgg7oarz.0_1603092151564_0.7652335854262102"},"_hasShrinkwrap":false},"3.2.3-canary.kgm10qxk.0":{"name":"tinspector","version":"3.2.3-canary.kgm10qxk.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"943ad6a5984efacbcf25d99c44cd50d3f601da33","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgm10qxk.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-kd2/UnBJrzppvdxVlx6Cfg3FgbomwrM3k0TYtwfA70nB5MKh4Ll3o0AflsL8I/dbXfmR02scNxlMmJB8wmhMOQ==","shasum":"2260686abf664093badf8c9f2dcbf1877d07f8f7","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgm10qxk.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfkpw8CRA9TVsSAnZWagAASfIQAIpX8QoN1zLFjZ2ntq6d\n3Lhu6RtCw9Ua7/Yn1jwCgRt2NZCuvrpOF6nb28wQVrarA2gBQ/EH37HTX2n4\n7xvcLDjHm2GQcmWNw3CZRuq87gaY8wuKWMhIv/b80CYhAzep7VA9AEz3wEn2\n1gidzOkNaVWx87xJYviDkjQzLeiNgRtuoDHHkRo1eVViL07BFSR4eSojvXkk\ngtxQ8CLDwgqgXD8ZEyveNNtLjL2+goP+yxELGDT/sKqdUiuaiLZo83QORqg5\nzjBxymFo6ZJ71OY9F/ei1y2UVyzccO51EcLpZ3Sq7HF2aI28wLhSghRKyXLE\nAr6Yxpg9MhMd6no9k95i7X7a6hC06ElumZWvr72wFoEmmUqu60sboNjVx7O3\nLBClwVpTb0LEEVFXRinbngsGlInEGzEMSaWO1H9xrXACiPQPx1n9IcVaCurI\nwmwx4cKoKcDE9pKOodC9WyYev3CUP5HEBeyxsjQ3gRcQSvnW50TLhdu+wbj+\nwhDa2iMDiZtrb+huEG7nvwHffmJBKVbJ1cN2DwfqsXp4CoL3hbdIH0xuEx31\nqO5E4fdeppPSaYTDN06cub7Kj3CXfoFG+i7Cr3+5xZaDFihnpA1NGpN8FdEw\nk/iSvPBKktW/NfgJDDDdhubHjh9h+Nf7DiXVGNsxXogjv/6xwpJDEhP3wh3Q\nT/0q\r\n=GAxN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDQTrF9k4n4MUCGEVe8Bok4kbd5LUJ73rQ68srBAnTwGgIhAIqq3eNJWL2peBgeI1NKgj2/+EAZVceCjalK5RdcUppE"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgm10qxk.0_1603443772058_0.7821812698895643"},"_hasShrinkwrap":false},"3.2.3-canary.kgm5iq6j.0":{"name":"tinspector","version":"3.2.3-canary.kgm5iq6j.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"92320ef4f5d93c8cc73a79f7f3b90ee710f67ea9","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgm5iq6j.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-QB4m+Fq6NYsCwClRPo9qaJjYdJciZMnBRNZMl58e9OMvxK5MmZYw7HvmS2dTePEpS3+nGLFDezpSaZz3M2lngQ==","shasum":"786464a89b69a97246329f1612b3ef995034a0f3","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgm5iq6j.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfkrnBCRA9TVsSAnZWagAAcj8P/igwUQpn8wRuP0FW+XoF\nZwUZJVsQd5frFEwRKK/HABAuRQZu5SRCLbDVMdlfdVVmfqsQd6hJuOnHpmno\nxp+u+K+flc3FOc6NkkvwhVU2BA4Ut6NF98mBzntKxMQ2tTxxjiY3vDLq15PO\nAys1AKmRnrdn00RVu34qOYz39/+nQCG7BwO4923ED3AqE+BKIYZNtoec/foq\nXR42JXg6B5yOxlZFoOknY5TvXsc8JHpEyUssyhKszjnNTBby/0d1jmd/lGZi\nOeSusj/1DE0yXblHYPgRHB7LTmoNqmm3S0l0kbHuvZ1zECBY463DhM8NXeIu\nm7RzYt1sTLtZ3yBGtKR2qp5GVutU5iXy75hgbQDETEnv332ujmyGxSj2gY5B\njRKPDwM36GPyw7zVjJP00Pjo4Bus/JIV803Ul/Fb8PszJkdEpLo1iCaYzDdf\nVsMER/doM0y0OMUINIabyUN6luoBG5J6kLJFh3hByeyud2+pd09Paj/Zzhic\nG7/N1uBfZBN7jNLbgf9WgsclJbsCNBDMZtSXlaWvYaf2QEBmcILSnP3gWO7S\nqh2fzBL0uHgJX9MAbzPuEyPL91+gmlexDq0D0JaGVrXwiorEW1mRpS4BsAEm\nPCd8U4WuMTl4oAhjgMbN1fBNJlT9E1bEQuS7IFSeXMQTYKJgSQ71rbuRg/6U\nhxSJ\r\n=Udms\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHd2V5Wxx0SO1bNrizA8fUAEOLMa7e7UMKTWFDneOkeNAiEA2GkJxvcBc3zCYrY4Mnwoc7BD2rK6MpGvhyDo9uVNH3E="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgm5iq6j.0_1603451329215_0.14496110056609024"},"_hasShrinkwrap":false},"3.2.3-canary.kgrcn168.0":{"name":"tinspector","version":"3.2.3-canary.kgrcn168.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"6223ca8337aa3db4e18b41465f25314d97d3ab99","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgrcn168.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-RxA8Os13lE1JZ5g9BWd5I8R6lKsukzF7NRJ+DbpP1MHSNGkCyngV7ib240TWSNwon94x9r2NQkUkQZn36vwFpQ==","shasum":"97ade1fbedae9a7ba48ef1a13da70d53dc36cc17","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgrcn168.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfl4V0CRA9TVsSAnZWagAAVh4P/RkkI6Bh80wSZuDzjUGZ\n6n/Etv94Svc1h58yBS679dvEB/wbGSCFlucYiYxp55LP1P0xwqf6MTeclpAs\nW87FJkSDo19JbEWRYQxG42yun1fOEQMPlmy8S8OYuM9xwmgJkVXb79aKAFQm\n3/b2jKPfg3M3XDo12YpUNN3sy8wpJKRSel14XclPTj64rTdxp+jVHSky4sDq\ngk49HiWIEH35PftHHOVjyqw0JNUfFBS/cDPOTaQWfXJLwpyQdyQrH0Qq8jDJ\n2fLozOgwzY/mc1SYiwkWKrsZGmE/Of+Xm3/l0wfaonPPDcGTyQJRJ1A28ASw\nBfuPAPJcl38yOzoEZO/wOb7+CCbUP3cqNA/WKZHFWcpGMR351HKkv8iwTOt5\njIZb0Obu9RORlSTshG9IS7SFDGSxNZ2B+Ogc8rTcHFlfFXX4qpi8tSsePmAn\n+ToN2nYqoe+Zth5+xpv0bQKtjtbEMCXVToVhKaXRwY9AODTkO2uwJsiqz3An\nt+hPdkNyos3Kh85cNEJeuRAH043nb3mlvcp1cZ/zfyL7JDrTDF6JQdXE4ECb\nqgdtDXOOoMDNsH3haPapCiJk6hKuF/Vd0wEMUYUTgEXoCh1c7ZMUL0deid8P\nZ2HPmRJp+OWWsXXWGv5E5LPWyqGcunmvyVs/iwgke2nltCmbHOKDGzJtplJx\nxK4k\r\n=oQMg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEO5SiBe0avKCpHn1MC1oJwZC/Xk0dNjapgamI1ApzbaAiBnAe0mVJS7yVIl0nGVxeVu9WR3wQPSWs6hgUVF/8X+dQ=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgrcn168.0_1603765619808_0.5671660799400895"},"_hasShrinkwrap":false},"3.2.3-canary.kgsjdgwx.0":{"name":"tinspector","version":"3.2.3-canary.kgsjdgwx.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"797e4013aa8d16bebff7657b839e8168eae9bc7d","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgsjdgwx.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-D67GeyVf9NAyAXJKiFwYjdVHKcSQB5MksXZKpHJU95OlUT9hkiWw5r8AvvFoeuL9vXwNhcUQ27xbxaMuFk6uWQ==","shasum":"0a62e77370ef0a7dc21dd2b2f5c9fe696c989fca","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgsjdgwx.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmJ3UCRA9TVsSAnZWagAALzUP/31W4bJTaJgGfUPWJGi/\nSIL0GZCqolxcUDD0GwTRGN37x9rHmAaNByfO2uxEjO6zamUMYAhDB6vxMhCS\nR9XPbU6YY1xl0P1IgY4SfPWS5p8t5wBpjT9EbYQkrW4XGzfZL1sQnbNVVAnf\nuQcnAmN2PyDHz7CrOms1bml4CMvMsEKl5avG4Ua2dNfaYMhjP0PdPNbTuqy+\n9vTl8qloPPoY74pbMjxqcjPF8UaVeyqXBOcBE4HYJEDzhOQwTNf51oJXRyy8\nNthQg7vQMBhFmy1Wt3bWAHV0IsziN7dY/evxx/OWInXQvW29eBQl0SI0lVbJ\nrBSF2Vkzf2znRPLfmqxQO4VHp3MimCLsSNAm46ZsxJFbrzZTToveKkexIjjP\ncEw/BA9vwSPLFqXeMWYC+aKg9AdQTZT2aYvk9gGs1/1sCK0JLMCAI9QBHUHw\njzJp72iSAcamCpC4XbEL4WCiz/nSqLq6aqqyCufSUahBI5UG4VBtheqHmJF8\nL+QmLDXZw4PoU33aaiALWo9mq/nr4tgfaUQVjmWZA3dWIYG0DL4F6oVowRCt\nAowwOdZfxMqfrt6yQHYViAihEOzTcIxLSj4k5sTcy4UCn4DsoxBS/6P8/uUm\nMXvXOZtghW90GRj0zT8FH+6Vu1SLd/kPoTuA/XJdtzXeHAkcB5wIflh8T+lR\nvOSm\r\n=dVGS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCb11wJVbiu/kr1pWb7UWfBeI+LtJfm27HxMRdGuro5DwIgTUdn9HpMv94P83tg48v3Yv9TeRGA4BgL/J2lRrKJSDM="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgsjdgwx.0_1603837395696_0.7534121385836161"},"_hasShrinkwrap":false},"3.2.3-canary.kgsps60c.0":{"name":"tinspector","version":"3.2.3-canary.kgsps60c.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"b543fc84949ac0ef83fe12db1def8949f78a8590","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgsps60c.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-1mnoY7qoHHMUiIn+yQoiOCekooKFEs2kFJ0MPU++/nojiy8QIEyfOkyJh56fhYZzEmkA8opYNf359cAJuX3e/g==","shasum":"0af3c61ee8e8a88433e2d0786f7a4e1c322a6951","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgsps60c.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmMfgCRA9TVsSAnZWagAA1rUQAJBkiWmXtURp5xs3VRQ2\nWRmRkAmoK4sf5T9v3X27j+ZXfAeKluFy1Ae1ljPEZAk/dJtPc7H/LGRkhAvI\ntrroKpnMjLqXIQQNKJ3+3Mf5qdzBAfH6Kz5iTC9+bHZVLF5TFFQLgdf+fytU\ntrtcr6FBEKth4uVswQV4123x+kP5yDZV5pkW8cL9krkVIujSvdAVtMKFFoXC\n4n5/PXPh9CLHE44ebIo7bvbe+cPrmtJOoPDofurDN7TNpdAA4YxiLLjSUFav\n7W9ZAXEr7bU3daewM/uGpE9lJq4ieRciV65jZ7fFlHcmuMbqo2vWyFgFtJMT\n1lh1es6vuO/KhRNO8fbworYp13ZSY9Bm5v8ebYDn9S4Ws2RHJSvplh3cyeCa\nZ9qz8fGyWFNpyX03qOLdkzhwxWUssiysGiuJN/nd2esPGpBSzAj2zL09y2jK\n4PjjEoRc7RVFcd+UXwRLNk515gIhDsvGR5kZk0EmCGHOwTJrdnuFJog/6GQC\nCnbS5k0VsjDgi8om1rDv++3W/NJ//mnFElTs26N/UCA4WFeJlDsDlSh21e6H\nZCVOBpaFhJlHwJEFTlA2Qj/2nuYWn8ZswAXb5p+N6o33jTPq8ltUKqeuEuDa\n/IW9qU2gyAdgbfiCiu6cdxIx6cvAedQS8GyCsWKrWmyXcGbJnVq3jCYxeasE\nl37g\r\n=9Kge\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICf9rOwDZCX3gmGRczQfGpdyqn+JyCrsMd69goMKt/gfAiEAk+MoGWtVgxG217vNT9nP/d6JsZ9+rjAeEab7yzQgQwU="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgsps60c.0_1603848159964_0.2324285801564756"},"_hasShrinkwrap":false},"3.2.3-canary.kgxa6f2k.0":{"name":"tinspector","version":"3.2.3-canary.kgxa6f2k.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"ec70d4caf5f05b7fd9710de0162b7809538d6627","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgxa6f2k.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-mh5OGa1RsKWHVDkJkdEBH2RAl3poEQwSA9suRxcLB2bFUgF/gxm5pD8Q7scHAMKKBREX6EB6PxD6LbVdHLwVMQ==","shasum":"82bd753d630cfca935f6fed5fb432d70c2cca78d","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgxa6f2k.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfnP55CRA9TVsSAnZWagAAohIP/0zgYaWHpCQUe9dVQeHE\nZKTbyQpwAY0iIEaCHSTZ8QHhiyrqRSPFqvoR9baXokZWWPub70zNvBj5m1Y/\ndDVClOFM/Dij+ZIk4R7uDflO4J9IPVMgYUcjIiXShXUrpjfQD2ar83QfbAew\ngnnOTPihm/2SNaygW8yCNYd3AAqNdh6aSsCOzqZxo051REwr8DnPF5LXIV+1\ni3HxSi4tQAQzGb6ySGvYy3qoDh0NTDq8xxSbFYMyTp0Ws8u9D4Ti2UcGuL8O\nVC0uSoOIdxubnuotBImb4jSBGhfFgebBd9YAERvurh8vJ6uP+0XUpJD4dM4m\nAKtxkeHuNXDSu3LMcJCMLUwjCAp+9E2dalsnkcLDozQMZELs9I598nQwM2C2\nU8GJJ3yKJmhbe6T351ZIpZMyFuUG3HPeap42L0SsLvgsBvEwGl7j1eWRs2rk\nSNpzmahThzheHUBPhosEqO61HnK8TrT6ydiaUMAbnf2GGdBDUzEL542zba9s\nbM1ZyoCFLYD4UBMlrssSLqRaSkFORTmY7ZJLYwGaoW3igByAgjjnNnLc7k1H\nIdSzQNIcj5tuTF7RlICp4arBn+OL0uMuSHPUJe7A4UoSnZR9XwrnfZjrPCuu\nePjn9bYIpEVAN2pOHruY8YdetTis4xrIyAtd+odJpyS6ELT518jolM+SuMY/\nR09E\r\n=d9Xx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIClR+iAkUIVR9WVxGD9XYt652wcVEtymCEUiutSZ2LAdAiBtUXrCc5HGodfAvkju0F8xTuBg4mO7aP0HLM3FyOFE0Q=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgxa6f2k.0_1604124280967_0.31534647785399206"},"_hasShrinkwrap":false},"3.2.3-canary.kgxnbu9k.0":{"name":"tinspector","version":"3.2.3-canary.kgxnbu9k.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"73c2aabfb053333477af3c6d26ea8171c1f955f3","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgxnbu9k.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-BAaBLv7sEQyH4ej5O26/GzdDtxWEk+topv8H5dMsXfrzBjSxtPAoC0kNTt5opVdgpCMk7A1JR+IvZ/gkKnFpUA==","shasum":"95c9a1089631777b122db83bec5f4d0fe1073896","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgxnbu9k.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfnVTBCRA9TVsSAnZWagAAKaAQAKMsW7GjpMo0Q9aVx4d/\ncjy4karLZULj28mXjvAqELcNx0qRYKNNYUlsyeGrX7zxo4FF8pXaOiuLk6jY\nzS1JS81kBURVMdmbUKAODqSMl1hoJAALlkzo3EENuWcIA9rWp6cmTpjnocE4\napkFzzTm9WAYfqb/b8Rr3PMZKZOOr0y6bl85ZhEQNB45UmDwpH6eGg5rfa55\nqeL4EZ+IQhnH0N5ESOGmfWy2YA/+yZooE5ICNfjUy+U0ezO98Wsx0njs3QfK\nTOKJ/tZhWf/QXV2hwmFYw9Z1U4Bfvnv3agfmo4jQuLU7Woq9ng3hgM0pefDf\nak1KWSR5XcRKmuQYEmTIssem6YQEaecx7vsanrYjxOsYddu6UPe9NZacjZAE\nk+r1s+wUE+rm+MuGVvNTLm9VuPnr03bdH6MWh7t0lFvbLYxiJyRBBGlFFnFK\nI5PTPtogsOPg1QuTgy2gUTXCyqVQqKiiWlHTxK8AgXLxBv8TmZ6dEWeWG/DZ\njgKSqHS8rW7sXTGGL1gm4/oueWa+qVC5BHlFMcGsarMuIRfrM/dLlEGTFeY/\nzSCkxGo9SW+1ze00GbpYMvrr5x1F0KvrgmRKcNbZeGN8XurKdOk/ojKEzYjG\n2WYwmJ2N2VtX3C/2NvIu78/+nYrJbV3LczpvEFoZzlvjdThDWIQfyG9lrFIC\nNywW\r\n=maNT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWTXTWSNz/iRY9FIecL3J8jqpgfIiwUhIa42Ys9oZlUwIhALNUY1IWgk1NDa0/uj9iZ0RS11Ff3uCMgo6BpaGibZGJ"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgxnbu9k.0_1604146369042_0.13622174445956658"},"_hasShrinkwrap":false},"3.2.3-canary.kgy8ctsk.0":{"name":"tinspector","version":"3.2.3-canary.kgy8ctsk.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"da37e0a1f6e349e180229c197a0904162774dd15","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgy8ctsk.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-Waa1apeIvywC7xD2R/ZTYr/KoiEM2b1YQ1YLy3WSU2TR6yS1eLixa7uuZjuB/VEycxwcLHRNZIrOAJYPSA5KmQ==","shasum":"ac2f2ee91e4cebf9d4a4d2e7bf1c02fd57c8c1d9","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgy8ctsk.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfnd63CRA9TVsSAnZWagAARksQAIydEujLNxPwSjac3B4P\nn7OwZaIULP2R1QxNskqjphHXWvnap0DWzvOYA+RsH549zqndiradHJoLyXWp\naRcCmym7pHNob9+h02hro51dOaI4KxJr0aY8BbJWsYpQbyMzzA1QutprLRQR\nqDtt2D0qKe9apEfgMF4AP7ix0MyYGW1Cgloa6oZUMPpbrwRXWxYRU/FU726S\n+GwSrqu+0Oqx9DP0iYvhi/YY5BIGo/BR8gsfomxv3dAL+9uPv27JaoQ+1G5z\njVnEpLv8kwuCFyNuDyixXLCqu78QsARr1nkQRYAeMWCfqMPZDh3ks6kuE5Xi\nkQvuEff17UDE6uw91/BRqdE5uPfElcENyyanvk/mBNGKUZ+zXEvb9gcFeNv9\nuNUkcRhigphrgJwk3zIw9QU8CQUFfqSVQCVUdAxNjFaAlg33AWuYSextv841\nsDx8Awbjn1/BP1JT6kGs6eJ/m4SYaNPNoz1BTgJJLt923hTGI4vUcVDeUQVO\nt1byqEoVHcWrvHtiNF9feV6L6lGLhMZ+An+ouxu7nIgYlJY+BtsSDpflD7Se\nX+svWo/u0BeryjmMQjPuANFmFB2RUng3Jd2ZktpRR4wLv/elUAfvohCRB1mY\nSI5aDYDzpnuWnifNN/wBjdnMK0rQdjl1JVxKoaenPwbcH5MKC488qGgxL4hC\nu1Dk\r\n=dWvb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICL1UkihPtFKCop4k/6JlUSVG0PM9RC2PMozXmwPFlUdAiEAtbl+h6r5D3UqBJEmOL9MGGgREv0MGU9G89XOAKIOapc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgy8ctsk.0_1604181687148_0.12741465613347036"},"_hasShrinkwrap":false},"3.2.3-canary.kgyal5xs.0":{"name":"tinspector","version":"3.2.3-canary.kgyal5xs.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"56ad51f6d19f7d1e4667ec77d0fa896af12cf68a","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgyal5xs.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-Eh84vpQjrIdKHBNwT3NljMHSjxblwkXCxlnAgR5MgYmJZKaJpciCdTm02ndgFii1yHDUlZGgSsbX/PnFrIRTzw==","shasum":"cb427ae191b19173c83c5e6ef1add039ee73ef0e","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgyal5xs.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfne1cCRA9TVsSAnZWagAANhYP/11zBieYMH9Y6pQPa9Q5\naiAWMH/iuP9uPqNjXqlxNGg9g6YrLg7lgtMqVuqvA4ynyIA5ZjCxxuhyNNwD\nbZtho4pC+CDTEG63TAb3h2mpAdd5SDQEvfAJuyN/4wISe7ANvSExZqRt2C+s\njUJutcxwxyPg811dSheuMkpa7bTv/kkdQgFxi5IAxQ+J48lAuz65paor5k4n\nnKFKQHNpf/nouj2W5qSmx3TrqakNXSFc7z/jG7VKWPwE70u0rQ+dQciowUSR\nApqK24tOjbXylW43004JEvr/721B+IDL8VSpbzq7UWam7b+/UgQkOtIJXOZ7\nikOj8FAMZGIDHuG4367TcqEVtRCdBRoOUy1BP7tTGR6liRWor0GSXzUjGnZ7\nv4Wo5TRex0qZBWdAleAAgMx0Y4/nCKlFSbKMttyJreYiLXS8SKG4Jn7FkYZy\n5VqdXwS9GzGACcgWrttJNpkJGTZKcMpgkM4NYsls/PYHX6IjYi7bfAoe2pJP\nj3dPGSAfkS0TzeC9aHFzDYFSjkDRgj1NnrvSZtX5MbD7vjZTuT+lmom4BnH0\nW89lLzL9VPR8vpJRHmsptK9OHED0/2J4Kds+ZED2a/LhYneWNdQaI19qMqD8\nYMHvou7R4Pq70brpJRkv/a7BQIcsRJwdWwO4KKJi7giS1e+EJQhteIbTgof5\nn/XX\r\n=ZcOd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE+SiuH/LPaDYbJTBpmWEQfkzzcEZuRLYt+cVYkyAK7oAiEA5YEAxDOeBqBZXZt3GUjD/n5j/kj4JyS9+deC/p5XRLc="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgyal5xs.0_1604185435525_0.04321400907760631"},"_hasShrinkwrap":false},"3.2.3-canary.kgydir3d.0":{"name":"tinspector","version":"3.2.3-canary.kgydir3d.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"567ece6c1645980648f6c33eefdc2d7b6bfe6d7f","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgydir3d.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-5oWGCN+dFmb1C3SICtkaO2y2KDqicRDYjC4Uh3yz0qK0a3Lc7Zm8i8iUruDkvo90D7SBOdb0GtMm0tlVANcKAA==","shasum":"a5f56f42f4039cc07e90b7434c6000f05c17b845","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgydir3d.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfngCaCRA9TVsSAnZWagAA85EP/jvjwyOTTrtuK2rlJSG/\n6WsU4/ilfZ5LCk8UtG1PMomKMo4da0j6w2W1tIXuZJ/JJZmgHiARTqOIo4tU\nD258Sam2rhstoMz2pMaVaBGV5OskmPOm9Qv4zHJQm4jeFyMOLEBN/6hwCvDW\nd8Z6qxQpuJT7dYvuHQGnAbH7XNu2hWgUo6H0SXqnElN9KEFEWX5vuqxcWYXR\nN8sIdSuFnbS8M9sK3njUA1CbqueOdE9EKSfFLGuCMRG3Jj5Y72ZiXJrtf8Cr\n1IE2REp0VbK9qnpkPw8liQSi5seGCPHy7nBm92+5CYUIFsJMRwODeJAAMR/L\nbzReSDz2rTBKyHri+ew3R3lem6mlqOGdMSiK5lXHJS2wZAYHuXjBIxbalX61\nvLOV9y4pytrdlYex/K720C4ezkjYabG2zP8ae6iM/hXmj7YB0win/rpNg1TW\ntM0jr/pDrfiMqVDc7ZbxEsWK/9u3m1HSXZ0mr4uJ90ML+lOz6poNekLRnEyw\nMCOoTXxyq39eJhFTCuyDnTirfD/gSUPIwsjBpTusf6D9AMLKVIY6dF9w1Ehj\nrkHoPyXGosgWJ9FCWTLj3UyOOS4tiGSgkA1z9QGsbB3iTNXNzkp985TSa06L\nHc3TQx8519MGzIEvyiXEF6fFh1GoiTEovnRqYirX/CNCzPDKF0zFO2IHs8EM\nsVR4\r\n=95aa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCI9LdyJ3ttP90l5S8+CLWdlGOlEON3UXTZmXvf3A3xywIgIBjLcNyai53T82rzrPsbV1b1J2kWvPTaPqFITNbfAD0="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgydir3d.0_1604190361959_0.8872140006735618"},"_hasShrinkwrap":false},"3.2.3-canary.kgzo7o56.0":{"name":"tinspector","version":"3.2.3-canary.kgzo7o56.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"b39b18963ee9792f9d49d79a6d9c17e80c586b9e","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgzo7o56.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-m9BBqSgdb2HypXBO0eIbUNqiuq9ViR/MzcUYP3kKzaVB8a6evfUeH68iAcKQLBLAUhsYVKS3LnhB6O96BboUhA==","shasum":"92fd18a1bb5b03f9e520252568eec0b79f377a94","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgzo7o56.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfnzLzCRA9TVsSAnZWagAABIAQAI0pVHH8QLhsVo1N4oOP\n1KviQ4IN8sO4ZEq2mFTs9/jupFntfieMElkZX7WzeVtIM6oVhTisL4mKJSOp\n0HQt+XO/AGtZOWgy1sLbvuqwbzd159EOmikLaf+hgRVsoLpsdNo0HTinXPWp\n0enxJ8vtmdKAzB5m2BJrtl+rzCxb3mxCiGFfMP91IXRGq2JYjSvWF+skZU8V\nz9yywDVSz7qO+5tiBsAHcOwUsp6eiGMh2E3424yKBbi/piLnXIM3FEkOU5N5\nCNPduod6S4Znmttz4eNoh9k02mfWAx2EDcF55cCQxDSxha21co8FzeNpveBu\nukROJWE2QQdgslJTDwMjzfdnt4za1zj8j7I+gD48NGzl57Y3bTLDqn08yXNE\nC4ST81Y8Xn4JXhsadtI4CDoJsYoDqrLe9WLp4X57GEk1BGH8W+MIswBLI9XN\nHj9bVV9ywN5RU9kA7uALMHZ6JjjZVCB+GvTPpOxMCdkc0DBdsxkmuuNx1u+q\n1fYQXEoA93Cw0f8KBYKbg2bwkMjfGJGVflqaf0cOtxcP8kTN1geu7y3uZdm1\nVLU2ISCGEvjLMqCN16DaoLU22ziuynTv1JCPsXFiWFW0LYMtMM7EQVRLx778\n3CR+7w6x0lVTY3JIw2UooCkbyItkd0g2COxQ6pqV7UtrwQVsL4Jtgy82R9q4\nnfV/\r\n=bzDO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHUcmZfFeb8kEzV4yv88JAGiDRFSEW6i8Bu2eIJhgVpHAiA8Ci82S/fUYHFaq5P3Mwq4IYPk5irk2MkQ6hYJDpp4PA=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgzo7o56.0_1604268786348_0.19261317576879966"},"_hasShrinkwrap":false},"3.2.3-canary.kgzuclth.0":{"name":"tinspector","version":"3.2.3-canary.kgzuclth.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"d74a0e3e7c0520483ff308575cd4f52ae7ceab7d","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgzuclth.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-eJTEyN2utwTSyzaUgTsien5JyJBQhLvWagOzDZS8fGSp/1PVDaPQlyY9uhx8Ac9m/EbKQZ6xFlEf+S1CcpXLHA==","shasum":"0b0add06d139c9cbb3013b44e2859131bf920f16","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgzuclth.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfn1s3CRA9TVsSAnZWagAAUPIQAKAUHJlHHgbGQL3NMWO/\nT0VPIYnfkhoki47/TQqMxLdDeBmGdoZF14v+6BMrTpgbW1qE43DccNmrPVES\nnf+sLrS4usZTVx+8A6sQ5TZvc2BNvLNYPh185yLoJowwoCAXmzb9vaH0PeFE\nXfGboCyqvVpdbZ755fi3D6E2Q1/L5OfAuchA6gn4nsWOdttYjRpFmKO57me4\nVk8DS5fxUzHHvkJu7BCWYLvBmzLUjFJJChU3ntvM8rLeNQaeBs3W8SDROnTv\nzhUVZubGSp8C0WsdachfojDuKrvsDZRe/ieUV+ouE64Bi2eQUiyp47qCUJka\ntIIaFwD54+0yIK/2fqBXce81IzRKL9zt+e9AiUHRAmD4Q00zpmCxHrur0hvo\nh48m4QAuAovV3PznBwykt0uB/jv3xbW6KfmsTx9gI8KZUf+Qng/AYcRqccKD\nfKWghno6geE6FR8X9uOO05OktbAxv9Y+PK/x5dfrGbctqbzm+cB5lVAY83TV\nWmefX0qvTkS5KifPLLScZt4uTay/AaX131QJrQ9ac3BboaC1sLnK5mq+xQrY\nBxXeY8ZtCzCrn9wdfbpYKteOR9aCncDfRDclGpsX/i9uTppeFhb8386NhyrU\nFBQYJToPlY0LTEuMke/4umMilOetafBckyzzQHMWxM5OuvDRBGLMKFD79G2l\ndbbq\r\n=Qmgo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA/o4R+KeSSV0mHrRE0yyv+Pj0QcV1HRz6vToaCkURIzAiBwmQ2GqOKFVxEFl865uMzBwCoen03pYu/IrZSm4rcuJg=="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgzuclth.0_1604279094505_0.5700565246670521"},"_hasShrinkwrap":false},"3.2.3-canary.kgzwhr7g.0":{"name":"tinspector","version":"3.2.3-canary.kgzwhr7g.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"4e753b2fc3683e8d19575fd82a56068ac9b393b1","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kgzwhr7g.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-qOVrgbnd2iNbHfgVvDTud85wQ4u/R1L5y6jQeVvccLjD86VKdDhVsZxuBOXhiTP7zsGv7n2/9PbX2PtZVfHarw==","shasum":"6393472bdb09281a9105cfa3dcf3604de2420411","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kgzwhr7g.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfn2lGCRA9TVsSAnZWagAATmcQAI9ELV5qwqQdN/M1mSSd\ni/EhLV4R9B9tzxJMwUhf1JPooGOLNUjw/eHTCl3WWdaaD5y37B1DgMoXerlB\nD6iP0aPg6oblRpTQGb5wt8/t8n4+iTx1wjo5zmpvvrq/NiKXUg/FMzk2GKrl\nnFXsHFotqKzBfhFQf8+tbDDRWHSi+zIngcJohaYdywOITyhCRl0ACs9l9Tc9\n0aGRzorWrKXPTU7PaNnzCyGGqSyIMOZk6Wwq+Ej5ESV6gD3KILvW6ZAUNgDj\nMB/+vz7VzfbZdwBpuNEp9eX3Z/oK0ZFWOHJY54j+AoI0qZe+o0gDXPrzXKoM\nyc/Q4uuCIwoXuzGDYYVlnsO5rQPfTrHOMKIVtifEN54ayABLV+/vv2RaqjMQ\n+VZhgEoi8QLrMirQoNS48A5pIjENr/PVJQ0UlscKEoF06uU94NBK5MVbtjFX\nEG23+yA8wegO9N8En1cMEjD/rtF9EeRGweVNVGuJFwUj3sRGGyduSqtjDWCc\nGmvug3KZqBMYzaG5d0ef5izAccmu+lr3Rvy8NHlu02EaI53vPLXKwAXr/rIS\nUzZmCaQ7N/9KVCjOL0JvosxR3oG6cFWJD+Ki7dqEH5usWxYBSHsOFIzsFa3v\neVzgvOgQlnD76bklUtn2P2iDU9tr6ED0W5jgbrngYSWJ48KCBu3D1aFxljvH\nB736\r\n=PryX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCzPta+x/C+90pLnMP/y9y6hBhZ4hWlEeqpoqIocgsM5wIhAIVt3W9fQuxad0nnT0LzCZ2NRuhg97CGW3OhiZpBNKB4"}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kgzwhr7g.0_1604282693884_0.8276788170905336"},"_hasShrinkwrap":false},"3.2.3-canary.kh1h0fly.0":{"name":"tinspector","version":"3.2.3-canary.kh1h0fly.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"1d1a6708a612c13408919170cd80c0fea18f9986","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh1h0fly.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-UxGqHicalCewTmMU+ElIOMO8qA7yUWxtM5YUjfP+EqDqRswqj6s6jpjD35MlQVAT975cJcpeDBAs9aO0qqBYcg==","shasum":"43cf800c16de9285dd386e1dd960add1dc297662","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh1h0fly.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfoNwYCRA9TVsSAnZWagAACQMP/1OcrxuoDfoZJGCnNSsP\nFD4s3Yf8x+6ED97py+JTf8JFCbBJv7wvFaVbs0xxk4QgSJbSdxWMN7jLj14G\nVDvJhC48BDYAfzk6Ybbm89jGbA1rwC45J1Wuxr2jIfzxPfailLKpFicGg4HJ\nfBhLmMzznXOQ5blNLiIwXWtcTzRJ+It4Frbb3LQNoIBZh3MYfi7pS6A50oVE\nGRJW2R+NCJXhZvtVPneSfqGyCXqZUxcTdssAqMiqzVRRweqzDqnWWu+HOukf\nqXJ4F4o9UFNFIabqtKHd+kJC2zD/MrNUp7ZpSIeC5eIPdR8uKrqT0b4ngVXO\nzW08RAGrjheLOK0Zhmya1SPcS+qVuH9croO08ZjC9ZCtprjF5bRAXxvC7Kyw\nTF54P2rd/PGKJH/N8UdMNgWF8aPimKTo+Ou8gLfXRqAtOZrZyixzbC+BttVp\noIlnVNnn24k5umDO5Md7+hQoepTF9aFTwjdZAqVuA4IskS5z/mynXUCgMb3x\nQJ4hlZS4F04Bu6B0AEyxBdORmHuJ+9qGnBRxXnrl+GyD+sKnbJHT+o5U6Ig4\n2Kdf8vJa11zWnsHctTfl5rmyR0w+7pSa6hIPsE/QVjbEjhlblPBvPEFsCOZi\nt6/1cd4bopLXyLwZHP49U08SjS3CMIsbOLd3WodjNSNWQmNTPGLCz697eQg6\nEC4l\r\n=UafP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQCtWr7q+tm7iTEpyZfGlNyGm2WqhwfxtWA22k6vzG1wIgI/axUsEDh7vM8OauavPA8Kx73Ok8vabYp5gmoWCoKyE="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh1h0fly.0_1604377624289_0.751028712321657"},"_hasShrinkwrap":false},"3.2.3-canary.kh1tdkjc.0":{"name":"tinspector","version":"3.2.3-canary.kh1tdkjc.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"77ff395adf798534a276ecbb01278994654d8207","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh1tdkjc.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-Vz4P71sd2Tg1VIsYSX2hjaAbAvkUMdtf7+ma6BLBHsXbw6ldhogKNehx9vYiZK1/j914br/dQ4KWVYj77/ZH+w==","shasum":"1f3f6efcf31b70cb29ab1eb3777040b47938ec33","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh1tdkjc.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfoS04CRA9TVsSAnZWagAAdSAP/ixFSNkhk2HwIpz9fxA7\nHEaoP6ddqdUzZdTnssQ3aZn6lOCbcRuqb0C84E2sspxtOJwMckx2Fd2Q0DV9\ncuEWyVfwmDLBX9DiL9Aijedub8ymJKPC/M/0wkY8+gBGzcW2v8y/dvfUYOsI\nXyohl35clXegTSxl053J3r8ig2GVlA0njoxWq1oB2MTlY/vbe8HGjN6swG3v\nFW28nb90IpjKKl9rFQvXod80SX+XC+VqAth4++6GFTAC1/prsZKBjxHUwuP5\nTrYPELemsBaydN7sYdJiKmYuH8zE5yO2K6edR0aGZRivsO8pyCpCYVxPuGPB\n2KW52VEWFv9sC/RyB2wdeo05AxKPrc3on/XThpfvcgcKCFvQwzi5eWoE0Agp\najvtqx8SVPLIQifhiYDfiR9tYLveF5AUVMD1YjlJb4GBg2SWvacHM0kFrM4O\n7EaG7xygem9n1SaUKkWHvB6/VsU0X/Yp/H9brnh1C5xcS0AcfTDxM60piS7R\nD20z/sdqUxqa1VboY1dYyaM0CvAcGTGmPYdc+ICm4wxPdeT+S60IZKs6bZ/l\n8dewPAnFo7kVW2ESICjGoOfArcycfh2eIEhX/u6ljen6AiAtvablAPVHYoxJ\nMqyhNuhGYI3w6wMuNzyhVEBwqYlY1Ef9mkTSgOd1w9qKrAWOq1hII86SIVfq\nAgXD\r\n=/wi7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDFeYB80LMkaGy/8uQ0sCPnD80VUJVtDop3qKeriIIGeAiEAyANUxBMiDrtS+jzfiCE3lvzhlaTeoy+Dnnuc87nh8ZA="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh1tdkjc.0_1604398392174_0.865159633418124"},"_hasShrinkwrap":false},"3.2.3-canary.kh1ut1x4.0":{"name":"tinspector","version":"3.2.3-canary.kh1ut1x4.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"de299dc23d09f530b930fc3772f08ade0ea01662","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh1ut1x4.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-coHHauJSU4Xw43ewWjckxSNxpG0mL1fftfbsGpwYWuZPnM+yE4v9EMh3ygv9TYszuke/P1CX/ziDHvfFLdBHSA==","shasum":"28fb629e2a79d5bb9d280aeddd2d50d9d8dffa7a","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh1ut1x4.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfoTaaCRA9TVsSAnZWagAAx9gP/1W1SQbjbIwBk14byr3f\nVnMOCCJIcf+j1ohB24c+5hysv2xbjctnDNbptpMnPDWH4dJUffoROSPdULLE\nGgpO4itTIRAhnZpbNIYYrPGqXFzTazDZR/AfpikKrTAaQK9gtCPGLmFxCHb1\ni8Z9WGNVkvJ/NrjwV7zx9y0Vee8ZcQ1F57kG/LD2XnMUOaZqRbu0LH5v3zZQ\nq1RFiG0IGNaLpkOhV10fsV8mVqyo/VuimlieTY8ZA/uPUo0w6KwKrXLMWEAP\n94diX6hhJSLY8ZQOH/rKxTULJT3wL+XAT0VZ83nT5L08UtX8d88k1FQ2gi/r\nG1jow2lbPNPpHz85WEsQvyMLqzfhqTqjvnJSV5v4LVowZieUHVEwKbDoHg1M\nqmptWVGxlrYQTk/ANfzXiBZmCvl3cNo+jVbyyNwkHCj9N8QAwOCcWITZ7MGI\n3TkKOAIK1fPBKDRtjfXyLXGbzN//9bYW8Y+QjJT6U03KOTQx2+cB8LjazIv0\nf8IcPZLDjhu+JuAeXOCaYsIc+3NHmP9+3CLTYvJUpr7NFNSDIyZROVVLKneg\npVcczLItKG9o2xKyTw72EJc1dafHkEOPTvxU+ROYXjGxpO+w1GAjHRFq3MNs\nnwYvp4pIw/wRLqQnEDBwchBqutGpCMvjOZxwZeDC35FW0KTRyvwiniUM/4XG\nAInl\r\n=Ixhd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCAyowRgFhdH0UcaEYZOEQUDnnSkU/mgd0jPa1mdvX2GAIgWHV+q4N2SQ3YwdQDOuHX372Eu2UwdXJhwdyn2jpbVt0="}]},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh1ut1x4.0_1604400794349_0.23331443117755368"},"_hasShrinkwrap":false},"3.2.3-canary.kh2ho8dd.0":{"name":"tinspector","version":"3.2.3-canary.kh2ho8dd.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.1","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.14","@types/node":"^14.11.2","coveralls":"^3.1.0","jest":"^26.4.2","ts-jest":"^26.4.0","tslib":"^2.0.1","typescript":"^4.0.3"},"gitHead":"35ecd980f098c9ecdc188471b7446d844a2125a7","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh2ho8dd.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-4zKqrSg1SPY2STcRmFiXLy/jKdM5kYfscbuYJyPI59HYCogi1xIexUCL/OmNX6rsLISDTa+t5B7HtKJXrdn2bg==","shasum":"97a21187b95243cc53598fcf13384ac4cb8ca5f2","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh2ho8dd.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfocyhCRA9TVsSAnZWagAAPcEP/1Cqy69bbkvHGYPHE3Mc\nNDDVG/dHGEg27kKbFY2ULgRvuyR/r48AUxnqCop63+/hczdmjqC5cKhycuXU\nVLjdXOmKntZDE+lNxr//IUH3mstQHkOauPEfOKkNQtP5d01wdx1jKMtviXtn\np697IAO4AdGtb4/RL3wZrk0zwZcXMzMJo/Wkl8oA7Q+skfyQEQKJfg+o1aqm\ner4OylN21+xnTTFA6eTdpRS3HM+3LhefSoYq6uCU9lTXyJtIAPoN+6Q4AAPh\nGMgoFRK6GP+tKGz4gr6D5JQ/JK00ok5HiiynyaSqn5XELUjsJYN7ns3tTZPG\n2dK3jw90Ak/et55I3141UI3GiEoZj8Dlioy2KHuVtwfq8+5g3xVUGM+C79mf\n25jWw01Bh/XGQgjmZMDOKuHTRI9WznA7JP1V/crGbN9/ZFaHGRKCPYCGbOHC\ntRSe9wLVq4juoVHH4FbLB9cdCS8LGHJed+NuHbg4+L/Uuh/oYnxOqUzyCTfx\nZYFuNcEXHFzKVAO5duYb6kpqfM5XozR1GL1WPWWhif5ssoXETF5IQ7JalbCg\nr10V6zf3/dkOZ1M9mGtApAShxyeHhSjbTjc0wA+mokBDFFlSiXm3zSjfUXxQ\nbj4wOn95pMET1v/fhY3fEp8NDVKliMvMxmg0iy9N/undvmtj3ODny5s7QijX\npOb1\r\n=KUlk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH5RUFSz1uiMYpgQFwxya/3bDiTFjnJzF9DodIQGBCMoAiEA0RcgZ8tBZmUlbgckx/MMkJbcxWEt+4twdfrSiGC481U="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh2ho8dd.0_1604439200957_0.28373687881620735"},"_hasShrinkwrap":false},"3.2.3-canary.kh2j3gf1.0":{"name":"tinspector","version":"3.2.3-canary.kh2j3gf1.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"9eb68fe3759d21dca66a9120dd83df976fbcdc78","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh2j3gf1.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-Yah8Xs/GMyHa0M2SghkXSI4eJjMhWjgi4hjNHYzsD+p7TeULV62aqNo9imb1+mPBqR8ZaP9jaaPRkqPW8XHwmA==","shasum":"cdc1e9185917389888094e01e8c83561c440b3a4","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh2j3gf1.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfodX3CRA9TVsSAnZWagAApz4P/2OUnYj8kuNs1R/409yu\nxfxPCSsKTnLXgtjUC37gYpjctT5IJJKTJqj37l60lBK3TuDY86/tZa/OWESn\nDu87VBaYLNRQaYJt/8bHYc9fhrcK45MYGWHS6VuQwleOb9U4gZus927f8srl\n9nGVjlQChQCFeFvP50Lb77VRS13bAW0XiCJZVrMgmZ2wyNvwHkd3Try+jA5s\n8gN8fyz8W0FhgujamG8+IpIuRKaa6N2hdvxca09XuVR1TOHM4nWXEvxXmD5A\nNVCv2xhhChhM2eJ7XcELMNX5f6swPvBAZjswWPUobgWyd9BKg/Sc+F83SWzK\n7wwBgTBQm6sJHAL54vhxBscSBcqiJudxNkE/x+DqTdVVAfgRYWBmydZmrqrl\noztLgqHUv+ZFtXxTdHtuLDwK1eiJCJaeVZxGoeVvudCubnMAAoR+T9rA2S7G\nxrb2TEgD9hEV71+S9VbkrPzDdK/RwpLXLH2D4DVeRFDZSo4aD2xwuofGtdH5\n52qXfgUXot9g5HTearDCI6mA3NG2LcRqIqMEd8bB1Dwrh+Z7JbaW+ZaMJrhL\ng6XocuWWPKnSx67lTcPZmZPxxhJwEHRlQ5Gd4zDjucrlz2ekYhtyJfOi+RNS\nR/cNi70oweCgCR2K/9giXIN1FHsPCpEGqCp/ITwDNqzod/ZefawdATDFIvcH\nAflk\r\n=ggam\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCiTTyRDgO5KQyWsnRhU/pAfRTc3DM8yiy9xOH4SUq7OQIgEZZUQ5SubkZTbiy+vw6yIyRXG4bP1OQM/0mdR0b7ZSE="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh2j3gf1.0_1604441590592_0.36974806189943865"},"_hasShrinkwrap":false},"3.2.3-canary.kh2jnpxg.0":{"name":"tinspector","version":"3.2.3-canary.kh2jnpxg.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"4a91ba1f635fa9841f21b333722d6b035ee5991e","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh2jnpxg.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-nHz3cEyhuz89+xLAzgpZLXMfIZlmXxUdNOPlZbFMwCRIuD5SRsJJfhXEPTjKMYvjrOC68C/7touMA7deAdh1zg==","shasum":"4a2a9994edda440ede421ec9c1370a8037d62cb6","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh2jnpxg.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfodmoCRA9TVsSAnZWagAAfdQQAITdIb8z0sTLDwvk1yuR\nyEikoWqqzDEpEcoT6Mw5DvLDCOw+bwOq0KSvjFECDv9DNJMnz4zLS8FGk1AC\nlSFONYvklQMMPa2MeBLPj6RfQTTAhtklt/FLRRuwL2bVx8Thsx95D4KI7caq\nz65pPudNy5lxwAVgG7XECHXjutv93gC3Yppc7iPN4Sexi+54c8fBvg8vQjCK\nesljBQXkCIv5LcaZpXoJyR414jzT8SrQoMLvujnfqMpE/1tG7L6nV79X179u\n0BG2JWHvDIk4ihQ1Db8vHuDPHqYAGhGdwWnC5inAd0YfzJ0Nu72u0rqgCmvD\nQaojAukonGEPBRnqA62R5gGsxsoWy8ilgD2Wz4W1tCwKA9HRCQxQf5ArwL0/\nERCkHjaNzM+1j38F404+8dE1O878xCIfNFV4Qu7ibWA4+yzuXtI1p9NwYXzA\nS7LVTqAxC4FKLuOrAIGSZb4kDe1lID/6/MrSNNFqQoQF6+sI91Tmhnq0aql4\nxStxpqHfS9P0ghw96m6+u+k2FzlUQLnzVvU24q6kuL4DnzUoYAWQWwzIeuEB\nQQp39WHl4J4iEH1CKxjskTB8IAu3ZMo9+SSdVM2yY14JYJkJ3JXCCIJfumGa\nyStYbF/1mc17RRbkxo14CLo9kr1DmGg4SYsRTtI/4te+vcD3uJ/PXJ9O/jwC\nfTIx\r\n=vl3+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDlNxWc46jawpLmlI4urPbhgHlwrMHZhPDsmLWJnMtALQIgUDLmciU8xdrZOFGQD/1y1neFUZmF0HsnlJLZGmpcsSM="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh2jnpxg.0_1604442536133_0.850170606241105"},"_hasShrinkwrap":false},"3.2.3-canary.kh2k6f0d.0":{"name":"tinspector","version":"3.2.3-canary.kh2k6f0d.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"e05c6947ff7d10880363c653710402a843e759ee","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh2k6f0d.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-4URIxrWIi1z7bDhP7pXqVc2i7r2U6DGKHMaWNLFUkbyALkdu/RQbGWqxjOdZWib8RyPdqHaPrt4L3n6eGXSL8w==","shasum":"b14e1363323cb11d78aa57405d6d80d751d89948","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh2k6f0d.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfod0QCRA9TVsSAnZWagAA2RwP/iwvWcwhWJzzTiCkFhOS\nqRiWTwifK0GKnhskjfupeTq4e5QNAN45EhWvkPSTXdJvRezPrYeuhCE2PliX\n/5HFvSIzWQNZyV4Sut1qqB9GdlZVivRSSecwlSnb7sDu9fCLhQejZP/+tU0b\nR1e05Yb4ENPmI89VtDRTgFdUvX4HrW7XZdCqBa0j/NYSEOHu7iAXK/Htl44y\nWaGceimJIeQcygXYHAABMgU2Xl3Y8TNVmF+e2BzMGlw80dEVhK5ALjGmLplc\niJsy4a9NPpNqEZfkRu/CW/D2XmFFTpTyeiHLikqyyMu6r+zSlAk+Fc+GQCoB\n4gjZSW5ToFxT1mC1b+t+qV7XPJF2CrmVjbp92lvuF25JwhKfZZ/QmwKpDi4y\naPsRhKxGhyChZfQgS6rLZi4nNlMYKgYNh4rVoijabkKL/ZBauR0yjs4lrxVu\ncmgNjuE4N8VVmjte1I7UfM8NAc5rw+D72FThO2ZE0SVlPqX4rCAXR5hKeFwN\nFEIlOlNOXly+welxkiC3TqTsXkpZh5IfCXM08O/he28K2rn2I5I0QcAP2dME\nnh/H1Df8QMzQz+5w99wyzOaWqZeNHeF8NtCSuVPTdE6jrHSdgV6evUkK9NUW\nMGQhZdzrLG5CVnZhM26LDWJkj4klQtKnGDJmZUhP2D7YNBDGD4sAus9BGd9Q\nXz+9\r\n=Ui03\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDczM5At1vy4wDXmrrdVc8N7upVSir01mRfpuOcj9VGPQIgCcQCSq7FoKhDT17GuGpSavNzzahTL1miE6hM3EYjmwM="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh2k6f0d.0_1604443407903_0.9888008584052776"},"_hasShrinkwrap":false},"3.2.3-canary.kh2lwwtd.0":{"name":"tinspector","version":"3.2.3-canary.kh2lwwtd.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"1c0f97c9b5b389e620642387a9801e3125207caf","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh2lwwtd.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-0hKY0BvtQEQT734P7kSyYY140unetZSL/J0XNAIByG6YkC81JYKA0xdqIFaADAA8ZFvht8RTjNniJUFDEXaNDw==","shasum":"a59ff976a2745402d1796afe40a969682d317966","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh2lwwtd.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfoeh0CRA9TVsSAnZWagAAdnUP/1esPZBfievSMgYCnGOB\nmv0o8lQeO2fVDbd1QecAiQHSzDsA4kjiaTGKGtRLqosq5Nce9tEISsiqrnWi\nzZh2TPbYbPQK32om7PGQQfuN/Uxe4TvSiB6QSKtcrb3Mjb6yRkP16F2X+gDJ\n94Mlop2XqjE/wDA/qtR9PQMrp1/y2NKkNSAdVaYyBJ9OyKvQJ8ubpbaEwfvU\ny3QtLxVuCAc6TIg3PgodmJFoCeQMZAklTmopqJhJPsckV2SmPp8EcIsT1+xg\neZ4eak1Wd2/ykMwDo60ZLGVLmgVpCIZq1MmNsLLYyzkax1jjA2hFNgJ3Um9o\ne+rdQryDrqEYriktcvl5fCsEb0NJZocsn9US3aumrJMxrEcu8+LkLCkp4mgG\nYFgW6tcqE8TK3BacpCQOfMyA9lr70PveOq3O0U9Q91T6Agu6ihQbaocFNaKy\nMYAgr4vruASs+cb4al5CKS/Cd++tAfeYprqoY5kZ/FofmNagx63w/FxHQ2P3\nZ70gXiKemlcE9CuSY4gjyna9fIPvUtZBsHZWb1XJrAuMUb6NEFzoQEIsc5Tz\nAU2EPmQ1dPg4f2bakj+aILAoVZaemCSC9NKfpHTaz5BjYfSY5ooYlSVRHzZ5\nGP3ibPx3QkiGhxSAQhLYg6tx/ZvgcHdPZodjKhh4DSylTZQVgOhObHaYAzMf\nRjZK\r\n=fx8E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDG9FDeHwLstM53Z3GDI4l6SVCxtztR4Q7R1hHqXHk6nQIgYXsX2p0p62kdZvSYy0ao+R+yctmAXTirf9ZSegfNFCE="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh2lwwtd.0_1604446324223_0.13232975019352655"},"_hasShrinkwrap":false},"3.2.3-canary.kh2p7j3o.0":{"name":"tinspector","version":"3.2.3-canary.kh2p7j3o.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"61f99c3da556755615955996608b0c00375f00d1","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh2p7j3o.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-qJQBV5Xh/c3PGEA+rwJj/jfOwUSRNfOmANXI9fWqxbVoJMPL+zdTz9jXNed4t4Nz4/2AQHnEH0Wtsab0//08HQ==","shasum":"cfcb808dbaf7b0199e3f43c2717cae9def49d8e9","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh2p7j3o.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfof4SCRA9TVsSAnZWagAAVbgP/1M+MA1ds22HxtQStrn8\nRvqnDpx0wUGZdfnbjFf3o9Rxe0+OOOppOW5EwtUTr+aoM2yYidQeTPkRV6/9\np/Fih7MRfGiVlDdh9DbukR9Gju54LcMeDGx4ExevDa/gm6OCpMVN/MNRdbab\niRVc1QDvAgMm/gNKOPyHHmZ1dE2bNlJPdEuP1pzMsRmQscIvQWs3rsxoXIM5\neSI1th9ykMLyS6sxynpNS4KlKl43OdwDiFaIZc6uODZmDtN4BpiAe9IyLjya\nx9zUyQ9bexLVArseLGlm53tVqDPTd2uQZr5qkMDvANVlNpspfyAmCCaJYNCY\nmNMTB2ziFHCyPUW6ScywI5VxKYQYgixnlglcMARu+v+LWFRN32Rv7i9rTsMG\nelnuj2h1d7BhwAyF9tBbkg9CZuP+l7yGrwo5vg4i/xuP1nvlfUUGMxaLuhpu\npiU5/kgRwXVwWeDrPOtecm9qYByMQlCA2HA/zxfBdf4ATKBesrmqq3A79ZmK\ns2HxjdcI6nITXzvHk4c+KUg9PyTQU20xrorJndH9WE+mwXrP9QhyvmwvncBj\ncgkGOp487lV92ONYK59zGZXS94up93gKEdOAKnFncAPQbGsCjWWohlBGJ7Y6\n8t/ja/1TbkvCnkb0VgMF0Xx/358DfDBDGh+H++hzq1xIbg46oDvc7QtfMCUS\n//Ps\r\n=hU4O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDeHKlGgcGZF7xYY5FfRxp6LxUbyZRbYGJcE7p3cGuNJAiEAg+ExAtgsUWHWtT0KPZPQdufTKLr5RSvxLyoO5G5ceiA="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh2p7j3o.0_1604451858201_0.3531601135751732"},"_hasShrinkwrap":false},"3.2.3-canary.kh4ew4ru.0":{"name":"tinspector","version":"3.2.3-canary.kh4ew4ru.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"22400ba78b7072b66ec3fee2eed9155ac4591d18","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh4ew4ru.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-Oqge2ThENZidU8oGw5VG8TSAK2mctY4Xd/vYSehSjhZhpCSo1e/7nVf3OkOAGtNh3qZ5ixnQHePQ8j57C7gaiQ==","shasum":"d6017c3df92e1a1e0e76f36da1df87368be5de0e","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh4ew4ru.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfo5LHCRA9TVsSAnZWagAAtpIP/ib91uXfq2XqO1Ofbjuu\nD5vsllql/zo94P5qa0YRSj1A28eo/FAqDaCxn+DBXXzeoygb5d+E0fRyF6ZH\ngVw5a2N3Bj00sP9UdQZuDzgFdRj1kpeljJuqAyKoAc6tUBwg0tWvW2CxT+km\naHgNa6CxasudHt/JATrgPLvUnW7tszLHSLTfdE8DSblMFHbfiTxESrG3ivnI\newYGxjQVV3ID5kyKqSYM7ao9bq5E6vS05sTkiU7TV1X3pq62Un+7LhiXYJ6d\n/FKKC+vTV+rU+uZvOm2EZVt68iwLEnf2dLSMYbnPwh40Dzdr6eDQnyxsVGtC\n/VFYEn/tILCbzhRGR825dqoj4o9QezNVdOQt21h8EDcoOX1DYDViosNwRcRi\nuZS7gehNG/SeEbSrGyhNqOU4WI9xz9gqHu2qzSCqXjObEPEtKynOvl0uTRX3\ne6AId4+kDydF9JTWZXvqYgUUh2MT2JFGwFqRfcgzccFHzj3aueC9O5mLpvE3\nirOXt4wmLTzyh+CQ7OngU6usk12+LMZh7LnIgeQN4+5PKulfHTPhEzMbObuv\nw/tqZ2bRZ5wzTaYGEYWMkDVajwDRLkWVkvAPU58E9XJ7jSH5LnMhU3FpGO82\nYawUtUNHJCcWrx8d1+oCSZXHni5PExPybRfJOjXlTTwHSMk6vUA9k2ClnumS\nBrGg\r\n=JHIH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCIbEU2VyxupnpKwSWxWYV4Yb0NpGjjhzaX/RK0axqAlgIgImC5AgDdTZfWywk5Fjfp2F4UnG9JXC9ze9s325rCn94="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh4ew4ru.0_1604555462571_0.3652408374588061"},"_hasShrinkwrap":false},"3.2.3-canary.kh5ddq10.0":{"name":"tinspector","version":"3.2.3-canary.kh5ddq10.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"495963a7de73e2c0551c46d527032ee0face0ea8","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh5ddq10.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-/JNFgVea+IAwzmya8HVP5woS4wI3uR7g4PHUCZ+g8CrpwSGvcD8bvFWVP1IDt01jGMALlDpRXsUbbw0BdqP0KA==","shasum":"4fbeeaed6f6c9c48f952623d42ec76b1d168c4b3","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh5ddq10.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfpHUOCRA9TVsSAnZWagAA6FwP+wWjc8Rg8vUterOnnR3y\nmDnd1zo4xO2BEhAsoLTZh3erLex2nj1eN6qHyDtP7LYKmCr0flg4V4ro7o0h\nUy7zEVaf4d/gSKIqeuATvegQpJRXalToPX2b5JjpJA3opEELDH8GbqMcrMza\nkShLB5AVK9cxu+qRxcSvSsEYVfApXeAoNmmtimtq5xSpvTMFx10Uqsyr1/74\nA3DcTzKGGci2bfcy+BGUhe/xdE3w5zgHAAJCuc3Cl4Ins+Yf1+/UsMq2PqXb\n2c7efn+ASV5dtQcwGoHcAOwWvCV/39dZqtc1pnFwvibd3Q5XPWm8PjCvxUii\nE8lk9Xi9bkjE4hK0oOF01DoZNRXacfnX8N8edGcm2+Ug+QYOlZRORTDqQuaS\nB+G9aNDpWDkFBNY9MkRwloY5JnWOSDyiDJAn87Z1PpIm7oYWENlQcnVJw9ct\nRe9GlOkjPiG2pnKhHVlfwA4bjxAoPZYosDwueiKCngPnCEgztsltBN+CIXgc\nZtpaIlD4Z3fLyik4QNdSjULyQTMtaSJOvKZeGvwm4ZgKxfO9BgnmkpW0IVB8\nv+ju637pL9+TqyXxy6Dszw4Si9RcULq5yzNpSQ6T1pjsF6xjstqoJ/hsNeQk\nztb4bayJIX65LhMFELVI45Yj9sR8HzNzmh+fzUBa+q1mHcbFfSMxdjN47iCr\nbhUT\r\n=VdLr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAr9wSNzOPFQGCkGD54x4xcLKRnOeLGxE7PbleLKSVfUAiBFOlOw/+ZxQOZ3fuVtYtBwEUuc8VUYXCoHqqrqPZJPAA=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh5ddq10.0_1604613390333_0.00425817547400853"},"_hasShrinkwrap":false},"3.2.3-canary.kh5h50n0.0":{"name":"tinspector","version":"3.2.3-canary.kh5h50n0.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"bd4dd0c3cb7df9e61614bf7202dadd7cf7cb8116","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh5h50n0.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-1kd2AgSoUNBSi4r4H5PrFL/u+qqdUJ6xuTFHDuuqyW3bIM0Xv24wneWO5jsxPK9ohGL9gLoowhdWKQ0TRrk7uA==","shasum":"760729705b40536499a7a3d365d9730506a425ee","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh5h50n0.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfpI23CRA9TVsSAnZWagAAa4cP/18/gq07OepdVAGcDJJL\nxFTQzRYGuqaXJe8fYRdvBc//Io3ULaH0aDfwftzZde5m5alOY3s6x9Hqr4pN\nZZaLrzupPCVGAiCh7ixlnxpVNIbIcOEgLs34SkiY3gFTaEqgng+AY4ocMktp\nxJ3enkwnXVYBwwC/Gf9xQ07rq46Bov3ktvb30LTOOvKFeRMinRErrIgaPUJc\nzaZ1IXw5XMOpvZb6I9INgKYFuJ/D8VkVk3dnUiBdzGSoAEXiqf9+zj/lS8+a\nyYILp42keYpGPct+uZy8T8zngvaV0JO1FhCKA1gaI7qz6zg4Qt31kttb/9Vg\nbthMHDefgXmekPLnSQHACLXHpm42cIbZh96KmCwLDjTqFZiIYGMADghfYEb3\nyFGKL/WAxqRBiNaWad7Io3hHi4VzwKzKJtbGQGbhuu5UY373uE6TVNh7kTm2\nDqrc7XTSIWDH3V3E0496QFKpSst76m0K7GP4G/YQMy60Ai8sMN4WngDrgkJY\nwjR1FCCmpqyB8JkJF/lFCchNat8QYtoCjevlfqolRDC6ppPw0SCDozl3bc77\naqqIE3KcLlO8RORKTrR+edIuenfs3F8YONp6xOHO8vRdL8Q43qbBwDUsKPTQ\n5eR1ZnqRibu+pxT6AxlHw6DCOYlbGT3Wukts6PBatlzz8bsBgVhjH0PGwB9S\nKw78\r\n=4h2C\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDCs2DWjDUXcGBBAQGlUEVeQrESo4HEOl8WBtpyCDRHhwIhANUh9l366YHQCVJZzZymED/VbqVQyx06c5uxms0Yw5iC"}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh5h50n0.0_1604619702367_0.5529257533768832"},"_hasShrinkwrap":false},"3.2.3-canary.kh5jla6k.0":{"name":"tinspector","version":"3.2.3-canary.kh5jla6k.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"4e643063666c140bd0bc7e5b74d999cca6d507a3","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh5jla6k.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-wswotD5lS3BSUYGAWNWWLFJgbtEToj2AkQjTGwfLOZTc3bVQrjK4KxCBSHfJSfc788cHGBSVV5lzcVMInW5VxA==","shasum":"356650b3dd548da67eaf9f29786984b898be192f","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh5jla6k.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfpJ3NCRA9TVsSAnZWagAAA1MP/2MEgpLnR414Aja0nQNu\nokQbxZ9KZWsEo7cSTSnV/5D79VYzapl9dtFXwO7ackAgGW+NIr6h0E51g+n1\n3cfT31sWoaNwNGM9/BY21niE5cirSg4Qys3xYl8jYY4pA1+OBm2Qm7jOxgOg\n8S2ZvTn2MHXMuOU1Z+2AaQQJOrXcZv5grgVXjwKV+ce8leT65+ub3n7/0opb\nufxlkGKEU9uASyJ2BzQWr5GfH7iiD5NV1MmbA/HgNu7Hh21gO/Sq2piIApa1\nEjLT0Y2fkmDD84yY6/LJ56BsX5eV6+toSBXUnAjH1YUQrgizZzw1Y2d8JOCy\nYVfIlXboxINg3VlP2IsEJ/bDSMUnFVHJMjdQ7BwF65D85UjnxV5YVjKLeHxt\n6VoyptYVkPmfnuqrstQmDDgugaOLJzOWdW7x9brwKDY5d7T6nUxUGJ0Ujw3l\ns06mPuCDpxTp6feYBKEsal+lyN6eKTK3Pb2/XWjHaYE8ORbOYFHpNTOfbIf5\nQyGmJKB19HZCCwJ96fwM4O7CI5Op0iR1SOen0QdEZbX9IQ8/eXyVg9BBUuTe\nWUv0iyg0BsE9q9l8FG0G7T6M//IvY6YIcB6lsZXDXxZZo2g0X301MkJKYU0T\nEyeQiugMJmT+Q0VSU7e0wYjvT81GI6BY450RE3AY0EIUmiZNC50tYxyGd4YJ\n+Smj\r\n=iL1j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWxa4CKSJqrn4ShjaZuZU8rG4WGjq5ohOAilaLeqM2RQIhAODh5tcNj+tICDfbu5plOlE/nz2ZjbgLeFe07PFvWmtE"}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh5jla6k.0_1604623820757_0.880266509476971"},"_hasShrinkwrap":false},"3.2.3-canary.kh5lyii8.0":{"name":"tinspector","version":"3.2.3-canary.kh5lyii8.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"f1d8fefe024a7c7567f66ab76c8a14b242cfbb84","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh5lyii8.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-xVZSjTQHU9ncf6xRpNYLUIt80ExJLSTbvLSfRB8ikQukVdU5P5rvyMKvlZ74l+ll8oUy+Y+eICx6bbzJ6HK9Zw==","shasum":"cdd32b825471425fcef71c8de7d98e4ed2a54089","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh5lyii8.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfpK1WCRA9TVsSAnZWagAAhlMQAINkTcLLA87TpH8Vg+iN\nizPzxo2k1XrMoqH2w66LQ4E4nZOS0V+PZe3iUxALb7cL5KUzHkvtjUyMMJmH\nZV5ijND+pyDMYYnBQGoHNtjXbivv9oZ7A7QTaCFUHfuN1AyTU24NLPmFjGJF\n29ltjvcx1kbrYcv0kojNQzLB81vC4n+1GS7WH3DzoY0qdhxnYxpH3eOe3KzK\nWBAQKGanoAv4EVrYxoyMJ8DNPfnsdy3O0XkrgL8+jRpsO0mLEgVDDdZdQDoN\nu4WI3xB1xg9UVMF5I7opzW5fmeywOZPaDwgnz0KfpgCv3D2ZNR00F16prKh1\nR3LFrYu2axc/Evf7nEYttPfjf7rE4UNv0kFwVIp+IiMw+9jxUQmDjbdMs2IB\nGQuLJwFLOarscP9nOfI4m4ZlpHwg9KWHwEF2XE4wUWsCSvyMdy4z9Zs8Lwmv\nv3ZcBmIYIXnQYYFAqot0HK+YZDm2W17k76G010KVxpFFMgax9rcg0ym8PId+\nFAy0MALIWUpPSbs55HsT62Fx9eH/I6HrzDRxdWNh9G75NIcfhso0OoKjk1aq\nj6SW3XvXWGF/uWYcohTMtJhXDtSPz3qQ6Ea48+ZSvsUBHAH6dCu/c/Kbilnc\nZFgzA+0aXb2PSrrgGCJsXm8Ps0k8o0quETNRGImCYPQyUZD5+VddIcw3e7d5\nLBjO\r\n=PqRu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqE+PnlXgRqp8fcSW7ZNfDsJX5WLIDe1yvJ3shOkw7JwIhAKRDJ5G0O2xg9sEqU6ViNkN3z0RRuqxtInqHQvY+q6GR"}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh5lyii8.0_1604627797495_0.738280716384899"},"_hasShrinkwrap":false},"3.2.3-canary.kh61az31.0":{"name":"tinspector","version":"3.2.3-canary.kh61az31.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"ffc0ac5f47893cbeb596e62ed5b4fb37184431f9","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kh61az31.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-EqjknsEhOWcT9otSS70gac8H7HSjOcQIwOsZSEWl2xoVEUL2pDzvUMA4jd7pm4GUvVKV7pU7HldK3jvr+zI9pw==","shasum":"81f4e6fd4f4465559c755ab76636dcd4dcc2a5dc","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kh61az31.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfpRIFCRA9TVsSAnZWagAAXoYQAI+b0eTx2pqAgoeCZm2s\ne42us1Cym/XNsa2iYGaf/dekvwiX0Qb6V+ybtE1bk7pboTJbns9Amnaddzko\nfXtBuemE7IvF3rS0ELMiOhLtkkI5GA7tjhPWFUIlKwITTfOGeJcdikLtW47q\n32nZGQWV089PVO+yK1MUbhji3rnqMjYYLKpeDjQAbMOqYcSJXYOtcpe8bDxs\nNXDNCaj+lEOR6ZXWjpE9qDfBJVjRA5u05bKXZbXhDqIpH1quW70JrMnb6D9F\nICuupjpNAcVANGVib6YTvbwbxLw9Muy6wNRhdt3Rfr9WstunG++/tJS1vO0S\nvFzQipoI26lCqTQyQAnELASnKzDLnem+pvaMl39ryVxGZVKzTg2umG885pfz\nzfug+xTicL6Fsk1PIjiMRUCD9NJdC6ii3hIeqEIVM1V7EnikliosI2x/1WNA\ncrq+2SEYPrH3TlVDpltScvq9iCwfWURaNU6GAERP62Lqnr/ISuzKSS5YeFAT\njlfUEEwRK+yf9bi6S4iCIePqt3prn3xBQjvBkWej4m1meHw6DbrgzNGeEGZ3\ncBbNTEMEf3dEZAho2l6FoKRZ89pNKfq+QemA83VlJpKGtDonjMn9imZJRfjF\nxVliOxQu3a+bRdLbBX1Ex9eKHZ0zYMW9SegewZxBaBLnss7B+O9BYlES00jf\nQhVu\r\n=Xqh0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHtKECFrxOuJfAa5umMCmZLUg0Gt9S37cu26FR52dWCuAiASwiQoydC7uqh2XZnSY0lUHsQnSw2uXfZUuw+UWBsAlw=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kh61az31.0_1604653572849_0.33540554556233837"},"_hasShrinkwrap":false},"3.2.3-canary.khbdcr5h.0":{"name":"tinspector","version":"3.2.3-canary.khbdcr5h.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"8cf40acf9659f9d721b395d57b1d6cb7e3d22343","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.khbdcr5h.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-pX8IGAwPUkJUB7OM2EcCgSVpAMoJMPsF14znuvk5KyXszARHE9dtOMSOhlWwJVjRVbqtRhGJJvvXskc8rURtxw==","shasum":"0cae112a60b133525460c971674b8faba07896f4","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.khbdcr5h.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqf4OCRA9TVsSAnZWagAA6dQP/jsCEvdmBIifgtVCTNi/\nY4VuMzEvVrreU5Stz4lYOLdVFgc/L3tEHghaQecqxmp5/9M6o8Ek5cvgCIoY\niMDcxIdKymoIPNE8o/ZmBYaItdw/gO8XiBPnnTFe9i6VVcJGDw6xE2zMHtNQ\n7S6g218IO54W4OZ7jk3KhwaCDsi1eOJX52hWHhFeim3zRKbenzjzeQ2xcGXe\npN9qstc2f3cBp0gR1Rm8kria9nqkuHeM8vM/pulTs4eJqAWT072EUAACcdK4\nlOYgr7tbjSEfeKY9fZXF7fKg58mH1pmrFuTlrNQSrXLgJ5znES8OwhjkeNL7\nAWK3mpif65VNYX5kI1l2+/fTwZWLCkYKbsMNGy27IkECnO299TByEsSuux8F\n842FrDkrGeszwe0cqNI0o9M1aQZ5KAWdJeTDztVy0G8e+wAXEC2uhhcFlL5m\nRXWVSpMWQWk5uA/L3D/SEKz+OH2ShI54ndpYxvbNgRZPURQdDJB9TGuq7sZX\ni2UjGL+DVMOJk3me1ZJm8aj9muojQ2UWlO4MxwKlFrfPKIUUr6iDzGmcuAsL\nDEfmG025ysS2OWHay3AvnYd5KYMd+Te396IA7wejka9WUIrmmFJOSRa4RZYL\ngquAKLqZUO7o/jG2sbS1MO7JaWC6pHSDD437EDK0xZhynNn0Ev9AdJ97z8PU\nfDAR\r\n=l9ve\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGfrI+kxcUsXtqt78RYuzjGGyXSoYPliDqKd0tuOqGqEAiEAy2fPo5e1IWT+wcKZkp1rnpGkMW+rY8/WLIUBIXUZqig="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.khbdcr5h.0_1604976142201_0.7677237194208666"},"_hasShrinkwrap":false},"3.2.3-canary.khchhyyz.0":{"name":"tinspector","version":"3.2.3-canary.khchhyyz.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"2c92beabb1d026fab857e78ea3c88ef1e15d832a","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.khchhyyz.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-2nGIsbaLJWYcosmwgp6fUIR1hsgPJaZpnC7UQc5fo+4CztfBw1VM0MMT9bea7qjC9H5rXuu3QuUP9eHl+nQogQ==","shasum":"52a4907505b79e07e5a74794c5722e9dcc07db80","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.khchhyyz.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqwVyCRA9TVsSAnZWagAAoMEP/jmpG4OuAuwjULJuww40\ns5cvYLg0ehDN4xRFutktxrQ0G4nRtqwXsdBLZ0Z6nSM/5voZK5YEgbtR8b/9\naj1tGx+jdVJ9xjQvmquTUp9r8j7uRFJ08lP3v5sfcuk4qSmSCvH7l2lzpmPs\nD0ifBABtXPd1o+L2UkEPxGIyri1CnrzMiM0yRa2R1IPT7B6YyOBZjKEsPQ7+\n5YSMhL8JPM+oEkXKlO1rwYCXWyrqacEJU5u1hukffXUjQb6mN5xx1il8Qek9\nwwslvd+Wj236ADRJZG40HFhgfZXiG85rf0jejH808o+l6h7vTosK8+t1qed5\njl6LWOXUPKQfMqLhYRGYx4lT07Lmadbb1urDo3ACrVwQai0OCJpb72HZlFTM\nDMgQWoqMjI9fhxQX2m9Pxp7D9SVG0r4QXYtSRc3Rxu94ajzPES/jf2nex+Ce\nqDcSH9hRnA8Z0c3z4oFD5EQtW7NlkGr0i33fpbCrK/nMExYxC3UiARq2/tNn\n5AX2XfZ7yX5GX1bIyXZtfNGjJbbghzs06Ehu2PSl76dYnJgQWLGBUiyQwCOj\nZw51I408Z7eiWi8EWLM7WnyJGJpHqq5mYUFJS0q0orZg/CDD+AUDaMx3HEv2\nQSMnmgum9KjM3dctLHzsVtMhnImE4sYUetTBPrMVqONpTT5eLLJnBWYBbn65\nralo\r\n=rl2E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICTsf3SkRy5P67RrYFgYcdkzXU4Rdsd8RUjK6afr5Q6bAiA8JzxWFpNMEl640mxfUjH2Gh1Zq/kJp+hDj4r85aDtIg=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.khchhyyz.0_1605043569951_0.1709506788254096"},"_hasShrinkwrap":false},"3.2.3-canary.khdxsl4k.0":{"name":"tinspector","version":"3.2.3-canary.khdxsl4k.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"aa862136af5fb25886e857feaad7bcc05087ac12","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.khdxsl4k.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-0dLqiDlVe/Nq0TBmaTdMeaJUY6HI9vD0K+UEKGjBPlty1+liHyefFJoKyZgQlxL8m1A1rhpp/ziwjAmKnB8Yfw==","shasum":"fc54a0c073f1e3f42b32bbc9fc019800feecf09a","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.khdxsl4k.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfrFyOCRA9TVsSAnZWagAAa5AP/RStSkga9Rqb/B/CbF/p\n1DvveuDieKFYOb2trAeC1I6mQQ3zHqfgws3kQIfRCFw1nDXteXmr/cRgbqGP\nxo9pvj3KjcofDjWsloriUKR9zda8FF325vDZc4mD85IcWKTpuD1Xa7aBlRZ1\nMRTl0g1GPvF3rZnngpuLgyohqniXY8kEwrjN+7CLEK/9QjiKexJTTNSDJ1tr\nAtyJh2v2AWrP0Dr+aQbKScmjKdQPtTFt9TYyPXjCPCZS7WFUdamhm18IuO/e\nDVztC3dntvoLBWKQ/mO7vLFuEv8AMJAZydOqdo9WB5bmTteud4JHVVvN9vJv\niKUA1dwGyyCmzd1EH2ct4yaWjRe6iF/WBi49mSaTcLDGS5t33cKei4RW9fQd\nqZfQarhpSIEBNPzEVttQ9RVzwxzqIu+3FKG/ftc0bHQ+jPtiNgpoa7TaKvVK\nRPuPttfPIFrUJVSeBoZ7caOPr7EtK9UFXILhwhIMBv9n2YCzFMoKkmVthRq5\nznzjzrzl9hp9DpFHIoHoL+/26p9dCjfj8vVWwNAUTokGU0eBNFMlNh7fi0Mp\nWDYrT3XhIrQra3Por9b6Ip+Is1MR3veLWJRsOBeRAeGSjesc9cvARNxnesBE\nx0pBV0ATMM4WZefaH4CQXq8kWCE7YzEGX2raXKPLzdGFT5oR+rIEWcbwZhQ4\n510E\r\n=VhM/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE+CAxUSBGyjpQvkxl/JUI38ulzNvIfo1f3CXBgRAicxAiAckb+xfwdFvkV5fc5F97r1HY8160kjhk7JFbfsXxQgoA=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.khdxsl4k.0_1605131405471_0.9907232431960276"},"_hasShrinkwrap":false},"3.2.3-canary.khelfoev.0":{"name":"tinspector","version":"3.2.3-canary.khelfoev.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"8bbc78180abc7658b87037719c1e2ca5104da79d","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.khelfoev.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-AXM+mcybdJLPcGVwfqiRlNTrbply7NL5Dc588z6swAzmwCKao5emUnE4JNhi1eOHqak/4thKnB63WlVaXYGJhQ==","shasum":"b77d23feabe50183285ec30b038f8b52146ee7cd","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.khelfoev.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfrPeqCRA9TVsSAnZWagAAxggQAJlwvj0sQKa7B/MAGfs9\nMaokFs4lgAjZx0tkfgj7+HP71mrchZghyT6nSB/gLcLJwviAWaxIpJQMI2SS\nDC/LshW3u9vt8+q1B4/HZPPUAahWRaQojHu+4t5ATzokZeEHf3BJ1+sq1Bnz\nsN436XNkzQuKQl1RQuiFOWugiJCLfqfE5LtggWYCaZ+mio9dfM1t/j0Ug9ev\nxoBmTADpKVwmiNNf+ZwpfV8zKDy48elf5ZQqDwfadu0qwYtxb064bWGjRE76\nXzN7rrMBp4Zyhymiv40YvwyhabZ5Y3T7/l61o8Qae2WeDp2nDe6jK+IMdtN9\ndAl5pGl5Sz7UxuNSgSKiuesSYf9I2sAGCTcIZ9N6xaasey8tlMZgpoTGDioU\nSQLOO8VjfjiuViloEP47UWWOEtXnixLGJiL0Yh5e/sSfU/fp33LS9ifVpvOs\n0jAkgfBkC2LJGlORpucH7cDabzjHhhC2x4UYW7rQyRUnRI6iVy2yCDuiFqc1\n42m55a5/KDTKGksW7Oo5hwya3LNSlNq3NG9Jn5PK6ztwPUOix3qAHiSAqDTi\na1ZOwmaYOWl5ckNhurXQaFKZGpnk9IPEUct0a3RSNgjAjQTHvOGfFlTYJAEY\nrHNa9AXina3b8oytQavyKgGAlvHO6mhHBmTd22grWs5IgJ/4UscNyDDGx1DA\ndpX/\r\n=DLZB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFQBgD7Y7pCPHfHipK9zn0jV3fRKB/uYuM1PEDDTi5k1AiAxfVBKpFerB8tLNHOMVI4g24I6mcgaLaso2G8ZwxeNHQ=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.khelfoev.0_1605171113575_0.8872512993625783"},"_hasShrinkwrap":false},"3.2.3-canary.khg09zf1.0":{"name":"tinspector","version":"3.2.3-canary.khg09zf1.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"321b26357baec80d3e2ea7e85b2704d7632ea366","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.khg09zf1.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-d/QKyf5PmTMoG122YOSmNVPIyp3m9LyMn2GG0osm3sjbLf+hu0St+hwUppPDRU8JI424xC4zxHl9wdcXmXD3oA==","shasum":"a6a7f93b91fa3022e8e6fb0f64e0a8ebddd2f0c4","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.khg09zf1.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfrkU9CRA9TVsSAnZWagAA0JsP/Rkmu3HyhmkEeVjcny90\nmX7Ygji91Ve9Noj0hxqilzociTGMAtc9JYdBQu4uv1Qv7aFFvU5J2dksTEx7\nUKVy+2rDgg3+4h2SD5GR2uSK5+o71NIbUrnkM2yw4jwT/IjoZFxx+WaSh/Cm\nws5g2lQamdVY/nrrpm7HmrBGQ8/QgrFtDcYyEop+za5VAQolYhm3832C9jmx\nEI0u3nyQwZsdyEIDTWjZbD8MPeYtp3Xx9U1GKZPyjkkz9YbSVUqiHrLmK4iE\nlPaNd89tG53VJKg0/jepWsWi90cjyHpjZkO3s7yQ73lc0UHlXhBj/EkgVWRR\ncKxkzHatcOiD+BgkLLQK3DAS+pvTfDk1qGgdoxhyA7gkDuVPHzt9QTswIIE7\nwr7CrPnPnMTLmN/R/Adu12oa7x3ceE+hSUYSocaWBAKRpGiSmGXzyYnOqwhq\nrdFqD62VrnAM3S9VJdGP8xsdpsusjfmmJqgHyPsmd6wpQz+ADIwVvBiespzZ\ncsnoFgLgMiKM4eDHD9/um5Xp9CmCcdaGXmiApY2iSiAYqA8f7VIiZ0op7DJN\nwq9hNKOgyAMFjK4sLoMBEaN1vUL3KRMMmyM1BAQR3NmVhfSvjjBEGUwYiT5H\nRJm3G56bvnkvoEGTR27PGuITx1hd8ygpbeGbzTu6wlPHVpzjA5LPBoYFf4hr\nWqaa\r\n=yYUc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFwbCZ/aceu7Bj6Z0sTgpHI5oXvSokt++MSGzHyid26oAiEAuB59SXizrb69STKAsyDbWuVZrSJljtScPhx84jMJ0PE="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.khg09zf1.0_1605256508694_0.9597061788866323"},"_hasShrinkwrap":false},"3.2.3-canary.khiras28.0":{"name":"tinspector","version":"3.2.3-canary.khiras28.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"68b4caeed2d95cd808fc0c876a2f71a12ce69e20","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.khiras28.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-XY6Tt2/wi34cVdZwwH9djN+V95gc2b9s2tzhcm4QpCDWkVfvzqjJ80tEOVjEN65hVHLp9KdQ5M3z14EzFf3yIw==","shasum":"2503949353e7fdc32236083dcc79b606cd842a33","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.khiras28.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfsM7sCRA9TVsSAnZWagAAZQQP/A9yPGCpElgrAvzPBHKh\net5LpbYdA/uY7TfN5F6SvF0GTwQVMggcxlz7x2zWt+WPlwvCbbeZaII1b1kv\n3qJkmsUV3Cw8l/ou+AYDRf8SWn9O1RB+8DdSehN8nm9doOI2MHMFOk4MgD6q\nZfpRaFZFJr/tid+p0caJd++2d0/C8F0/rNBUvkyE+FyNndqj/MZQPKkoetIG\n1eFAth4RP+Cvt5kkeyKrduM4/Bj6bQ38NDE134Af4nfF6sqCFazmu7o4mgnY\nWB3ag01MUzTaccFt+XYSwzJzOR2U3cgu6TAvmg8BOSkiDJeuoyw8qTqqjzue\nEESTEXwCS4KDnFchZ6GuZgFTO+ANuQ5WiijAUc+6AIzLw0DYFIyIMtswdL9X\nKPq4V0Jnx7pK1UcbNWr0O15lMguNAHYsFKA+uvBRf85evq4Kg6KqHXqWk6b7\nff2ndYL0oagyJOIM7HTJFoIeoY4DA0K6uhJjBJmS76po+LZ7/i2bs7bhawQZ\n+RRliii0uYRRf7lFKjsMd4E1skHrNgDV/TvfdbSd+AtkQAMuUUrVksV3kz96\nsIrHjNRG66ppOEndoPtQNqACoBbw7OG135OEYjQKp88Xu5q/rTi+MPc+X8c3\nJbs0msEjjrfPWbUwPBvccq6oXyDzIMiOM1L1VB1UjOplLSQ19jIcE4mBO0a2\naie1\r\n=W7Xf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHGcOu3cU8KFjiczu8cd7x73kahy/y5qNb2W1RGlblrXAiBIsZlLPooadTEGprGeho/ZVdkxZyUclRLNlMqoPzed2A=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.khiras28.0_1605422827861_0.7370364839819081"},"_hasShrinkwrap":false},"3.2.3-canary.khy4xbmr.0":{"name":"tinspector","version":"3.2.3-canary.khy4xbmr.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"5941bf4349c3ebef81a51f961e4a3aaccfcda32d","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.khy4xbmr.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-mN+2fKF+T/x0s+Sv5gTK1LFRG2qancHojkzcU5EJcidtj9KySmq00e9cfDyWDsL9LAaA7iUd8nPcaudI1P4sXg==","shasum":"4609077bc359e43c24b36bc792d2fc992032e46c","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.khy4xbmr.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvv9ECRA9TVsSAnZWagAAaHcQAIzGLTTZi34vQC+Lmoz+\nOtDhxM+OKf/i7Im5YvfmEu/EMZejwXRB6tsdAz1T3zSKffM7WKdjH7HTUSvu\nfACfxDzebFoyXg7DSZKASV6PGDr/WF3Seuq94F/rSPoogZlDVYYDFkdoNTin\nhTujRtkAB7N1ggUlt3xVANasQ9a7YnuvKYjKCKDMjwwejWoFS+8fV2wNQZLt\niA+L/yOnhN021pFoVakRkcEXrPvSb2zWmlyo5ZieItccZZL4gxXBsyq2ilD4\nJcznaRWu8rNXlWN9KSiKAzQbJTA5trpgLcwPVubOjE7D8CF0qZlMLkUIgd9c\nTWPSw62VlDEAc69Jt+jGiLBVFFAmf7SVEb8Dnjzxa9+Af5+ukySWrRgx3jkv\nX71CP+n4ATkZrnQ5a9YvHBTsIsMxEGYbJPym1CeJEgSnl0gtWcR/+46ikrfo\nf7VKnEj2UiL2KqXQOlrMFf2KSAhWVB3ihgtcqnEXVwr7VwSSUuLDErBYBYrd\nC1LybOM1zoc+zsqm2PST/izBMrOmELMQRUvIsKz3qpvusO65/MwDxaPcU2Ol\nym2u/9K3WI443Yjl3wK/3Aq4W2eE64+y9kbM/L7tEpPUKYzC1YzbRMEorZdw\nAa+8rZbdxFv48uHqOHEP0w6rvjX9Ks8CzrrG9sryAcfCB7YBYT3bkZBVARmb\noYkC\r\n=leWH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCSEJ/ljn38ZjcmeO0j72qJVnKFUd7Ur7b6rfNEt04ihQIgHK+Vcg4/3isshJgdDZvoNUZCTTs8nta9xh250rs4aYw="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.khy4xbmr.0_1606352707298_0.41762674324649574"},"_hasShrinkwrap":false},"3.2.3-canary.khye3mjx.0":{"name":"tinspector","version":"3.2.3-canary.khye3mjx.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"028cda16da32c4d838a9bfeae9f1599014432b0c","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.khye3mjx.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-o7gKmmx6zv2QOYvDA3JQRhUOoYoz9wy4xn+cjsXY5zs4YWDbJJ7JTakGExydC1qQTwYO4fTWKqTbfo8m7NDytw==","shasum":"f8af954506c170e31d781c43f7041cd907c76bd3","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.khye3mjx.0.tgz","fileCount":23,"unpackedSize":68541,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvzt2CRA9TVsSAnZWagAALW4P/3+YPAZujNBisTqTaisC\nBA+H3lyYfFpi7s1/ukGWxCTZLdWazRB/QuEGsU7cQsjCLRxjP7281rwwaDpx\nqYJSwlGsXYzWr+d1L5/9r3FsO4xcrFxA6KB54Pkk1vHKg7R6UJr824m374WB\ndZej/SV5sjt/y08VlE05KxQBjxvseGkNJLAwXdc3J1aIuYt3brLm/WZQtCQw\nYA+K868IV1XuxtOJwjUXbxc/0Vi3TC2UHJiyNbJaYbwdgZBACrf/Cvdeu4nP\nYKOUf5NbuqLe3DbXgsoQPYZHFsAd9MBKssvUxfm4+Rv89ENIqtqiO1c+rnJq\nz+JVDeuRa+LPJdbB2ZHCz+fZRz2Vqo0v1JalrjCxS0Qgqg9D5qfTe4n/fZB1\nOgKxtSLhKrBSiaD04b+iBZAQ/JnzskmP1vMnR1HT/JVv5NvuVG8pbxGGCofF\nhMEvWM1xeQEqQPfvuHWFBGQxOJEZY+j86DFfyBApz29bDE092mm9mtql+JcP\nKTI6W4aSpkI1WwX65Cq7eYVLhG/buoxcoa0Bu/zdi5mVP8mgyErYn6GYLdqo\nWzi+SqNIX33bZ2go8lM30gYXvZVS9aruMojJdDFrRaCAw1+wHlHcCXK9FPgD\nvUr0l8G4qaZXmY9HZW9WFv8fr9hZjeFcgSuFvTSHhPqUI4gPogRGGrcISNvO\ny2A5\r\n=mCEV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEqP4VNrStDpZ+6sbmRxLIkS9pMWqm/+f2GeVfEAH6o7AiAkhx5BaDI0RZs3JHrt7w9JLa1UgSxTncHgwNc8ssrgLg=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.khye3mjx.0_1606368118025_0.7349523978901107"},"_hasShrinkwrap":false},"3.2.3-canary.ki2idjwy.0":{"name":"tinspector","version":"3.2.3-canary.ki2idjwy.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"56bb41ad262bc68693ea9186c2715e356582d886","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ki2idjwy.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-tx0JV0mSm+UbdfNJoWwt7Gggj3wQYw2c1il8pm774GTdOHtNymZVAkROuJL+RTF4UiJsU0uix+6k6+l799meYg==","shasum":"a8066997e583aa8c344079684d9c6e1595e72bb4","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ki2idjwy.0.tgz","fileCount":25,"unpackedSize":71829,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfwwhMCRA9TVsSAnZWagAAu+YP/0tX8QTg+EajaIOOR4FG\nV2HopBzCFkrmbXIEVrkAUBNhpGgVqqr5wHLbVZQkwVH9vNfJX3JW34HmdQH4\nMPoRTFd9X5U6epxx6XxUt27dCsh0mqhGBLIxdu3/zVABEbinahDyrykcHQxv\nW+lv8LWpqqKrXyl+dkqAeavgQDJixqBuYbZBJvl/IAf1hTKTSmB9EVPl4yCo\nC+mLatxnMZKwWAqQNliFDcXoZc8TUl7FVGdBRlD48GEsfq7Kg3VIJoGC/KiW\nzDRjRkdoh8uHxgol3eW/himQqzBbOydGVZTeXVwunQ0qLxECHPAmMo5wbWvi\n4WUwhv1ic/XWV4RG7TJ19op1GQzNSztPOD9x5Kyi2X4KYR1+eEGzpDKWcQvi\netOnswyz6PHd7AcAX7ohBehTSYahNNZVc39YS9JI147vPn271Wwfwvfks2ym\nEflkkgDw+WEOuAKuJrI06rRd43tFN7/5yBpgcyE3KYtP5J2QFGYcTQsSCqWM\n3l3W4FB3obm0QWJyITbLt3TyXd4Rt/yxlFf5ckthwmkaKSorPnsv0PjI4Cnc\nRj/CHf0+0mr+qT3+gAAr9GJpbC0N0Jk5f8J8H6jtzTIy++FopQXlmdINw8uA\n0aoEJzwDLJUbaUgx3gvXKXDKtrAEMvD7MGOR0ebmv6iA4T3ad+NKiRrpl0yV\nnj3K\r\n=LjeU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICHzrqrAG3HQmEl1veWlu5MTT/TH5dUYbA2KGoftoUfhAiBY4lxEhkPXwtoRMk0TXIrXODVlH+t1WwzJTi5OPYcn0w=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ki2idjwy.0_1606617164097_0.5319456841162842"},"_hasShrinkwrap":false},"3.2.3-canary.ki34emgi.778":{"name":"tinspector","version":"3.2.3-canary.ki34emgi.778","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"7c0080bc977b16cf2b733533f15dce836736acc7","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ki34emgi.778","_nodeVersion":"10.19.0","_npmVersion":"lerna/3.22.1/node@v10.19.0+x64 (darwin)","dist":{"integrity":"sha512-fpbWadWvGaodNbJf670hjllHf4Cvxm3KTA31ohCfLP8NzxE9SXBwxPXxiupmKZpX44i2gPX3nWRvhn5cFXKhTA==","shasum":"ee51b23500a67a876d17f960be409c89bfb94555","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ki34emgi.778.tgz","fileCount":25,"unpackedSize":71831,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfw5jYCRA9TVsSAnZWagAA7A0P/1GLbhz2gbpC3ILa7a9g\nZHPRQr+aA7r001JIMOBJWLaH8MwfApR5PUd4PSADxUqoVu8JFT2LY3gWuX6n\n0RkodlfMq2hc6xzpmpTG5wKiagYZ/OT2OolkXVn+sZhucleDfCBrOhyaFqpY\ne4LJXZPSvjJH/XYaYldLPTMEyQ6WFdvS4uD4qpIzJWoi/x7gQK4WiGwuYXzT\nWpezAXMFMfh7n9F2aoiWzSea/OiM3wCPbldwTOzhUcJ8ydkcCsVKTfmOedYY\nRWM7AWD1p0kfiLJoQpDwbwER4xRXzvKEPavfvH5Db+jXy0YqLLF1ts9NR4sB\nWA92jrOdy86nDZB3dkOzvh9Ap8cZS/GMayTI2QPPPLdpbzARJ4jY5BLEGgrk\neFwrfUIvzyoY5EMVw/5fbT2NHhlfxGrkontm9V6Y6p2tXSQAMsgshI7YYRoB\neZsrwjhDBmQp4Hylz464wpwf7rb4brw6YlsUxhwdjoIhB/6eclKRkcjJGwLr\npyJlLHagFmWOhq6hK0omLmSz6gZfuUDLscizctU7dnfye/48vT9Nk+c/j/hO\n0BykS1+Fgt25IBSi4tVYTQPSI66fyq3rPKE1s975wFpeNsDnTRqL5/DSHiKy\n071H+TqR3sgpOkr8ohFr1W33MRr0dEXxJ23aVj8nrIyy6uDOCyVVEugyrAZi\nV/1V\r\n=i7yB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTwSeR5Xk6h4QGYUC2hLfK3ELpaF0fPRGAi+eHP1DF1AIgWvXJqgDeGJ5kQtAJ2DjnG1j9rjTRSsOeebhG8vEImaU="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ki34emgi.778_1606654167990_0.4505051343148865"},"_hasShrinkwrap":false},"3.2.3-canary.ki3i90va.0":{"name":"tinspector","version":"3.2.3-canary.ki3i90va.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"0a18e03d481ff54e227ab4b2774c42ad34164f08","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ki3i90va.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-+VsDE4tF/pbzWBYvNlh//5DMEb3JTwuBLic8ITdqjIM7hAn6pR5jAUAIOp/pYn6/FSBvR7EihWWO9vL1ISttaA==","shasum":"9f93663d49275ce59c284713ccbf83fa984046de","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ki3i90va.0.tgz","fileCount":25,"unpackedSize":71829,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfw/OrCRA9TVsSAnZWagAAKBwP/2esCxTu746FRWQZBfpa\nvmraWjHXjdgvCLpDL2WAuwpt0I4nCW4eGZqOJtsE3vRn4t3Az/ce4JPbW4D4\nO1af0N98IX1Nso2WDXxb0E5vJ4yDDpPZO9ukl/pyQEbtHrnLrpskt1wpy2EE\nlYh5ncE8ffoEIGV0pYKa5gbeAyyh1NQ6u6DSm2rs5kWP0Ut4DHjvd9xBjA5Y\niPsD8ahG/zMy+lDyypmS3NRKDvhB/Sl+/NLsA1V3Z96R9uTnqbDCVBcNGd7K\nsZfEG7MLNG9cn1RQN9rCSx0rFy0T86DXaPcFDTyzjFYlPby1vd7QnTZNS7eD\nh1k3fSA5RiY7bQsjltmDT2fHz44bpeSw7Yj/lpjKmuCDVwH3PYDPbMb9qbXQ\nfZTP5B0wO1Ak2TC2TP/c5V3AXv39R7gfNLTEwoKAgZ8MsSiV55bo1YD88+iB\n4+o3G7oyGhFgW2Tcy5X6KBa+hiIEf2vlrcb2kauarGjHoWAWIel2Y+UYQxRH\nMhlkEZJ4C6OPBbtQSC+wLIfnTS81kfTgdvZtK3TmEkFO+24D9l6mz2w2CT0A\n862KXPb3b803FAk6fBOVIAzv+bWAk0cw9f78WqEVyP51SV2icdjJWZ1ueLL0\naZ70PrNuIondu06iyaWda0t6wOc1qK2amdumOw0pSoo8KbgyE+ZyaTy3dBRz\nDAqJ\r\n=7391\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/YXnthwtIVIp8tkblcRgiK8rO7Pt5JTvphjADeVX7eAIhAIguNA8j7Yp9E6ZYyJ9YT6JspThUbD6anq2mzbkxZvph"}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ki3i90va.0_1606677419083_0.8401994270915418"},"_hasShrinkwrap":false},"3.2.3-canary.ki3imu3t.0":{"name":"tinspector","version":"3.2.3-canary.ki3imu3t.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"fe84b4f9ebbfe82900620c108f1de20e952749c3","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ki3imu3t.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-WAd1USnnpnzBevcp6/KcmbmXMvAN+8dQov036ks67j8rASf5P5rXOf6UQy7J5YdirYfhbhDUkrl8rgdfdAAoyQ==","shasum":"10ff78bbd5145282448c15f897b748843b271949","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ki3imu3t.0.tgz","fileCount":25,"unpackedSize":71829,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfw/YvCRA9TVsSAnZWagAAZsIP/3UBfAtZq1CJVk5NHX8d\n1dh6XsQ3Knf14GJdjB5Nc3rIfOAz2gTyXuEDHoEHSLW6KT7rcWaUHeS1fjgc\nk3KVG0OTmCZ9E7c4L7AaDXQTPUHnAX2bAx21NHkjEJF8cxAWHR2csqU/RMF2\nTIURZ9VSGl1HdzehgbOnsV7G9RdwqMY8Z5q7G1ysednWex14HvMzqfCYvK4B\nPaNHydj409v71ZTL1ZXiS6QUmhRLt7dguiNZIqIqVITwBkzZf2qYmRzwWMTr\ngSvUez3KZF9gPiBgHVEyPWZ/2MUN6fdUKugzRUWbq/aUcosjhAfZEb9fsphF\nbdB4sEM/EOwgk03OpKOBIe7bKUdBXDk6jja9kNR/gs8TmtM8xJaiWauaBNCN\nPPuWn26kUSwapxKdWeObCbv7UMFl0EiDUXDlmiBFEosiBFazgElQXUXKXzel\nkwDAM+8mb7KhSIFB/eGLvy2zMvuDCjHnPrtSaagieWpq+70n2SGOWmZgEUjW\n8IBXdZmtt5o/uipwB205G/5DY1UpTmVIGtWArJ7jxqcOtDkz7DRoirEQAwHF\n0PZ1xzVmnY0AnDmS/DcjWmYMX3CnxsOhnayaXPzZ9plOki2WejCSX9uI4K/U\nuikkLTWW4h6t5O9OigGcWsBPfBtkT/YydR65+TQNaQkX+FPaL+t4iycttMTm\nvBMb\r\n=a/Ua\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFvNKBLyZun0W72ESNPPa1CPSZPZVkwrOn+cECSvMibEAiALojKkaZcJj+n7VMsFs9WlSAIhsXB5lv2XV4bdivwknQ=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ki3imu3t.0_1606678063073_0.8938352571142931"},"_hasShrinkwrap":false},"3.2.3-canary.ki3w8w7z.0":{"name":"tinspector","version":"3.2.3-canary.ki3w8w7z.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.6","coveralls":"^3.1.0","jest":"^26.6.2","ts-jest":"^26.4.3","tslib":"^2.0.3","typescript":"^4.0.5"},"gitHead":"d0c04c6d33c2ac4eadcd55de4ed5a4d0a4b143bd","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ki3w8w7z.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-5lrbRG5GzsgRKvyt6e+kUdZHRWmCl0oBJSv2KeS7xMDvXNlGnS+BIUWd8vML/tigKIhNi95+XSN5Gv3YiayW2Q==","shasum":"5f8b25b1d7a481daf97829acc40a474d85feac1b","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ki3w8w7z.0.tgz","fileCount":25,"unpackedSize":71829,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxE+ACRA9TVsSAnZWagAAzEEQAJjrlndtY99eWlB+LFgy\n1DcLWRhVbTbbqAAMnjzhcEDRyVqPWHXO2G3uJvhpw7VsMLGnjo1K8XT/6zli\nX3Cv/GXVS7FWa0KR+lVtqQb7UCyHuiYGmTUOdDStGhhm1NZei88HeAtMHrWG\nUYY7g5bg/Skm9/M2WdVpil4/dv0o92+xGDQU1a7oW4Us1gUsU/XeX5e1DV9I\nwh+ixE9K8DrN05K0ApSnHXWUXxquq+moVNc++zOBtUFi+I5xKy4vIMFci2ta\n5jBQzJp/PeLz0W8HkOFOwxNocep3CYLMOanGuFsLi+ZN28pz+ft4UU2seMwV\nrFz/wX8ZCEnlo2c61/qE9K7GH3MGQn46lGwIka2IZkLBQsL1yqLKILVmpZcN\n0dF5eLVRrju51q8bxBsQHjUw8hwI863lSI5xesMNujeROuIEpKUduFUu0aX9\nVUioUa5TU0PelgkrSXaCLD32wu5NxaTYQ7of6gWlmQPwdlZIMy6XSf7juQTd\n7qw5rxS+beG3xeHIjBrjgXfvI1QkFND+euhtn5iERTWK7I9nTnwHe7cf4T0i\ndIHulaMP/6JdIccVppcRCVjqzKGsVnUzzlhQkjbL9yDjPFfYPPqDBRkk0IaP\ny+yT/IDbwQWVfrhzjWxH23Vikw4CP0DY/Fpczn1CF1O8iMsDRQSpPl/tAE+y\nz92+\r\n=s6nL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICO/wc94eFun/8GrFzKxzLxOh+L5YDTi/7Oi/JdFOIFAAiEA+B58HIf2dBgKCt66Tkx96TuDnZfjCJryg4Vcl+jdGxo="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ki3w8w7z.0_1606700927424_0.8070965109537052"},"_hasShrinkwrap":false},"3.2.3-canary.ki3x3sog.0":{"name":"tinspector","version":"3.2.3-canary.ki3x3sog.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.10","coveralls":"^3.1.0","jest":"^26.6.3","ts-jest":"^26.4.4","tslib":"^2.0.3","typescript":"^4.1.2"},"gitHead":"e37131074c87abf70db6584fde37777b83588104","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ki3x3sog.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-eS9YTlNvOCyB5u6EPV2cMePPrsPP/ZK//m0OVHWC2i02xt6Mwd788sRkVIY+JSBxNREcjysMoel4+F7FeuwE9Q==","shasum":"f0fd9eba119378c44812d58f1bda852ea304a4c9","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ki3x3sog.0.tgz","fileCount":25,"unpackedSize":71830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxFUhCRA9TVsSAnZWagAAwHsP/jIDg0kQtINHyG5Zl/c/\nV3Or+YOWPLAUB3m1B/9NxiuVVKaHFJPV755LPq5ccxAsl1rnUJerbkUOvThN\n6gtyUGCk7ESCpZSlfzdZ0NDg8wV2WmOKtQ8JXMYP2JC6uQAQelh4n7JninJZ\n39jyy3j54Lh5WinOaTTVbf0GXy1J/pRUqONZqTQK+mVzIj4ln/UMWGI70dWR\n4/fZxVIhKDAzkL/eLol2YECPGs/QuY7OBmdOL47Nkq3Pig1USnFSTikBfEBg\nMur0Ty5IHGBzX92/dFEmp1F8EnBA5qhCOOuwWWbogrZoUhBDzIL9cHrAgX9Y\nkQrpj6dOBqHZHqOfVpWpgmnATRC/XnafQgvDXZKqrU3qIWdFrzkKV6nqXKzT\nNJG6fLR6b0F6YdBIN+gmEJaK756Qe7sk2mxk8JzPgYa6T/jQqKUZ/YeTVPEC\nxGbY5ZMPzVSHjpLRdOHoisFr0tJYU4/iRz3m437bx8BQnRoIM4kVu7v0B26Y\nHUr+y/aA+UBNxDu71BxAMF34KJOG/EKbwlr7O/lk3Rc+WOv7WnwT4tL4vO7d\n+jD60H95OsaaA72kLriSs6siA6+vGgTnYAOPvi1nNoiO4jl+iQRfoOyWBjvC\nBRxUR5VqwQaW6l323PkRo1Mxywsa9uf1g3zKRosS2yAKrApwiHw0f7Ks2feC\ncwoV\r\n=aIj4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5ITfXv8xy5ZD+I+/k/UbxoOFVWjz78+8DbZOP3I8rvgIhAJGPqNCzlYnwRuxTuC0EP/DzX0iFyxKo075zzJfE0g9h"}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ki3x3sog.0_1606702369321_0.10034351656406026"},"_hasShrinkwrap":false},"3.2.3-canary.ki6vxtqr.0":{"name":"tinspector","version":"3.2.3-canary.ki6vxtqr.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.10","coveralls":"^3.1.0","jest":"^26.6.3","ts-jest":"^26.4.4","tslib":"^2.0.3","typescript":"^4.1.2"},"gitHead":"a931fb773dba6f069b38df347f355a29eba54a71","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ki6vxtqr.0","_nodeVersion":"12.19.0","_npmVersion":"lerna/3.22.1/node@v12.19.0+x64 (linux)","dist":{"integrity":"sha512-G8rrC5D61IYfIKcyY9AN29n9mCQwcx7olffjbAuUkEQ89rbUqCcsUD7zaXdvEneGXTwmdNeaqOAB0Q+voZ2ZyQ==","shasum":"e333739f4f402dab8da92316b97e9144f5625bce","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ki6vxtqr.0.tgz","fileCount":25,"unpackedSize":71830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfxxISCRA9TVsSAnZWagAAOQwP/1dDWUPqBv4V6s0hqjEr\n2BVWky4nzMtMqKZ7+bmkWJwDn3ZdKefvF3AMLl07eXUfmnVfUEGzgDbT7D9K\nc33deXMKrvjmNaL1nSTOmi5hDoJpKuyPm41+G547Hm4ozp4NQHcDZT5I2NeJ\nRsmdcMdVHxmH8M8XPBqyVP2m1YjEIQagz2fZOmVovhTyTdZJORP5R3gHbiem\nYBqL6LpSsnmrZ5Mc0pYHIgCM95o4ymNCY06wHoTVCzVWUP9ZfsNLJDX+qRZF\nwmbBZx1ndrD1/bMKdWvSSBs6MV7pTYYJHu6p7phXBBxfZt8x9R/XwD070ZaW\n5XxCvd56wljmen8Z3LU1WNpSzf/BycZMvjwBVXJQKD/LGPdI8lNCUWG6tzBn\nI/BII8U6BItjaCpOL4T5r0+0L421dQVdeGJM45dnGNrhKiLNT/HSN4C3CPH/\nfekk4sBbMKP5XHiu9E/DXJiLdcCe2xz3h3UkuJd+yGnX+vokkLXY5OKwmSUp\nPcYLA4EOdEBko8iuXs+7IusC/Q4169iklzat3m+HV2Yahg68FLLcvhRbgiQN\n2w9uuUW8KVq6LqDXnXMqIjybxvVmsH6H2KM0xb+y9A66CIx5qtxqM+PpiPyx\nrgmPwLzBo/lJEQFiZp0tj0I5YpI21CkaCz1+BSpRj7aNmIKazXClXh1cas1c\nVnIo\r\n=/ZMG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCOBrDoOnx3kEktoPzJjEPqSH7ETR/cobx5tzLfGOG1PgIhAMHtd+PRaVa3+rHe7P6u3Er7IS2r5xVuD+gK4SsdTYU7"}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ki6vxtqr.0_1606881809917_0.2373618622600664"},"_hasShrinkwrap":false},"3.2.3-canary.ki7l9jjj.0":{"name":"tinspector","version":"3.2.3-canary.ki7l9jjj.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.10","coveralls":"^3.1.0","jest":"^26.6.3","ts-jest":"^26.4.4","tslib":"^2.0.3","typescript":"^4.1.2"},"gitHead":"fb59053dfa51105c0c9a307a487f87045eee7518","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.ki7l9jjj.0","_nodeVersion":"12.20.0","_npmVersion":"lerna/3.22.1/node@v12.20.0+x64 (linux)","dist":{"integrity":"sha512-XdDU51oDf2K7OE3W7WiHW7PuKLs8xKFuvTUDnq3F9mUcDATP9koVnu3z+zwFUwpiANFc1H6QlmSgDkO+GXJ4+w==","shasum":"c9de8e76052c14edc576c54f8002a8fc56ecf02f","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.ki7l9jjj.0.tgz","fileCount":25,"unpackedSize":71830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfx7g8CRA9TVsSAnZWagAAhi4P/iUbpRYHsssl0KIwoRcU\nq+WoFd7DjMwVoN65h7X1YYm4JcblGqibfhElNnx/JQGGa8xjW4kDM7/F6428\nEBbSSP7B2+1q+Ba7H6Eo31tsdJiuDLLJFHpx+7OjYru5FnYLaMC8EScEi7VF\nH0IFzplluqoxykycekpEKS1KaiTlBLlGJ/z4dw63f2In2P1TvZe6YE8UKiu+\nvn2ScO9p+0GcrQnNzS3suwlE+z7QqcTP/YM2pBsXxckl/GwnTtZEbnfUOpGP\n/V4V9FHsa8frZ4LAnen0DHnN3VMHoMggH7WsOqSGtzb9yaT6/wYqPdtdZQHM\ndHn6GGptePVM5CbpBtmhYmUwqcX5pKyctqlgQocW6bePKUFvy3oK4oGQVNV7\n37SWiCQCksUEgl/biCA7NmvAQcxHnB7ln2PfBdCHx4MZL4CyXnd2bhEWFkGk\nPzxirNUvi381QWbAXOYLqKLatSAY3E4nPJqXmBxw+3iBifU2pvpOb5Ql/u1o\nsH1bJ0HU39TJhso35+1ZrR/KLZt7aJvloe0TegcT/i7DunyF4eaXLiug3wNS\nmLtY5Ks5+wqLMO/ihxjcAYGbXmXVWa8BPiVg56AzRRJEFgnlzEkF6J1VLAqW\n/1+ojOxF0Xc+sJmQ+jf61YeCxLcs8ng0BQe0ErJWTe3qDLGNWpGeVIwIkde9\nLXZh\r\n=bK44\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCyN/1tc/SXdCY8xHmCgVoMmNEplc89apz0xRR8WrX/WQIgECn58szmH/a8gkx+yMoMrDK7DF7VHJYnQwAE0N/STsw="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.ki7l9jjj.0_1606924347567_0.7518687372627391"},"_hasShrinkwrap":false},"3.2.3-canary.kibdskyc.0":{"name":"tinspector","version":"3.2.3-canary.kibdskyc.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.10","coveralls":"^3.1.0","jest":"^26.6.3","ts-jest":"^26.4.4","tslib":"^2.0.3","typescript":"^4.1.2"},"gitHead":"629b163f15360fbd0bb448cc9732d4c146437756","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kibdskyc.0","_nodeVersion":"12.20.0","_npmVersion":"lerna/3.22.1/node@v12.20.0+x64 (linux)","dist":{"integrity":"sha512-YuBhcfBS5bpXSmiID+fKo9NCEGU+ADOdpshhr0bCFSaxmUINtj5gx2agGp4rJmPhw9v5q2i+WJXGqh9zhTH6Hg==","shasum":"ff93fd0ff81aadaf2bac5d7e260a24e3f4ff4f24","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kibdskyc.0.tgz","fileCount":25,"unpackedSize":71830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfyzf/CRA9TVsSAnZWagAAG6MP/RII31RlKX4GHMNM7ABV\nRQeNNRwW25QzakVHJDZbh0wI7CyHY6aLhE9gJtdYMu525SlyjCD303i9KpoC\nBRAOVADUFc9LDTadubYKkmXYYAr5SUwMPOhPoS1yPlEJOnDj5xq+vFRi7B6b\nGt/yfpdSXKzz+gNpnWyJ7OAXvxUUkIpM0PEB5OsFohh9buMl2mtVXZiSIKMS\nPi/mV38TZzXhUBjguvNzbMinV8a5sYjZ8b5LVTrbW1vz0sfKZKbQasQsK3R0\nS54o/ovudaxwQQk79DeJqlalKvYkAbFgZMB7e0AcV6+oi+Ug/HKM40cuulAr\nXMHuVRQSrs52UkQs39CNkYW24AW/fyzoPTfDNNe6ei1BgDyRrr11MJXP/y+u\nWbSKBrjJVl2HBIOeRwqfhOxVK3MXAjxmrKNSQAFfVs305v3w63isBWJ5eB10\nWY62bYWSKdTfQ+F2s9NeykkLjp5d+ia7sW9AInKUqauR5MoiaBgT9PaTHhBh\nmW7APHeVoU60vPOjO117Zhr4nK3tFJbH6i1FF3A3qR1/hRzRkxo1TNngobK1\nvW08DoI9U5Zv9C7oHH+E6PjiwCGJrLU0sm3dXpqIzEwyYJ8vZupxWID5M+91\nlJeP9FwNXfTVZ7vhsB3fPcXp91cgEXEirz80l3nC1Pr5QQN/Hzx1k02/vJZ0\nP1bu\r\n=VGfo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICW8SowY/YgC2yMF1aMOn+BxBPanJQQCE3v13bLa/ZqzAiEAt2bWzvuJmcpcmCaarjHdU9ENUkKSzyGz8CJEX2QZG/U="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kibdskyc.0_1607153662928_0.4060968099507529"},"_hasShrinkwrap":false},"3.2.3-canary.kicmb1c7.0":{"name":"tinspector","version":"3.2.3-canary.kicmb1c7.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.10","coveralls":"^3.1.0","jest":"^26.6.3","ts-jest":"^26.4.4","tslib":"^2.0.3","typescript":"^4.1.2"},"gitHead":"8d194e27a3a92a5d05a355ebbf0c85c945ce7624","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kicmb1c7.0","_nodeVersion":"12.20.0","_npmVersion":"lerna/3.22.1/node@v12.20.0+x64 (linux)","dist":{"integrity":"sha512-bII25yyhxuZPkTLgFAongAXOA+0fruWRpm9Di4L+53iThGSmbvwaK4qX/BsyP2gCqNc+jCsnKfNbSr0h4Qzw/A==","shasum":"396cc2efcf81a66f69890d307366fe8854987dfa","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kicmb1c7.0.tgz","fileCount":25,"unpackedSize":71830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfzFwLCRA9TVsSAnZWagAAdXwP/0rXHJq4itmi5B2624zs\nM946XPchU5QciBsdb2ACqkhfXIegPeYhkrdSX2lSKwH02yzmt0vTCfLajKY1\nx3NphJHqE1fWzl9cmxFpgwAZUBfFGXldw9iV5/PVpsTojFnqE9baraoywBS3\n4iHdiJgVF5udAph6YqB5Oa8JPLKkp/8/gNGrlEDsa0FKN7zWFalHXOjtaMT2\n0K2U4otRQBpBreNzmkvI6baBUMxI8rIUC9xXL9hnXfzZCZ/Wp9HkaHFetK8/\nghuvAWM6jvZGMCwzznhiAo6TQuAsGxDHbYt6f4lnGpKkmMZ1d+A0Gz7+kUYy\ntaQiIHofY/eKxGo0t3hdvJ5hdb56tamkvhzaa5zCLBoezdvAYPosnxDTUow8\nmhNIPQfYNnJFpCi9xNmv8idsVaO1n3Ilg486Ss5j7Ze6Ag7mMTHYEuUbyk7G\nT0YxTisjvZm6AfyaS6mhuyE1a8CmZ+/enNbSb8QolATG0hwMfQAd+jKF06MG\nbbAbdozCz8CPuq12ZuFVInd8gY8jsUtKOUFVnPkedKLzBjO67kPCri1z1VLM\nB+Aa4vGCbJfKzxnQ4RePFxdEq7OiQZRzgIYMYO9+GlUlpNm3grEx4dtlBSfx\nbFiyLKrezH0RHcJ71g+0ki01OYsFp8nB5ZMrDoy3PZwGyupRJwkNY5SpG56B\nX/nz\r\n=QO0U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBWit3kvNAaoaUB2jT8r37fQU5BzPXeB/7ZV8Ipkyj7QAiA7s715N7jPZgFOmXyOE0DSwn81BFF985NN3HIA/KDidg=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kicmb1c7.0_1607228427091_0.34225607929303914"},"_hasShrinkwrap":false},"3.2.3-canary.kijl4du6.0":{"name":"tinspector","version":"3.2.3-canary.kijl4du6.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.10","coveralls":"^3.1.0","jest":"^26.6.3","ts-jest":"^26.4.4","tslib":"^2.0.3","typescript":"^4.1.2"},"gitHead":"9f4dbcda252eecad193e47ee70220dd28311f1be","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kijl4du6.0","_nodeVersion":"12.20.0","_npmVersion":"lerna/3.22.1/node@v12.20.0+x64 (linux)","dist":{"integrity":"sha512-g3mn4mQCHs5iQCLX0aTS39g+ioIx3+2chVnIyNhqS6NEbymbPx+Ay71UU25dTLcRgWvabD5cC5ca2hJpH4LDQg==","shasum":"facaee0f75e3a16b8795b2f993ac40dfc2214e90","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kijl4du6.0.tgz","fileCount":25,"unpackedSize":71830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0smkCRA9TVsSAnZWagAAA/sP/Rdww56w1E10upVzhSA/\nHiWjgrw090YJiDj/qFbt8w0kNvBd37giCXAs91xmY5ssEShjjoRCR8YiUOea\nNSe3cTkScsNbqqbl6Qp2r1K49Qf3bn+CJ15+UnVkJbdvCZe9TuVbt6kiClZW\nrcuJklxo1S/kDJfmvfzhzxgkVYk5TkdpYy/IGBYnmPVF++hmrLX8ULRsvgPq\nsy35pTXr0GYuT3OK3ZMrAPHQ1WMgrL6ySQerT8SlkC25aK6DAdoOjjObF73O\nC14gUyuMe+IAfNmOWVktMZMjFRWJ3vDyPZ+uf1I5asoteDYh0RGyKvpUOCZ5\nTP7runYrK92xUZScOXRYeQR7WwlPUZdpaU5QaEODV5j/ErwZFrcg5nJ+1YCr\nqu4JHFPxR+2+eJm5RmNOpbpVYvEIyBB7CCb0yupvsbWZWokItZFm31gSEAmB\nQpi2Lvtu5Wg1CNe+ezvsP7wMTXt0D8jO5i8rykPAGV+M6zWPalnndtwXexkq\nXAuPdCUJJmso/UQq0rLgKRQ6Dc0ypYH2lRDKeOjhqAU7j2+09Hha2yzANizc\n4+BVjZcPlUR2WGhUwtk/Gw2Bdz9C8n/2JRQlJL6z9d3JbQaLq1wtLsR2wmNL\n4ZCKlpfFXTK7395CdvGhwlG68hlLgimEL6RJ/QoSGeLkUxjZQbpIt6valvRk\nYvSQ\r\n=dJuD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFgEylTWYQVKH0paUISz8xSSStSL/O1ZVCjWL0lOACs5AiA0KiE4NOYpXkgHbxT8mFLCJWMuqZLhmRSGt2r677d/qw=="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kijl4du6.0_1607649700037_0.6947419995793749"},"_hasShrinkwrap":false},"3.2.3-canary.kijvk681.0":{"name":"tinspector","version":"3.2.3-canary.kijvk681.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.15","@types/node":"^14.14.10","coveralls":"^3.1.0","jest":"^26.6.3","ts-jest":"^26.4.4","tslib":"^2.0.3","typescript":"^4.1.2"},"gitHead":"93c4776c63a7577c9e1c430d25a1a90d4189395b","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kijvk681.0","_nodeVersion":"12.20.0","_npmVersion":"lerna/3.22.1/node@v12.20.0+x64 (linux)","dist":{"integrity":"sha512-z5bPBD6G/N6QFKd8AwahzhW8VNuPHiaDqnJOgc23osvR9aHbGR0H/JV1J1YQOrNM1ZjzbS0lyUqzhdDVtrMiFg==","shasum":"86c36629e2eba1235de35ec2348b80c28b8fe347","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kijvk681.0.tgz","fileCount":25,"unpackedSize":71830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0w4iCRA9TVsSAnZWagAAopsP/RZ2JV44MMNH4pBvAFIr\nmcBLlWnV6DXcrRSWr94oQbyI5pfLnzqBNqbC+X57ZQU/R0KYVhLFRePnZN2I\ni3O1tlNsX/2WKbUfp9jUA/s1WoSQxXNLKbL5xvFwmXdWsW++C7Lex1UTsnTC\ncWjXl5So/DQ37d7h+SKBO56eUm6lugh2T9Y18JWr8d1HmQMIvE4mKkkBQqVk\niwQeNpRR0nvYrso9QZVK6vXgoC4sZZBV3PKjcW0k1wbNkIb4GynlTJuAaPHL\nPMgtU6rAvkQhHKVII2VeBoHsPJpVBms5qnwVWStezx1lgbJedkEvk/WtYHYa\nYIKI5UZ4ZGHkheztA5cx/cspFoJjZJvMk+UrhhHRaC6SA78RZxkS15CCVGF4\n4ND0jDz80s37oWBUHZSGzYCHmhcSxWN2hvqnx+eRHH4EtAMDLbOo9QzCfwTi\nOjsC1K/KkosYAEFOYXGbGZ1BLFpBjy825VgXVLkDJbfxsynYRskxAp+WSPOc\n5WT7R2OOs57rRxuNj1ADqH4z9gU/8NRABgoC4BrxSfNLgJfwyQJMaQlHIhjb\noE6NdNO+b/29Y6gV9X4+iSSVeJXAazF47A9i3j2cdonKm5RUntVy+cbA2/0W\ni0R48jxadGDEfOSgftXNrhTL1+MWzTAh0tmz4ttTwypoBWyrs1Fp2/j7WEEM\nGoim\r\n=Nn7P\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCU2yPuWHfB808XuI/judTsv1b5cQZllsLMzn1GkvJBwIhAPHEK4be256Bcq6+3mgzP3xLe4XAm2zUdUVnXQoS7Ahn"}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kijvk681.0_1607667233472_0.42097241472857716"},"_hasShrinkwrap":false},"3.2.3-canary.kik3wda7.0":{"name":"tinspector","version":"3.2.3-canary.kik3wda7.0","description":"TypeScript type inspector","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest","compile":"tsc -p tsconfig.build.json","clean":"rm -rf src/*.js && rm -rf test/*.js && rm -rf test/**/*.js && rm -rf lib"},"keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","dependencies":{"@types/acorn":"4.0.5","acorn":"8.0.4","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/jest":"^26.0.19","@types/node":"^14.14.12","coveralls":"^3.1.0","jest":"^26.6.3","ts-jest":"^26.4.4","tslib":"^2.0.3","typescript":"^4.1.2"},"gitHead":"4c6ac59976b1e9bf75998f39ccaeec896d300322","readme":"# tinspector\n\n![ubuntu](https://github.com/plumier/tinspector/workflows/ubuntu/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/plumier/tinspector/badge.svg?branch=master)](https://coveralls.io/github/plumier/tinspector?branch=master) \n[![Greenkeeper badge](https://badges.greenkeeper.io/plumier/tinspector.svg)](https://greenkeeper.io/)\n\nAn introspection (reflection) library, extract JavaScript/TypeScript type into metadata information such as class name, methods, parameters and their appropriate data types\n\n## Example\n\n```typescript\nimport reflect from \"tinspector\"\n\nclass Awesome{\n    awesome(){}\n}\n\nclass MyAwesomeClass extends Awesome {\n    @decorateMethod({ cache: \"20s\" })\n    myAwesomeMethod(stringPar:string, numberPar:number): number {\n        return Math.random()\n    }\n}\n\nconst metadata = reflect(MyAwesomeClass)\n```\n\nResult of `metadata` variable above is like below\n    \n```javascript\n{\n    kind: 'Class',\n    name: 'MyAwesomeClass',\n    type: MyAwesomeClass,\n    decorators: [],\n    properties: [],\n    ctor: {\n        kind: 'Constructor',\n        name: 'constructor',\n        parameters: []\n    },\n    methods: [\n        {\n            kind: 'Method',\n            name: 'myAwesomeMethod',\n            parameters: [\n                {\n                    kind: 'Parameter',\n                    name: 'stringPar',\n                    type: String,\n                    decorators: [],\n                    properties: {}\n                },\n                {\n                    kind: 'Parameter',\n                    name: 'numberPar',\n                    type: Number,\n                    decorators: [],\n                    properties: {}\n                }\n            ],\n            decorators: [{ cache: '20s' }],\n            returnType: Number,\n        },\n        {\n            kind: 'Method',\n            name: 'awesome',\n            parameters: [],\n            decorators: [],\n            returnType: undefined,\n        }\n    ]\n}\n```\n\n## Features\n\n- [x] Inspect function\n- [x] Inspect module or file\n- [x] Inspect class\n- [x] Inspect class with inheritance\n- [x] Inspect getter and setter\n- [x] Inspect methods\n- [x] Inspect parameters\n- [x] Supported inspect destructured parameter\n- [x] Supported inspect rest parameter\n- [x] Supported inspect parameter with complex default value\n- [x] (TypeScript only) Inspect decorators\n- [x] (TypeScript only) Inspect parameter properties\n- [x] (TypeScript only) Inspect type information \n- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)\n- [x] (TypeScript only) Generic class inheritance\n\n\n## TypeScript Requirement\nTo be able to inspect type information its required to enable configuration below in `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true           \n  }\n}\n```\n\n## Inspect Type Information\nTypeScript when `emitDecoratorMetadata` enabled, TypeScript will add type information during compile time. This make it possible to extract typescript type information during runtime. \n\n> **CAVEAT**\n>  \n> TypeScript `emitDecoratorMetadata` has some limitation. \n> * Declaration should have at least one decorator to get metadata (type information)\n> * Array element type information not included. \n> * Generic type information not included.\n\nBased on limitation above its required at least have one decorator to make tinspector to be able to extract type information: \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    awesome(multiply:number): number { return 1 }\n}\n\nconst metadata = reflect(Awesome)\n```\n\ntinspector will be able to get type information of the method's return type and parameters of the `awesome` method above. Note that we applied `@reflect.noop()` decorator on the `awesome` method. `@reflect.noop()` does nothing except to force TypeScript to emit metadata information.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.noop()\n    aweProperty:number\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get type information of a property. \n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.noop()\nclass Awesome {\n    constructor(multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\nAbove code showing that we able to get type information of parameters of the constructor, by applying decorator on the class level. \n\n## Inspect Array and Generic Type\nTo get type information of an Array and Generic type its required to use `@reflect.type()` decorator and provide the type on the callback parameter.\n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Awesome {\n    @reflect.type([Number])\n    awesome(multiply:number): Array<number> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we able to get method's return type information by providing `@reflect.type([Number])`. Note that the `[Number]` is an array of `Number`. \n\n```typescript \nimport reflect from \"tinspector\"\n\nclass Option { \n    data:string\n}\n\nclass Awesome {\n    @reflect.type(Option)\n    awesome(multiply:number): Partial<Option> {}\n}\n\nconst metadata = reflect(Awesome)\n```\n\nWe will be able to get generic type information such as `Partial`, `Required` etc by applying `@reflect.type()` like above. \n\n> If you receive `ReferenceError: <type name> is not defined` error, thats mean you use `@reflect.type(MyType)` prior than its declaration. To solve this issue you can use callback `@reflect.type(x => MyType)` or `@reflect.type(x => [MyType])` for array type.\n\n## Inspect Generic Class Information\nWith above trick its possible to get generic type information in a generic class members with some extra configuration below\n\n```typescript\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    awesome(@reflect.type(\"T\") par: T, @reflect.type(\"U\") par2: U) {}\n}\n\n@generic.type(Number, String)\nclass Awesome extends SuperAwesome<Number, String> { }\n\nconst metadata = reflect(Awesome)\n```\n\nAbove code showing that we add a specialized decorator `@generic.template()` to define generic template type. We also defined data type of the generic parameters using `@reflect.type()` decorator. Next on the inherited class we specify `@generic.type()` to define types replace the generic template. Note that the order of the parameter on `@generic.template()` and `@generic.type()` is important.\n\n<!-- tinspector support more complex scenario regarding generic data type, for example if your property or parameter uses generic data type type which its parameter uses its class generic parameter like below: \n\n```typescript\n@generic.template(\"T\")\nclass MyPropertyType {\n\n}\n@generic.template(\"T\", \"U\")\nclass SuperAwesome<T, U> {\n    \n}\n``` -->\n\n\n\n## Inspect Parameter Properties\nTypeScript has parameter properties feature, which make it possible to use constructor parameter as property. tinspector able to extract parameter properties type information by using `@reflect.parameterProperties()` decorator.\n\n```typescript \nimport reflect from \"tinspector\"\n\n@reflect.parameterProperties()\nclass Awesome {\n    constructor(public multiply:number){}\n}\n\nconst metadata = reflect(Awesome)\n```\n\n## Custom Decorator \nTinspector able to extract classes/methods/properties/parameters decorated with predefined decorators. There are predefined decorators should be use to be able for Tinspector to inspect the decorators\n\n| Decorator           | Description                                                                          |\n| ------------------- | ------------------------------------------------------------------------------------ |\n| `decorateClass`     | Decorate class with object specified in parameter                                    |\n| `decorateProperty`  | Decorate property with object specified in parameter                                 |\n| `decorateMethod`    | Decorate method with object specified in parameter                                   |\n| `decorateParameter` | Decorate parameter with object specified in parameter                                |\n| `decorate`          | Decorate any (class, property, method, parameter) with object specified in parameter |\n| `mergeDecorator`    | Merge multiple decorators into one, useful on creating custom decorator               |\n\nExample usage\n\n```typescript\nimport { decorateClass, decorateProperty } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" })\nclass Awesome {\n    @decorateProperty({ message: \"awesome!\" })\n    awesome: number = 10\n}\n```\n\nParameter passed on each decorator can be any object contains value, methods etc, those value will be returned when the class metadata extracted.\n\nCreate your own custom decorator by creating function returns decorator above\n\n```typescript\nimport { decorateMethod } from \"tinspector\"\n\n// create custom decorator\nfunction cache(duration:number){\n    return decorateMethod({ type: \"Cache\", duration })\n}\n\nclass Awesome{\n    @cache() // use it like usual decorator\n    awesome(){}\n}\n```\n\nUse `mergeDecorator` to combine multiple decorator on custom decorator\n\n\n```typescript\nimport { decorateMethod, mergeDecorator } from \"tinspector\"\n\n// create custom decorator\nfunction cacheAndDelay(duration:number){\n    return mergeDecorator([\n        decorateMethod({ type: \"Cache\", duration }), \n        decorateMethod({ type: \"Delay\", duration })\n    ])\n}\n```\n\n## Decorator Option (Inheritance, Allow Multiple)\nDecorator can be further configured to match the behavior you need like below.\n\n```typescript\ndecorateMethod(<data>, <option>)\n```\n\nOption is a simple object with properties: \n\n* `inherit` `Boolean` If `false` decorator will not be merged on the derived class. Default `true` \n* `allowMultiple` `Boolean` If `false` throw error when multiple decorator applied on class. Also when set `false` will prevent super class decorator being merged into derived class when already exists. When set `false`, decorator required to have `DecoratorId` property to identify the similar decorator.\n* `applyTo` `String` or `String[]` apply decorator into the specified properties or methods.\n* `removeApplied` `Boolean` Remove applied decorator using `applyTo` on the class scope. Default `true`.\n\n\nExample disable decorator inheritance\n\n```typescript\n@decorateClass({ log:true }, { inherit: false })\nclass Awesome {\n    awesome(){}\n}\n\n// { log: true} will not inherited on this class\nclass IamAwesome extends Awesome{ }\n```\n\nExample disable multiple decorator on inheritance\n\n```typescript\nimport { DecoratorId, decorateClass } from \"tinspector\"\n\nfunction log(){\n    return @decorateClass({ [DecoratorId]: \"logging\",  log:true }, { allowMultiple: false })\n}\n\n@log()\nclass Awesome {\n    awesome(){}\n}\n\n// parent decorator will not merged\n// guaranteed derived class only have single decorator with specific ID\n@log()\nclass IamAwesome extends Awesome{ }\n```\n\n## Apply Decorator from Class\nSometime its required to add decorator into specific methods or properties from class. This is useful when you want to decorate specific super class method from derived class. Use `applyTo` and `removeApplied` properties on decorator option to control decorator to be copied into the properties or methods.\n\n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\" })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nBy specifying `{ applyTo: \"myMethod\" }` on the decorator option will make the decorator copied into the `myMethod` method, while the decorator removed from the class. \n\n```typescript\nimport { decorateClass } from \"tinspector\"\n\n@decorateClass({ message: \"hello world\" }, { applyTo: \"myMethod\", removeApplied: false })\nclass Awesome {\n    myMethod(){}\n}\n```\n\nAbove code will copy decorator into `myMethod` method but keep the decorator on the class.\n\n## Flush Cache \nBy default reflect process cached globally for performance reason. But in some case if you modify the class preferences by adding a new decorator etc, your new update will not returned until you flush the cache.\n\n```typescript\nreflect.flush(Type)\n```","readmeFilename":"readme.md","_id":"tinspector@3.2.3-canary.kik3wda7.0","_nodeVersion":"12.20.0","_npmVersion":"lerna/3.22.1/node@v12.20.0+x64 (linux)","dist":{"integrity":"sha512-JYrs+oAWVkhtsiW3A75OsYyvog9TFx6IbdgeSlVJFqg+hCF0svaYB2mXT1fX/ha1qU686sS34o1P9kJX9AlX/Q==","shasum":"fc6d7f995fa5c9ce2549ab64989a6b0fdee9ae04","tarball":"https://registry.npmjs.org/tinspector/-/tinspector-3.2.3-canary.kik3wda7.0.tgz","fileCount":25,"unpackedSize":71830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf00TXCRA9TVsSAnZWagAAiK8P/jNly80uU7134y8LHV7q\nlJVn0H62AtZdfd+TEInQ+AQ97Tws2dW/jkP3KHBz1E8WXyh7heDWsubG9yCn\nSrqSK2D+uEJmL3uir6B8xfu3i+QbtE+iKDrEKxapg3PWoC3cfF6lc6n2khPN\noFnzOuqCKmQY8XjnVTVXLwnZdUMAZCLj7/AEI/kUaogHwD/VTajaCskAC/tD\nSy5GPB6IVSmv6yWciO0K819FudGJoYvUWEKl3Xe2ljsFHG0fA2OMGBunHLhM\nsd+v8nbnGX+zdHnoUmp/wwR0lpKvA+0cmEGGPyvBBC4B1zmbgFhZM31/iFKb\nYIQjmrfoIzjXd7ejm7mCBNf3+eIk1jUM79wAFY154KCGBtYgVHzPkPKWn60r\nrkHrNK3ugGloIP9KU6huYs55tjYio94FhElKIQbNU7p/qAJiCZv1m1cMQrZO\nKHp7ywA7f/i2ABKbalfCvs8qgl0mjWfLLNRIUL6F6FwyG8m/TFVCidAx3eqC\nuSxNqUKJUAdexZ/SWu1mqrX0y3Jj7OLB892VlLhDJPGxhJz0VDEFkadXBlT3\nOp6Seg5XzpBKV2YDflFTlQa4Pt5qsItamEOhzjtUfs4GCBohXY5H7Omd/RDf\ndV3RnrREXI/vMb4I9MdJ9/ZYC04nrG/fcYUjfKUkGLwzkfHP32527g/pUjFf\nPCqS\r\n=GmJH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqB8wOwMBljE+fiWmQr5/AQSJQIMBpEmHBqrCvmbWJjQIgbq/ZReAzb9ilac4AkJReziBIiRzqlG+rlL83GmgqhJ8="}]},"_npmUser":{"name":"ktutnik","email":"ktutnik@gmail.com"},"directories":{},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tinspector_3.2.3-canary.kik3wda7.0_1607681238722_0.3325669122079544"},"_hasShrinkwrap":false}},"time":{"created":"2018-07-08T03:08:54.465Z","1.4.0-alpha.b123904d":"2018-07-08T03:08:54.528Z","modified":"2022-06-27T06:56:58.652Z","1.4.0-alpha.79af24d3":"2018-07-15T22:02:33.660Z","1.4.0-alpha.caa0578b":"2018-07-15T23:22:45.580Z","2.0.0-0":"2019-01-17T21:10:25.078Z","2.0.0-1":"2019-01-17T21:43:30.692Z","2.0.0-2":"2019-01-18T10:33:41.398Z","2.0.0-3":"2019-01-18T12:11:05.954Z","2.0.0":"2019-01-21T06:05:46.415Z","2.1.0":"2019-01-30T07:31:32.363Z","2.1.1":"2019-01-30T10:59:26.698Z","2.1.2":"2019-02-02T07:28:30.622Z","2.2.0":"2019-03-15T23:33:26.951Z","2.2.1":"2019-04-01T06:44:28.367Z","2.2.2":"2019-06-25T22:11:54.463Z","2.2.3":"2019-09-14T01:28:58.240Z","2.2.5":"2019-09-24T03:28:42.668Z","2.2.6":"2019-10-04T09:45:54.449Z","2.2.7":"2019-10-04T10:03:18.329Z","2.2.8":"2019-12-01T06:12:21.315Z","2.2.9":"2019-12-02T00:26:43.493Z","2.2.10":"2020-02-03T14:05:22.045Z","2.3.0":"2020-02-29T04:31:27.050Z","2.3.1":"2020-03-15T07:02:46.810Z","3.0.0":"2020-04-26T20:20:42.418Z","3.0.1":"2020-04-27T23:23:37.849Z","3.0.2":"2020-04-29T21:57:44.994Z","3.0.3":"2020-05-09T04:43:33.418Z","3.0.4":"2020-05-12T04:57:10.032Z","3.0.5":"2020-05-16T07:06:14.683Z","3.0.6":"2020-05-18T02:03:38.855Z","3.0.7":"2020-05-27T06:38:36.014Z","3.0.8":"2020-05-27T08:54:55.717Z","3.1.0":"2020-05-28T19:57:07.588Z","3.1.1":"2020-06-06T22:15:22.184Z","3.1.2":"2020-06-07T00:00:09.132Z","3.2.0":"2020-06-11T06:37:12.581Z","3.2.1":"2020-06-13T03:44:10.095Z","3.2.2":"2020-06-21T07:33:49.686Z","3.2.3-canary1592806142.0":"2020-06-22T06:09:04.606Z","3.2.3-canary1592877058.0":"2020-06-23T01:51:01.423Z","3.2.3-canary1592886862.0":"2020-06-23T04:34:25.066Z","3.2.3-canary1593026645.0":"2020-06-24T19:24:07.995Z","3.2.3-canary1593069049.0":"2020-06-25T07:10:53.079Z","3.2.3-canary1593125083.0":"2020-06-25T22:44:46.523Z","3.2.3-canary.kbwv88am.0":"2020-06-26T23:47:39.556Z","3.2.3-canary.kbwxgwmn.0":"2020-06-27T00:50:24.202Z","3.2.3-canary.kbwy7dnv.0":"2020-06-27T01:10:58.927Z","3.2.3-canary.kbx8uhbt.0":"2020-06-27T06:08:53.026Z","3.2.3-canary.kby6baek.0":"2020-06-27T21:45:44.861Z","3.2.3-canary.kbyejgob.0":"2020-06-28T01:36:03.066Z","3.2.3-canary.kbyvfeer.0":"2020-06-28T09:28:47.683Z","3.2.3-canary.kc1bv7t9.0":"2020-06-30T02:44:30.844Z","3.2.3-canary.kc1j62zf.0":"2020-06-30T06:08:55.427Z","3.2.3-canary.kc1pwqwc.0":"2020-06-30T09:17:38.013Z","3.2.3-canary.kc6u1s8b.0":"2020-07-03T23:12:21.428Z","3.2.3-canary.kc6zqei2.0":"2020-07-04T01:51:28.125Z","3.2.3-canary.kc7ailpb.0":"2020-07-04T06:53:19.829Z","3.2.3-canary.kciolr74.0":"2020-07-12T06:13:09.905Z","3.2.3-canary.kckaf5hv.0":"2020-07-13T09:11:39.028Z","3.2.3-canary.kcras9pq.0":"2020-07-18T06:56:14.446Z","3.2.3-canary.kcrinrbo.0":"2020-07-18T10:36:41.192Z","3.2.3-canary.kcs5b8ny.0":"2020-07-18T21:10:47.870Z","3.2.3-canary.kcs8mlx5.0":"2020-07-18T22:43:37.210Z","3.2.3-canary.kctvam2m.0":"2020-07-20T02:05:55.150Z","3.2.3-canary.kcvksj6x.0":"2020-07-21T06:47:27.540Z","3.2.3-canary.kcwgd771.0":"2020-07-21T21:31:19.853Z","3.2.3-canary.kd1392pj.0":"2020-07-25T03:23:03.433Z","3.2.3-canary.kd13oe59.0":"2020-07-25T03:34:57.935Z","3.2.3-canary.kd18a18n.0":"2020-07-25T05:43:46.100Z","3.2.3-canary.kd1i13g6.0":"2020-07-25T10:16:45.414Z","3.2.3-canary.kd2p0nhi.0":"2020-07-26T06:20:07.992Z","3.2.3-canary.kd3mpv1u.0":"2020-07-26T22:03:31.500Z","3.2.3-canary.kd3rqvd4.0":"2020-07-27T00:24:16.884Z","3.2.3-canary.kd6wewq6.0":"2020-07-29T04:58:15.470Z","3.2.3-canary.kdf0lwtn.0":"2020-08-03T21:17:49.906Z","3.2.3-canary.kdgfdc3a.0":"2020-08-04T20:58:50.179Z","3.2.3-canary.kdi5mwkd.0":"2020-08-06T02:01:52.793Z","3.2.3-canary.kdi9bq15.0":"2020-08-06T03:45:09.864Z","3.2.3-canary.kdid6yqc.0":"2020-08-06T05:33:26.018Z","3.2.3-canary.kdjdfg7t.0":"2020-08-06T22:27:48.410Z","3.2.3-canary.kdjj7hrf.0":"2020-08-07T01:09:34.469Z","3.2.3-canary.kdkqxkys.0":"2020-08-07T21:33:35.341Z","3.2.3-canary.kdqpr7yp.0":"2020-08-12T01:47:16.036Z","3.2.3-canary.kdtej428.0":"2020-08-13T22:56:20.174Z","3.2.3-canary.kdtibqoo.0":"2020-08-14T00:42:34.825Z","3.2.3-canary.kdvw2za0.0":"2020-08-15T16:43:13.228Z","3.2.3-canary.ke8zqwdv.0":"2020-08-24T20:46:48.060Z","3.2.3-canary.ke91wrl1.0":"2020-08-24T21:47:21.165Z","3.2.3-canary.ke93q61k.0":"2020-08-24T22:38:12.731Z","3.2.3-canary.keao8m4o.0":"2020-08-26T01:00:11.831Z","3.2.3-canary.keaththw.0":"2020-08-26T03:27:19.866Z","3.2.3-canary.kebz3sj5.0":"2020-08-26T22:52:08.659Z","3.2.3-canary.kedxkqhh.0":"2020-08-28T07:44:52.504Z","3.2.3-canary.keeqwum9.0":"2020-08-28T21:26:06.499Z","3.2.3-canary.keexw8ts.0":"2020-08-29T00:41:35.738Z","3.2.3-canary.kef2e3lg.0":"2020-08-29T02:47:26.928Z","3.2.3-canary.kef5312a.0":"2020-08-29T04:02:49.490Z","3.2.3-canary.kefh7qik.0":"2020-08-29T09:42:24.482Z","3.2.3-canary.kejh0j48.0":"2020-09-01T04:47:52.869Z","3.2.3-canary.kel7fsyz.0":"2020-09-02T09:55:21.335Z","3.2.3-canary.kela2rem.0":"2020-09-02T11:09:11.919Z","3.2.3-canary.kenou8nl.0":"2020-09-04T03:38:02.346Z","3.2.3-canary.keoswy6l.0":"2020-09-04T22:19:51.688Z","3.2.3-canary.kepjwxp9.0":"2020-09-05T10:55:41.034Z","3.2.3-canary.keqn8ee3.0":"2020-09-06T05:16:20.840Z","3.2.3-canary.kerx6yap.0":"2020-09-07T02:42:55.703Z","3.2.3-canary.key2i6eu.0":"2020-09-11T09:58:15.274Z","3.2.3-canary.keyz518l.0":"2020-09-12T01:11:49.989Z","3.2.3-canary.kezbpkd4.0":"2020-09-12T07:03:42.049Z","3.2.3-canary.kezj7wpq.0":"2020-09-12T10:33:55.489Z","3.2.3-canary.kf1ngfd8.0":"2020-09-13T22:08:03.501Z","3.2.3-canary.kf32nfdw.0":"2020-09-14T22:01:11.191Z","3.2.3-canary.kf3gt31v.0":"2020-09-15T04:37:28.955Z","3.2.3-canary.kf6gpx8m.0":"2020-09-17T06:58:22.577Z","3.2.3-canary.kf6lwncy.0":"2020-09-17T09:23:31.832Z","3.2.3-canary.kf6ox8zq.0":"2020-09-17T10:47:58.582Z","3.2.3-canary.kf83flsl.0":"2020-09-18T10:21:56.244Z","3.2.3-canary.kf8yuiqx.0":"2020-09-19T01:01:19.892Z","3.2.3-canary.kf9he5u8.0":"2020-09-19T09:40:29.338Z","3.2.3-canary.kfdk5pvu.0":"2020-09-22T06:08:59.200Z","3.2.3-canary.kfg7x8ie.0":"2020-09-24T02:49:46.324Z","3.2.3-canary.kfku9xyl.0":"2020-09-27T08:26:35.638Z","3.2.3-canary.kflwpa3o.0":"2020-09-28T02:22:16.778Z","3.2.3-canary.kfm9pqez.0":"2020-09-28T08:26:32.716Z","3.2.3-canary.kfnbyb01.0":"2020-09-29T02:16:58.378Z","3.2.3-canary.kfndaw7c.0":"2020-09-29T02:54:45.352Z","3.2.3-canary.kfok0ubn.0":"2020-09-29T22:50:39.767Z","3.2.3-canary.kg3h9ub9.0":"2020-10-10T09:30:13.200Z","3.2.3-canary.kg3j85u4.0":"2020-10-10T10:24:54.140Z","3.2.3-canary.kg45m6uw.0":"2020-10-10T20:51:40.051Z","3.2.3-canary.kg4vj92q.0":"2020-10-11T08:57:12.875Z","3.2.3-canary.kg68uhyf.0":"2020-10-12T07:57:38.660Z","3.2.3-canary.kg6g8g5u.0":"2020-10-12T11:24:31.996Z","3.2.3-canary.kg736xd2.0":"2020-10-12T22:07:07.282Z","3.2.3-canary.kg8ugq0v.0":"2020-10-14T03:38:20.161Z","3.2.3-canary.kg9x6kqr.0":"2020-10-14T21:42:11.698Z","3.2.3-canary.kgbtqzo0.0":"2020-10-16T05:41:37.988Z","3.2.3-canary.kgc219pd.0":"2020-10-16T09:33:34.480Z","3.2.3-canary.kgd3ozpo.0":"2020-10-17T03:07:46.878Z","3.2.3-canary.kgdlm368.0":"2020-10-17T11:29:24.903Z","3.2.3-canary.kgdmgzlm.0":"2020-10-17T11:53:26.236Z","3.2.3-canary.kgea9t96.0":"2020-10-17T22:59:42.580Z","3.2.3-canary.kgelgslo.0":"2020-10-18T04:13:04.023Z","3.2.3-canary.kgevjcoc.0":"2020-10-18T08:54:59.006Z","3.2.3-canary.kgg7oarz.0":"2020-10-19T07:22:31.788Z","3.2.3-canary.kgm10qxk.0":"2020-10-23T09:02:52.233Z","3.2.3-canary.kgm5iq6j.0":"2020-10-23T11:08:49.398Z","3.2.3-canary.kgrcn168.0":"2020-10-27T02:27:00.279Z","3.2.3-canary.kgsjdgwx.0":"2020-10-27T22:23:15.858Z","3.2.3-canary.kgsps60c.0":"2020-10-28T01:22:40.227Z","3.2.3-canary.kgxa6f2k.0":"2020-10-31T06:04:41.151Z","3.2.3-canary.kgxnbu9k.0":"2020-10-31T12:12:49.197Z","3.2.3-canary.kgy8ctsk.0":"2020-10-31T22:01:27.355Z","3.2.3-canary.kgyal5xs.0":"2020-10-31T23:03:55.733Z","3.2.3-canary.kgydir3d.0":"2020-11-01T00:26:02.159Z","3.2.3-canary.kgzo7o56.0":"2020-11-01T22:13:06.550Z","3.2.3-canary.kgzuclth.0":"2020-11-02T01:04:54.686Z","3.2.3-canary.kgzwhr7g.0":"2020-11-02T02:04:54.134Z","3.2.3-canary.kh1h0fly.0":"2020-11-03T04:27:04.492Z","3.2.3-canary.kh1tdkjc.0":"2020-11-03T10:13:12.408Z","3.2.3-canary.kh1ut1x4.0":"2020-11-03T10:53:14.511Z","3.2.3-canary.kh2ho8dd.0":"2020-11-03T21:33:21.159Z","3.2.3-canary.kh2j3gf1.0":"2020-11-03T22:13:10.771Z","3.2.3-canary.kh2jnpxg.0":"2020-11-03T22:28:56.316Z","3.2.3-canary.kh2k6f0d.0":"2020-11-03T22:43:28.049Z","3.2.3-canary.kh2lwwtd.0":"2020-11-03T23:32:04.412Z","3.2.3-canary.kh2p7j3o.0":"2020-11-04T01:04:18.401Z","3.2.3-canary.kh4ew4ru.0":"2020-11-05T05:51:02.832Z","3.2.3-canary.kh5ddq10.0":"2020-11-05T21:56:30.568Z","3.2.3-canary.kh5h50n0.0":"2020-11-05T23:41:42.612Z","3.2.3-canary.kh5jla6k.0":"2020-11-06T00:50:21.001Z","3.2.3-canary.kh5lyii8.0":"2020-11-06T01:56:37.665Z","3.2.3-canary.kh61az31.0":"2020-11-06T09:06:13.052Z","3.2.3-canary.khbdcr5h.0":"2020-11-10T02:42:22.415Z","3.2.3-canary.khchhyyz.0":"2020-11-10T21:26:10.136Z","3.2.3-canary.khdxsl4k.0":"2020-11-11T21:50:05.625Z","3.2.3-canary.khelfoev.0":"2020-11-12T08:51:53.797Z","3.2.3-canary.khg09zf1.0":"2020-11-13T08:35:08.905Z","3.2.3-canary.khiras28.0":"2020-11-15T06:47:08.062Z","3.2.3-canary.khy4xbmr.0":"2020-11-26T01:05:07.587Z","3.2.3-canary.khye3mjx.0":"2020-11-26T05:21:58.246Z","3.2.3-canary.ki2idjwy.0":"2020-11-29T02:32:44.324Z","3.2.3-canary.ki34emgi.778":"2020-11-29T12:49:28.232Z","3.2.3-canary.ki3i90va.0":"2020-11-29T19:16:59.253Z","3.2.3-canary.ki3imu3t.0":"2020-11-29T19:27:43.264Z","3.2.3-canary.ki3w8w7z.0":"2020-11-30T01:48:47.621Z","3.2.3-canary.ki3x3sog.0":"2020-11-30T02:12:49.541Z","3.2.3-canary.ki6vxtqr.0":"2020-12-02T04:03:30.096Z","3.2.3-canary.ki7l9jjj.0":"2020-12-02T15:52:27.715Z","3.2.3-canary.kibdskyc.0":"2020-12-05T07:34:23.085Z","3.2.3-canary.kicmb1c7.0":"2020-12-06T04:20:27.326Z","3.2.3-canary.kijl4du6.0":"2020-12-11T01:21:40.247Z","3.2.3-canary.kijvk681.0":"2020-12-11T06:13:53.717Z","3.2.3-canary.kik3wda7.0":"2020-12-11T10:07:18.902Z"},"maintainers":[{"name":"ktutnik","email":"ktutnik@gmail.com"}],"description":"TypeScript type inspector","keywords":["Reflection","Reflect","Metadata"],"author":{"name":"Ketut Sandiarsa"},"license":"MIT","readme":"","readmeFilename":""}