UNPKG

pims

Version:

An ORM for document-oriented database systems, written in and for TypeScript.

143 lines 7.47 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const index_1 = require("./index"); const model_1 = require("../model"); const relationships_1 = require("../relationships"); const column_1 = require("../column"); function getHasAndBelongsName(leftName, rightName) { if (leftName < rightName) { return `${leftName}_${rightName}`; } return `${rightName}_${leftName}`; } class AdapterBase { constructor(opts) { this.models = opts.models; const tableNames = new Map(); opts.models.forEach(model => { model[index_1.adapterKey] = this; const modelInfo = model_1.Model.getInfo(model); const relations = modelInfo.relationships.filter(relation => relation.kind === relationships_1.Relationship.HasAndBelongsToMany); relations.forEach(relation => { const relatedModel = model_1.Model.getInfo(relation.model(model)); let tableName = getHasAndBelongsName(modelInfo.table, relatedModel.table); tableNames.set(tableName, { leftModel: modelInfo, rightModel: relatedModel, }); }); }); Array.from(tableNames.entries()).forEach(([tableName, { leftModel, rightModel }]) => { let LinkedModel = class LinkedModel { }; LinkedModel = __decorate([ model_1.Model({ database: leftModel.database, table: tableName, }) ], LinkedModel); column_1.Column({ primary: true })(LinkedModel.prototype, 'id'); column_1.Column({ secondary: true })(LinkedModel.prototype, `${leftModel.table}_id`); column_1.Column({ secondary: true })(LinkedModel.prototype, `${rightModel.table}_id`); this.models.push(LinkedModel); }); } /** * Ensures all tables exist, and waits for them to be ready. */ ensure() { return Promise.all(this.models.map(this.ensureTable, this)).then(() => undefined); } /** * Save the model to the Database. * * If replace is set to true, the entire model will be **replaced**. Otherwise * default action would be to update the document. */ save(model, replace = false) { return __awaiter(this, void 0, void 0, function* () { const ctor = model.constructor; const modelInfo = model_1.Model.getInfo(ctor); model_1.Model.notify(model, 'beforeSave'); // todo(birtles): Actually figure out what changed. const changed = modelInfo.columns.filter(col => !col.computed).reduce((doc, col) => (Object.assign({}, doc, { [col.key]: model[col.modelKey] })), {}); yield this.updateStore(model, changed, replace); model_1.Model.notify(model, 'afterSave'); return model; }); } delete(model) { return __awaiter(this, void 0, void 0, function* () { const ctor = model.constructor; const modelInfo = model_1.Model.getInfo(ctor); model_1.Model.notify(model, 'beforeDelete'); if (!model[modelInfo.primaryKey]) { throw new Error('Cannot delete model without a populated primary key.'); } yield this.deleteFromStore(model); model_1.Model.notify(model, 'afterDelete'); }); } join(model, relationshipKey, opts = {}) { return __awaiter(this, void 0, void 0, function* () { const ctor = model.constructor; const modelInfo = model_1.Model.getInfo(ctor); const relationship = modelInfo.relationships.find(relationship => relationship.key === relationshipKey); if (!relationship) { throw new Error(`No relationship found for ${relationshipKey}`); } model_1.Model.notify(model, 'beforeJoin', relationship); let joinData; const relationshipModel = relationship.model(model); const relationshipModelInfo = model_1.Model.getInfo(relationshipModel); switch (relationship.kind) { case relationships_1.Relationship.HasMany: joinData = yield this.get(relationshipModel, model[modelInfo.primaryKey], { index: relationship.foreignKey }); if (opts.predicate) { yield Promise.all(joinData.map(opts.predicate)); } break; case relationships_1.Relationship.BelongsTo: joinData = yield this.getOne(relationshipModel, model[relationship.foreignKey]); if (opts.predicate) { yield opts.predicate(joinData); } break; case relationships_1.Relationship.HasOne: joinData = yield this.getOne(relationshipModel, model[modelInfo.primaryKey], { index: relationship.foreignKey }); if (opts.predicate) { yield opts.predicate(joinData); } break; case relationships_1.Relationship.HasAndBelongsToMany: const linkedModels = yield this.get(this.getModelByName(getHasAndBelongsName(modelInfo.table, relationshipModelInfo.table)), model[modelInfo.primaryKey], { index: `${modelInfo.table}_id` }); joinData = yield Promise.all(linkedModels.map(model => this.getOne(relationshipModel, model[`${relationshipModelInfo.table}_id`]))); break; default: throw new Error(`Unhandled relationship type ${relationship.kind}`); } model[relationship.key] = joinData; model_1.Model.notify(model, 'afterJoin', relationship); return model; }); } getModelByName(name) { return this.models.find(model => model_1.Model.getInfo(model).table === name); } } exports.AdapterBase = AdapterBase; //# sourceMappingURL=base.js.map