Skip to content

Commit

Permalink
dynamo: Initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
luaneyed committed Mar 16, 2020
1 parent ad2362d commit 82c4865
Show file tree
Hide file tree
Showing 27 changed files with 2,841 additions and 0 deletions.
13 changes: 13 additions & 0 deletions packages/dynamo/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"env": {
"node": true
},
"extends": [
"@croquiscom/eslint-config/requiring-type-checking"
],
"parserOptions": {
"project": [
"./tsconfig.json"
]
}
}
1 change: 1 addition & 0 deletions packages/dynamo/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src
25 changes: 25 additions & 0 deletions packages/dynamo/lib/BaseModel.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Query from './Query';
export declare class BaseModel {
static dynogelsModel: any;
static setSchema(name: any, schema: any): void;
private static checkHasModelInstance;
static query(hashKey: any): Query;
static scan(indexName?: string): Query;
static getAsync(hashKey: string | number, options?: object): Promise<any>;
static getAsync(hashKey: string | number, rangeKey: string | number, options?: object): Promise<any>;
static createAsync(data: any, options?: object): Promise<any>;
static updateAsync(data: any, options?: object): Promise<any>;
static destroyAsync(hashKey: string | number, options?: object): Promise<any>;
static destroyAsync(hashKey: string | number, rangeKey: string | number, options?: object): Promise<any>;
static create<M extends BaseModel>(this: (new () => M) & typeof BaseModel, data: any, options?: object): Promise<M>;
static createBulk<M extends BaseModel>(this: (new () => M) & typeof BaseModel, data: any[], options?: object): Promise<M[]>;
static get(hashKey: string | number, options?: object): Promise<any>;
static get(hashKey: string | number, rangeKey: string | number, options?: object): Promise<any>;
static update<M extends BaseModel>(this: (new () => M) & typeof BaseModel, data: any, options?: object): Promise<M>;
static destroy(hashKey: string | number, options?: object): Promise<any>;
static destroy(hashKey: string | number, rangeKey: string | number, options?: object): Promise<any>;
static updateTable(params?: any): Promise<any>;
static describeTable(): Promise<any>;
static list(cursor?: string): Promise<import("./Types").QueryResult<unknown>>;
static getItems(keys: any[], options?: any): Promise<any[]>;
}
127 changes: 127 additions & 0 deletions packages/dynamo/lib/BaseModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const _ = __importStar(require("lodash"));
const Dynogels = __importStar(require("./Dynogels"));
const ResultMapper_1 = require("./ResultMapper");
class BaseModel {
static setSchema(name, schema) {
this.dynogelsModel = Dynogels.define(name, schema);
}
static checkHasModelInstance() {
if (!this.dynogelsModel) {
throw new Error('setSchema should be called');
}
}
static query(hashKey) {
this.checkHasModelInstance();
return this.dynogelsModel.query(hashKey);
}
static scan(indexName) {
this.checkHasModelInstance();
const scan = this.dynogelsModel.scan();
if (indexName) {
_.assign(scan.request, { IndexName: indexName });
}
return scan;
}
static getAsync(hashKey, rangeKeyOrOptions, options) {
this.checkHasModelInstance();
if (options) {
return this.dynogelsModel.getAsync(hashKey, rangeKeyOrOptions, options);
}
else {
return this.dynogelsModel.getAsync(hashKey, rangeKeyOrOptions);
}
}
static createAsync(data, options) {
this.checkHasModelInstance();
return this.dynogelsModel.createAsync(data, options);
}
static updateAsync(data, options) {
this.checkHasModelInstance();
return this.dynogelsModel.updateAsync(data, options);
}
static destroyAsync(hashKey, rangeKeyOrOptions, options) {
this.checkHasModelInstance();
if (options) {
return this.dynogelsModel.destroyAsync(hashKey, rangeKeyOrOptions, options);
}
else {
return this.dynogelsModel.destroyAsync(hashKey, rangeKeyOrOptions);
}
}
// V2, with mapItem
static async create(data, options) {
this.checkHasModelInstance();
const createResult = await this.dynogelsModel.createAsync(data, options);
return ResultMapper_1.ResultMapper.mapItem(createResult);
}
static async createBulk(data, options) {
this.checkHasModelInstance();
if (data.length === 0) {
return [];
}
const results = await this.dynogelsModel.createAsync(data, options);
return results.map((result) => ResultMapper_1.ResultMapper.mapItem(result));
}
static async get(hashKey, rangeKeyOrOptions, options) {
this.checkHasModelInstance();
let getResult;
if (options) {
getResult = await this.dynogelsModel.getAsync(hashKey, rangeKeyOrOptions, options);
}
else {
getResult = await this.dynogelsModel.getAsync(hashKey, rangeKeyOrOptions);
}
return ResultMapper_1.ResultMapper.mapItem(getResult);
}
static async update(data, options) {
/**
* Dynogel이 undefined 처리를 못하므로 직접 null로 변경
*/
Object.keys(data).forEach((key) => {
if (data[key] === undefined) {
data[key] = null;
}
});
this.checkHasModelInstance();
const updateResult = await this.dynogelsModel.updateAsync(data, options);
return ResultMapper_1.ResultMapper.mapItem(updateResult);
}
static async destroy(hashKey, rangeKeyOrOptions, options) {
this.checkHasModelInstance();
let destroyResult;
if (options) {
destroyResult = await this.dynogelsModel.destroyAsync(hashKey, rangeKeyOrOptions, options);
}
else {
destroyResult = await this.dynogelsModel.destroyAsync(hashKey, rangeKeyOrOptions);
}
return ResultMapper_1.ResultMapper.mapItem(destroyResult);
}
static updateTable(params) {
return this.dynogelsModel.updateTableAsync(params);
}
static describeTable() {
return this.dynogelsModel.describeTableAsync();
}
static async list(cursor) {
const scan = this.scan();
if (cursor) {
scan.startKey(cursor);
}
return ResultMapper_1.ResultMapper.mapQueryResult(await scan.execAsync());
}
static async getItems(keys, options) {
const getResult = await this.dynogelsModel.getItemsAsync(keys, options);
return _.map(getResult, (item) => ResultMapper_1.ResultMapper.mapItem(item));
}
}
exports.BaseModel = BaseModel;
9 changes: 9 additions & 0 deletions packages/dynamo/lib/Decorators.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
declare function Model(target: any): void;
export declare function SubModel(target: any): void;
declare function HashKey(target: any, property: string | symbol): void;
declare function RangeKey(target: any, property: string | symbol): void;
declare function Field(type: any): (target: any, property: string | symbol) => void;
export declare function ArrayField(type: any): (target: any, property: string | symbol) => void;
declare function GlobalIndex(hashKey: string, rangeKey?: string, projection?: object): (target: any, property: string | symbol) => void;
declare function LocalIndex(rangeKey: string): (target: any, property: string | symbol) => void;
export { Model, HashKey, RangeKey, Field, GlobalIndex, LocalIndex };
97 changes: 97 additions & 0 deletions packages/dynamo/lib/Decorators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const _ = __importStar(require("lodash"));
const Dynogels_1 = require("./Dynogels");
const ModelDefs = {};
function getModelDefinition(name) {
if (!ModelDefs[name]) {
ModelDefs[name] = { schema: {}, indexes: [] };
}
return ModelDefs[name];
}
function Model(target) {
const modelName = target.prototype.constructor.name;
const def = getModelDefinition(modelName);
target.setSchema(modelName, def);
}
exports.Model = Model;
function SubModel(target) {
const modelName = target.prototype.constructor.name;
const def = getModelDefinition(modelName);
ModelDefs[modelName] = Dynogels_1.types.object().keys(def.schema);
}
exports.SubModel = SubModel;
function HashKey(target, property) {
const modelName = target.constructor.name;
const def = getModelDefinition(modelName);
def.hashKey = property;
}
exports.HashKey = HashKey;
function RangeKey(target, property) {
const modelName = target.constructor.name;
const def = getModelDefinition(modelName);
def.rangeKey = property;
}
exports.RangeKey = RangeKey;
function getModelDefinitionByVariantType(type) {
if (typeof type === 'string') {
return getModelDefinition(type);
}
else if (typeof type === 'function') {
return getModelDefinition(type.prototype.constructor.name);
}
else {
return type;
}
}
function Field(type) {
// tslint:disable-next-line: only-arrow-functions
return function (target, property) {
const modelName = target.constructor.name;
const def = getModelDefinition(modelName);
def.schema[property] = getModelDefinitionByVariantType(type);
};
}
exports.Field = Field;
function ArrayField(type) {
// tslint:disable-next-line: only-arrow-functions
return function (target, property) {
const modelName = target.constructor.name; // AdDisplaySlot
const def = getModelDefinition(modelName);
const arrayModel = getModelDefinitionByVariantType(type);
def.schema[property] = Dynogels_1.types.array().items(arrayModel);
};
}
exports.ArrayField = ArrayField;
function GlobalIndex(hashKey, rangeKey, projection) {
// tslint:disable-next-line: only-arrow-functions
return function (target, property) {
const modelName = target.prototype.constructor.name;
const def = getModelDefinition(modelName);
const globalIndex = { name: property, hashKey, type: 'global', projection };
if (rangeKey) {
_.assign(globalIndex, { rangeKey });
}
def.indexes.push(globalIndex);
target[property] = `${property.toString()}`;
};
}
exports.GlobalIndex = GlobalIndex;
function LocalIndex(rangeKey) {
// tslint:disable-next-line: only-arrow-functions
return function (target, property) {
const modelName = target.prototype.constructor.name;
const def = getModelDefinition(modelName);
const localIndex = { name: property, hashKey: def.hashKey, rangeKey, type: 'local' };
def.indexes.push(localIndex);
target[property] = `${property.toString()}`;
};
}
exports.LocalIndex = LocalIndex;
4 changes: 4 additions & 0 deletions packages/dynamo/lib/Dynogels.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare function getEndPoint(): string;
declare function define(name: any, schema: any): any;
declare const types: any;
export { types, define, getEndPoint };
61 changes: 61 additions & 0 deletions packages/dynamo/lib/Dynogels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const AWS = __importStar(require("aws-sdk"));
const dynogels = __importStar(require("dynogels-promisified"));
const Joi = __importStar(require("joi"));
const _ = __importStar(require("lodash"));
/**
* enabled WARN log level on all tables
*/
// import * as logger from 'winston';
// dynogels.log = logger;
const { NODE_ENV } = process.env;
const useRealDatabase = Boolean(NODE_ENV && ['real-prod', 'production', 'real-alpha', 'alpha'].indexOf(NODE_ENV) > -1);
function getEndPoint() {
return 'http://localhost:11505';
}
exports.getEndPoint = getEndPoint;
if (!useRealDatabase) {
if (NODE_ENV === 'test') {
const dynamodb = new AWS.DynamoDB({
endpoint: getEndPoint(),
accessKeyId: 'mock',
secretAccessKey: 'mock',
region: 'us-east-1',
});
dynogels.dynamoDriver(dynamodb);
}
else {
const dynamodb = new AWS.DynamoDB({
endpoint: getEndPoint(),
region: 'localhost',
});
dynogels.dynamoDriver(dynamodb);
}
}
else if (NODE_ENV === 'real-prod' || NODE_ENV === 'real-alpha') {
const dynamodb = new AWS.DynamoDB({
region: 'ap-northeast-2',
});
dynogels.dynamoDriver(dynamodb);
}
function define(name, schema) {
if (process.env.NODE_ENV === 'test') {
schema.tableName = 'test-' + name;
}
else {
schema.tableName = name;
}
const output = dynogels.define(name, schema);
return output;
}
exports.define = define;
const types = _.assign({}, dynogels.types, Joi);
exports.types = types;
40 changes: 40 additions & 0 deletions packages/dynamo/lib/Query.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { IndexType, ValueTypes } from './Types';
interface RawQueryResult {
LastEvaluatedKey?: ValueTypes;
Count: number;
Items?: any[];
}
interface Query {
usingIndex(index: IndexType): Query;
descending(): Query;
ascending(): Query;
limit(count: number): Query;
where(field: string): Query;
equals(value: ValueTypes): Query;
eq(value: ValueTypes): Query;
filter(field: string): Query;
gt(value: ValueTypes): Query;
gte(value: ValueTypes): Query;
lt(value: ValueTypes): Query;
lte(value: ValueTypes): Query;
beginsWith(value: ValueTypes): Query;
between(fromValue: ValueTypes, toValue: ValueTypes): Query;
ne(value: ValueTypes): Query;
null(): Query;
notNull(): Query;
exists(): Query;
contains(value: ValueTypes): Query;
notContains(value: ValueTypes): Query;
in(values: ValueTypes[]): Query;
select(field: string): Query;
attributes(fields: string[]): Query;
startKey(key: string): Query;
loadAll(): Query;
consistentRead(): Query;
returnConsumedCapacity(): Query;
filterExpression(expr: string): Query;
expressionAttributeValues(params: any): Query;
expressionAttributeNames(params: any): Query;
execAsync(): Promise<RawQueryResult>;
}
export default Query;
2 changes: 2 additions & 0 deletions packages/dynamo/lib/Query.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
Loading

0 comments on commit 82c4865

Please sign in to comment.