Skip to content

Commit

Permalink
fix: make injected svcs optional, assert existence before use (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed Jan 6, 2019
1 parent d9a7261 commit b73d42a
Show file tree
Hide file tree
Showing 26 changed files with 76 additions and 68 deletions.
25 changes: 13 additions & 12 deletions src/BaseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { checkFilter, Filter, FilterData, FilterValue } from 'src/filter/Filter'
import { ServiceModule } from 'src/module/ServiceModule';
import { Schema } from 'src/schema';
import { Service, ServiceDefinition, ServiceEvent } from 'src/Service';
import { mustExist } from 'src/utils';
import { Clock } from 'src/utils/Clock';
import { JsonPath } from 'src/utils/JsonPath';
import { dictToMap } from 'src/utils/Map';
Expand All @@ -31,15 +32,15 @@ export const INJECT_TEMPLATE = Symbol('inject-template');
* TODO: these should be optional and must be included in the decorator to be available
*/
export interface InjectedServiceOptions {
[INJECT_CLOCK]: Clock;
[INJECT_JSONPATH]: JsonPath;
[INJECT_LOGGER]: Logger;
[INJECT_MATH]: MathFactory;
[INJECT_METRICS]: Registry;
[INJECT_REQUEST]: RequestFactory;
[INJECT_SCHEMA]: Schema;
[INJECT_SERVICES]: ServiceModule;
[INJECT_TEMPLATE]: TemplateCompiler;
[INJECT_CLOCK]?: Clock;
[INJECT_JSONPATH]?: JsonPath;
[INJECT_LOGGER]?: Logger;
[INJECT_MATH]?: MathFactory;
[INJECT_METRICS]?: Registry;
[INJECT_REQUEST]?: RequestFactory;
[INJECT_SCHEMA]?: Schema;
[INJECT_SERVICES]?: ServiceModule;
[INJECT_TEMPLATE]?: TemplateCompiler;
}

export interface BaseServiceData {
Expand Down Expand Up @@ -69,20 +70,20 @@ export abstract class BaseService<TData extends BaseServiceData> implements Serv

this.data = options.data;
this.filters = [];
this.services = options[INJECT_SERVICES];
this.services = mustExist(options[INJECT_SERVICES]);

// check this, because bunyan will throw if it is missing
if (isNil(this.name) || this.name === '') {
throw new MissingValueError('missing service name');
}

this.logger = options[INJECT_LOGGER].child({
this.logger = mustExist(options[INJECT_LOGGER]).child({
kind: kebabCase(Reflect.getPrototypeOf(this).constructor.name),
service: options.metadata.name,
});

// validate the data
const result = options[INJECT_SCHEMA].match(options.data, schemaPath);
const result = mustExist(options[INJECT_SCHEMA]).match(options.data, schemaPath);
if (!result.valid) {
this.logger.error({ data: options.data, errors: result.errors }, 'failed to validate config');
throw new SchemaError('failed to validate config');
Expand Down
4 changes: 2 additions & 2 deletions src/Bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ export class Bot extends BaseService<BotData> implements Service {
this.logger.info(options, 'creating bot');

this.container = options.container;
this.metrics = options[INJECT_METRICS];
this.services = options[INJECT_SERVICES];
this.metrics = mustExist(options[INJECT_METRICS]);
this.services = mustExist(options[INJECT_SERVICES]);

// set up deps
this.controllers = [];
Expand Down
9 changes: 5 additions & 4 deletions src/BotService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Bot } from 'src/Bot';
import { Context } from 'src/entity/Context';
import { Locale } from 'src/locale';
import { Service } from 'src/Service';
import { mustExist } from 'src/utils';

export type BotServiceData = BaseServiceData;

Expand All @@ -17,9 +18,9 @@ export const INJECT_STORAGE = Symbol('inject-storage');
* Exposed injected services available to child services.
*/
export interface BotServiceOptions<TData extends BotServiceData> extends BaseServiceOptions<TData> {
[INJECT_BOT]: Bot;
[INJECT_LOCALE]: Locale;
[INJECT_STORAGE]: Connection;
[INJECT_BOT]?: Bot;
[INJECT_LOCALE]?: Locale;
[INJECT_STORAGE]?: Connection;
}

/**
Expand All @@ -33,7 +34,7 @@ export abstract class BotService<TData extends BotServiceData> extends BaseServi
constructor(options: BotServiceOptions<TData>, schemaPath: string) {
super(options, schemaPath);

this.bot = options[INJECT_BOT];
this.bot = mustExist(options[INJECT_BOT]);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/controller/AccountController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ export class AccountController extends BaseController<AccountControllerData> imp
constructor(options: AccountControllerOptions) {
super(options, 'isolex#/definitions/service-controller-account', [NOUN_GRANT, NOUN_ACCOUNT, NOUN_SESSION]);

this.clock = options[INJECT_CLOCK];
this.storage = options[INJECT_STORAGE];
this.clock = mustExist(options[INJECT_CLOCK]);
this.storage = mustExist(options[INJECT_STORAGE]);
this.roleRepository = this.storage.getRepository(Role);
this.tokenRepository = this.storage.getRepository(Token);
this.userRepository = this.storage.getCustomRepository(UserRepository);
Expand Down
4 changes: 2 additions & 2 deletions src/controller/BaseController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ export abstract class BaseController<TData extends ControllerData> extends BotSe
constructor(options: BaseControllerOptions<TData>, schemaPath: string, nouns: Array<string> = []) {
super(options, schemaPath);

this.locale = options[INJECT_LOCALE];
this.locale = mustExist(options[INJECT_LOCALE]);
this.nouns = new Set(nouns);
this.services = options[INJECT_SERVICES];
this.services = mustExist(options[INJECT_SERVICES]);
this.transforms = [];
}

Expand Down
6 changes: 2 additions & 4 deletions src/controller/CompletionController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isNil } from 'lodash';
import { Inject } from 'noicejs';
import { Connection, Repository } from 'typeorm';
import { Repository } from 'typeorm';

import { INJECT_STORAGE } from 'src/BotService';
import { CheckRBAC, Handler } from 'src/controller';
Expand All @@ -25,15 +25,13 @@ export type CompletionControllerOptions = ControllerOptions<CompletionController

@Inject(INJECT_STORAGE)
export class CompletionController extends BaseController<CompletionControllerData> implements Controller {
protected readonly storage: Connection;
protected readonly fragmentRepository: Repository<Fragment>;
protected target?: Listener;

constructor(options: CompletionControllerOptions) {
super(options, 'isolex#/definitions/service-controller-completion', [NOUN_FRAGMENT]);

this.storage = options[INJECT_STORAGE];
this.fragmentRepository = this.storage.getRepository(Fragment);
this.fragmentRepository = mustExist(options[INJECT_STORAGE]).getRepository(Fragment);
}

public async start() {
Expand Down
9 changes: 4 additions & 5 deletions src/controller/CountController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isNil } from 'lodash';
import { Inject } from 'noicejs';
import { Connection, Repository } from 'typeorm';
import { Repository } from 'typeorm';

import { INJECT_STORAGE } from 'src/BotService';
import { CheckRBAC, Handler } from 'src/controller';
Expand All @@ -9,6 +9,7 @@ import { Controller, ControllerData, ControllerOptions } from 'src/controller/Co
import { Command, CommandVerb } from 'src/entity/Command';
import { Context } from 'src/entity/Context';
import { Counter } from 'src/entity/misc/Counter';
import { mustExist } from 'src/utils';
import { clamp } from 'src/utils/Math';

export const NOUN_COUNTER = 'counter';
Expand All @@ -32,14 +33,12 @@ export type CountControllerOptions = ControllerOptions<CountControllerData>;

@Inject(INJECT_STORAGE)
export class CountController extends BaseController<CountControllerData> implements Controller {
protected storage: Connection;
protected counterRepository: Repository<Counter>;
protected readonly counterRepository: Repository<Counter>;

constructor(options: CountControllerOptions) {
super(options, 'isolex#/definitions/service-controller-count', [NOUN_COUNTER]);

this.storage = options[INJECT_STORAGE];
this.counterRepository = this.storage.getRepository(Counter);
this.counterRepository = mustExist(options[INJECT_STORAGE]).getRepository(Counter);
}

@Handler(NOUN_COUNTER, CommandVerb.Get)
Expand Down
2 changes: 1 addition & 1 deletion src/controller/DiceController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class DiceController extends BaseController<DiceControllerData> implement
constructor(options: DiceControllerOptions) {
super(options, 'isolex#/definitions/service-controller-dice', [NOUN_ROLL]);

this.math = options[INJECT_MATH].create({});
this.math = mustExist(options[INJECT_MATH]).create({});
}

@Handler(NOUN_ROLL, CommandVerb.Create)
Expand Down
5 changes: 2 additions & 3 deletions src/controller/LearnController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Controller, ControllerData, ControllerOptions } from 'src/controller/Co
import { Command, CommandVerb } from 'src/entity/Command';
import { Context } from 'src/entity/Context';
import { Keyword } from 'src/entity/misc/Keyword';
import { mustExist } from 'src/utils';
import { Checklist, ChecklistOptions } from 'src/utils/Checklist';

export const NOUN_KEYWORD = 'keyword';
Expand All @@ -24,14 +25,12 @@ export type LearnControllerOptions = ControllerOptions<LearnControllerData>;
export class LearnController extends BaseController<LearnControllerData> implements Controller {
protected readonly checkNoun: Checklist<string>;
protected readonly keywordRepository: Repository<Keyword>;
protected readonly storage: Connection;

constructor(options: LearnControllerOptions) {
super(options, 'isolex#/definitions/service-controller-learn', [NOUN_KEYWORD]);

this.checkNoun = new Checklist(options.data.nouns);
this.storage = options[INJECT_STORAGE];
this.keywordRepository = this.storage.getRepository(Keyword);
this.keywordRepository = mustExist(options[INJECT_STORAGE]).getRepository(Keyword);
}

@Handler(NOUN_KEYWORD, CommandVerb.Create)
Expand Down
3 changes: 2 additions & 1 deletion src/controller/MathController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BaseController } from 'src/controller/BaseController';
import { Controller, ControllerData, ControllerOptions } from 'src/controller/Controller';
import { Command, CommandVerb } from 'src/entity/Command';
import { Context } from 'src/entity/Context';
import { mustExist } from 'src/utils';
import { formatResult, ResultFormatOptions } from 'src/utils/Math';

export const NOUN_MATH = 'math';
Expand All @@ -28,7 +29,7 @@ export class MathController extends BaseController<MathControllerData> implement
constructor(options: MathControllerOptions) {
super(options, 'isolex#/definitions/service-controller-math', [NOUN_MATH]);

this.math = options[INJECT_MATH].create(options.data.math);
this.math = mustExist(options[INJECT_MATH]).create(options.data.math);
}

@Handler(NOUN_MATH, CommandVerb.Create)
Expand Down
5 changes: 3 additions & 2 deletions src/controller/SearchController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BaseController } from 'src/controller/BaseController';
import { Controller, ControllerData, ControllerOptions } from 'src/controller/Controller';
import { Command, CommandVerb } from 'src/entity/Command';
import { Context } from 'src/entity/Context';
import { mustExist } from 'src/utils';
import { RequestFactory } from 'src/utils/Request';
import { Template } from 'src/utils/Template';

Expand All @@ -30,8 +31,8 @@ export class SearchController extends BaseController<SearchControllerData> imple
constructor(options: SearchControllerOptions) {
super(options, 'isolex#/definitions/service-controller-search', [NOUN_SEARCH]);

this.request = options[INJECT_REQUEST];
this.url = options[INJECT_TEMPLATE].compile(options.data.request.url);
this.request = mustExist(options[INJECT_REQUEST]);
this.url = mustExist(options[INJECT_TEMPLATE]).compile(options.data.request.url);
}

@Handler(NOUN_SEARCH, CommandVerb.Get)
Expand Down
3 changes: 2 additions & 1 deletion src/controller/TimeController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BaseController } from 'src/controller/BaseController';
import { Controller, ControllerData, ControllerOptions } from 'src/controller/Controller';
import { Command, CommandVerb } from 'src/entity/Command';
import { Context } from 'src/entity/Context';
import { mustExist } from 'src/utils';
import { Clock } from 'src/utils/Clock';

export const NOUN_TIME = 'time';
Expand All @@ -24,7 +25,7 @@ export class TimeController extends BaseController<TimeControllerData> implement
constructor(options: TimeControllerOptions) {
super(options, 'isolex#/definitions/service-controller-time', [NOUN_TIME]);

this.clock = options[INJECT_CLOCK];
this.clock = mustExist(options[INJECT_CLOCK]);
}

@Handler(NOUN_TIME, CommandVerb.Get)
Expand Down
4 changes: 2 additions & 2 deletions src/controller/TokenController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export class TokenController extends BaseController<TokenControllerData> impleme
constructor(options: TokenControllerOptions) {
super(options, 'isolex#/definitions/service-controller-token', [NOUN_TOKEN]);

this.clock = options[INJECT_CLOCK];
this.storage = options[INJECT_STORAGE];
this.clock = mustExist(options[INJECT_CLOCK]);
this.storage = mustExist(options[INJECT_STORAGE]);
this.tokenRepository = this.storage.getRepository(Token);
}

Expand Down
8 changes: 4 additions & 4 deletions src/controller/UserController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { User } from 'src/entity/auth/User';
import { UserRepository } from 'src/entity/auth/UserRepository';
import { Command, CommandVerb } from 'src/entity/Command';
import { Context } from 'src/entity/Context';
import { mustExist } from 'src/utils';

export const NOUN_ROLE = 'role';
export const NOUN_USER = 'user';
Expand All @@ -21,15 +22,14 @@ export type UserControllerOptions = ControllerOptions<UserControllerData>;
@Inject(INJECT_STORAGE)
export class UserController extends BaseController<UserControllerData> implements Controller {
protected readonly roleRepository: Repository<Role>;
protected readonly storage: Connection;
protected readonly userRepository: UserRepository;

constructor(options: UserControllerOptions) {
super(options, 'isolex#/definitions/service-controller-user', [NOUN_ROLE, NOUN_USER]);

this.storage = options[INJECT_STORAGE];
this.roleRepository = this.storage.getRepository(Role);
this.userRepository = this.storage.getCustomRepository(UserRepository);
const storage = mustExist(options[INJECT_STORAGE]);
this.roleRepository = storage.getRepository(Role);
this.userRepository = storage.getCustomRepository(UserRepository);
}

@Handler(NOUN_ROLE, CommandVerb.Create)
Expand Down
3 changes: 2 additions & 1 deletion src/controller/WeatherController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BaseController } from 'src/controller/BaseController';
import { Controller, ControllerData, ControllerOptions } from 'src/controller/Controller';
import { Command, CommandVerb } from 'src/entity/Command';
import { Context } from 'src/entity/Context';
import { mustExist } from 'src/utils';
import { RequestFactory } from 'src/utils/Request';

export interface WeatherControllerData extends ControllerData {
Expand All @@ -26,7 +27,7 @@ export class WeatherController extends BaseController<WeatherControllerData> imp
constructor(options: WeatherControllerOptions) {
super(options, 'isolex#/definitions/service-controller-weather', [NOUN_WEATHER]);

this.request = options[INJECT_REQUEST];
this.request = mustExist(options[INJECT_REQUEST]);
}

@Handler(NOUN_WEATHER, CommandVerb.Get)
Expand Down
11 changes: 6 additions & 5 deletions src/interval/BaseInterval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Tick } from 'src/entity/Tick';
import { NotImplementedError } from 'src/error/NotImplementedError';
import { Interval, IntervalData } from 'src/interval/Interval';
import { Listener } from 'src/listener/Listener';
import { doesExist } from 'src/utils';
import { doesExist, mustExist } from 'src/utils';
import { Clock } from 'src/utils/Clock';

export type BaseIntervalOptions<TData extends IntervalData> = BotServiceOptions<TData>;
Expand All @@ -28,11 +28,12 @@ export abstract class BaseInterval<TData extends IntervalData> extends BotServic
constructor(options: BaseIntervalOptions<TData>, schemaPath: string) {
super(options, schemaPath);

this.clock = options[INJECT_CLOCK];
this.math = options[INJECT_MATH].create({});
this.clock = mustExist(options[INJECT_CLOCK]);
this.math = mustExist(options[INJECT_MATH]).create({});

this.contextRepository = options[INJECT_STORAGE].getRepository(Context);
this.tickRepository = options[INJECT_STORAGE].getRepository(Tick);
const storage = mustExist(options[INJECT_STORAGE]);
this.contextRepository = storage.getRepository(Context);
this.tickRepository = storage.getRepository(Tick);
}

public async start() {
Expand Down
3 changes: 2 additions & 1 deletion src/interval/MetricsInterval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Tick } from 'src/entity/Tick';
import { InvalidArgumentError } from 'src/error/InvalidArgumentError';
import { BaseInterval, BaseIntervalOptions } from 'src/interval/BaseInterval';
import { IntervalData } from 'src/interval/Interval';
import { mustExist } from 'src/utils';

export type MetricsIntervalData = IntervalData;
export type MetricsIntervalOptions = BaseIntervalOptions<MetricsIntervalData>;
Expand All @@ -22,7 +23,7 @@ export class MetricsInterval extends BaseInterval<MetricsIntervalData> {
constructor(options: MetricsIntervalOptions) {
super(options, 'isolex#/definitions/service-interval-metrics');

this.metrics = options[INJECT_METRICS];
this.metrics = mustExist(options[INJECT_METRICS]);
}

public async startInterval() {
Expand Down
2 changes: 1 addition & 1 deletion src/listener/BaseListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export abstract class BaseListener<TData extends ListenerData> extends BotServic
constructor(options: ListenerOptions<TData>, schemaPath: string) {
super(options, schemaPath);

this.contextRepository = options[INJECT_STORAGE].getRepository(Context);
this.contextRepository = mustExist(options[INJECT_STORAGE]).getRepository(Context);
}

/**
Expand Down
Loading

0 comments on commit b73d42a

Please sign in to comment.