New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

tinspector

Package Overview
Dependencies
Maintainers
1
Versions
194
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tinspector - npm Package Compare versions

Comparing version 2.3.1 to 3.0.0

.github/workflows/ubuntu.yml

137

lib/index.d.ts
import "reflect-metadata";
export declare const DecoratorOption: unique symbol;
export declare const DecoratorId: unique symbol;
declare type Class = new (...arg: any[]) => any;
export declare type DecoratorTargetType = "Method" | "Class" | "Parameter" | "Property" | "Constructor";
export interface Decorator {
targetType: DecoratorTargetType;
target: string;
value: any;
inherit: boolean;
allowMultiple: boolean;
}
export interface ParamDecorator extends Decorator {
targetType: "Parameter";
targetIndex: number;
}
export declare type Reflection = ParameterReflection | FunctionReflection | PropertyReflection | MethodReflection | ClassReflection | ObjectReflection;
export interface ReflectionBase {
kind: string;
name: string;
}
export interface ParameterReflection extends ReflectionBase {
kind: "Parameter";
properties: string | {
[key: string]: string[];
};
decorators: any[];
type?: any;
typeClassification?: "Class" | "Array" | "Primitive";
}
export interface PropertyReflection extends ReflectionBase {
kind: "Property";
decorators: any[];
type?: any;
get: any;
set: any;
typeClassification?: "Class" | "Array" | "Primitive";
}
export interface MethodReflection extends ReflectionBase {
kind: "Method";
parameters: ParameterReflection[];
returnType: any;
decorators: any[];
typeClassification?: "Class" | "Array" | "Primitive";
}
export interface ConstructorReflection extends ReflectionBase {
kind: "Constructor";
parameters: ParameterReflection[];
}
export interface FunctionReflection extends ReflectionBase {
kind: "Function";
parameters: ParameterReflection[];
returnType: any;
}
export interface ClassReflection extends ReflectionBase {
kind: "Class";
ctor: ConstructorReflection;
methods: MethodReflection[];
properties: PropertyReflection[];
decorators: any[];
type: Class;
typeClassification?: "Class" | "Array" | "Primitive";
}
export interface ObjectReflection extends ReflectionBase {
kind: "Object";
members: Reflection[];
}
export interface ArrayDecorator {
kind: "Array";
type: Class;
}
export interface TypeDecorator {
kind: "Override";
type: Class;
info?: string;
}
export interface PrivateDecorator {
kind: "Ignore";
}
export interface DecoratorOption {
inherit?: boolean;
allowMultiple?: boolean;
}
export declare type PropertyDecorator = (target: Object, propertyKey: string | symbol, ...index: any[]) => void;
export declare const DECORATOR_KEY = "plumier.key:DECORATOR";
export declare const DESIGN_TYPE = "design:type";
export declare const DESIGN_PARAMETER_TYPE = "design:paramtypes";
export declare const DESIGN_RETURN_TYPE = "design:returntype";
export declare function getParameterNames(fn: Function): (string | {
[key: string]: string[];
})[];
export declare function getMethodParameters(fn: Class, method: string): (string | {
[key: string]: string[];
})[];
export declare function getConstructorParameters(fn: Class): (string | {
[key: string]: string[];
})[];
export declare function getMembers(fun: Function): string[];
export declare function useCache<K, P extends any[], R>(cache: Map<K, R>, fn: (...args: P) => R, getKey: (...args: P) => K): (...args: P) => R;
export declare function decorateParameter(callback: ((target: Class, name: string, index: number) => any), option?: DecoratorOption): ParameterDecorator;
export declare function decorateParameter(data: any, option?: DecoratorOption): ParameterDecorator;
export declare function decorateMethod(callback: ((target: Class, name: string) => any), option?: DecoratorOption): MethodDecorator;
export declare function decorateMethod(data: any, option?: DecoratorOption): MethodDecorator;
export declare function decorateProperty(callback: ((target: Class, name: string, index?: any) => any), option?: DecoratorOption): PropertyDecorator;
export declare function decorateProperty(data: any, option?: DecoratorOption): PropertyDecorator;
export declare function decorateClass(callback: ((target: Class) => any), option?: DecoratorOption): ClassDecorator;
export declare function decorateClass(data: any, option?: DecoratorOption): ClassDecorator;
export declare function decorate(data: any | ((...args: any[]) => any), targetTypes?: DecoratorTargetType[], option?: Partial<DecoratorOption>): (...args: any[]) => void;
export declare function mergeDecorator(...fn: (ClassDecorator | PropertyDecorator | ParamDecorator | MethodDecorator)[]): (...args: any[]) => void;
/**
* Reflect module
* @param path module name
*/
export declare function reflect(path: string): ObjectReflection;
export declare namespace reflect {
var noop: () => (...args: any[]) => void;
var ignore: () => (...args: any[]) => void;
var type: (type: Class | Class[], info?: string | undefined) => (...args: any[]) => void;
var array: (type: Class) => (...args: any[]) => void;
var parameterProperties: () => ClassDecorator;
}
/**
* Reflect class
* @param classType Class
*/
export declare function reflect(classType: Class): ClassReflection;
export declare namespace reflect {
var noop: () => (...args: any[]) => void;
var ignore: () => (...args: any[]) => void;
var type: (type: Class | Class[], info?: string | undefined) => (...args: any[]) => void;
var array: (type: Class) => (...args: any[]) => void;
var parameterProperties: () => ClassDecorator;
}
export * from "./types";
export * from "./decorators";
export * from "./helpers";
import { reflect } from "./reflect";
export { reflect };
export default reflect;
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
const acorn_1 = require("acorn");
/* ---------------------------------------------------------------- */
/* --------------------------- TYPES ------------------------------ */
/* ---------------------------------------------------------------- */
exports.DecoratorOption = Symbol("tinspector:decoratorOption");
exports.DecoratorId = Symbol("tinspector:decoratorId");
exports.DECORATOR_KEY = "plumier.key:DECORATOR";
exports.DESIGN_TYPE = "design:type";
exports.DESIGN_PARAMETER_TYPE = "design:paramtypes";
exports.DESIGN_RETURN_TYPE = "design:returntype";
const cacheStore = new Map();
/* ---------------------------------------------------------------- */
/* --------------------------- HELPERS ---------------------------- */
/* ---------------------------------------------------------------- */
function getNode(node, criteria) {
if (criteria(node))
return node;
if (!node.body)
return;
if (Array.isArray(node.body)) {
for (const child of node.body) {
const result = getNode(child, criteria);
if (result)
return result;
}
}
return getNode(node.body, criteria);
}
function getNamesFromAst(nodes) {
const getName = (node) => {
if (node.type === "Identifier")
return node.name;
if (node.type === "AssignmentPattern")
return node.left.name;
if (node.type === "RestElement")
return node.argument.name;
if (node.type === "Property") {
if (node.value.type === "Identifier")
return node.value.name;
else {
const result = {};
result[node.key.name] = getName(node.value);
return result;
}
}
//if (node.type === "ObjectPattern") {
return node.properties.map((x) => getName(x));
//}
};
return nodes.map(x => getName(x)).filter((x) => !!x);
}
function getParameterNames(fn) {
try {
const body = fn.toString();
const ast = acorn_1.parse(body);
return getNamesFromAst(ast.body[0].params);
}
catch (_a) {
return [];
}
}
exports.getParameterNames = getParameterNames;
function getMethodParameters(fn, method) {
const body = fn.toString();
const ast = acorn_1.parse(body);
const ctor = getNode(ast, x => x.type === "MethodDefinition" && x.kind === "method" && x.key.name === method);
return getNamesFromAst(ctor ? ctor.value.params : []);
}
exports.getMethodParameters = getMethodParameters;
function getConstructorParameters(fn) {
const body = fn.toString();
const ast = acorn_1.parse(body);
const ctor = getNode(ast, x => x.type === "MethodDefinition" && x.kind === "constructor");
return getNamesFromAst(ctor ? ctor.value.params : []);
}
exports.getConstructorParameters = getConstructorParameters;
function isConstructor(value) {
return ("" + value).indexOf("class") == 0;
}
function getType(object) {
if (typeof object === "function") {
if (isConstructor(object))
return "Class";
else
return "Function";
}
else if (Array.isArray(object))
return "Array";
else if (typeof object === "boolean"
|| typeof object === "number"
|| typeof object === "bigint"
|| typeof object === "string"
|| typeof object === "symbol"
|| typeof object === "undefined")
return "Value";
else
return "Object";
}
function getMembers(fun) {
const isGetter = (name) => Object.getOwnPropertyDescriptor(fun.prototype, name).get;
const isSetter = (name) => Object.getOwnPropertyDescriptor(fun.prototype, name).set;
const isFunction = (name) => typeof fun.prototype[name] === "function";
const members = Object.getOwnPropertyNames(fun.prototype)
.filter(name => isGetter(name) || isSetter(name) || isFunction(name));
const properties = (Reflect.getOwnMetadata(exports.DECORATOR_KEY, fun) || [])
.filter((x) => x.targetType === "Property")
.map((x) => x.target);
const names = members.concat(properties)
.filter(name => name !== "constructor" && !~name.indexOf("__"));
return [...new Set(names)];
}
exports.getMembers = getMembers;
function isCustomClass(type) {
switch (type) {
case Boolean:
case String:
case Array:
case Number:
case Object:
case Date:
return false;
default:
return true;
}
}
function getTypeClassification(type) {
if (type === undefined)
return undefined;
else if (Array.isArray(type))
return "Array";
else if (isCustomClass(type))
return "Class";
else
return "Primitive";
}
function addDecorator(target, decorator) {
const decorators = Reflect.getOwnMetadata(exports.DECORATOR_KEY, target) || [];
decorators.push(decorator);
Reflect.defineMetadata(exports.DECORATOR_KEY, decorators, target);
}
function getDecorators(target) {
return Reflect.getOwnMetadata(exports.DECORATOR_KEY, target) || [];
}
function getDecoratorIterator(fn) {
return (type, target, index) => getDecorators(fn)
.filter(x => {
const par = x;
return x.targetType === type && x.target === target
&& (par.targetIndex === undefined || par.targetIndex === index);
})
.map(x => {
const { value, inherit, allowMultiple } = x;
value[exports.DecoratorOption] = { inherit, allowMultiple };
return value;
});
}
function getReflectionType(decorators, type) {
const array = decorators.find((x) => x.kind === "Array");
const override = decorators.find((x) => x.kind === "Override");
if (override)
return override.type;
else if (array)
return [array.type];
else if (type === Array)
return [Object];
else
return type;
}
function useCache(cache, fn, getKey) {
return (...args) => {
const key = getKey(...args);
const result = cache.get(key);
if (!!result)
return result;
else {
const newResult = fn(...args);
cache.set(key, newResult);
return newResult;
}
};
}
exports.useCache = useCache;
function printDestruct(params) {
const result = [];
for (const key in params) {
const par = params[key];
if (typeof par === "string")
result.push(par);
else {
const key = Object.keys(par)[0];
result.push(`${key}: ${printDestruct(par[key])}`);
}
}
return `{ ${result.join(", ")} }`;
}
function isIncluded(x) {
return !x.decorators.some((x) => x.kind === "Ignore");
}
function decorateParameter(data, option) {
return decorate(data, ["Parameter"], option);
}
exports.decorateParameter = decorateParameter;
function decorateMethod(data, option) {
return decorate(data, ["Method"], option);
}
exports.decorateMethod = decorateMethod;
function decorateProperty(data, option) {
return decorate(data, ["Property", "Parameter"], option);
}
exports.decorateProperty = decorateProperty;
function decorateClass(data, option) {
return decorate(data, ["Class"], option);
}
exports.decorateClass = decorateClass;
function decorate(data, targetTypes = [], option) {
const throwIfNotOfType = (target) => {
if (targetTypes.length > 0 && !targetTypes.some(x => x === target))
throw new Error(`Reflect Error: Decorator of type ${targetTypes.join(", ")} applied into ${target}`);
};
const opt = Object.assign({ allowMultiple: true, inherit: true }, option);
return (...args) => {
const theData = typeof data === "function" ? data(...args) : data;
if (!opt.allowMultiple && !theData[exports.DecoratorId]) {
const ctorName = isConstructor(args[0]) ? args[0].name : args[0].constructor.name;
throw new Error(`Reflect Error: Decorator with allowMultiple set to false must have DecoratorId property in ${ctorName}`);
}
//class decorator
if (args.length === 1) {
throwIfNotOfType("Class");
return addDecorator(args[0], Object.assign({ targetType: "Class", target: args[0].name, value: typeof data === "function" ? data(args[0]) : data }, opt));
}
//parameter decorator
if (args.length === 3 && typeof args[2] === "number") {
throwIfNotOfType("Parameter");
const isCtorParam = isConstructor(args[0]);
const targetType = isCtorParam ? args[0] : args[0].constructor;
const targetName = isCtorParam ? "constructor" : args[1];
return addDecorator(targetType, Object.assign({ targetType: "Parameter", target: targetName, targetIndex: args[2], value: typeof data === "function" ? data(targetType, targetName, args[2]) : data }, opt));
}
//property
if (args[2] === undefined || args[2].get || args[2].set) {
throwIfNotOfType("Property");
return addDecorator(args[0].constructor, Object.assign({ targetType: "Property", target: args[1], value: typeof data === "function" ? data(args[0].constructor, args[1]) : data }, opt));
}
throwIfNotOfType("Method");
return addDecorator(args[0].constructor, Object.assign({ targetType: "Method", target: args[1], value: typeof data === "function" ? data(args[0].constructor, args[1]) : data }, opt));
};
}
exports.decorate = decorate;
function mergeDecorator(...fn) {
return (...args) => {
fn.forEach(x => x(...args));
};
}
exports.mergeDecorator = mergeDecorator;
// --------------------------------------------------------------------- //
// --------------------- EXTEND METADATA FUNCTIONS --------------------- //
// --------------------------------------------------------------------- //
function extendDecorators(child, parent) {
const result = [...child];
for (const decorator of parent) {
const options = decorator[exports.DecoratorOption];
// continue, if the decorator is not inheritable
if (!options.inherit)
continue;
// continue, if allow multiple and already has decorator with the same ID
if (!options.allowMultiple && child.some(x => x[exports.DecoratorId] === decorator[exports.DecoratorId]))
continue;
result.push(decorator);
}
return result;
}
function extendParameter(child, parent) {
const result = [];
for (const member of child) {
const exists = parent.find(x => x.name === member.name);
member.decorators = extendDecorators(member.decorators, exists.decorators);
result.push(member);
}
return result;
}
function extendProperty(child, parent) {
const result = [...child];
for (const member of parent) {
const exists = result.find(x => x.name === member.name);
if (exists) {
exists.decorators = extendDecorators(exists.decorators, member.decorators);
continue;
}
member.decorators = extendDecorators([], member.decorators);
result.push(member);
}
return result;
}
function extendMethod(child, parent) {
const result = [...child];
for (const member of parent) {
const exists = result.find(x => x.name === member.name);
if (exists) {
exists.parameters = extendParameter(exists.parameters, member.parameters);
exists.decorators = extendDecorators(exists.decorators, member.decorators);
continue;
}
member.decorators = extendDecorators([], member.decorators);
result.push(member);
}
return result;
}
function extendClass(child, parent) {
const { ctor, methods, properties, decorators } = child, result = __rest(child, ["ctor", "methods", "properties", "decorators"]);
return Object.assign(Object.assign({}, result), { ctor, decorators: extendDecorators(child.decorators, parent.decorators), methods: extendMethod(child.methods, parent.methods), properties: extendProperty(child.properties, parent.properties) });
}
// --------------------------------------------------------------------- //
// -------------------------- REFLECT FUNCTION ------------------------- //
// --------------------------------------------------------------------- //
function reflectParameter(name, typeAnnotation, decs) {
const decorators = decs || [];
const type = getReflectionType(decorators, typeAnnotation);
const typeClassification = getTypeClassification(type);
let parName;
let properties = {};
if (typeof name === "object") {
parName = printDestruct(name);
properties = name;
}
else {
parName = name;
}
return { kind: "Parameter", name: parName, type, decorators, typeClassification, properties };
}
function reflectFunction(fn) {
const parameters = getParameterNames(fn).map(x => reflectParameter(x));
return { kind: "Function", name: fn.name, parameters, returnType: undefined };
}
function reflectMethod(clazz, method, iterator) {
const parType = Reflect.getOwnMetadata(exports.DESIGN_PARAMETER_TYPE, clazz.prototype, method) || [];
const rawReturnType = Reflect.getOwnMetadata(exports.DESIGN_RETURN_TYPE, clazz.prototype, method);
const parameters = getMethodParameters(clazz, method).map((x, i) => reflectParameter(x, parType[i], iterator("Parameter", method, i)));
const decorators = iterator("Method", method);
const returnType = getReflectionType(decorators, rawReturnType);
const typeClassification = getTypeClassification(returnType);
return { kind: "Method", name: method, parameters, decorators, returnType, typeClassification };
}
function reflectProperty(name, typeAnnotation, des, iterator) {
const decorators = iterator("Property", name);
const type = getReflectionType(decorators, typeAnnotation);
const typeClassification = getTypeClassification(type);
return {
kind: "Property", name, type, decorators, typeClassification,
get: des && des.get, set: des && des.set
};
}
function reflectMember(clazz, name, iterator) {
const type = Reflect.getOwnMetadata(exports.DESIGN_TYPE, clazz.prototype, name);
const des = Reflect.getOwnPropertyDescriptor(clazz.prototype, name);
if (des && typeof des.value === "function" && !des.get && !des.set) {
return reflectMethod(clazz, name, iterator);
}
else {
return reflectProperty(name, type, des, iterator);
}
}
function reflectConstructor(fn, iterator) {
const parTypes = Reflect.getOwnMetadata(exports.DESIGN_PARAMETER_TYPE, fn) || [];
const params = getConstructorParameters(fn);
return {
kind: "Constructor",
name: "constructor",
parameters: params.map((x, i) => reflectParameter(x, parTypes[i], iterator("Parameter", "constructor", i)))
};
}
function reflectClass(fn) {
const iterator = getDecoratorIterator(fn);
const members = getMembers(fn).map(x => reflectMember(fn, x, iterator));
const ctor = reflectConstructor(fn, iterator);
const decorators = iterator("Class", fn.name);
const properties = members.filter((x) => x.kind === "Property" && isIncluded(x));
if (decorators.some(x => x.type === "ParameterProperties")) {
const parProps = ctor.parameters.filter(x => isIncluded(x)).map(x => ({
decorators: x.decorators, type: x.type,
name: x.name, kind: "Property", get: undefined, set: undefined
}));
properties.push(...parProps);
}
return {
kind: "Class", ctor, name: fn.name,
methods: members.filter((x) => x.kind === "Method" && isIncluded(x)),
properties, decorators, type: fn, typeClassification: "Class"
};
}
function reflectClassRecursive(fn) {
const defaultRef = {
kind: "Class", type: Object, name: "Object",
ctor: {},
methods: [], properties: [], decorators: []
};
const childMeta = reflectClass(fn);
const parent = Object.getPrototypeOf(fn);
const parentMeta = parent.prototype ? reflectClassRecursive(parent) : defaultRef;
return extendClass(childMeta, parentMeta);
}
function reflectObject(object, name = "module") {
return {
kind: "Object", name,
members: Object.keys(object).map(x => traverse(object[x], x)).filter((x) => !!x)
};
}
function traverse(fn, name) {
switch (getType(fn)) {
case "Function":
return reflectFunction(fn);
case "Class":
return reflectClassRecursive(fn);
case "Object":
return reflectObject(fn, name);
default:
return;
}
}
const reflectObjectCached = useCache(cacheStore, reflectObject, x => x);
const reflectClassRecursiveCached = useCache(cacheStore, reflectClassRecursive, x => x);
function reflect(option) {
if (typeof option === "string") {
return reflectObjectCached(require(option));
}
else {
return reflectClassRecursiveCached(option);
}
}
exports.reflect = reflect;
/* ---------------------------------------------------------------- */
/* ------------------------- DECORATORS --------------------------- */
/* ---------------------------------------------------------------- */
const IgnoreId = Symbol("ignore");
const OverrideId = Symbol("override");
const ArrayId = Symbol("array");
const ParamPropId = Symbol("paramProp");
/**
* Decorator that do nothing, intended to be able to inspect data type
*/
reflect.noop = function () {
return decorate({});
};
/**
* Ignore member from metadata generated
*/
reflect.ignore = function () {
return decorate({ [exports.DecoratorId]: IgnoreId, kind: "Ignore" }, ["Parameter", "Method", "Property"], { allowMultiple: false });
};
/**
* Override type definition information. Useful to add type definition for some data type that is erased
* after transfile such as Partial<Type> or ReadOnly<Type>
*
* If applied to parameter it will override the parameter type
*
* If applied to property it will override the property type
*
* if applied to method it will overrid the method return value
* @param type The type overridden
* @param info Additional information about type (readonly, partial etc)
*/
reflect.type = function (type, info) {
return decorate({ [exports.DecoratorId]: OverrideId, kind: "Override", type: type, info }, ["Parameter", "Method", "Property"], { allowMultiple: false });
};
/**
* Add type information for array element
* @param type Data type of array element
*/
reflect.array = function (type) {
return decorate({ [exports.DecoratorId]: ArrayId, kind: "Array", type: type }, ["Parameter", "Method", "Property"], { allowMultiple: false });
};
/**
* Mark all constructor parameters as properties
*/
reflect.parameterProperties = function () {
return decorateClass({ [exports.DecoratorId]: ParamPropId, type: "ParameterProperties" }, { allowMultiple: false });
};
exports.default = reflect;
__export(require("./types"));
__export(require("./decorators"));
__export(require("./helpers"));
const reflect_1 = require("./reflect");
exports.reflect = reflect_1.reflect;
exports.default = reflect_1.reflect;
{
"name": "tinspector",
"version": "2.3.1",
"version": "3.0.0",
"description": "TypeScript type inspector",

@@ -25,6 +25,6 @@ "main": "lib/index.js",

"devDependencies": {
"@types/jest": "^25.1.4",
"@types/node": "^13.9.1",
"coveralls": "^3.0.9",
"jest": "^25.1.0",
"@types/jest": "^25.2.1",
"@types/node": "^13.13.4",
"coveralls": "^3.1.0",
"jest": "^25.4.0",
"tslib": "^1.11.1",

@@ -31,0 +31,0 @@ "typescript": "^3.8.3"

@@ -92,2 +92,3 @@ # tinspector

- [x] (TypeScript only) Configurable decorator (inheritable / allow multiple)
- [x] (TypeScript only) Generic class inheritance

@@ -190,2 +191,20 @@

## Inspect Generic Class Information
With above trick its possible to get generic type information in a generic class members with some extra configuration below
```typescript
@generic.template("T", "U")
class SuperAwesome<T, U> {
awesome(@reflect.type("T") par: T, @reflect.type("U") par2: U) {}
}
@generic.type(Number, String)
class Awesome extends SuperAwesome<Number, String> { }
const metadata = reflect(Awesome)
```
Above 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.
## Inspect Parameter Properties

@@ -192,0 +211,0 @@ TypeScript 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.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc