Skip to content

Commit

Permalink
feat(all): initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
willsoto committed Feb 3, 2019
0 parents commit a7ec179
Show file tree
Hide file tree
Showing 16 changed files with 7,106 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json"
},
extends: [
"plugin:@typescript-eslint/recommended",
"@willsoto/eslint-config-base",
"prettier",
"prettier/@typescript-eslint"
],
env: {
node: true,
jest: true
}
};
83 changes: 83 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

/dist
/typings
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"singleQuote": false,
"arrowParens": "always",
"endOfLine": "auto",
"trailingComma": "none"
}
20 changes: 20 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "typescript",
"autoFix": true
},
{
"language": "typescriptreact",
"autoFix": true
}
],
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.preferences.quoteStyle": "double"
}
13 changes: 13 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
presets: [
"@babel/preset-typescript",
[
"@babel/preset-env",
{
targets: {
node: "current"
}
}
]
]
};
7 changes: 7 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
clearMocks: true,
collectCoverage: true,
coverageDirectory: "coverage",
coverageReporters: ["json", "text", "lcov"],
testEnvironment: "node"
};
9 changes: 9 additions & 0 deletions lib/__tests__/constants.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as constants from "../constants";

describe("NestJS Objection constants", () => {
test("has 3", () => {
const expected = 3;

expect(Object.keys(constants)).toHaveLength(expected);
});
});
38 changes: 38 additions & 0 deletions lib/__tests__/module.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Test, TestingModule } from "@nestjs/testing";
import knex from "knex";
import { Model } from "objection";
import { ObjectionCoreModule } from "../module";

describe("NestJS Objection module", () => {
describe("forRoot", () => {
let testingModule: TestingModule;

beforeEach(async () => {
testingModule = await Test.createTestingModule({
imports: [
ObjectionCoreModule.forRoot({
config: {
client: "sqlite3",
useNullAsDefault: true,
connection: {
filename: "./testing.sqlite"
}
}
})
]
}).compile();
});

test("provides a connection", () => {
const connection = testingModule.get<knex>("KnexConnectionProvider");

expect(connection).toBeDefined();
});

test("provides a base model", () => {
const model = testingModule.get<Model>("ObjectionBaseModelProvider");

expect(model).toBeDefined();
});
});
});
4 changes: 4 additions & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const OBJECTION_MODULE_OPTIONS_PROVIDER =
"ObjectionModuleOptionsProvider";
export const OBJECTION_BASE_MODEL_PROVIDER = "ObjectionBaseModelProvider";
export const KNEX_CONNECTION_PROVIDER = "KnexConnectionProvider";
3 changes: 3 additions & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./constants";
export * from "./interfaces";
export * from "./module";
29 changes: 29 additions & 0 deletions lib/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Type } from "@nestjs/common";
import { ModuleMetadata } from "@nestjs/common/interfaces";
import Knex from "knex";
import { Model } from "objection";

export interface ObjectionModuleOptions {
Model?: typeof Model;
config?: Knex.Config;
}

export interface ObjectionModuleOptionsFactory {
createObjectionModuleOptions():
| Promise<ObjectionModuleOptions>
| ObjectionModuleOptions;
}

export interface ObjectionModuleAsyncOptions
extends Pick<ModuleMetadata, "imports"> {
useExisting?: Type<ObjectionModuleOptionsFactory>;
useClass?: Type<ObjectionModuleOptionsFactory>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
inject?: any[];
useFactory?(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...args: any[]
): Promise<ObjectionModuleOptions> | ObjectionModuleOptions;
}

export type Connection = Knex;
128 changes: 128 additions & 0 deletions lib/module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { DynamicModule, Provider } from "@nestjs/common";
import knex from "knex";
import { Model } from "objection";
import {
KNEX_CONNECTION_PROVIDER,
OBJECTION_BASE_MODEL_PROVIDER,
OBJECTION_MODULE_OPTIONS_PROVIDER
} from "./constants";
import {
Connection,
ObjectionModuleAsyncOptions,
ObjectionModuleOptions,
ObjectionModuleOptionsFactory
} from "./interfaces";

export class ObjectionCoreModule {
public static forRoot(options: ObjectionModuleOptions): DynamicModule {
const knexConfig = options.config || {};
const Base = options.Model || Model;
const connection = knex(knexConfig);

Base.knex(connection);

const objectionModuleOptions: Provider = {
provide: OBJECTION_MODULE_OPTIONS_PROVIDER,
useValue: options
};

const objectionBaseModelProvider: Provider = {
provide: OBJECTION_BASE_MODEL_PROVIDER,
useValue: Base
};

const knexConnectionProvider: Provider = {
provide: KNEX_CONNECTION_PROVIDER,
useValue: connection
};

return {
module: ObjectionCoreModule,
providers: [
objectionModuleOptions,
objectionBaseModelProvider,
knexConnectionProvider
],
exports: [objectionBaseModelProvider, knexConnectionProvider]
};
}

public static forRootAsync(
options: ObjectionModuleAsyncOptions
): DynamicModule {
const knexConnectionProvider: Provider = {
provide: KNEX_CONNECTION_PROVIDER,
inject: [OBJECTION_MODULE_OPTIONS_PROVIDER],
useFactory(objectionModuleOptions: ObjectionModuleOptions) {
const config = objectionModuleOptions.config || {};

return knex(config);
}
};

const objectionBaseModelProvider: Provider = {
provide: OBJECTION_BASE_MODEL_PROVIDER,
inject: [KNEX_CONNECTION_PROVIDER, OBJECTION_MODULE_OPTIONS_PROVIDER],
useFactory(
connection: Connection,
objectionModuleOptions: ObjectionModuleOptions
) {
const Base = objectionModuleOptions.Model || Model;

return Base.knex(connection);
}
};
const asyncProviders = this.createAsyncProviders(options);

return {
module: ObjectionCoreModule,
imports: options.imports,
providers: [
...asyncProviders,
knexConnectionProvider,
objectionBaseModelProvider
],
exports: [objectionBaseModelProvider, knexConnectionProvider]
};
}

private static createAsyncProviders(
options: ObjectionModuleAsyncOptions
): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)];
}

if (!options.useClass) {
throw new Error("Invalid configuration");
}

return [
this.createAsyncOptionsProvider(options),
{
provide: options.useClass,
useClass: options.useClass
}
];
}

private static createAsyncOptionsProvider(
options: ObjectionModuleAsyncOptions
): Provider {
if (options.useFactory) {
return {
provide: OBJECTION_MODULE_OPTIONS_PROVIDER,
useFactory: options.useFactory,
inject: options.inject || []
};
}

return {
provide: OBJECTION_MODULE_OPTIONS_PROVIDER,
useFactory(optionsFactory: ObjectionModuleOptionsFactory) {
return optionsFactory.createObjectionModuleOptions();
},
inject: [options.useClass || options.useExisting]
};
}
}
Loading

0 comments on commit a7ec179

Please sign in to comment.