Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@travetto/di

Package Overview
Dependencies
Maintainers
1
Versions
313
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@travetto/di - npm Package Compare versions

Comparing version 0.0.9 to 0.0.10

2

package.json

@@ -22,3 +22,3 @@ {

},
"version": "0.0.9"
"version": "0.0.10"
}

@@ -25,9 +25,27 @@ import { InjectableConfig, Dependency } from '../types';

export function Inject(config?: InjectConfig) {
function extractSymbolOrConfig<T extends { qualifier?: Symbol }>(args: any[]) {
const out = {} as T;
if (args) {
let extra = args[0];
if (typeof extra === 'symbol') {
out.qualifier = extra;
extra = args[1];
}
Object.assign(out, extra);
}
return out;
}
export function Inject(symbol: symbol, config?: InjectConfig): ParameterDecorator & PropertyDecorator;
export function Inject(config?: InjectConfig): ParameterDecorator & PropertyDecorator;
export function Inject(...args: any[]): ParameterDecorator & PropertyDecorator {
return (target: any, propertyKey: string | symbol, idx?: number) => {
if (typeof idx !== 'number') { // Only register if on property
const config: InjectConfig = extractSymbolOrConfig(args);
DependencyRegistry.registerProperty(
target.constructor,
propertyKey as string,
config as any as Dependency);
(typeof config === 'symbol' ? { qualifier: config } : config) as any as Dependency);
}

@@ -37,6 +55,10 @@ };

export function InjectableFactory(config: InjectableFactoryConfig<any>): MethodDecorator {
export function InjectableFactory(config: InjectableFactoryConfig<any>): MethodDecorator;
export function InjectableFactory(symbol: symbol, config?: InjectableFactoryConfig<any>): MethodDecorator;
export function InjectableFactory(...args: any[]): MethodDecorator {
return (target: any, property: string | symbol, descriptor: TypedPropertyDescriptor<any>) => {
const config: InjectableFactoryConfig<any> = extractSymbolOrConfig(args);
DependencyRegistry.registerFactory({ ...config, fn: descriptor.value, id: `${target.__id}#${property}` });
};
}

@@ -7,2 +7,4 @@ import { Dependency, InjectableConfig, ClassTarget, InjectableFactoryConfig } from '../types';

import * as _ from 'lodash';
export const DEFAULT_INSTANCE = Symbol('__default');

@@ -21,2 +23,14 @@

function mergeWithOptional<T extends { original?: symbol | object, qualifier?: symbol }>(o: T) {
if (o.original) {
if (typeof o.original === 'symbol') {
o.qualifier = o.original;
} else if (_.isPlainObject(o.original)) {
_.merge(o, o.original)
}
o.original = undefined;
}
return o;
}
export class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {

@@ -78,14 +92,3 @@ private pendingFinalize: Class[] = [];

async construct<T>(target: ClassTarget<T & ManagedExtra>, qualifier: symbol = DEFAULT_INSTANCE): Promise<T> {
const targetId = target.__id;
const aliasMap = this.aliases.get(targetId);
if (!aliasMap || !aliasMap.has(qualifier)) {
throw new InjectionError(`Dependency not found: ${targetId}[${getName(qualifier)}]`);
}
const clz = aliasMap.get(qualifier)!;
const managed = this.get(clz)!;
async computeDependencies(managed: InjectableConfig<any>) {
const fieldKeys = Object.keys(managed.dependencies.fields!);

@@ -96,2 +99,6 @@

for (const dep of allDeps) {
mergeWithOptional(dep);
}
const promises = allDeps

@@ -115,2 +122,30 @@ .map(async x => {

const fields = new Map<string, any>();
for (let i = 0; i < fieldKeys.length; i++) {
fields.set(fieldKeys[i], fieldValues[i]);
}
return { consValues, fields }
}
applyFieldDependencies(inst: any, fields: Map<string, any>) {
for (const [key, value] of fields.entries()) {
inst[key] = value;
}
}
async construct<T>(target: ClassTarget<T & ManagedExtra>, qualifier: symbol = DEFAULT_INSTANCE): Promise<T> {
const targetId = target.__id;
const aliasMap = this.aliases.get(targetId);
if (!aliasMap || !aliasMap.has(qualifier)) {
throw new InjectionError(`Dependency not found: ${targetId}[${getName(qualifier)}]`);
}
const clz = aliasMap.get(qualifier)!;
const managed = this.get(clz)!;
const { consValues, fields } = await this.computeDependencies(managed);
const inst = managed.factory ?

@@ -120,5 +155,3 @@ managed.factory(...consValues) :

for (let i = 0; i < fieldKeys.length; i++) {
(inst as any)[fieldKeys[i]] = fieldValues[i];
}
this.applyFieldDependencies(inst, fields);

@@ -128,2 +161,3 @@ if (inst.postConstruct) {

}
return inst;

@@ -211,2 +245,3 @@ }

const conf = this.getOrCreatePending(cls);
conf.dependencies!.fields[field] = dependency;

@@ -242,5 +277,9 @@ dependency.qualifier = dependency.qualifier || DEFAULT_INSTANCE;

const finalConfig: InjectableConfig<any> = {} as any;
mergeWithOptional(config);
if (typeof config.autoCreate === 'boolean') {
finalConfig.autoCreate = { create: config.autoCreate } as any;
}
finalConfig.factory = config.fn;

@@ -253,6 +292,16 @@ finalConfig.target = config.class;

finalConfig.dependencies = { fields: {} };
if (config.dependencies) {
finalConfig.dependencies = {
cons: config.dependencies,
fields: {}
finalConfig.dependencies.cons = config.dependencies;
}
// Mirror target's field dependencies
if (config.class) {
const targetConfig = this.get(config.class);
if (targetConfig && targetConfig.dependencies) {
finalConfig.dependencies.fields = {};
for (const k of Object.keys(targetConfig.dependencies.fields)) {
finalConfig.dependencies.fields[k] = targetConfig.dependencies.fields[k];
}
}

@@ -276,2 +325,3 @@ }

// Allow for the factory to fulfill the target
const parentClass = Object.getPrototypeOf(cls);

@@ -278,0 +328,0 @@ const parentConfig = this.get(parentClass.__id);

@@ -21,4 +21,23 @@ import * as ts from 'typescript';

const finalTarget = TransformUtil.importIfExternal(param.type!, state);
const injectConfig = TransformUtil.getPrimaryArgument<ts.ObjectLiteralExpression>(injection);
let injectConfig = TransformUtil.getPrimaryArgument<ts.ObjectLiteralExpression>(injection);
let original = undefined;
const callExpr = (injection && injection.expression as any as ts.CallExpression);
if (callExpr) {
const args = callExpr.arguments! || [];
// Handle special case
if (args.length && ts.isIdentifier(args[0])) {
original = args[0];
injectConfig = args[1] as any;
}
}
if (injectConfig === undefined) {
injectConfig = TransformUtil.fromLiteral({});
}
let optional = TransformUtil.getObjectValue(injectConfig, 'optional');

@@ -31,2 +50,3 @@

return TransformUtil.fromLiteral({
original,
target: finalTarget,

@@ -138,2 +158,3 @@ optional,

let injectArgs: object[] = [];
let original: any;

@@ -149,30 +170,49 @@ try {

if (injectArgs.length) {
const foundExpr = (foundDec.expression as ts.CallExpression);
let injectConfig = TransformUtil.getPrimaryArgument<ts.ObjectLiteralExpression>(foundDec);
const args = TransformUtil.extendObjectLiteral({
dependencies: injectArgs
}, foundExpr.arguments[0] as ts.ObjectLiteralExpression);
const callExpr = (foundDec && foundDec.expression as any as ts.CallExpression);
if (callExpr) {
const args = callExpr.arguments! || [];
// Handle special case
if (args[0] && ts.isIdentifier(args[0])) {
original = args[0];
injectConfig = args[1] as any;
}
}
node = ts.createMethod(
decls!.filter(x => x !== foundDec).concat([
ts.createDecorator(
ts.createCall(
foundExpr.expression,
foundExpr.typeArguments,
ts.createNodeArray([args])
)
)
]),
node.modifiers,
node.asteriskToken,
node.name,
node.questionToken,
node.typeParameters,
node.parameters,
node.type,
node.body
) as any;
if (injectConfig === undefined) {
injectConfig = TransformUtil.fromLiteral({});
}
// Handle when
let target = TransformUtil.getObjectValue(injectConfig, 'target');
if (node.type && target === undefined) { // TODO: infer from typings, not just text?
target = TransformUtil.importIfExternal(node.type!, state);
}
const args = TransformUtil.extendObjectLiteral({
dependencies: injectArgs,
class: target,
original
}, injectConfig);
node = ts.createMethod(
decls!.filter(x => x !== foundDec).concat([
ts.createDecorator(
ts.createCall(
callExpr.expression,
callExpr.typeArguments,
ts.createNodeArray([args])
)
)
]),
node.modifiers,
node.asteriskToken,
node.name,
node.questionToken,
node.typeParameters,
node.parameters,
node.type,
node.body
) as any;
return node;

@@ -179,0 +219,0 @@ } else {

@@ -19,2 +19,3 @@ import { Class } from '@travetto/registry';

optional?: boolean;
original?: Symbol | object;
}

@@ -27,2 +28,3 @@

autoCreate?: boolean
original?: Symbol | object;
}

@@ -1,8 +0,21 @@

import { Injectable } from '../src/decorator';
import { Injectable, Inject } from '../src/decorator';
import { Util } from './util';
import { Config } from '@travetto/config';
@Injectable()
export class Empty {
public age = 10;
}
class Basic {
@Inject()
public empty: Empty;
}
@Config('a')
export class DbConfig<A, B> {
export class DbConfig<A, B> extends Basic {
public temp: any;
constructor() {
super();
console.log('Creating dbconfigs');

@@ -9,0 +22,0 @@ }

import { Injectable, Inject, InjectableFactory } from '../src';
import { DbConfig, AltConfig } from './config';
import { DbConfig, AltConfig, Empty } from './config';

@@ -47,8 +47,28 @@ @Injectable()

export const CUSTOM_SERVICE_INHERIT = Symbol('Custom');
export const CUSTOM_DATABSE = Symbol('CUSTOM DB');
export const CUSTOM_EMPTY = Symbol('Custom EMPTY');
class TestConfig {
@InjectableFactory({ class: ServiceInherit, qualifier: CUSTOM_SERVICE_INHERIT })
static getObject(@Inject({ qualifier: SERVICE_INHERIT_2 }) svc: ServiceInherit) {
@InjectableFactory(CUSTOM_EMPTY)
static getNewEmpty(): Empty {
const out = new Empty();
out.age = 20;
console.log('Custom EMPTY 1', out);
return out;
}
@InjectableFactory(CUSTOM_SERVICE_INHERIT)
static getObject(@Inject(SERVICE_INHERIT_2) svc: ServiceInherit): ServiceInherit {
return new ServiceInherit2(svc.db);
}
@InjectableFactory(CUSTOM_DATABSE)
static getCustomDB(config: DbConfig<any, any>, @Inject(CUSTOM_EMPTY) empty: Empty): Database {
console.log('Custom EMPTY 2', empty);
const ret = new Database();
config.temp = 'any';
ret.dbConfig = config;
ret.dbConfig.empty = empty;
return ret;
}
}
import { DependencyRegistry } from '../src/service';
import { ServiceInherit, SERVICE_INHERIT_2, CUSTOM_SERVICE_INHERIT } from './deps';
import { Suite, Test } from '@travetto/test';
import { ServiceInherit, SERVICE_INHERIT_2, CUSTOM_SERVICE_INHERIT, CUSTOM_DATABSE, Database } from './deps';
import { Suite, Test, BeforeEach } from '@travetto/test';
import * as assert from 'assert';

@@ -9,3 +9,3 @@

function doWork() {
// throw new Error('ahhh');
throw new Error('ahhh');
}

@@ -38,5 +38,6 @@

assert(1 === 1);
assert(2 + 2 === FOUR);
doWork();
assert.throws(doWork, Error);
}

@@ -48,6 +49,10 @@ }

@BeforeEach()
async each() {
await DependencyRegistry.init();
}
@Test('run')
async run() {
console.log('starting');
await DependencyRegistry.init();
assert(30 === 30);

@@ -76,8 +81,29 @@

async factory() {
await DependencyRegistry.init();
assert(true);
const inst = await DependencyRegistry.getInstance(ServiceInherit, CUSTOM_SERVICE_INHERIT);
assert(inst);
assert(inst.db.dbConfig);
assert.ok(!inst.db.dbConfig.temp);
assert(inst.db.dbConfig.empty.age === 10);
}
@Test('factory with autowire after')
async factory2() {
assert(true);
const inst = await DependencyRegistry.getInstance(Database, CUSTOM_DATABSE);
assert(inst);
assert(inst.altConfig === undefined);
assert.ok(inst.dbConfig);
assert(inst.dbConfig.temp === 'any');
assert(inst.dbConfig.empty.age === 20);
}
}
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