├── .babelrc ├── .editorconfig ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── dist ├── es2015 │ ├── connection │ │ ├── connector.interface.js │ │ ├── connector.interface.js.map │ │ ├── connector.js │ │ ├── connector.js.map │ │ ├── idb-event.interface.js │ │ └── idb-event.interface.js.map │ ├── errors │ │ ├── invalid-transaction.js │ │ ├── invalid-transaction.js.map │ │ ├── not-found.js │ │ └── not-found.js.map │ ├── index.js │ ├── index.js.map │ ├── migration │ │ ├── migration.interface.js │ │ ├── migration.interface.js.map │ │ ├── migration.js │ │ └── migration.js.map │ ├── models │ │ ├── aggregate.js │ │ ├── aggregate.js.map │ │ ├── base-model.js │ │ ├── base-model.js.map │ │ ├── base-write-actions.js │ │ ├── base-write-actions.js.map │ │ ├── find-fail-actions.js │ │ ├── find-fail-actions.js.map │ │ ├── find-or-create-actions.js │ │ ├── find-or-create-actions.js.map │ │ ├── model.interface.js │ │ ├── model.interface.js.map │ │ ├── model.js │ │ ├── model.js.map │ │ ├── orm-relation-builder.js │ │ ├── orm-relation-builder.js.map │ │ ├── query-builder.js │ │ ├── query-builder.js.map │ │ ├── relation.builder.js │ │ ├── relation.builder.js.map │ │ ├── search-actions.js │ │ ├── search-actions.js.map │ │ ├── transaction-handling.js │ │ └── transaction-handling.js.map │ ├── relations │ │ ├── has-many-multi.js │ │ ├── has-many-multi.js.map │ │ ├── has-many-through-multi.js │ │ ├── has-many-through-multi.js.map │ │ ├── has-many.js │ │ ├── has-many.js.map │ │ ├── has-one.js │ │ ├── has-one.js.map │ │ ├── relation.interface.js │ │ ├── relation.interface.js.map │ │ ├── relations.js │ │ └── relations.js.map │ ├── utils.js │ └── utils.js.map ├── idb.js └── idb.js.map ├── example ├── index.html └── worker.js ├── package.json ├── src ├── connection │ ├── connector.d.ts │ ├── connector.interface.d.ts │ ├── connector.interface.ts │ ├── connector.ts │ ├── idb-event.interface.d.ts │ └── idb-event.interface.ts ├── errors │ ├── invalid-transaction.d.ts │ ├── invalid-transaction.ts │ ├── not-found.d.ts │ └── not-found.ts ├── index.d.ts ├── index.ts ├── migration │ ├── migration.d.ts │ ├── migration.interface.d.ts │ ├── migration.interface.ts │ └── migration.ts ├── models │ ├── aggregate.d.ts │ ├── aggregate.ts │ ├── base-model.d.ts │ ├── base-model.ts │ ├── base-write-actions.d.ts │ ├── base-write-actions.ts │ ├── find-fail-actions.d.ts │ ├── find-fail-actions.ts │ ├── find-or-create-actions.d.ts │ ├── find-or-create-actions.ts │ ├── model.d.ts │ ├── model.interface.d.ts │ ├── model.interface.ts │ ├── model.ts │ ├── orm-relation-builder.d.ts │ ├── orm-relation-builder.ts │ ├── query-builder.d.ts │ ├── query-builder.ts │ ├── relation.builder.d.ts │ ├── relation.builder.ts │ ├── search-actions.d.ts │ ├── search-actions.ts │ ├── transaction-handling.d.ts │ └── transaction-handling.ts ├── relations │ ├── has-many-multi.d.ts │ ├── has-many-multi.ts │ ├── has-many-through-multi.d.ts │ ├── has-many-through-multi.ts │ ├── has-many.d.ts │ ├── has-many.ts │ ├── has-one.d.ts │ ├── has-one.ts │ ├── relation.interface.d.ts │ ├── relation.interface.ts │ ├── relations.d.ts │ └── relations.ts ├── utils.d.ts └── utils.ts ├── tsconfig.json ├── tslint.json ├── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/env"], 3 | "plugins": ["@babel/plugin-transform-runtime"] 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at max.gaurav@ithands.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **ORM version:** (check one with "x") 2 | [ ] **1.x** 3 | [ ] **2.x** 4 | 5 | **I'm submitting a ...** (check one with "x") 6 | ``` 7 | [ ] bug report => search github for a similar issue or PR before submitting 8 | [ ] feature request 9 | [ ] support request => Please do not submit support request here, instead use WordPress forums 10 | ``` 11 | 12 | **Tell about your platform** 13 | * Operating System : x.x.x 14 | * Browser and version: Chrome|Firefox|Safari|IE|Edge vx.x.x 15 | 16 | 17 | **Current behavior** 18 | 19 | 20 | **Expected behavior** 21 | 22 | 23 | **Steps to reproduce:** 24 | 25 | 26 | **Minimal reproduction of the problem with instructions** 27 | 30 | 31 | **Related code:** 32 | 33 | ``` 34 | insert any relevant code here 35 | ``` 36 | 37 | **Relevant error:** 38 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **ORM version:** (check one with "x") 2 | ``` 3 | [ ] 1.x 4 | [ ] 2.x 5 | ``` 6 | 7 | **What kind of change does this PR introduce?** (check one with "x") 8 | ``` 9 | [ ] Bugfix 10 | [ ] Feature 11 | [ ] Code style update (formatting, local variables) 12 | [ ] Refactoring (no functional changes) 13 | [ ] Build related changes 14 | [ ] CI related changes 15 | [ ] Other... Please describe: 16 | ``` 17 | 18 | **Tell about your platform if it fixes a bug** 19 | * Operating System : x.x.x 20 | * Browser and version: Chrome|Firefox|Safari|IE|Edge vx.x.x 21 | 22 | **What is the current behavior?** (You can also link to an open issue here) 23 | 24 | 25 | **What is the new behavior?** -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /node_modules 3 | .DS_Store 4 | dist/es2015/tsconfig.tsbuildinfo 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [3.2.1](https://github.com/maxgaurav/indexeddb-orm/releases/tag/v3.2.1) _(Latest Release)_ 4 | 5 | ### Added 6 | - Added close connection function **close** to close currently open connection 7 | 8 | ## [3.2.0](https://github.com/maxgaurav/indexeddb-orm/releases/tag/v3.2.0) 9 | ### Bug Fixes 10 | - Fix **openTransaction** on model not returning ORM Class. 11 | 12 | ### Added 13 | - Sync actions **(sync, syncIndex, syncIndexAll)** to update and retrieve the updated record on success. 14 | - Added schema configuration to allow opt-in for maintaining synced on date when calling sync actions. Will add/update **syncOn** attribute 15 | - Added **saveIndex** to save data on index. It's optimized for single action transaction over update 16 | - Added **saveAllIndex** to save data on all matching index. 17 | 18 | ### Changed 19 | - **Connector** class and **index** file refactored to remove reference of **window** action so that the package can be imported in web workers. 20 | 21 | ### Other 22 | - Refactored **model.ts** file to multiple files to maintain single file single responsibility principle. 23 | 24 | ## [3.1.1](https://github.com/maxgaurav/indexeddb-orm/releases/tag/v3.1.1) 25 | ### Bug Fixes 26 | - Fixed find or create actions some times opening in read mode only 27 | 28 | ### Added 29 | - Find or create actions now throw **InvalidTransaction** error if transaction is not in write mode 30 | 31 | ## [3.1.0](https://github.com/maxgaurav/indexeddb-orm/releases/tag/v3.1.0) 32 | ### Added 33 | - Add **firstOrFail, findOrFail, findIndexOrFail** actions which will find the value or throw **NotFound** error 34 | - Add **firstOrCreate, findOrCreate, findIndexOrCreate** actions which will find the value or create new value return it. 35 | - Add **findAllIndex** action which will return all values as array for the matching index. 36 | 37 | ### Changed 38 | - **save** now throws **NotFound** Error over default Error. 39 | - **findIndex** resets the builder settings before finding on index. 40 | - Readme changes with latest usage of library. 41 | 42 | ### Bug Fixes 43 | - Fix: Orm Class instance mapping in Schema for typescript causing interface mismatch 44 | 45 | 46 | ## [3.0.1](https://github.com/maxgaurav/indexeddb-orm/releases/tag/v3.0.1) 47 | - Readme changes 48 | 49 | ## [3.0.0](https://github.com/maxgaurav/indexeddb-orm/releases/tag/v3.0.0) 50 | 51 | ### Added 52 | - Added **with** to add relation handling. Takes in array of relations. 53 | - Added **withCustom** to add relation of ORM as string values. 54 | - Added **delete** to replace **destroyId**. 55 | - Added **deleteIndex** to delete matching values directly on index. 56 | - Added ORM class instance extending Model class to be used over default Model class 57 | - Added new relation **HasManyThroughMultiEntry**. 58 | - Providing both es6 module for modular programming and direct script based injection through **idb.js** 59 | 60 | ### Deprecation 61 | - Deprecated **relation** function on models to add relation. Use **with**. 62 | - Deprecated **destroyId** function mon models. Use **delete**. 63 | 64 | ### Removals 65 | - Worker instance handling 66 | - Deletion of indexes and object stores by providing drop settings is removed. These are now handled automatically by comparing 67 | existing database structure with table schemas provided. 68 | 69 | ## [2.1.0](https://github.com/maxgaurav/indexeddb-orm) 70 | - Addition of Multi-Entry relation 71 | - Add documentation of usage of multi-entry relation 72 | 73 | ## [2.0.0](https://github.com/maxgaurav/indexeddb-orm) Release _(Breaking Changes)_ 74 | 75 | ### Change 76 | - Main code base moved to typescript 77 | - Web Worker handling changed from event driven to MessageChannel 78 | - MessageChannel implementation in future will allow use of SharedArrayBuffer to improve performance 79 | - Settings now takes **name** over **dbName** for database name 80 | - Settings now takes **version** over **dbVersion** for database version 81 | - New **idb** instance now takes in settings, useWebworker and pathToWebworker parameters over single config settings 82 | - Primary keyPath of objectstores/tables changed to **_id** from **id** 83 | 84 | ### Added 85 | - Dedicated transaction action to both main thread and worker thread 86 | - DB instance gives access to Migration 87 | - DB instance gives access to IDBDatabase 88 | - Models now have **openTransaction** function to create dedicated transaction 89 | 90 | ### Updated 91 | - Model interaction handling to code to be asynchronous 92 | 93 | ### Fixed 94 | - Nested relation not working with normal transaction 95 | 96 | ### Removed 97 | - Removed build folder and replaced with dist folder 98 | - Removed **transaction** function from the main database **DB** instance. Instead use **_model_.openTransaction** 99 | - Removed **get** function and replaced with **all**. 100 | 101 | ## [1.0.1](https://github.com/maxgaurav/indexeddb-orm/tree/orm-1.0.1) Initial Release 102 | - Add base DB interface 103 | - Add migrations 104 | - Add models content on DB connect 105 | - Base Model interaction 106 | - Web Worker implementation 107 | - Model Relations 108 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Max Gaurav 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /dist/es2015/connection/connector.interface.js: -------------------------------------------------------------------------------- 1 | //# sourceMappingURL=connector.interface.js.map -------------------------------------------------------------------------------- /dist/es2015/connection/connector.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"connector.interface.js","sourceRoot":"","sources":["../../../src/connection/connector.interface.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/es2015/connection/connector.js: -------------------------------------------------------------------------------- 1 | import { Migration } from "../migration/migration.js"; 2 | import { Model } from "../models/model.js"; 3 | /** 4 | * 5 | */ 6 | export class Connector { 7 | constructor(migrationSchema) { 8 | this.migrationSchema = migrationSchema; 9 | /** 10 | * Database open request 11 | */ 12 | this.dbOpenConnection = null; 13 | /** 14 | * Migration builder instance 15 | */ 16 | this.migration = null; 17 | /** 18 | * IndexedDB Database instance 19 | */ 20 | this.database = null; 21 | } 22 | /** 23 | * Create/Update and connects the database 24 | */ 25 | connect() { 26 | this.dbOpenConnection = this.indexedDB().open(this.migrationSchema.name, this.migrationSchema.version); 27 | return new Promise((resolve, reject) => { 28 | if (this.dbOpenConnection === null) { 29 | throw new Error('Database connection did not open'); 30 | } 31 | this.dbOpenConnection.addEventListener('success', (event) => { 32 | const models = this.completeHandler(event); 33 | resolve(models); 34 | }); 35 | this.dbOpenConnection.addEventListener('error', (event) => { 36 | reject(event); 37 | }); 38 | this.dbOpenConnection.addEventListener('upgradeneeded', async (event) => { 39 | await this.migrateHandler(event); 40 | }); 41 | }); 42 | } 43 | /** 44 | * Deletes the database 45 | */ 46 | destroy(databaseName) { 47 | const request = this.indexedDB().deleteDatabase(databaseName); 48 | return new Promise((resolve, reject) => { 49 | request.addEventListener('success', () => resolve(true)); 50 | request.addEventListener('error', (e) => reject(e)); 51 | }); 52 | } 53 | /** 54 | * Returns the IDBFactory. 55 | */ 56 | indexedDB() { 57 | const idb = indexedDB || self.indexedDB || self.mozIndexedDB || self.webkitIndexedDB || self.msIndexedDB; 58 | if (!idb) { 59 | throw new Error("IndexedDB constructor not found in environment"); 60 | } 61 | return idb; 62 | } 63 | /** 64 | * Called when database version is updated. Runs migrations to update schema structure 65 | * @param event 66 | */ 67 | async migrateHandler(event) { 68 | const migration = new Migration(this.migrationSchema.tables, event.target.result, event.target.transaction); 69 | this.migrationSchema.tables = await migration.run(); 70 | return true; 71 | } 72 | /** 73 | * Called when connection to database is successful. Creates various models for the tables. 74 | * @param event 75 | */ 76 | completeHandler(event) { 77 | const storeNames = this.migrationSchema.tables.map(table => table.name); 78 | const transaction = event.target.transaction || event.target.result.transaction(storeNames); 79 | this.database = event.target.result; 80 | const migration = new Migration(this.migrationSchema.tables, event.target.result, transaction); 81 | this.migration = migration; 82 | const stores = migration.listObjectStores(); 83 | const models = {}; 84 | for (const store of stores) { 85 | const table = this.migrationSchema.tables.find(schema => schema.name === store.name); 86 | Object.defineProperty(models, store.name, { 87 | get: () => { 88 | if (table.ormClass) { 89 | return new table.ormClass(event.target.result, table, this); 90 | } 91 | else { 92 | return new Model(event.target.result, table, this); 93 | } 94 | } 95 | }); 96 | } 97 | return models; 98 | } 99 | /** 100 | * Returns migration instance 101 | */ 102 | getMigration() { 103 | return this.migration; 104 | } 105 | /** 106 | * Returns database instance 107 | */ 108 | getDatabase() { 109 | return this.database; 110 | } 111 | /** 112 | * Opens a transaction to allow fine control on commits. 113 | * @param mode 114 | */ 115 | openTransaction(mode) { 116 | if (this.database === null) { 117 | throw new Error('First initialize the connection using connect.'); 118 | } 119 | const transaction = this.database.transaction(this.migrationSchema.tables.map(table => table.name)); 120 | const models = {}; 121 | for (const table of this.migrationSchema.tables) { 122 | Object.defineProperty(models, table.name, { 123 | get: () => { 124 | const model = new Model(this.database, table, this); 125 | model.setTransaction(transaction); 126 | return model; 127 | } 128 | }); 129 | } 130 | return { models, transaction }; 131 | } 132 | /** 133 | * Closes currently open connection to database 134 | */ 135 | close() { 136 | if (this.database) { 137 | this.database.close(); 138 | return Promise.resolve(true); 139 | } 140 | return Promise.reject('No Connection open'); 141 | } 142 | } 143 | //# sourceMappingURL=connector.js.map -------------------------------------------------------------------------------- /dist/es2015/connection/connector.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"connector.js","sourceRoot":"","sources":["../../../src/connection/connector.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/es2015/connection/idb-event.interface.js: -------------------------------------------------------------------------------- 1 | //# sourceMappingURL=idb-event.interface.js.map -------------------------------------------------------------------------------- /dist/es2015/connection/idb-event.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"idb-event.interface.js","sourceRoot":"","sources":["../../../src/connection/idb-event.interface.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/es2015/errors/invalid-transaction.js: -------------------------------------------------------------------------------- 1 | export class InvalidTransaction extends Error { 2 | } 3 | //# sourceMappingURL=invalid-transaction.js.map -------------------------------------------------------------------------------- /dist/es2015/errors/invalid-transaction.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"invalid-transaction.js","sourceRoot":"","sources":["../../../src/errors/invalid-transaction.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;CAE5C"} -------------------------------------------------------------------------------- /dist/es2015/errors/not-found.js: -------------------------------------------------------------------------------- 1 | export class NotFound extends Error { 2 | constructor() { 3 | super('Record not found'); 4 | } 5 | } 6 | //# sourceMappingURL=not-found.js.map -------------------------------------------------------------------------------- /dist/es2015/errors/not-found.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"not-found.js","sourceRoot":"","sources":["../../../src/errors/not-found.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC;QACE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC5B,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/index.js: -------------------------------------------------------------------------------- 1 | import { Connector } from "./connection/connector.js"; 2 | import { Model } from "./models/model.js"; 3 | import { Migration } from "./migration/migration.js"; 4 | import { CursorDirection, RelationTypes, TransactionModes } from "./models/model.interface.js"; 5 | ((self) => { 6 | self.idb = (schema) => { 7 | return new Connector(schema); 8 | }; 9 | self.idbTypes = { 10 | CursorTypes: { 11 | 'AscendingUnique': CursorDirection.AscendingUnique, 12 | 'Ascending': CursorDirection.Ascending, 13 | 'Descending': CursorDirection.Descending, 14 | 'DescendingUnique': CursorDirection.DescendingUnique 15 | }, 16 | RelationTypes: { 17 | 'HasManyThroughMultiEntry': RelationTypes.HasManyThroughMultiEntry, 18 | 'HasManyMultiEntry': RelationTypes.HasManyMultiEntry, 19 | 'HasMany': RelationTypes.HasMany, 20 | 'HasOne': RelationTypes.HasOne 21 | }, 22 | TransactionModes: { 23 | 'ReadOnly': TransactionModes.ReadOnly, 24 | 'Write': TransactionModes.Write, 25 | 'VersionChange': TransactionModes.VersionChange, 26 | } 27 | }; 28 | })(self); 29 | export { Connector, Model, Migration, RelationTypes, CursorDirection }; 30 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/es2015/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAC,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAC,MAAM,6BAA6B,CAAC;AAG7F,CAAC,CAAC,IAAI,EAAE,EAAE;IAER,IAAI,CAAC,GAAG,GAAG,CAAC,MAAgB,EAAE,EAAE;QAC9B,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,IAAI,CAAC,QAAQ,GAAG;QACd,WAAW,EAAE;YACX,iBAAiB,EAAE,eAAe,CAAC,eAAe;YAClD,WAAW,EAAE,eAAe,CAAC,SAAS;YACtC,YAAY,EAAE,eAAe,CAAC,UAAU;YACxC,kBAAkB,EAAE,eAAe,CAAC,gBAAgB;SACrD;QACD,aAAa,EAAE;YACb,0BAA0B,EAAE,aAAa,CAAC,wBAAwB;YAClE,mBAAmB,EAAE,aAAa,CAAC,iBAAiB;YACpD,SAAS,EAAE,aAAa,CAAC,OAAO;YAChC,QAAQ,EAAE,aAAa,CAAC,MAAM;SAC/B;QACD,gBAAgB,EAAE;YAChB,UAAU,EAAE,gBAAgB,CAAC,QAAQ;YACrC,OAAO,EAAE,gBAAgB,CAAC,KAAK;YAC/B,eAAe,EAAE,gBAAgB,CAAC,aAAa;SAChD;KACF,CAAC;AACJ,CAAC,CAAC,CAAC,IAAW,CAAC,CAAC;AAGhB,OAAO,EAAC,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAC,CAAC"} -------------------------------------------------------------------------------- /dist/es2015/migration/migration.interface.js: -------------------------------------------------------------------------------- 1 | export const DEFAULT_SYNC_COLUMN_NAME = 'syncOn'; 2 | //# sourceMappingURL=migration.interface.js.map -------------------------------------------------------------------------------- /dist/es2015/migration/migration.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"migration.interface.js","sourceRoot":"","sources":["../../../src/migration/migration.interface.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,wBAAwB,GAAG,QAAQ,CAAC"} -------------------------------------------------------------------------------- /dist/es2015/migration/migration.js: -------------------------------------------------------------------------------- 1 | import { DEFAULT_SYNC_COLUMN_NAME } from "./migration.interface.js"; 2 | import { DEFAULT_PRIMARY_ID } from "../models/model.interface.js"; 3 | export class Migration { 4 | constructor(tables, db, transaction) { 5 | this.tables = tables; 6 | this.db = db; 7 | this.transaction = transaction; 8 | } 9 | /** 10 | * Runs the migration action to update the database with new stores or deletes unwanted stored and then creates or 11 | * drops indexes for the stores. 12 | */ 13 | async run() { 14 | for (const table of this.tables) { 15 | if (!this.db.objectStoreNames.contains(table.name)) { 16 | table.objectStore = this.createObjectStore(table); 17 | } 18 | else { 19 | table.objectStore = this.transaction.objectStore(table.name); 20 | } 21 | this.createColumns(table, table.objectStore); 22 | this.dropOldColumns(table, table.objectStore); 23 | this.setupSyncColumn(table, table.objectStore); 24 | } 25 | for (const tableName of this.allStoreNames()) { 26 | if (!this.tables.find(table => table.name === tableName)) { 27 | this.db.deleteObjectStore(tableName); 28 | } 29 | } 30 | return this.tables; 31 | } 32 | /** 33 | * Creates an index in object store 34 | * @param column 35 | * @param objectStore 36 | */ 37 | createIndex(column, objectStore) { 38 | const attributes = column.attributes || {}; 39 | const index = column.index || column.name; 40 | return objectStore.createIndex(column.name, index, attributes); 41 | } 42 | /** 43 | * Drops an index in object store 44 | * @param column 45 | * @param objectStore 46 | */ 47 | dropIndex(column, objectStore) { 48 | objectStore.deleteIndex(column); 49 | return true; 50 | } 51 | /** 52 | * Creates new object store 53 | * @param schema 54 | */ 55 | createObjectStore(schema) { 56 | let primary = schema.primary || DEFAULT_PRIMARY_ID; 57 | return this.db.createObjectStore(schema.name, { 58 | keyPath: primary, 59 | autoIncrement: true 60 | }); 61 | } 62 | /** 63 | * Drops existing object store 64 | * @param schema 65 | */ 66 | dropObjectStore(schema) { 67 | return true; 68 | } 69 | /** 70 | * Creates various indexes on object store 71 | * @param table 72 | * @param objectStore 73 | */ 74 | createColumns(table, objectStore) { 75 | for (const column of table.columns) { 76 | if (!objectStore.indexNames.contains(column.name)) { 77 | column.dbIndex = this.createIndex(column, objectStore); 78 | } 79 | } 80 | } 81 | /** 82 | * Drops indexes in object store 83 | * @param table 84 | * @param objectStore 85 | */ 86 | dropOldColumns(table, objectStore) { 87 | const indexNames = objectStore.indexNames; 88 | for (let i = 0; i < indexNames.length; i++) { 89 | if (!table.columns.find(column => column.name === indexNames[i])) { 90 | this.dropIndex(indexNames[i], objectStore); 91 | } 92 | } 93 | } 94 | /** 95 | * Returns a list of all object store names which are in current database 96 | */ 97 | allStoreNames() { 98 | const names = []; 99 | for (let i = 0; i < this.db.objectStoreNames.length; i++) { 100 | names.push(this.db.objectStoreNames[i]); 101 | } 102 | return names; 103 | } 104 | /** 105 | * Returns all object store instances in database 106 | */ 107 | listObjectStores() { 108 | const stores = []; 109 | for (const tableName of this.allStoreNames()) { 110 | stores.push(this.transaction.objectStore(tableName)); 111 | } 112 | return stores; 113 | } 114 | /** 115 | * Returns true if column is to be created 116 | * @param schema 117 | * @param objectStore 118 | */ 119 | setupSyncColumn(schema, objectStore) { 120 | const columnName = schema.syncColumnName || DEFAULT_SYNC_COLUMN_NAME; 121 | if (schema.syncColumn) { 122 | if (!objectStore.indexNames.contains(columnName)) { 123 | this.createIndex({ 124 | name: columnName, 125 | index: columnName 126 | }, objectStore); 127 | } 128 | } 129 | else { 130 | if (objectStore.indexNames.contains(columnName)) { 131 | this.dropIndex(columnName, objectStore); 132 | } 133 | } 134 | } 135 | } 136 | //# sourceMappingURL=migration.js.map -------------------------------------------------------------------------------- /dist/es2015/migration/migration.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"migration.js","sourceRoot":"","sources":["../../../src/migration/migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,wBAAwB,EAA+C,MAAM,0BAA0B,CAAC;AAChH,OAAO,EAAC,kBAAkB,EAAC,MAAM,8BAA8B,CAAC;AAEhE,MAAM,OAAO,SAAS;IACpB,YAAmB,MAAqB,EAAS,EAAe,EAAS,WAAkC;QAAxF,WAAM,GAAN,MAAM,CAAe;QAAS,OAAE,GAAF,EAAE,CAAa;QAAS,gBAAW,GAAX,WAAW,CAAuB;IAC3G,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,GAAG;QACd,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;YAC/B,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;gBAClD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;aAEnD;iBAAM;gBACL,KAAK,CAAC,WAAW,GAAI,IAAI,CAAC,WAA8B,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;aAClF;YAED,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;YAC7C,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;YAC9C,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;SAChD;QAED,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE;YAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE;gBACxD,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;aACtC;SACF;QAED,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACI,WAAW,CAAC,MAAmB,EAAE,WAA2B;QACjE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC;QAC1C,OAAO,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IACjE,CAAC;IAED;;;;OAIG;IACI,SAAS,CAAC,MAAc,EAAE,WAA2B;QAC1D,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAEhC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACI,iBAAiB,CAAC,MAAmB;QAC1C,IAAI,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,kBAAkB,CAAC;QAEnD,OAAO,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE;YAC5C,OAAO,EAAE,OAAO;YAChB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACI,eAAe,CAAC,MAAmB;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACO,aAAa,CAAC,KAAkB,EAAE,WAA2B;QACrE,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE;YAElC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;gBACjD,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;aACxD;SACF;IACH,CAAC;IAED;;;;OAIG;IACO,cAAc,CAAC,KAAkB,EAAE,WAA2B;QACtE,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;gBAChE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;aAC5C;SACF;IAEH,CAAC;IAED;;OAEG;IACK,aAAa;QACnB,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACxD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;SACzC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACI,gBAAgB;QACrB,MAAM,MAAM,GAAqB,EAAE,CAAC;QACpC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAE,IAAI,CAAC,WAA8B,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;SAC1E;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACI,eAAe,CAAC,MAAmB,EAAE,WAA2B;QACrE,MAAM,UAAU,GAAG,MAAM,CAAC,cAAc,IAAI,wBAAwB,CAAC;QAErE,IAAI,MAAM,CAAC,UAAU,EAAE;YACrB,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;gBAChD,IAAI,CAAC,WAAW,CAAC;oBACf,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,UAAU;iBAClB,EAAE,WAAW,CAAC,CAAC;aACjB;SAEF;aAAM;YACL,IAAI,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;gBAC/C,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;aACzC;SACF;IACH,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/models/aggregate.js: -------------------------------------------------------------------------------- 1 | import { TransactionModes } from "./model.interface.js"; 2 | import { nestedAttributeValue } from "../utils.js"; 3 | import { BaseModel } from "./base-model.js"; 4 | export class Aggregate extends BaseModel { 5 | constructor(db, table) { 6 | super(); 7 | this.db = db; 8 | this.table = table; 9 | } 10 | /** 11 | * Returns the count of matching records 12 | */ 13 | count() { 14 | const tables = [this.table.name]; 15 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 16 | const objectStore = transaction.objectStore(this.table.name); 17 | let request; 18 | if (this.builder.length === 0 && this.indexBuilder === null) { 19 | request = objectStore.count(); 20 | } 21 | else if (this.builder.length === 0 && this.indexBuilder !== null) { 22 | request = objectStore.count(this.keyRange(this.indexBuilder)); 23 | } 24 | else { 25 | request = this.request(objectStore); 26 | } 27 | return new Promise((resolve, reject) => { 28 | let count = 0; 29 | request.addEventListener("success", async (event) => { 30 | if (this.builder.length === 0) { 31 | return resolve(event.target.result); 32 | } 33 | const cursor = event.target.result; 34 | if (cursor) { 35 | if (!this.allowedToProcess(cursor.value)) { 36 | return cursor.continue(); 37 | } 38 | count++; 39 | return cursor.continue(); 40 | } 41 | resolve(count); 42 | }); 43 | request.addEventListener("error", (error) => reject(error)); 44 | }); 45 | } 46 | /** 47 | * Returns average of attribute value on matching records. 48 | * If value is not numeric then its skipped 49 | * @param attribute 50 | */ 51 | average(attribute) { 52 | const tables = [this.table.name]; 53 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 54 | const objectStore = transaction.objectStore(this.table.name); 55 | const request = this.request(objectStore); 56 | return new Promise((resolve, reject) => { 57 | let count = 0; 58 | let total = 0; 59 | request.addEventListener("success", async (event) => { 60 | const cursor = event.target.result; 61 | if (cursor) { 62 | if (!this.allowedToProcess(cursor.value)) { 63 | return cursor.continue(); 64 | } 65 | const value = nestedAttributeValue(attribute, cursor.value); 66 | if (!isNaN(parseFloat(value))) { 67 | total += parseFloat(cursor.value[attribute]); 68 | } 69 | count++; 70 | return cursor.continue(); 71 | } 72 | resolve(total / count); 73 | }); 74 | request.addEventListener("error", (error) => reject(error)); 75 | }); 76 | } 77 | reduce(func, defaultCarry) { 78 | const tables = [this.table.name]; 79 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 80 | const objectStore = transaction.objectStore(this.table.name); 81 | const request = this.request(objectStore); 82 | return new Promise((resolve, reject) => { 83 | let result = defaultCarry; 84 | request.addEventListener("success", async (event) => { 85 | const cursor = event.target.result; 86 | if (cursor) { 87 | if (!this.allowedToProcess(cursor.value)) { 88 | return cursor.continue(); 89 | } 90 | result = func(cursor.value, result); 91 | return cursor.continue(); 92 | } 93 | resolve(result); 94 | }); 95 | request.addEventListener("error", (error) => reject(error)); 96 | }); 97 | } 98 | } 99 | //# sourceMappingURL=aggregate.js.map -------------------------------------------------------------------------------- /dist/es2015/models/aggregate.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../../src/models/aggregate.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/es2015/models/base-model.js: -------------------------------------------------------------------------------- 1 | import { TransactionHandling } from "./transaction-handling.js"; 2 | export class BaseModel extends TransactionHandling { 3 | /** 4 | * Opens IDBRequest to perform action on object store 5 | * @param objectStore 6 | */ 7 | request(objectStore) { 8 | const direction = this.cursor || undefined; 9 | if (this.indexBuilder) { 10 | const keyRange = this.keyRange(this.indexBuilder); 11 | const cursor = this.indexBuilder.index !== this.primaryId ? objectStore.index(this.indexBuilder.index) : objectStore; 12 | return cursor.openCursor(keyRange, direction); 13 | } 14 | else { 15 | return objectStore.openCursor(undefined, direction); 16 | } 17 | } 18 | } 19 | //# sourceMappingURL=base-model.js.map -------------------------------------------------------------------------------- /dist/es2015/models/base-model.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"base-model.js","sourceRoot":"","sources":["../../../src/models/base-model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,2BAA2B,CAAC;AAG9D,MAAM,OAAgB,SAAU,SAAQ,mBAAmB;IAMzD;;;OAGG;IACO,OAAO,CAAC,WAA2B;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC;QAE3C,IAAI,IAAI,CAAC,YAAY,EAAE;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;YACrH,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;SAC/C;aAAM;YACL,OAAO,WAAW,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;SACrD;IACH,CAAC;CAEF"} -------------------------------------------------------------------------------- /dist/es2015/models/base-write-actions.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"base-write-actions.js","sourceRoot":"","sources":["../../../src/models/base-write-actions.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/es2015/models/find-fail-actions.js: -------------------------------------------------------------------------------- 1 | import { SearchActions } from "./search-actions.js"; 2 | import { NotFound } from "../errors/not-found.js"; 3 | export class FindFailActions extends SearchActions { 4 | async firstOrFail() { 5 | const record = await this.first(); 6 | if (!record) { 7 | throw new NotFound(); 8 | } 9 | return record; 10 | } 11 | async findOrFail(id) { 12 | const record = await this.find(id); 13 | if (!record) { 14 | throw new NotFound(); 15 | } 16 | return record; 17 | } 18 | async findIndexOrFail(indexName, id) { 19 | const record = await this.findIndex(indexName, id); 20 | if (!record) { 21 | throw new NotFound(); 22 | } 23 | return record; 24 | } 25 | } 26 | //# sourceMappingURL=find-fail-actions.js.map -------------------------------------------------------------------------------- /dist/es2015/models/find-fail-actions.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"find-fail-actions.js","sourceRoot":"","sources":["../../../src/models/find-fail-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAEhD,MAAM,OAAgB,eAAgB,SAAQ,aAAa;IAOlD,KAAK,CAAC,WAAW;QACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAElC,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,IAAI,QAAQ,EAAE,CAAC;SACtB;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAQM,KAAK,CAAC,UAAU,CAAC,EAAO;QAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,IAAI,QAAQ,EAAE,CAAC;SACtB;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IASM,KAAK,CAAC,eAAe,CAAC,SAAiB,EAAE,EAAO;QACrD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,IAAI,QAAQ,EAAE,CAAC;SACtB;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CAEF"} -------------------------------------------------------------------------------- /dist/es2015/models/find-or-create-actions.js: -------------------------------------------------------------------------------- 1 | import { BaseWriteActions } from "./base-write-actions.js"; 2 | import { TransactionModes } from "./model.interface.js"; 3 | import { InvalidTransaction } from "../errors/invalid-transaction.js"; 4 | export class FindOrCreateActions extends BaseWriteActions { 5 | async firstOrCreate(data) { 6 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 7 | const transaction = this.createTransaction(tables, TransactionModes.Write); 8 | if (transaction.mode !== TransactionModes.Write) { 9 | throw new InvalidTransaction('Transaction not in write mode'); 10 | } 11 | const record = await this.first(); 12 | if (!record) { 13 | return this.create(data); 14 | } 15 | return record; 16 | } 17 | async findOrCreate(id, data) { 18 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 19 | const transaction = this.createTransaction(tables, TransactionModes.Write); 20 | if (transaction.mode !== TransactionModes.Write) { 21 | throw new InvalidTransaction('Transaction not in write mode'); 22 | } 23 | this.setTransaction(transaction); 24 | const record = await this.find(id); 25 | if (!record) { 26 | return this.create(data); 27 | } 28 | return record; 29 | } 30 | async findIndexOrCreate(indexName, id, data) { 31 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 32 | const transaction = this.createTransaction(tables, TransactionModes.Write); 33 | if (transaction.mode !== TransactionModes.Write) { 34 | throw new InvalidTransaction('Transaction not in write mode'); 35 | } 36 | const record = await this.findIndex(indexName, id); 37 | if (!record) { 38 | return this.create(data); 39 | } 40 | return record; 41 | } 42 | } 43 | //# sourceMappingURL=find-or-create-actions.js.map -------------------------------------------------------------------------------- /dist/es2015/models/find-or-create-actions.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"find-or-create-actions.js","sourceRoot":"","sources":["../../../src/models/find-or-create-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAA8B,gBAAgB,EAAC,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAC,kBAAkB,EAAC,MAAM,kCAAkC,CAAC;AAEpE,MAAM,OAAgB,mBAAoB,SAAQ,gBAAgB;IAOzD,KAAK,CAAC,aAAa,CAAC,IAAS;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9F,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC3E,IAAI,WAAW,CAAC,IAAI,KAAK,gBAAgB,CAAC,KAAK,EAAE;YAC/C,MAAM,IAAI,kBAAkB,CAAC,+BAA+B,CAAC,CAAC;SAC/D;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAElC,IAAI,CAAC,MAAM,EAAE;YACX,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;SAC1B;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IASM,KAAK,CAAC,YAAY,CAAC,EAAO,EAAE,IAAS;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9F,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC3E,IAAI,WAAW,CAAC,IAAI,KAAK,gBAAgB,CAAC,KAAK,EAAE;YAC/C,MAAM,IAAI,kBAAkB,CAAC,+BAA+B,CAAC,CAAC;SAC/D;QAED,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAEjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEnC,IAAI,CAAC,MAAM,EAAE;YACX,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;SAC1B;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAUM,KAAK,CAAC,iBAAiB,CAAC,SAAiB,EAAE,EAAO,EAAE,IAAS;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9F,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC3E,IAAI,WAAW,CAAC,IAAI,KAAK,gBAAgB,CAAC,KAAK,EAAE;YAC/C,MAAM,IAAI,kBAAkB,CAAC,+BAA+B,CAAC,CAAC;SAC/D;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAEnD,IAAI,CAAC,MAAM,EAAE;YACX,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;SAC1B;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/models/model.interface.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Default index name and attribute name for auto-generating key 3 | */ 4 | export const DEFAULT_PRIMARY_ID = '_id'; 5 | /** 6 | * Transaction modes available 7 | */ 8 | export var TransactionModes; 9 | (function (TransactionModes) { 10 | TransactionModes["ReadOnly"] = "readonly"; 11 | TransactionModes["Write"] = "readwrite"; 12 | TransactionModes["VersionChange"] = "versionchange"; 13 | })(TransactionModes || (TransactionModes = {})); 14 | /** 15 | * Relation Types available 16 | */ 17 | export var RelationTypes; 18 | (function (RelationTypes) { 19 | RelationTypes["HasOne"] = "hasOne"; 20 | RelationTypes["HasMany"] = "hasMany"; 21 | RelationTypes["HasManyMultiEntry"] = "hasManyMultiEntry"; 22 | RelationTypes["HasManyThroughMultiEntry"] = "hasManyThroughMultiEntry"; 23 | })(RelationTypes || (RelationTypes = {})); 24 | export var QueryTypes; 25 | (function (QueryTypes) { 26 | QueryTypes["Between"] = "between"; 27 | QueryTypes["Where"] = "where"; 28 | QueryTypes["WhereIn"] = "whereIn"; 29 | QueryTypes["WhereInArray"] = "whereInArray"; 30 | QueryTypes["GreaterThan"] = "gt"; 31 | QueryTypes["GreaterThanEqual"] = "gte"; 32 | QueryTypes["LessThanEqual"] = "lte"; 33 | QueryTypes["LessThan"] = "lt"; 34 | })(QueryTypes || (QueryTypes = {})); 35 | export var CursorDirection; 36 | (function (CursorDirection) { 37 | CursorDirection["Ascending"] = "next"; 38 | CursorDirection["AscendingUnique"] = "nextunique"; 39 | CursorDirection["Descending"] = "prev"; 40 | CursorDirection["DescendingUnique"] = "prevunique"; 41 | })(CursorDirection || (CursorDirection = {})); 42 | //# sourceMappingURL=model.interface.js.map -------------------------------------------------------------------------------- /dist/es2015/models/model.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"model.interface.js","sourceRoot":"","sources":["../../../src/models/model.interface.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAcxC;;GAEG;AACH,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,yCAAqB,CAAA;IACrB,uCAAmB,CAAA;IACnB,mDAA+B,CAAA;AACjC,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,kCAAiB,CAAA;IACjB,oCAAmB,CAAA;IACnB,wDAAuC,CAAA;IACvC,sEAAqD,CAAA;AACvD,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB;AA6CD,MAAM,CAAN,IAAY,UASX;AATD,WAAY,UAAU;IACpB,iCAAmB,CAAA;IACnB,6BAAe,CAAA;IACf,iCAAmB,CAAA;IACnB,2CAA6B,CAAA;IAC7B,gCAAkB,CAAA;IAClB,sCAAwB,CAAA;IACxB,mCAAqB,CAAA;IACrB,6BAAe,CAAA;AACjB,CAAC,EATW,UAAU,KAAV,UAAU,QASrB;AAED,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,qCAAkB,CAAA;IAClB,iDAA8B,CAAA;IAC9B,sCAAmB,CAAA;IACnB,kDAA+B,CAAA;AACjC,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B"} -------------------------------------------------------------------------------- /dist/es2015/models/model.js: -------------------------------------------------------------------------------- 1 | import { DEFAULT_PRIMARY_ID, RelationTypes } from "./model.interface.js"; 2 | import { DEFAULT_SYNC_COLUMN_NAME } from "../migration/migration.interface.js"; 3 | import { FindOrCreateActions } from "./find-or-create-actions.js"; 4 | import { HasOne } from "../relations/has-one.js"; 5 | import { HasMany } from "../relations/has-many.js"; 6 | import { HasManyMulti } from "../relations/has-many-multi.js"; 7 | import { HasManyThroughMulti } from "../relations/has-many-through-multi.js"; 8 | import { mergeDeep as mergeDeepUtil } from "../utils.js"; 9 | export class Model extends FindOrCreateActions { 10 | constructor(db, table, connector) { 11 | super(db, table); 12 | this.db = db; 13 | this.table = table; 14 | this.connector = connector; 15 | this.transaction = null; 16 | } 17 | async sync(id, data, mergeDeep = true) { 18 | await this.save(id, this.syncObj(data), mergeDeep); 19 | return this.find(id); 20 | } 21 | async syncIndex(indexName, id, data, mergeDeep = true) { 22 | await this.saveIndex(indexName, id, this.syncObj(data), mergeDeep); 23 | return this.findIndex(indexName, id); 24 | } 25 | async syncAllIndex(indexName, id, data, mergeDeep = true) { 26 | await this.saveAllIndex(indexName, id, this.syncObj(data), mergeDeep); 27 | return this.resetBuilder().whereIndex(indexName, id).all(); 28 | } 29 | /** 30 | * Opens new transaction for all models and returns transaction instance 31 | * @param mode 32 | */ 33 | openTransaction(mode) { 34 | const transaction = this.db.transaction(this.connector.migrationSchema.tables.map(table => table.name)); 35 | const models = {}; 36 | for (const table of this.connector.migrationSchema.tables) { 37 | Object.defineProperty(models, table.name, { 38 | get: () => { 39 | let model; 40 | if (this.table.ormClass) { 41 | model = new this.table.ormClass(this.db, table, this.connector); 42 | } 43 | else { 44 | model = new Model(this.db, table, this.connector); 45 | } 46 | model.setTransaction(transaction); 47 | return model; 48 | } 49 | }); 50 | } 51 | return { models, transaction }; 52 | } 53 | /** 54 | * Loads relations against the model results 55 | * 56 | * @param results 57 | */ 58 | loadRelations(results) { 59 | const relationsArray = []; 60 | for (const relation of this.relations) { 61 | let loader; 62 | switch (relation.type) { 63 | case RelationTypes.HasOne: 64 | loader = new HasOne(this.db, this.connector, this, relation); 65 | relationsArray.push(loader.fetch(results)); 66 | break; 67 | case RelationTypes.HasMany: 68 | loader = new HasMany(this.db, this.connector, this, relation); 69 | relationsArray.push(loader.fetch(results)); 70 | break; 71 | case RelationTypes.HasManyMultiEntry: 72 | loader = new HasManyMulti(this.db, this.connector, this, relation); 73 | relationsArray.push(loader.fetch(results)); 74 | break; 75 | case RelationTypes.HasManyThroughMultiEntry: 76 | loader = new HasManyThroughMulti(this.db, this.connector, this, relation); 77 | relationsArray.push(loader.fetch(results)); 78 | break; 79 | default: 80 | throw new Error(`Unknown relation ${relation.type}`); 81 | } 82 | } 83 | return relationsArray.concat(this.loadCustomRelations(results)); 84 | } 85 | /** 86 | * The primary key of the model 87 | */ 88 | get primaryId() { 89 | return this.table.primary || DEFAULT_PRIMARY_ID; 90 | } 91 | /** 92 | * Loads custom relation created in the ORM classes extending the base model class 93 | * @param results 94 | */ 95 | loadCustomRelations(results) { 96 | const relationPromises = []; 97 | for (const customRelation of this.customRelations) { 98 | if (!Reflect.has(this, customRelation)) { 99 | throw new Error(`Method ${customRelation} not defined.`); 100 | } 101 | const relation = (Reflect.get(this, customRelation)()); 102 | relationPromises.push(relation.fetch(results)); 103 | } 104 | return relationPromises; 105 | } 106 | /** 107 | * Adds sync column if table requires to have sync date 108 | * @param data 109 | */ 110 | syncObj(data) { 111 | if (this.table.syncColumn) { 112 | const attr = this.table.syncColumnName || DEFAULT_SYNC_COLUMN_NAME; 113 | const obj = {}; 114 | obj[attr] = new Date(); 115 | return mergeDeepUtil(data, obj); 116 | } 117 | return data; 118 | } 119 | } 120 | //# sourceMappingURL=model.js.map -------------------------------------------------------------------------------- /dist/es2015/models/model.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/models/model.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/es2015/models/orm-relation-builder.js: -------------------------------------------------------------------------------- 1 | import { QueryBuilder } from "./query-builder.js"; 2 | import { HasOne } from "../relations/has-one.js"; 3 | import { RelationTypes } from "./model.interface.js"; 4 | import { HasMany } from "../relations/has-many.js"; 5 | import { HasManyMulti } from "../relations/has-many-multi.js"; 6 | import { HasManyThroughMulti } from "../relations/has-many-through-multi.js"; 7 | export class OrmRelationBuilder extends QueryBuilder { 8 | /** 9 | * Returns has one relation 10 | * @param model 11 | * @param foreignKey 12 | * @param localKey 13 | * @param parentKeyName 14 | */ 15 | hasOne(model, foreignKey, localKey, parentKeyName) { 16 | const current = this; 17 | const relation = this.convertToRelation(model, RelationTypes.HasOne, foreignKey); 18 | if (localKey) { 19 | relation.localKey = localKey; 20 | } 21 | if (parentKeyName) { 22 | relation.attributeName = parentKeyName; 23 | } 24 | return new HasOne(this.db, this.connector, current, relation); 25 | } 26 | /** 27 | * Returns has many relation 28 | * @param model 29 | * @param foreignKey 30 | * @param localKey 31 | * @param parentKeyName 32 | */ 33 | hasMany(model, foreignKey, localKey, parentKeyName) { 34 | const current = this; 35 | const relation = this.convertToRelation(model, RelationTypes.HasMany, foreignKey); 36 | if (localKey) { 37 | relation.localKey = localKey; 38 | } 39 | if (parentKeyName) { 40 | relation.attributeName = parentKeyName; 41 | } 42 | return new HasMany(this.db, this.connector, current, relation); 43 | } 44 | /** 45 | * Returns has many multi entry relation 46 | * @param model 47 | * @param foreignKey 48 | * @param localKey 49 | * @param parentKeyName 50 | */ 51 | hasManyMultiEntry(model, foreignKey, localKey, parentKeyName) { 52 | const current = this; 53 | const relation = this.convertToRelation(model, RelationTypes.HasManyMultiEntry, foreignKey); 54 | if (localKey) { 55 | relation.localKey = localKey; 56 | } 57 | if (parentKeyName) { 58 | relation.attributeName = parentKeyName; 59 | } 60 | return new HasManyMulti(this.db, this.connector, current, relation); 61 | } 62 | /** 63 | * Returns relation has many through multi entry relation 64 | * @param model 65 | * @param foreignKey 66 | * @param localKey 67 | * @param parentKeyName 68 | */ 69 | hasManyThroughMultiEntry(model, foreignKey, localKey, parentKeyName) { 70 | const current = this; 71 | const relation = this.convertToRelation(model, RelationTypes.HasManyThroughMultiEntry, foreignKey); 72 | if (localKey) { 73 | relation.localKey = localKey; 74 | } 75 | if (parentKeyName) { 76 | relation.attributeName = parentKeyName; 77 | } 78 | return new HasManyThroughMulti(this.db, this.connector, current, relation); 79 | } 80 | convertToRelation(modelConstructor, type, foreignKey) { 81 | const model = this.newModel(modelConstructor); 82 | return { model, type, foreignKey }; 83 | } 84 | newModel(modelConstructor) { 85 | const table = this.connector.migrationSchema.tables.find(tableSchema => tableSchema.name === modelConstructor.TableName); 86 | if (!table) { 87 | throw new Error('Table schema not found'); 88 | } 89 | return new modelConstructor(this.db, table, this.connector); 90 | } 91 | } 92 | //# sourceMappingURL=orm-relation-builder.js.map -------------------------------------------------------------------------------- /dist/es2015/models/orm-relation-builder.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"orm-relation-builder.js","sourceRoot":"","sources":["../../../src/models/orm-relation-builder.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/es2015/models/query-builder.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../../../src/models/query-builder.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/es2015/models/relation.builder.js: -------------------------------------------------------------------------------- 1 | export class RelationBuilder { 2 | constructor() { 3 | /** 4 | * Array of relations to be loaded 5 | */ 6 | this.relations = []; 7 | /** 8 | * Custom relations list 9 | */ 10 | this.customRelations = []; 11 | } 12 | /** 13 | * Returns list of childRelation tables required by the model action 14 | * @param tables 15 | */ 16 | tableNames(tables) { 17 | return tables.map(table => table.name); 18 | } 19 | /** 20 | * Adds childRelation to be fetched 21 | * @param relations 22 | */ 23 | with(relations) { 24 | // first filtering existing relations for same table 25 | const filteredRelations = this.relations.filter(relation => !relations.find(newRelation => newRelation.model === relation.model)); 26 | this.relations = filteredRelations.concat(relations); 27 | return this; 28 | } 29 | /** 30 | * Adds childRelation to be fetched 31 | * 32 | * @deprecated 33 | * @param modelName 34 | * @param type 35 | * @param localKey 36 | * @param foreignKey 37 | * @param func 38 | */ 39 | relation(modelName, type, localKey, foreignKey, func) { 40 | const index = this.relations.findIndex(relation => relation.model === modelName); 41 | if (index !== -1) { 42 | this.relations.splice(index, 1); 43 | } 44 | this.relations.push({ 45 | model: modelName, 46 | type, 47 | localKey, 48 | foreignKey, 49 | func 50 | }); 51 | return this; 52 | } 53 | /** 54 | * Adds custom relations 55 | * @param relations 56 | */ 57 | withCustom(relations) { 58 | const filteredRelations = this.customRelations.filter(relation => !relations.find(newRelation => newRelation === relation)); 59 | this.customRelations = filteredRelations.concat(relations); 60 | return this; 61 | } 62 | } 63 | //# sourceMappingURL=relation.builder.js.map -------------------------------------------------------------------------------- /dist/es2015/models/relation.builder.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"relation.builder.js","sourceRoot":"","sources":["../../../src/models/relation.builder.ts"],"names":[],"mappings":"AAYA,MAAM,OAAgB,eAAe;IAArC;QAEE;;WAEG;QACI,cAAS,GAAe,EAAE,CAAC;QAElC;;WAEG;QACI,oBAAe,GAAa,EAAE,CAAC;IAsExC,CAAC;IApEC;;;OAGG;IACI,UAAU,CAAC,MAAqB;QACrC,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACI,IAAI,CAAC,SAAqB;QAC/B,oDAAoD;QAEpD,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAC7C,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CACzB,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,CAAC,CACvD,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAErD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;OASG;IACI,QAAQ,CACb,SAAiB,EAAE,IAAmB,EAAE,QAAgB,EAAE,UAAkB,EAAE,IAAgE;QAG9I,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;QAEjF,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;YAChB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;SACjC;QAED,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAClB,KAAK,EAAE,SAAS;YAChB,IAAI;YACJ,QAAQ;YACR,UAAU;YACV,IAAI;SACL,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACI,UAAU,CAAC,SAAmB;QACnC,MAAM,iBAAiB,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CACnD,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CACzB,WAAW,CAAC,EAAE,CAAC,WAAW,KAAK,QAAQ,CAAC,CAC3C,CAAC;QACF,IAAI,CAAC,eAAe,GAAG,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAE3D,OAAO,IAAI,CAAC;IACd,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/models/search-actions.js: -------------------------------------------------------------------------------- 1 | import { Aggregate } from "./aggregate.js"; 2 | import { TransactionModes } from "./model.interface.js"; 3 | export class SearchActions extends Aggregate { 4 | all() { 5 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 6 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 7 | const objectStore = transaction.objectStore(this.table.name); 8 | const request = this.request(objectStore); 9 | return new Promise((resolve, reject) => { 10 | let results = []; 11 | request.addEventListener("success", async (event) => { 12 | const cursor = event.target.result; 13 | if (cursor) { 14 | if (!this.allowedToProcess(cursor.value)) { 15 | return cursor.continue(); 16 | } 17 | results.push(cursor.value); 18 | return cursor.continue(); 19 | } 20 | if (results.length === 0 || this.relations.length === 0) { 21 | resolve(results); 22 | } 23 | const relations = this.loadRelations(results); 24 | await Promise.all(relations); 25 | resolve(results); 26 | }); 27 | request.addEventListener("error", (error) => reject(error)); 28 | }); 29 | } 30 | first() { 31 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 32 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 33 | const objectStore = transaction.objectStore(this.table.name); 34 | const request = this.request(objectStore); 35 | return new Promise((resolve, reject) => { 36 | let result; 37 | request.addEventListener("success", async (event) => { 38 | const cursor = event.target.result; 39 | if (cursor) { 40 | if (!this.allowedToProcess(cursor.value)) { 41 | return cursor.continue(); 42 | } 43 | result = cursor.value; 44 | } 45 | if (!result || this.relations.length === 0) { 46 | resolve(result || null); 47 | } 48 | const relations = this.loadRelations([result]); 49 | await Promise.all(relations); 50 | resolve(result); 51 | }); 52 | request.addEventListener("error", (error) => reject(error)); 53 | }); 54 | } 55 | find(id) { 56 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 57 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 58 | const objectStore = transaction.objectStore(this.table.name); 59 | const request = objectStore.get(id); 60 | return new Promise((resolve, reject) => { 61 | request.addEventListener("success", async (event) => { 62 | const result = event.target.result; 63 | if (!result || this.relations.length === 0) { 64 | resolve(result || null); 65 | } 66 | const relations = this.loadRelations([result]); 67 | await Promise.all(relations); 68 | resolve(result || null); 69 | }); 70 | request.addEventListener("error", (error) => reject(error)); 71 | }); 72 | } 73 | findIndex(indexName, id) { 74 | this.resetBuilder(); 75 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 76 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 77 | const objectStore = transaction.objectStore(this.table.name); 78 | const request = objectStore.index(indexName).get(id); 79 | return new Promise((resolve, reject) => { 80 | request.addEventListener("success", async (event) => { 81 | const result = event.target.result; 82 | if (!result || this.relations.length === 0) { 83 | resolve(result || null); 84 | } 85 | const relations = this.loadRelations([result]); 86 | await Promise.all(relations); 87 | resolve(result); 88 | }); 89 | request.addEventListener("error", (error) => reject(error)); 90 | }); 91 | } 92 | findAllIndex(indexName, id) { 93 | this.resetBuilder(); 94 | this.whereIndex(indexName, id); 95 | return this.all(); 96 | } 97 | } 98 | //# sourceMappingURL=search-actions.js.map -------------------------------------------------------------------------------- /dist/es2015/models/search-actions.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"search-actions.js","sourceRoot":"","sources":["../../../src/models/search-actions.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/es2015/models/transaction-handling.js: -------------------------------------------------------------------------------- 1 | import { OrmRelationBuilder } from "./orm-relation-builder.js"; 2 | export class TransactionHandling extends OrmRelationBuilder { 3 | constructor() { 4 | super(...arguments); 5 | this.transaction = null; 6 | } 7 | /** 8 | * Retrieves current transaction and if ne transaction exists then creates new one. 9 | * 10 | * @param stores 11 | * @param mode 12 | * @param overwrite 13 | */ 14 | getTransaction(stores, mode, overwrite = false) { 15 | if (this.transaction === null || overwrite) { 16 | this.transaction = this.createTransaction(stores, mode); 17 | } 18 | return this.transaction; 19 | } 20 | /** 21 | * Sets transaction for the model 22 | * @param transaction 23 | */ 24 | setTransaction(transaction) { 25 | this.transaction = transaction; 26 | } 27 | /** 28 | * Creates new transaction 29 | * @param stores 30 | * @param mode 31 | */ 32 | createTransaction(stores, mode) { 33 | const transaction = this.db.transaction(stores, mode); 34 | this.setTransaction(transaction); 35 | return transaction; 36 | } 37 | } 38 | //# sourceMappingURL=transaction-handling.js.map -------------------------------------------------------------------------------- /dist/es2015/models/transaction-handling.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"transaction-handling.js","sourceRoot":"","sources":["../../../src/models/transaction-handling.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,kBAAkB,EAAC,MAAM,2BAA2B,CAAC;AAE7D,MAAM,OAAgB,mBAAoB,SAAQ,kBAAkB;IAApE;;QAEY,gBAAW,GAA0B,IAAI,CAAC;IAmCtD,CAAC;IAjCC;;;;;;OAMG;IACI,cAAc,CAAC,MAAgB,EAAE,IAAsB,EAAE,YAAqB,KAAK;QACxF,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,SAAS,EAAE;YAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;SACzD;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACI,cAAc,CAAC,WAA2B;QAC/C,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACI,iBAAiB,CAAC,MAAgB,EAAE,IAAsB;QAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAEjC,OAAO,WAAW,CAAC;IACrB,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/relations/has-many-multi.js: -------------------------------------------------------------------------------- 1 | import { Relations } from "./relations.js"; 2 | export class HasManyMulti extends Relations { 3 | constructor(db, connector, parentModel, childRelation) { 4 | super(); 5 | this.db = db; 6 | this.connector = connector; 7 | this.parentModel = parentModel; 8 | this.childRelation = childRelation; 9 | } 10 | async fetch(results) { 11 | let model = this.getRelationModel(this.childRelation); 12 | model = this.filteredModel(model, this.childRelation); 13 | const values = results.map(result => result[this.getLocalKey(this.parentModel, this.childRelation)]); 14 | model.whereMultiIndexIn(this.childRelation.foreignKey, values); 15 | const relationResults = await model.all(); 16 | return this.bindResults(results, relationResults, this.childRelation); 17 | } 18 | bindResults(parentResults, relationResults, relation) { 19 | const localKey = this.getLocalKey(this.parentModel, this.childRelation); 20 | parentResults.forEach(parentResult => { 21 | parentResult[this.getAttributeName(this.parentModel, relation)] = relationResults.filter((relationResult) => !!relationResult[relation.foreignKey].find((multiValue) => multiValue === parentResult[localKey])); 22 | }); 23 | return Promise.resolve(parentResults); 24 | } 25 | } 26 | //# sourceMappingURL=has-many-multi.js.map -------------------------------------------------------------------------------- /dist/es2015/relations/has-many-multi.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"has-many-multi.js","sourceRoot":"","sources":["../../../src/relations/has-many-multi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAIzC,MAAM,OAAO,YAAa,SAAQ,SAAS;IAEzC,YACS,EAAe,EACf,SAAoB,EACjB,WAA2B,EAC9B,aAAuB;QAE9B,KAAK,EAAE,CAAC;QALD,OAAE,GAAF,EAAE,CAAa;QACf,cAAS,GAAT,SAAS,CAAW;QACjB,gBAAW,GAAX,WAAW,CAAgB;QAC9B,kBAAa,GAAb,aAAa,CAAU;IAGhC,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,OAAc;QAC/B,IAAI,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtD,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEtD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QACrG,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAE/D,MAAM,eAAe,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC;QAE1C,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACxE,CAAC;IAEM,WAAW,CAAC,aAAoB,EAAE,eAAsB,EAAE,QAAkB;QACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAExE,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;YACnC,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,GAAG,eAAe,CAAC,MAAM,CACtF,CAAC,cAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CACjE,CAAC,UAAe,EAAE,EAAE,CAAC,UAAU,KAAK,YAAY,CAAC,QAAQ,CAAC,CAC3D,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/relations/has-many-through-multi.js: -------------------------------------------------------------------------------- 1 | import { Relations } from "./relations.js"; 2 | export class HasManyThroughMulti extends Relations { 3 | constructor(db, connector, parentModel, childRelation) { 4 | super(); 5 | this.db = db; 6 | this.connector = connector; 7 | this.parentModel = parentModel; 8 | this.childRelation = childRelation; 9 | } 10 | async fetch(results) { 11 | let model = this.getRelationModel(this.childRelation); 12 | model = this.filteredModel(model, this.childRelation); 13 | const values = results.reduce((carry, result) => carry.concat(result[this.getLocalKey(this.parentModel, this.childRelation)]), []); 14 | model.whereIndexIn(this.childRelation.foreignKey, values); 15 | const relationResults = await model.all(); 16 | return this.bindResults(results, relationResults, this.childRelation); 17 | } 18 | bindResults(parentResults, relationResults, relation) { 19 | const localKey = this.getLocalKey(this.parentModel, this.childRelation); 20 | parentResults.forEach(parentResult => { 21 | parentResult[this.getAttributeName(this.parentModel, relation)] = relationResults.filter((relationResult) => !!parentResult[localKey].find((multiValue) => multiValue === relationResult[relation.foreignKey])); 22 | }); 23 | return Promise.resolve(parentResults); 24 | } 25 | } 26 | //# sourceMappingURL=has-many-through-multi.js.map -------------------------------------------------------------------------------- /dist/es2015/relations/has-many-through-multi.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"has-many-through-multi.js","sourceRoot":"","sources":["../../../src/relations/has-many-through-multi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAIzC,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAChD,YACS,EAAe,EACf,SAAoB,EACjB,WAA2B,EAC9B,aAAuB;QAE9B,KAAK,EAAE,CAAC;QALD,OAAE,GAAF,EAAE,CAAa;QACf,cAAS,GAAT,SAAS,CAAW;QACjB,gBAAW,GAAX,WAAW,CAAgB;QAC9B,kBAAa,GAAb,aAAa,CAAU;IAGhC,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,OAAc;QAC/B,IAAI,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtD,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEtD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAC3B,CAAC,KAAY,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3G,CAAC;QACF,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAE1D,MAAM,eAAe,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC;QAE1C,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACxE,CAAC;IAEM,WAAW,CAAC,aAAoB,EAAE,eAAsB,EAAE,QAAkB;QACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAExE,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;YACnC,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,GAAG,eAAe,CAAC,MAAM,CACtF,CAAC,cAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,IAAI,CACpD,CAAC,UAAe,EAAE,EAAE,CAAC,UAAU,KAAK,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,CACxE,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/relations/has-many.js: -------------------------------------------------------------------------------- 1 | import { Relations } from "./relations.js"; 2 | export class HasMany extends Relations { 3 | constructor(db, connector, parentModel, childRelation) { 4 | super(); 5 | this.db = db; 6 | this.connector = connector; 7 | this.parentModel = parentModel; 8 | this.childRelation = childRelation; 9 | } 10 | /** 11 | * Fetch relation results 12 | * @param results 13 | */ 14 | async fetch(results) { 15 | let model = this.getRelationModel(this.childRelation); 16 | model = this.filteredModel(model, this.childRelation); 17 | const values = results.map(result => result[this.getLocalKey(this.parentModel, this.childRelation)]); 18 | model.whereIndexIn(this.childRelation.foreignKey, values); 19 | const relationResults = await model.all(); 20 | return this.bindResults(results, relationResults, this.childRelation); 21 | } 22 | /** 23 | * Bind relation results to parent results 24 | * @param parentResults 25 | * @param relationResults 26 | * @param relation 27 | */ 28 | bindResults(parentResults, relationResults, relation) { 29 | const localKey = this.getLocalKey(this.parentModel, this.childRelation); 30 | parentResults.forEach(parentResult => { 31 | parentResult[this.getAttributeName(this.parentModel, relation)] = relationResults.filter((relationResult) => relationResult[relation.foreignKey] === parentResult[localKey]); 32 | }); 33 | return Promise.resolve(parentResults); 34 | } 35 | } 36 | //# sourceMappingURL=has-many.js.map -------------------------------------------------------------------------------- /dist/es2015/relations/has-many.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"has-many.js","sourceRoot":"","sources":["../../../src/relations/has-many.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAIzC,MAAM,OAAO,OAAQ,SAAQ,SAAS;IAEpC,YACS,EAAe,EACf,SAAoB,EACjB,WAA2B,EAC9B,aAAuB;QAE9B,KAAK,EAAE,CAAC;QALD,OAAE,GAAF,EAAE,CAAa;QACf,cAAS,GAAT,SAAS,CAAW;QACjB,gBAAW,GAAX,WAAW,CAAgB;QAC9B,kBAAa,GAAb,aAAa,CAAU;IAGhC,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,KAAK,CAAC,OAAc;QAC/B,IAAI,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtD,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEtD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QACrG,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAE1D,MAAM,eAAe,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC;QAE1C,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACxE,CAAC;IAED;;;;;OAKG;IACI,WAAW,CAAC,aAAoB,EAAE,eAAoB,EAAE,QAAkB;QAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACxE,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;YACnC,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,GAAG,eAAe,CAAC,MAAM,CACtF,CAAC,cAAmB,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,YAAY,CAAC,QAAQ,CAAC,CACxF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/relations/has-one.js: -------------------------------------------------------------------------------- 1 | import { Relations } from "./relations.js"; 2 | import { CursorDirection } from "../models/model.interface.js"; 3 | export class HasOne extends Relations { 4 | constructor(db, connector, parentModel, childRelation) { 5 | super(); 6 | this.db = db; 7 | this.connector = connector; 8 | this.parentModel = parentModel; 9 | this.childRelation = childRelation; 10 | } 11 | async fetch(results) { 12 | let model = this.getRelationModel(this.childRelation); 13 | model = this.filteredModel(model, this.childRelation); 14 | let relationResults = []; 15 | // optimizing query 16 | if (results.length === 1) { 17 | model.whereIndex(this.childRelation.foreignKey, results[0][this.getLocalKey(this.parentModel, this.childRelation)]); 18 | relationResults = [await model.first()]; 19 | } 20 | else { 21 | const values = results.map(result => result[this.getLocalKey(this.parentModel, this.childRelation)]); 22 | model.whereIndexIn(this.childRelation.foreignKey, values) 23 | .cursorDirection(CursorDirection.AscendingUnique); 24 | relationResults = await model.all(); 25 | } 26 | return this.bindResults(results, relationResults, this.childRelation); 27 | } 28 | bindResults(parentResults, relationResults, relation) { 29 | const localKey = this.getLocalKey(this.parentModel, this.childRelation); 30 | parentResults.forEach(result => { 31 | const mappedResult = relationResults.find(relationResult => relationResult[relation.foreignKey] === result[localKey]); 32 | result[this.getAttributeName(this.parentModel, relation)] = mappedResult || null; 33 | }); 34 | return Promise.resolve(parentResults); 35 | } 36 | } 37 | //# sourceMappingURL=has-one.js.map -------------------------------------------------------------------------------- /dist/es2015/relations/has-one.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"has-one.js","sourceRoot":"","sources":["../../../src/relations/has-one.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAC,eAAe,EAA2B,MAAM,8BAA8B,CAAC;AAEvF,MAAM,OAAO,MAAO,SAAQ,SAAS;IAEnC,YACS,EAAe,EACf,SAAoB,EACjB,WAA2B,EAC9B,aAAuB;QAE9B,KAAK,EAAE,CAAC;QALD,OAAE,GAAF,EAAE,CAAa;QACf,cAAS,GAAT,SAAS,CAAW;QACjB,gBAAW,GAAX,WAAW,CAAgB;QAC9B,kBAAa,GAAb,aAAa,CAAU;IAGhC,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,OAAc;QAC/B,IAAI,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtD,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEtD,IAAI,eAAe,GAAU,EAAE,CAAC;QAChC,mBAAmB;QACnB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;YACxB,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACpH,eAAe,GAAG,CAAC,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;SAEzC;aAAM;YACL,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACrG,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC;iBACtD,eAAe,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;YAEpD,eAAe,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC;SACrC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACxE,CAAC;IAEM,WAAW,CAAC,aAAoB,EAAE,eAAsB,EAAE,QAAkB;QACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACxE,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YAE7B,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YACtH,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,GAAG,YAAY,IAAI,IAAI,CAAC;QACnF,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/relations/relation.interface.js: -------------------------------------------------------------------------------- 1 | //# sourceMappingURL=relation.interface.js.map -------------------------------------------------------------------------------- /dist/es2015/relations/relation.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"relation.interface.js","sourceRoot":"","sources":["../../../src/relations/relation.interface.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/es2015/relations/relations.js: -------------------------------------------------------------------------------- 1 | import { DEFAULT_PRIMARY_ID, } from "../models/model.interface.js"; 2 | import { Model } from "../models/model.js"; 3 | import { QueryBuilder } from "../models/query-builder.js"; 4 | export class Relations extends QueryBuilder { 5 | /** 6 | * Sets builder values created through callback function 7 | * @param model 8 | * @param relation 9 | */ 10 | filteredModel(model, relation) { 11 | model = this.bindBuilder(model); 12 | const builder = new QueryBuilder(); 13 | if (relation.func) { 14 | const query = relation.func(builder); 15 | model.builder = model.builder.concat(query.builder); 16 | model.with(builder.relations); 17 | } 18 | return model; 19 | } 20 | bindBuilder(model) { 21 | model.builder = model.builder.concat(this.builder); 22 | model.with(this.relations); 23 | return model; 24 | } 25 | /** 26 | * Retrieves th childRelation model instance 27 | * @param relation 28 | */ 29 | getRelationModel(relation) { 30 | let model; 31 | if (typeof relation.model === "string") { 32 | const tableSchema = this.connector.migrationSchema.tables.find(table => table.name === relation.model); 33 | if (!tableSchema) { 34 | throw new Error('Table schema not found'); 35 | } 36 | model = new Model(this.db, tableSchema, this.connector); 37 | } 38 | else { 39 | model = relation.model; 40 | } 41 | return model; 42 | } 43 | /** 44 | * Retrieves the local key of parent model 45 | * @param model 46 | * @param relation 47 | */ 48 | getLocalKey(model, relation) { 49 | const primaryKey = model.table.primary || DEFAULT_PRIMARY_ID; 50 | return relation.localKey ? relation.localKey : primaryKey; 51 | } 52 | /** 53 | * Returns the attribute name by which childRelation is to be attached with parent model 54 | * @param model 55 | * @param relation 56 | */ 57 | getAttributeName(model, relation) { 58 | return relation.attributeName || model.table.name; 59 | } 60 | } 61 | //# sourceMappingURL=relations.js.map -------------------------------------------------------------------------------- /dist/es2015/relations/relations.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"relations.js","sourceRoot":"","sources":["../../../src/relations/relations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAInB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAIxD,MAAM,OAAgB,SAAU,SAAQ,YAAY;IA0BlD;;;;OAIG;IACI,aAAa,CAAC,KAAqB,EAAE,QAAkB;QAC5D,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;QAEnC,IAAI,QAAQ,CAAC,IAAI,EAAE;YACjB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;SAC/B;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,WAAW,CAAC,KAAqB;QACtC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACI,gBAAgB,CAAC,QAAkB;QACxC,IAAI,KAAqB,CAAC;QAE1B,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,EAAE;YACtC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;YACvG,IAAI,CAAC,WAAW,EAAE;gBAChB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;aAC3C;YAED,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;SACzD;aAAM;YACL,KAAK,GAAmB,QAAQ,CAAC,KAAK,CAAC;SACxC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACI,WAAW,CAAC,KAAqB,EAAE,QAAkB;QAC1D,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,kBAAkB,CAAC;QAC7D,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACI,gBAAgB,CAAC,KAAqB,EAAE,QAAkB;QAC/D,OAAO,QAAQ,CAAC,aAAa,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;IACpD,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/es2015/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Retrieves the nested attribute value using dot "." values 3 | * @param attributeString 4 | * @param value 5 | */ 6 | export function nestedAttributeValue(attributeString, value) { 7 | const attributes = attributeString.split('.'); 8 | let content = value; 9 | for (let index = 0; index < attributes.length; index++) { 10 | if (content[attributes[index]] === undefined) { 11 | return undefined; 12 | } 13 | content = content[attributes[index]]; 14 | } 15 | return content; 16 | } 17 | /** 18 | * Deep merges two object taking first input as reference and second input being the properties to be merged to first. 19 | * @param object1 20 | * @param object2 21 | */ 22 | export function mergeDeep(object1, object2) { 23 | for (const key in object1) { 24 | if (object2.hasOwnProperty(key)) { 25 | if (object2[key] instanceof Object) { 26 | object1[key] = mergeDeep({}, object2[key]); 27 | } 28 | else { 29 | object1[key] = object2[key]; 30 | } 31 | } 32 | } 33 | for (const key in object2) { 34 | if (!object1.hasOwnProperty(key)) { 35 | object1[key] = object2[key]; 36 | } 37 | } 38 | return object1; 39 | } 40 | //# sourceMappingURL=utils.js.map -------------------------------------------------------------------------------- /dist/es2015/utils.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,eAAuB,EAAE,KAAU;IACtE,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9C,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QACtD,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,SAAS,EAAE;YAC5C,OAAO,SAAS,CAAC;SAClB;QAED,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;KACtC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACvB,OAAuC,EACvC,OAAuC;IACvC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE;QACzB,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;YAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,EAAE;gBAClC,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;aAC5C;iBAAM;gBACL,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;aAC7B;SACF;KACF;IAED,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE;QACzB,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;YAChC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;SAC7B;KACF;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"} -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Indexed DB Orm 6 | 7 | 9 | 10 | 11 | 12 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /example/worker.js: -------------------------------------------------------------------------------- 1 | import {Connector} from "../dist/es2015/index.js"; 2 | import {Model} from "../dist/es2015/models/model.js"; 3 | import {RelationTypes} from "../dist/es2015/models/model.interface.js"; 4 | 5 | class Users extends Model { 6 | static TableName = 'users'; 7 | 8 | constructor(db, table, connector) { 9 | super(db, table, connector); 10 | } 11 | 12 | userProfiles = () => { 13 | return this.hasOne(UserProfiles, 'userId', undefined, 'user_profiles').with([{ 14 | model: 'users', 15 | foreignKey: '_id', 16 | type: RelationTypes.HasOne, 17 | localKey: 'userId', 18 | attributeName: 'user', 19 | func: (builder) => { 20 | builder.with([{ 21 | model: 'addresses', 22 | foreignKey: 'userIds', 23 | type: RelationTypes.HasManyMultiEntry, 24 | attributeName: 'addresses', 25 | }]); 26 | return builder; 27 | } 28 | }]); 29 | } 30 | } 31 | 32 | class UserProfiles extends Model { 33 | static TableName = 'userProfiles'; 34 | 35 | constructor(db, table, connector) { 36 | super(db, table, connector); 37 | } 38 | } 39 | 40 | // 41 | // const model = new Model(); 42 | // window.model = model; 43 | console.log(RelationTypes); 44 | const a = new Connector({ 45 | tables: [{ 46 | name: 'users', 47 | ormClass: Users, 48 | columns: [{ 49 | name: 'email', 50 | attributes: { 51 | unique: true 52 | } 53 | }] 54 | }, { 55 | name: 'userProfiles', 56 | columns: [{ 57 | name: 'userId' 58 | }] 59 | }, { 60 | name: 'addresses', 61 | columns: [{ 62 | name: 'userIds', 63 | attributes: { 64 | multiEntry: true 65 | } 66 | }] 67 | }, { 68 | name: 'tasks', 69 | columns: [{ 70 | name: 'userId', 71 | }] 72 | }], 73 | name: 'sample', 74 | version: 1 75 | }); 76 | 77 | a.connect().then(async (models) => { 78 | console.log(a, models); 79 | self.models = models; 80 | 81 | }); 82 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "indexeddb-orm", 3 | "version": "3.2.1", 4 | "main": "./dist/es2015/index.js", 5 | "types": "./src/index.d.ts", 6 | "scripts": { 7 | "build.browser.module": "./node_modules/.bin/tsc --build tsconfig.json", 8 | "build.browser.all": "./node_modules/.bin/webpack --config=webpack.config.js --mode=production" 9 | }, 10 | "author": "Max Gaurav max.gaurav@ithands.net", 11 | "description": "A promise based ORM wrapper for indexedDB", 12 | "devDependencies": { 13 | "@babel/core": "^7.4.5", 14 | "@babel/plugin-transform-runtime": "^7.4.4", 15 | "@babel/preset-env": "^7.4.5", 16 | "@babel/runtime": "^7.4.5", 17 | "babel-loader": "^8.0.6", 18 | "ts-loader": "^6.0", 19 | "tslint": "^5.18.0", 20 | "tslint-eslint-rules": "^5.4.0", 21 | "tslint-no-toplevel-property-access": "^0.0.2", 22 | "typescript": "^3.5", 23 | "vrsource-tslint-rules": "^6.0.0", 24 | "webpack": "^4.35.0", 25 | "webpack-cli": "^3.3.5" 26 | }, 27 | "files": [ 28 | "/src", 29 | "/dist" 30 | ], 31 | "keywords": [ 32 | "indexeddb", 33 | "indexed-db", 34 | "browser", 35 | "database" 36 | ], 37 | "bugs": { 38 | "url": "https://github.com/maxgaurav/indexeddb-orm/issues", 39 | "email": "max.gaurav@ithands.net" 40 | }, 41 | "repository": { 42 | "type": "git", 43 | "url": "https://github.com/maxgaurav/indexeddb-orm.git" 44 | }, 45 | "license": "MIT", 46 | "dependencies": {} 47 | } 48 | -------------------------------------------------------------------------------- /src/connection/connector.d.ts: -------------------------------------------------------------------------------- 1 | import { ConnectorInterface } from "./connector.interface.js"; 2 | import { Database, MigrationInterface } from "../migration/migration.interface.js"; 3 | import { DBSuccessEvent, DBVersionChangeEvent } from "./idb-event.interface.js"; 4 | import { Migration } from "../migration/migration.js"; 5 | import { ModelInterface, ModelKeysInterface, TransactionModes } from "../models/model.interface.js"; 6 | /** 7 | * 8 | */ 9 | export declare class Connector implements ConnectorInterface { 10 | migrationSchema: Database; 11 | /** 12 | * Database open request 13 | */ 14 | private dbOpenConnection; 15 | /** 16 | * Migration builder instance 17 | */ 18 | protected migration: Migration | null; 19 | /** 20 | * IndexedDB Database instance 21 | */ 22 | protected database: IDBDatabase | null; 23 | constructor(migrationSchema: Database); 24 | /** 25 | * Create/Update and connects the database 26 | */ 27 | connect(): Promise; 28 | /** 29 | * Deletes the database 30 | */ 31 | destroy(databaseName: string): Promise; 32 | /** 33 | * Returns the IDBFactory. 34 | */ 35 | indexedDB(): IDBFactory; 36 | /** 37 | * Called when database version is updated. Runs migrations to update schema structure 38 | * @param event 39 | */ 40 | migrateHandler(event: DBVersionChangeEvent): Promise; 41 | /** 42 | * Called when connection to database is successful. Creates various models for the tables. 43 | * @param event 44 | */ 45 | protected completeHandler(event: DBSuccessEvent): { 46 | [key: string]: ModelInterface; 47 | }; 48 | /** 49 | * Returns migration instance 50 | */ 51 | getMigration(): MigrationInterface | null; 52 | /** 53 | * Returns database instance 54 | */ 55 | getDatabase(): IDBDatabase | null; 56 | /** 57 | * Opens a transaction to allow fine control on commits. 58 | * @param mode 59 | */ 60 | openTransaction(mode: TransactionModes): { 61 | models: ModelKeysInterface; 62 | transaction: IDBTransaction; 63 | }; 64 | /** 65 | * Closes currently open connection to database 66 | */ 67 | close(): Promise; 68 | } 69 | -------------------------------------------------------------------------------- /src/connection/connector.interface.d.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface } from "../migration/migration.interface.js"; 2 | import { ModelKeysInterface, TransactionModes } from "../models/model.interface.js"; 3 | export interface ConnectorInterface { 4 | connect(): Promise; 5 | destroy(databaseName: string): Promise; 6 | indexedDB(): IDBFactory; 7 | getMigration(): MigrationInterface | null; 8 | getDatabase(): IDBDatabase | null; 9 | openTransaction(mode: TransactionModes): { 10 | models: ModelKeysInterface; 11 | transaction: IDBTransaction; 12 | }; 13 | close(): Promise; 14 | } 15 | -------------------------------------------------------------------------------- /src/connection/connector.interface.ts: -------------------------------------------------------------------------------- 1 | import {MigrationInterface} from "../migration/migration.interface.js"; 2 | import {ModelKeysInterface, TransactionModes} from "../models/model.interface.js"; 3 | 4 | export interface ConnectorInterface { 5 | 6 | connect(): Promise; 7 | 8 | destroy(databaseName: string): Promise; 9 | 10 | indexedDB(): IDBFactory; 11 | 12 | getMigration(): MigrationInterface | null; 13 | 14 | getDatabase(): IDBDatabase | null; 15 | 16 | openTransaction(mode: TransactionModes): { models: ModelKeysInterface, transaction: IDBTransaction }; 17 | 18 | close(): Promise; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/connection/connector.ts: -------------------------------------------------------------------------------- 1 | import {ConnectorInterface} from "./connector.interface.js"; 2 | import {Database, MigrationInterface, TableSchema} from "../migration/migration.interface.js"; 3 | import {DBSuccessEvent, DBVersionChangeEvent} from "./idb-event.interface.js"; 4 | import {Migration} from "../migration/migration.js"; 5 | import {ModelInterface, ModelKeysInterface, TransactionModes} from "../models/model.interface.js"; 6 | import {Model} from "../models/model.js"; 7 | 8 | /** 9 | * 10 | */ 11 | export class Connector implements ConnectorInterface { 12 | 13 | /** 14 | * Database open request 15 | */ 16 | private dbOpenConnection: IDBOpenDBRequest | null = null; 17 | 18 | /** 19 | * Migration builder instance 20 | */ 21 | protected migration: Migration | null = null; 22 | 23 | /** 24 | * IndexedDB Database instance 25 | */ 26 | protected database: IDBDatabase | null = null; 27 | 28 | public constructor(public migrationSchema: Database) { 29 | } 30 | 31 | /** 32 | * Create/Update and connects the database 33 | */ 34 | public connect(): Promise { 35 | this.dbOpenConnection = this.indexedDB().open(this.migrationSchema.name, this.migrationSchema.version); 36 | 37 | return new Promise((resolve, reject) => { 38 | 39 | if (this.dbOpenConnection === null) { 40 | throw new Error('Database connection did not open'); 41 | } 42 | 43 | this.dbOpenConnection.addEventListener('success', (event) => { 44 | const models = this.completeHandler(event as DBSuccessEvent); 45 | resolve(models); 46 | }); 47 | 48 | this.dbOpenConnection.addEventListener('error', (event) => { 49 | reject(event); 50 | }); 51 | 52 | this.dbOpenConnection.addEventListener('upgradeneeded', async (event) => { 53 | await this.migrateHandler(event as DBVersionChangeEvent); 54 | }); 55 | }); 56 | } 57 | 58 | /** 59 | * Deletes the database 60 | */ 61 | public destroy(databaseName: string): Promise { 62 | const request = this.indexedDB().deleteDatabase(databaseName); 63 | return new Promise((resolve, reject) => { 64 | request.addEventListener('success', () => resolve(true)); 65 | request.addEventListener('error', (e) => reject(e)); 66 | }); 67 | 68 | } 69 | 70 | /** 71 | * Returns the IDBFactory. 72 | */ 73 | public indexedDB(): IDBFactory { 74 | const idb = indexedDB || self.indexedDB || (self as any).mozIndexedDB || (self as any).webkitIndexedDB || (self as any).msIndexedDB; 75 | if (!idb) { 76 | throw new Error("IndexedDB constructor not found in environment"); 77 | } 78 | 79 | return idb; 80 | } 81 | 82 | /** 83 | * Called when database version is updated. Runs migrations to update schema structure 84 | * @param event 85 | */ 86 | public async migrateHandler(event: DBVersionChangeEvent): Promise { 87 | const migration = new Migration(this.migrationSchema.tables, event.target.result, event.target.transaction); 88 | this.migrationSchema.tables = await migration.run(); 89 | return true; 90 | } 91 | 92 | /** 93 | * Called when connection to database is successful. Creates various models for the tables. 94 | * @param event 95 | */ 96 | protected completeHandler(event: DBSuccessEvent): { [key: string]: ModelInterface } { 97 | const storeNames = this.migrationSchema.tables.map(table => table.name); 98 | const transaction = event.target.transaction || event.target.result.transaction(storeNames); 99 | this.database = event.target.result; 100 | 101 | const migration = new Migration(this.migrationSchema.tables, event.target.result, transaction); 102 | this.migration = migration; 103 | 104 | const stores = migration.listObjectStores(); 105 | const models: { [key: string]: ModelInterface } = {}; 106 | 107 | for (const store of stores) { 108 | const table = this.migrationSchema.tables.find(schema => schema.name === store.name); 109 | 110 | 111 | Object.defineProperty(models, store.name, { 112 | get: () => { 113 | 114 | if (table.ormClass) { 115 | return new table.ormClass(event.target.result, table, this); 116 | } else { 117 | return new Model(event.target.result, table, this); 118 | } 119 | } 120 | }); 121 | } 122 | 123 | return models; 124 | } 125 | 126 | /** 127 | * Returns migration instance 128 | */ 129 | public getMigration(): MigrationInterface | null { 130 | return this.migration; 131 | } 132 | 133 | /** 134 | * Returns database instance 135 | */ 136 | public getDatabase(): IDBDatabase | null { 137 | return this.database; 138 | } 139 | 140 | /** 141 | * Opens a transaction to allow fine control on commits. 142 | * @param mode 143 | */ 144 | public openTransaction(mode: TransactionModes): {models: ModelKeysInterface, transaction: IDBTransaction} { 145 | if (this.database === null) { 146 | throw new Error('First initialize the connection using connect.'); 147 | } 148 | 149 | const transaction = this.database.transaction(this.migrationSchema.tables.map(table => table.name)); 150 | 151 | const models: { [key: string]: ModelInterface } = {}; 152 | 153 | for (const table of this.migrationSchema.tables) { 154 | 155 | Object.defineProperty(models, table.name, { 156 | get: () => { 157 | const model = new Model(this.database, table, this); 158 | model.setTransaction(transaction); 159 | return model; 160 | } 161 | }); 162 | } 163 | 164 | return {models, transaction}; 165 | } 166 | 167 | /** 168 | * Closes currently open connection to database 169 | */ 170 | public close(): Promise { 171 | if (this.database) { 172 | this.database.close(); 173 | return Promise.resolve(true); 174 | } 175 | 176 | return Promise.reject('No Connection open'); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/connection/idb-event.interface.d.ts: -------------------------------------------------------------------------------- 1 | export interface IDBEventTarget extends EventTarget { 2 | result: IDBDatabase; 3 | transaction: IDBTransaction | null; 4 | } 5 | export interface DBVersionChangeEvent extends IDBVersionChangeEvent { 6 | target: IDBEventTarget; 7 | } 8 | export interface DBSuccessEvent extends Event { 9 | target: IDBEventTarget; 10 | } 11 | /** 12 | * Normal result fetch event target which contains the main result 13 | */ 14 | export interface IDBResultEventTarget extends EventTarget { 15 | result: IDBCursorWithValue | null | undefined | any; 16 | } 17 | export interface IDBResultEvent extends Event { 18 | target: IDBResultEventTarget; 19 | } 20 | -------------------------------------------------------------------------------- /src/connection/idb-event.interface.ts: -------------------------------------------------------------------------------- 1 | export interface IDBEventTarget extends EventTarget { 2 | result: IDBDatabase; 3 | transaction: IDBTransaction | null; 4 | } 5 | 6 | export interface DBVersionChangeEvent extends IDBVersionChangeEvent { 7 | target: IDBEventTarget; 8 | } 9 | 10 | export interface DBSuccessEvent extends Event { 11 | target: IDBEventTarget; 12 | } 13 | 14 | /** 15 | * Normal result fetch event target which contains the main result 16 | */ 17 | export interface IDBResultEventTarget extends EventTarget { 18 | result: IDBCursorWithValue | null | undefined | any; 19 | } 20 | 21 | export interface IDBResultEvent extends Event { 22 | target: IDBResultEventTarget; 23 | } 24 | -------------------------------------------------------------------------------- /src/errors/invalid-transaction.d.ts: -------------------------------------------------------------------------------- 1 | export declare class InvalidTransaction extends Error { 2 | } 3 | -------------------------------------------------------------------------------- /src/errors/invalid-transaction.ts: -------------------------------------------------------------------------------- 1 | export class InvalidTransaction extends Error { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/errors/not-found.d.ts: -------------------------------------------------------------------------------- 1 | export declare class NotFound extends Error { 2 | constructor(); 3 | } 4 | -------------------------------------------------------------------------------- /src/errors/not-found.ts: -------------------------------------------------------------------------------- 1 | export class NotFound extends Error { 2 | public constructor() { 3 | super('Record not found'); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Connector } from "./connection/connector.js"; 2 | import { Model } from "./models/model.js"; 3 | import { Migration } from "./migration/migration.js"; 4 | import { CursorDirection, RelationTypes } from "./models/model.interface.js"; 5 | export { Connector, Model, Migration, RelationTypes, CursorDirection }; 6 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import {Connector} from "./connection/connector.js"; 2 | import {Model} from "./models/model.js"; 3 | import {Migration} from "./migration/migration.js"; 4 | import {CursorDirection, RelationTypes, TransactionModes} from "./models/model.interface.js"; 5 | import {Database} from "./migration/migration.interface.js"; 6 | 7 | ((self) => { 8 | 9 | self.idb = (schema: Database) => { 10 | return new Connector(schema); 11 | }; 12 | 13 | self.idbTypes = { 14 | CursorTypes: { 15 | 'AscendingUnique': CursorDirection.AscendingUnique, 16 | 'Ascending': CursorDirection.Ascending, 17 | 'Descending': CursorDirection.Descending, 18 | 'DescendingUnique': CursorDirection.DescendingUnique 19 | }, 20 | RelationTypes: { 21 | 'HasManyThroughMultiEntry': RelationTypes.HasManyThroughMultiEntry, 22 | 'HasManyMultiEntry': RelationTypes.HasManyMultiEntry, 23 | 'HasMany': RelationTypes.HasMany, 24 | 'HasOne': RelationTypes.HasOne 25 | }, 26 | TransactionModes: { 27 | 'ReadOnly': TransactionModes.ReadOnly, 28 | 'Write': TransactionModes.Write, 29 | 'VersionChange': TransactionModes.VersionChange, 30 | } 31 | }; 32 | })(self as any); 33 | 34 | 35 | export {Connector, Model, Migration, RelationTypes, CursorDirection}; 36 | 37 | -------------------------------------------------------------------------------- /src/migration/migration.d.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, TableColumn, TableSchema } from "./migration.interface.js"; 2 | export declare class Migration implements MigrationInterface { 3 | tables: TableSchema[]; 4 | db: IDBDatabase; 5 | transaction: IDBTransaction | null; 6 | constructor(tables: TableSchema[], db: IDBDatabase, transaction: IDBTransaction | null); 7 | /** 8 | * Runs the migration action to update the database with new stores or deletes unwanted stored and then creates or 9 | * drops indexes for the stores. 10 | */ 11 | run(): Promise; 12 | /** 13 | * Creates an index in object store 14 | * @param column 15 | * @param objectStore 16 | */ 17 | createIndex(column: TableColumn, objectStore: IDBObjectStore): IDBIndex; 18 | /** 19 | * Drops an index in object store 20 | * @param column 21 | * @param objectStore 22 | */ 23 | dropIndex(column: string, objectStore: IDBObjectStore): boolean; 24 | /** 25 | * Creates new object store 26 | * @param schema 27 | */ 28 | createObjectStore(schema: TableSchema): IDBObjectStore; 29 | /** 30 | * Drops existing object store 31 | * @param schema 32 | */ 33 | dropObjectStore(schema: TableSchema): boolean; 34 | /** 35 | * Creates various indexes on object store 36 | * @param table 37 | * @param objectStore 38 | */ 39 | protected createColumns(table: TableSchema, objectStore: IDBObjectStore): void; 40 | /** 41 | * Drops indexes in object store 42 | * @param table 43 | * @param objectStore 44 | */ 45 | protected dropOldColumns(table: TableSchema, objectStore: IDBObjectStore): void; 46 | /** 47 | * Returns a list of all object store names which are in current database 48 | */ 49 | private allStoreNames; 50 | /** 51 | * Returns all object store instances in database 52 | */ 53 | listObjectStores(): IDBObjectStore[]; 54 | /** 55 | * Returns true if column is to be created 56 | * @param schema 57 | * @param objectStore 58 | */ 59 | setupSyncColumn(schema: TableSchema, objectStore: IDBObjectStore): void; 60 | } 61 | -------------------------------------------------------------------------------- /src/migration/migration.interface.d.ts: -------------------------------------------------------------------------------- 1 | import { ModelConstructorInterface } from "../models/model.interface.js"; 2 | export declare const DEFAULT_SYNC_COLUMN_NAME = "syncOn"; 3 | export interface MigrationInterface { 4 | run(): Promise; 5 | createObjectStore(schema: TableSchema): IDBObjectStore; 6 | dropObjectStore(schema: TableSchema): boolean; 7 | createIndex(column: TableColumn, objectStore: IDBObjectStore): IDBIndex; 8 | dropIndex(column: string, objectStore: IDBObjectStore): boolean; 9 | listObjectStores(): IDBObjectStore[]; 10 | setupSyncColumn(schema: TableSchema, objectStore: IDBObjectStore): void; 11 | } 12 | export interface TableColumn { 13 | name: string; 14 | index: string[] | string; 15 | attributes?: IDBIndexParameters; 16 | dbIndex?: IDBIndex | null; 17 | } 18 | export interface TableSchema { 19 | name: string; 20 | columns: TableColumn[]; 21 | ormClass?: ModelConstructorInterface; 22 | primary?: string; 23 | objectStore?: IDBObjectStore | null; 24 | syncColumn?: boolean; 25 | syncColumnName?: string; 26 | } 27 | export interface Database { 28 | name: string; 29 | version: number; 30 | tables: TableSchema[]; 31 | } 32 | -------------------------------------------------------------------------------- /src/migration/migration.interface.ts: -------------------------------------------------------------------------------- 1 | import {ModelConstructorInterface} from "../models/model.interface.js"; 2 | 3 | export const DEFAULT_SYNC_COLUMN_NAME = 'syncOn'; 4 | 5 | export interface MigrationInterface { 6 | run(): Promise; 7 | 8 | createObjectStore(schema: TableSchema): IDBObjectStore; 9 | 10 | dropObjectStore(schema: TableSchema): boolean; 11 | 12 | createIndex(column: TableColumn, objectStore: IDBObjectStore): IDBIndex; 13 | 14 | dropIndex(column: string, objectStore: IDBObjectStore): boolean; 15 | 16 | listObjectStores(): IDBObjectStore[]; 17 | 18 | setupSyncColumn(schema: TableSchema, objectStore: IDBObjectStore): void; 19 | } 20 | 21 | export interface TableColumn { 22 | name: string; 23 | index: string[] | string; 24 | attributes?: IDBIndexParameters; 25 | dbIndex?: IDBIndex | null; 26 | } 27 | 28 | export interface TableSchema { 29 | name: string; 30 | columns: TableColumn[]; 31 | ormClass?: ModelConstructorInterface; 32 | primary?: string; 33 | objectStore?: IDBObjectStore | null; 34 | syncColumn?: boolean; 35 | syncColumnName?: string; 36 | } 37 | 38 | export interface Database { 39 | name: string; 40 | version: number; 41 | tables: TableSchema[]; 42 | } 43 | -------------------------------------------------------------------------------- /src/migration/migration.ts: -------------------------------------------------------------------------------- 1 | import {DEFAULT_SYNC_COLUMN_NAME, MigrationInterface, TableColumn, TableSchema} from "./migration.interface.js"; 2 | import {DEFAULT_PRIMARY_ID} from "../models/model.interface.js"; 3 | 4 | export class Migration implements MigrationInterface { 5 | constructor(public tables: TableSchema[], public db: IDBDatabase, public transaction: IDBTransaction | null) { 6 | } 7 | 8 | /** 9 | * Runs the migration action to update the database with new stores or deletes unwanted stored and then creates or 10 | * drops indexes for the stores. 11 | */ 12 | public async run(): Promise { 13 | for (const table of this.tables) { 14 | if (!this.db.objectStoreNames.contains(table.name)) { 15 | table.objectStore = this.createObjectStore(table); 16 | 17 | } else { 18 | table.objectStore = (this.transaction as IDBTransaction).objectStore(table.name); 19 | } 20 | 21 | this.createColumns(table, table.objectStore); 22 | this.dropOldColumns(table, table.objectStore); 23 | this.setupSyncColumn(table, table.objectStore); 24 | } 25 | 26 | for (const tableName of this.allStoreNames()) { 27 | if (!this.tables.find(table => table.name === tableName)) { 28 | this.db.deleteObjectStore(tableName); 29 | } 30 | } 31 | 32 | return this.tables; 33 | } 34 | 35 | /** 36 | * Creates an index in object store 37 | * @param column 38 | * @param objectStore 39 | */ 40 | public createIndex(column: TableColumn, objectStore: IDBObjectStore): IDBIndex { 41 | const attributes = column.attributes || {}; 42 | const index = column.index || column.name; 43 | return objectStore.createIndex(column.name, index, attributes); 44 | } 45 | 46 | /** 47 | * Drops an index in object store 48 | * @param column 49 | * @param objectStore 50 | */ 51 | public dropIndex(column: string, objectStore: IDBObjectStore): boolean { 52 | objectStore.deleteIndex(column); 53 | 54 | return true; 55 | } 56 | 57 | /** 58 | * Creates new object store 59 | * @param schema 60 | */ 61 | public createObjectStore(schema: TableSchema): IDBObjectStore { 62 | let primary = schema.primary || DEFAULT_PRIMARY_ID; 63 | 64 | return this.db.createObjectStore(schema.name, { 65 | keyPath: primary, 66 | autoIncrement: true 67 | }); 68 | } 69 | 70 | /** 71 | * Drops existing object store 72 | * @param schema 73 | */ 74 | public dropObjectStore(schema: TableSchema): boolean { 75 | return true; 76 | } 77 | 78 | /** 79 | * Creates various indexes on object store 80 | * @param table 81 | * @param objectStore 82 | */ 83 | protected createColumns(table: TableSchema, objectStore: IDBObjectStore) { 84 | for (const column of table.columns) { 85 | 86 | if (!objectStore.indexNames.contains(column.name)) { 87 | column.dbIndex = this.createIndex(column, objectStore); 88 | } 89 | } 90 | } 91 | 92 | /** 93 | * Drops indexes in object store 94 | * @param table 95 | * @param objectStore 96 | */ 97 | protected dropOldColumns(table: TableSchema, objectStore: IDBObjectStore) { 98 | const indexNames = objectStore.indexNames; 99 | for (let i = 0; i < indexNames.length; i++) { 100 | if (!table.columns.find(column => column.name === indexNames[i])) { 101 | this.dropIndex(indexNames[i], objectStore); 102 | } 103 | } 104 | 105 | } 106 | 107 | /** 108 | * Returns a list of all object store names which are in current database 109 | */ 110 | private allStoreNames(): string[] { 111 | const names: string[] = []; 112 | 113 | for (let i = 0; i < this.db.objectStoreNames.length; i++) { 114 | names.push(this.db.objectStoreNames[i]); 115 | } 116 | 117 | return names; 118 | } 119 | 120 | /** 121 | * Returns all object store instances in database 122 | */ 123 | public listObjectStores(): IDBObjectStore[] { 124 | const stores: IDBObjectStore[] = []; 125 | for (const tableName of this.allStoreNames()) { 126 | stores.push((this.transaction as IDBTransaction).objectStore(tableName)); 127 | } 128 | 129 | return stores; 130 | } 131 | 132 | /** 133 | * Returns true if column is to be created 134 | * @param schema 135 | * @param objectStore 136 | */ 137 | public setupSyncColumn(schema: TableSchema, objectStore: IDBObjectStore): void { 138 | const columnName = schema.syncColumnName || DEFAULT_SYNC_COLUMN_NAME; 139 | 140 | if (schema.syncColumn) { 141 | if (!objectStore.indexNames.contains(columnName)) { 142 | this.createIndex({ 143 | name: columnName, 144 | index: columnName 145 | }, objectStore); 146 | } 147 | 148 | } else { 149 | if (objectStore.indexNames.contains(columnName)) { 150 | this.dropIndex(columnName, objectStore); 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/models/aggregate.d.ts: -------------------------------------------------------------------------------- 1 | import { AggregateInterface } from "./model.interface.js"; 2 | import { TableSchema } from "../migration/migration.interface.js"; 3 | import { BaseModel } from "./base-model.js"; 4 | export declare abstract class Aggregate extends BaseModel implements AggregateInterface { 5 | db: IDBDatabase; 6 | table: TableSchema; 7 | constructor(db: IDBDatabase, table: TableSchema); 8 | /** 9 | * Returns the count of matching records 10 | */ 11 | count(): Promise; 12 | /** 13 | * Returns average of attribute value on matching records. 14 | * If value is not numeric then its skipped 15 | * @param attribute 16 | */ 17 | average(attribute: string): Promise; 18 | /** 19 | * Provides reduce action on matching records to return a single value 20 | * @param func 21 | * @param defaultCarry 22 | */ 23 | reduce(func: (value: U, result: any) => any, defaultCarry: any): Promise; 24 | reduce(func: (value: any, result: any) => any, defaultCarry: any): Promise; 25 | } 26 | -------------------------------------------------------------------------------- /src/models/aggregate.ts: -------------------------------------------------------------------------------- 1 | import {AggregateInterface, IndexBuilder, QueryTypes, TransactionModes} from "./model.interface.js"; 2 | import {TableSchema} from "../migration/migration.interface.js"; 3 | import {QueryBuilder} from "./query-builder.js"; 4 | import {IDBResultEvent} from "../connection/idb-event.interface.js"; 5 | import {OrmRelationBuilder} from "./orm-relation-builder.js"; 6 | import {nestedAttributeValue} from "../utils.js"; 7 | import {TransactionHandling} from "./transaction-handling.js"; 8 | import {BaseModel} from "./base-model.js"; 9 | 10 | export abstract class Aggregate extends BaseModel implements AggregateInterface { 11 | 12 | public constructor(public db: IDBDatabase, public table: TableSchema) { 13 | super(); 14 | } 15 | 16 | /** 17 | * Returns the count of matching records 18 | */ 19 | public count(): Promise { 20 | const tables = [this.table.name]; 21 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 22 | const objectStore = transaction.objectStore(this.table.name); 23 | let request: IDBRequest; 24 | 25 | if (this.builder.length === 0 && this.indexBuilder === null) { 26 | request = objectStore.count(); 27 | } else if (this.builder.length === 0 && this.indexBuilder !== null) { 28 | request = objectStore.count(this.keyRange(this.indexBuilder)); 29 | } else { 30 | request = this.request(objectStore); 31 | } 32 | 33 | return new Promise((resolve, reject) => { 34 | let count = 0; 35 | request.addEventListener<'success'>("success", async (event) => { 36 | if (this.builder.length === 0) { 37 | return resolve((event as IDBResultEvent).target.result); 38 | } 39 | 40 | const cursor = (event).target.result as IDBCursorWithValue | undefined; 41 | 42 | if (cursor) { 43 | 44 | if (!this.allowedToProcess(cursor.value)) { 45 | return cursor.continue(); 46 | } 47 | count++; 48 | return cursor.continue(); 49 | } 50 | 51 | resolve(count); 52 | 53 | }); 54 | 55 | request.addEventListener<'error'>("error", (error) => reject(error)); 56 | }); 57 | } 58 | 59 | /** 60 | * Returns average of attribute value on matching records. 61 | * If value is not numeric then its skipped 62 | * @param attribute 63 | */ 64 | public average(attribute: string): Promise { 65 | const tables = [this.table.name]; 66 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 67 | const objectStore = transaction.objectStore(this.table.name); 68 | const request = this.request(objectStore); 69 | 70 | return new Promise((resolve, reject) => { 71 | let count = 0; 72 | let total = 0; 73 | request.addEventListener<'success'>("success", async (event) => { 74 | const cursor = (event).target.result as IDBCursorWithValue | undefined; 75 | 76 | if (cursor) { 77 | 78 | if (!this.allowedToProcess(cursor.value)) { 79 | return cursor.continue(); 80 | } 81 | const value = nestedAttributeValue(attribute, cursor.value); 82 | if (!isNaN(parseFloat(value))) { 83 | total += parseFloat(cursor.value[attribute]); 84 | } 85 | 86 | count++; 87 | return cursor.continue(); 88 | } 89 | 90 | resolve(total / count); 91 | 92 | }); 93 | 94 | request.addEventListener<'error'>("error", (error) => reject(error)); 95 | }); 96 | } 97 | 98 | /** 99 | * Provides reduce action on matching records to return a single value 100 | * @param func 101 | * @param defaultCarry 102 | */ 103 | public reduce(func: (value: U, result: any) => any, defaultCarry: any): Promise; 104 | public reduce(func: (value: any, result: any) => any, defaultCarry: any): Promise; 105 | public reduce(func: (value: any, result: any) => any, defaultCarry: any): Promise{ 106 | const tables = [this.table.name]; 107 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 108 | const objectStore = transaction.objectStore(this.table.name); 109 | const request = this.request(objectStore); 110 | 111 | return new Promise((resolve, reject) => { 112 | let result = defaultCarry; 113 | request.addEventListener<'success'>("success", async (event) => { 114 | const cursor = (event).target.result as IDBCursorWithValue | undefined; 115 | 116 | if (cursor) { 117 | 118 | if (!this.allowedToProcess(cursor.value)) { 119 | return cursor.continue(); 120 | } 121 | 122 | result = func(cursor.value, result); 123 | return cursor.continue(); 124 | } 125 | 126 | resolve(result); 127 | 128 | }); 129 | 130 | request.addEventListener<'error'>("error", (error) => reject(error)); 131 | }); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/models/base-model.d.ts: -------------------------------------------------------------------------------- 1 | import { TransactionHandling } from "./transaction-handling.js"; 2 | import { TableSchema } from "../migration/migration.interface.js"; 3 | export declare abstract class BaseModel extends TransactionHandling { 4 | abstract table: TableSchema; 5 | abstract readonly primaryId: string; 6 | /** 7 | * Opens IDBRequest to perform action on object store 8 | * @param objectStore 9 | */ 10 | protected request(objectStore: IDBObjectStore): IDBRequest; 11 | } 12 | -------------------------------------------------------------------------------- /src/models/base-model.ts: -------------------------------------------------------------------------------- 1 | import {TransactionHandling} from "./transaction-handling.js"; 2 | import {TableSchema} from "../migration/migration.interface.js"; 3 | 4 | export abstract class BaseModel extends TransactionHandling { 5 | 6 | public abstract table: TableSchema; 7 | 8 | public abstract get primaryId(): string; 9 | 10 | /** 11 | * Opens IDBRequest to perform action on object store 12 | * @param objectStore 13 | */ 14 | protected request(objectStore: IDBObjectStore): IDBRequest { 15 | const direction = this.cursor || undefined; 16 | 17 | if (this.indexBuilder) { 18 | const keyRange = this.keyRange(this.indexBuilder); 19 | const cursor = this.indexBuilder.index !== this.primaryId ? objectStore.index(this.indexBuilder.index) : objectStore; 20 | return cursor.openCursor(keyRange, direction); 21 | } else { 22 | return objectStore.openCursor(undefined, direction); 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/models/base-write-actions.d.ts: -------------------------------------------------------------------------------- 1 | import { FindFailActions } from "./find-fail-actions.js"; 2 | import { BaseWriteActionsInterface } from "./model.interface.js"; 3 | export declare abstract class BaseWriteActions extends FindFailActions implements BaseWriteActionsInterface { 4 | /** 5 | * Creates new record entry 6 | * @param data 7 | */ 8 | create(data: any): Promise; 9 | /** 10 | * Creates multiple record entry by passing array of entries to be created 11 | * @param entries 12 | */ 13 | createMultiple(entries: any[]): Promise; 14 | /** 15 | * Deletes matching entry. 16 | * If no builder/index for filtering is provided then throws error. 17 | */ 18 | destroy(): Promise; 19 | /** 20 | * Delete record at id of primary key 21 | * @param id 22 | */ 23 | delete(id: any): Promise; 24 | /** 25 | * Delete records matching index. 26 | * @param indexName 27 | * @param value 28 | * @param isMulti 29 | */ 30 | deleteIndex(indexName: string, value: any, isMulti?: boolean): Promise; 31 | /** 32 | * Clears entire object store 33 | */ 34 | truncate(): Promise; 35 | /** 36 | * Delete record at id 37 | * 38 | * @deprecated 39 | * @param id 40 | */ 41 | destroyId(id: any): Promise; 42 | /** 43 | * Updates all matching records. 44 | * By default deep merges the input data with existing data records. 45 | * @param data 46 | * @param mergeDeep 47 | */ 48 | update(data: any, mergeDeep?: boolean): Promise; 49 | /** 50 | * Updates the records at id 51 | * By default deep merges the input data with existing data record. 52 | * 53 | * @param id 54 | * @param data 55 | * @param mergeDeep 56 | * @throws NotFound 57 | */ 58 | save(id: any, data: any, mergeDeep?: boolean): Promise; 59 | /** 60 | * Updates all matching records at index 61 | * By default deep merges the input data with existing data record. 62 | * 63 | * @param indexName 64 | * @param id 65 | * @param data 66 | * @param mergeDeep 67 | * @throws NotFound 68 | */ 69 | saveIndex(indexName: string, id: any, data: any, mergeDeep?: boolean): Promise; 70 | /** 71 | * Updates all matching records at index 72 | * By default deep merges the input data with existing data record. 73 | * 74 | * @param indexName 75 | * @param id 76 | * @param data 77 | * @param mergeDeep 78 | * @throws NotFound 79 | */ 80 | saveAllIndex(indexName: string, id: any, data: any, mergeDeep?: boolean): Promise; 81 | } 82 | -------------------------------------------------------------------------------- /src/models/find-fail-actions.d.ts: -------------------------------------------------------------------------------- 1 | import { SearchActions } from "./search-actions.js"; 2 | export declare abstract class FindFailActions extends SearchActions { 3 | /** 4 | * Returns fist matching record or throws NotFound exception 5 | * @throws NotFound 6 | */ 7 | firstOrFail(): Promise; 8 | /** 9 | * Finds the record on primary key or throws error 10 | * @param id 11 | * @throws NotFound 12 | */ 13 | findOrFail(id: any): Promise; 14 | /** 15 | * Finds value at index or throws NotFound exception. 16 | * @param indexName 17 | * @param id 18 | * @throws NotFound 19 | */ 20 | findIndexOrFail(indexName: string, id: any): Promise; 21 | } 22 | -------------------------------------------------------------------------------- /src/models/find-fail-actions.ts: -------------------------------------------------------------------------------- 1 | import {SearchActions} from "./search-actions.js"; 2 | import {NotFound} from "../errors/not-found.js"; 3 | 4 | export abstract class FindFailActions extends SearchActions { 5 | 6 | /** 7 | * Returns fist matching record or throws NotFound exception 8 | * @throws NotFound 9 | */ 10 | public async firstOrFail(): Promise; 11 | public async firstOrFail(): Promise { 12 | const record = await this.first(); 13 | 14 | if (!record) { 15 | throw new NotFound(); 16 | } 17 | 18 | return record; 19 | } 20 | 21 | /** 22 | * Finds the record on primary key or throws error 23 | * @param id 24 | * @throws NotFound 25 | */ 26 | public async findOrFail(id: any): Promise; 27 | public async findOrFail(id: any): Promise { 28 | const record = await this.find(id); 29 | if (!record) { 30 | throw new NotFound(); 31 | } 32 | 33 | return record; 34 | } 35 | 36 | /** 37 | * Finds value at index or throws NotFound exception. 38 | * @param indexName 39 | * @param id 40 | * @throws NotFound 41 | */ 42 | public async findIndexOrFail(indexName: string, id: any): Promise; 43 | public async findIndexOrFail(indexName: string, id: any): Promise { 44 | const record = await this.findIndex(indexName, id); 45 | if (!record) { 46 | throw new NotFound(); 47 | } 48 | 49 | return record; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/models/find-or-create-actions.d.ts: -------------------------------------------------------------------------------- 1 | import { BaseWriteActions } from "./base-write-actions.js"; 2 | import { FindOrCreateActionInterface } from "./model.interface.js"; 3 | export declare abstract class FindOrCreateActions extends BaseWriteActions implements FindOrCreateActionInterface { 4 | /** 5 | * Finds the first record else creates the record with accordance to builder provided for filtering 6 | * @param data 7 | * @throws InvalidTransaction 8 | */ 9 | firstOrCreate(data: any): Promise; 10 | /** 11 | * Finds the record at primary key else creates the record 12 | * @param id 13 | * @param data 14 | * @throws InvalidTransaction 15 | */ 16 | findOrCreate(id: any, data: any): Promise; 17 | /** 18 | * Finds the record at index else creates the record 19 | * @param indexName 20 | * @param id 21 | * @param data 22 | * @throws InvalidTransaction 23 | */ 24 | findIndexOrCreate(indexName: string, id: any, data: any): Promise; 25 | } 26 | -------------------------------------------------------------------------------- /src/models/find-or-create-actions.ts: -------------------------------------------------------------------------------- 1 | import {BaseWriteActions} from "./base-write-actions.js"; 2 | import {FindOrCreateActionInterface, TransactionModes} from "./model.interface.js"; 3 | import {InvalidTransaction} from "../errors/invalid-transaction.js"; 4 | 5 | export abstract class FindOrCreateActions extends BaseWriteActions implements FindOrCreateActionInterface { 6 | /** 7 | * Finds the first record else creates the record with accordance to builder provided for filtering 8 | * @param data 9 | * @throws InvalidTransaction 10 | */ 11 | public async firstOrCreate(data: any): Promise; 12 | public async firstOrCreate(data: any): Promise { 13 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 14 | const transaction = this.createTransaction(tables, TransactionModes.Write); 15 | if (transaction.mode !== TransactionModes.Write) { 16 | throw new InvalidTransaction('Transaction not in write mode'); 17 | } 18 | 19 | const record = await this.first(); 20 | 21 | if (!record) { 22 | return this.create(data); 23 | } 24 | 25 | return record; 26 | } 27 | 28 | /** 29 | * Finds the record at primary key else creates the record 30 | * @param id 31 | * @param data 32 | * @throws InvalidTransaction 33 | */ 34 | public async findOrCreate(id: any, data: any): Promise; 35 | public async findOrCreate(id: any, data: any): Promise { 36 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 37 | const transaction = this.createTransaction(tables, TransactionModes.Write); 38 | if (transaction.mode !== TransactionModes.Write) { 39 | throw new InvalidTransaction('Transaction not in write mode'); 40 | } 41 | 42 | this.setTransaction(transaction); 43 | 44 | const record = await this.find(id); 45 | 46 | if (!record) { 47 | return this.create(data); 48 | } 49 | 50 | return record; 51 | } 52 | 53 | /** 54 | * Finds the record at index else creates the record 55 | * @param indexName 56 | * @param id 57 | * @param data 58 | * @throws InvalidTransaction 59 | */ 60 | public async findIndexOrCreate(indexName: string, id: any, data: any): Promise; 61 | public async findIndexOrCreate(indexName: string, id: any, data: any): Promise { 62 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 63 | const transaction = this.createTransaction(tables, TransactionModes.Write); 64 | if (transaction.mode !== TransactionModes.Write) { 65 | throw new InvalidTransaction('Transaction not in write mode'); 66 | } 67 | 68 | const record = await this.findIndex(indexName, id); 69 | 70 | if (!record) { 71 | return this.create(data); 72 | } 73 | 74 | return record; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/models/model.d.ts: -------------------------------------------------------------------------------- 1 | import { ModelInterface, ModelKeysInterface, TransactionModes } from "./model.interface.js"; 2 | import { TableSchema } from "../migration/migration.interface.js"; 3 | import { Connector } from "../connection/connector.js"; 4 | import { FindOrCreateActions } from "./find-or-create-actions.js"; 5 | export declare class Model extends FindOrCreateActions implements ModelInterface { 6 | db: IDBDatabase; 7 | table: TableSchema; 8 | connector: Connector; 9 | protected transaction: IDBTransaction | null; 10 | constructor(db: IDBDatabase, table: TableSchema, connector: Connector); 11 | /** 12 | * Syncs data at primary index and returns newly updated record 13 | * @param id 14 | * @param data 15 | * @param mergeDeep [Defaults true] 16 | */ 17 | sync(id: any, data: any, mergeDeep?: boolean): Promise; 18 | /** 19 | * Syncs data at index and returns newly updated record 20 | * @param indexName 21 | * @param id 22 | * @param data 23 | * @param mergeDeep [Defaults true] 24 | */ 25 | syncIndex(indexName: string, id: any, data: any, mergeDeep?: boolean): Promise; 26 | /** 27 | * Syncs data at index and returns newly updated record 28 | * @param indexName 29 | * @param id 30 | * @param data 31 | * @param mergeDeep [Defaults true] 32 | */ 33 | syncAllIndex(indexName: string, id: any, data: any, mergeDeep?: boolean): Promise; 34 | /** 35 | * Opens new transaction for all models and returns transaction instance 36 | * @param mode 37 | */ 38 | openTransaction(mode: TransactionModes): { 39 | models: ModelKeysInterface; 40 | transaction: IDBTransaction; 41 | }; 42 | /** 43 | * Loads relations against the model results 44 | * 45 | * @param results 46 | */ 47 | protected loadRelations(results: any[]): Promise[]; 48 | /** 49 | * The primary key of the model 50 | */ 51 | readonly primaryId: string; 52 | /** 53 | * Loads custom relation created in the ORM classes extending the base model class 54 | * @param results 55 | */ 56 | protected loadCustomRelations(results: any[]): Promise[]; 57 | /** 58 | * Adds sync column if table requires to have sync date 59 | * @param data 60 | */ 61 | private syncObj; 62 | } 63 | -------------------------------------------------------------------------------- /src/models/model.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DEFAULT_PRIMARY_ID, 3 | ModelInterface, 4 | ModelKeysInterface, RelationTypes, 5 | TransactionModes 6 | } from "./model.interface.js"; 7 | import {DEFAULT_SYNC_COLUMN_NAME, TableSchema} from "../migration/migration.interface.js"; 8 | import {Connector} from "../connection/connector.js"; 9 | import {FindOrCreateActions} from "./find-or-create-actions.js"; 10 | import {HasOne} from "../relations/has-one.js"; 11 | import {HasMany} from "../relations/has-many.js"; 12 | import {HasManyMulti} from "../relations/has-many-multi.js"; 13 | import {HasManyThroughMulti} from "../relations/has-many-through-multi.js"; 14 | import {Relations} from "../relations/relations.js"; 15 | import {mergeDeep as mergeDeepUtil} from "../utils.js"; 16 | 17 | export class Model extends FindOrCreateActions implements ModelInterface { 18 | 19 | protected transaction: IDBTransaction | null = null; 20 | 21 | public constructor(public db: IDBDatabase, public table: TableSchema, public connector: Connector) { 22 | super(db, table); 23 | } 24 | 25 | /** 26 | * Syncs data at primary index and returns newly updated record 27 | * @param id 28 | * @param data 29 | * @param mergeDeep [Defaults true] 30 | */ 31 | public async sync(id: any, data: any, mergeDeep?: boolean): Promise; 32 | public async sync(id: any, data: any, mergeDeep: boolean = true): Promise { 33 | await this.save(id, this.syncObj(data), mergeDeep); 34 | return this.find(id); 35 | } 36 | 37 | /** 38 | * Syncs data at index and returns newly updated record 39 | * @param indexName 40 | * @param id 41 | * @param data 42 | * @param mergeDeep [Defaults true] 43 | */ 44 | public async syncIndex(indexName: string, id: any, data: any, mergeDeep?: boolean): Promise; 45 | public async syncIndex(indexName: string, id: any, data: any, mergeDeep: boolean = true): Promise { 46 | await this.saveIndex(indexName, id, this.syncObj(data), mergeDeep); 47 | return this.findIndex(indexName, id); 48 | } 49 | 50 | /** 51 | * Syncs data at index and returns newly updated record 52 | * @param indexName 53 | * @param id 54 | * @param data 55 | * @param mergeDeep [Defaults true] 56 | */ 57 | public async syncAllIndex(indexName: string, id: any, data: any, mergeDeep?: boolean): Promise; 58 | public async syncAllIndex(indexName: string, id: any, data: any, mergeDeep: boolean = true): Promise { 59 | await this.saveAllIndex(indexName, id, this.syncObj(data), mergeDeep); 60 | return (this.resetBuilder().whereIndex(indexName, id) as Model).all(); 61 | } 62 | 63 | /** 64 | * Opens new transaction for all models and returns transaction instance 65 | * @param mode 66 | */ 67 | public openTransaction(mode: TransactionModes): { models: ModelKeysInterface, transaction: IDBTransaction } { 68 | 69 | const transaction = this.db.transaction(this.connector.migrationSchema.tables.map(table => table.name)); 70 | 71 | const models: { [key: string]: ModelInterface } = {}; 72 | 73 | for (const table of this.connector.migrationSchema.tables) { 74 | 75 | Object.defineProperty(models, table.name, { 76 | get: () => { 77 | let model: ModelInterface; 78 | if (this.table.ormClass) { 79 | model = new this.table.ormClass(this.db, table, this.connector); 80 | } else { 81 | model = new Model(this.db, table, this.connector); 82 | } 83 | 84 | model.setTransaction(transaction); 85 | return model; 86 | 87 | } 88 | }); 89 | } 90 | 91 | return {models, transaction}; 92 | } 93 | 94 | /** 95 | * Loads relations against the model results 96 | * 97 | * @param results 98 | */ 99 | protected loadRelations(results: any[]): Promise[] { 100 | const relationsArray: Promise[] = []; 101 | 102 | for (const relation of this.relations) { 103 | let loader: HasOne | HasMany | HasManyMulti | HasManyThroughMulti; 104 | switch (relation.type) { 105 | case RelationTypes.HasOne: 106 | loader = new HasOne(this.db, this.connector, this, relation); 107 | relationsArray.push(loader.fetch(results)); 108 | break; 109 | case RelationTypes.HasMany: 110 | loader = new HasMany(this.db, this.connector, this, relation); 111 | relationsArray.push(loader.fetch(results)); 112 | break; 113 | case RelationTypes.HasManyMultiEntry: 114 | loader = new HasManyMulti(this.db, this.connector, this, relation); 115 | relationsArray.push(loader.fetch(results)); 116 | break; 117 | case RelationTypes.HasManyThroughMultiEntry: 118 | loader = new HasManyThroughMulti(this.db, this.connector, this, relation); 119 | relationsArray.push(loader.fetch(results)); 120 | break; 121 | default: 122 | throw new Error(`Unknown relation ${relation.type}`); 123 | } 124 | } 125 | 126 | return relationsArray.concat(this.loadCustomRelations(results)); 127 | } 128 | 129 | /** 130 | * The primary key of the model 131 | */ 132 | public get primaryId(): string { 133 | return this.table.primary || DEFAULT_PRIMARY_ID; 134 | } 135 | 136 | /** 137 | * Loads custom relation created in the ORM classes extending the base model class 138 | * @param results 139 | */ 140 | protected loadCustomRelations(results: any[]): Promise[] { 141 | const relationPromises: Promise[] = []; 142 | 143 | for (const customRelation of this.customRelations) { 144 | 145 | if (!Reflect.has(this, customRelation)) { 146 | throw new Error(`Method ${customRelation} not defined.`); 147 | } 148 | 149 | const relation = (Reflect.get(this, customRelation)()); 150 | relationPromises.push(relation.fetch(results)); 151 | } 152 | 153 | return relationPromises; 154 | } 155 | 156 | /** 157 | * Adds sync column if table requires to have sync date 158 | * @param data 159 | */ 160 | private syncObj(data: any): any { 161 | if (this.table.syncColumn) { 162 | const attr = this.table.syncColumnName || DEFAULT_SYNC_COLUMN_NAME; 163 | const obj: { [key: string]: any | Date } = {}; 164 | obj[attr] = new Date(); 165 | return mergeDeepUtil(data, obj); 166 | } 167 | 168 | return data; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/models/orm-relation-builder.d.ts: -------------------------------------------------------------------------------- 1 | import { QueryBuilder } from "./query-builder.js"; 2 | import { HasOne } from "../relations/has-one.js"; 3 | import { ModelConstructorInterface, OrmRelationBuilderInterface, Relation, RelationTypes } from "./model.interface.js"; 4 | import { Connector } from "../connection/connector.js"; 5 | import { HasMany } from "../relations/has-many.js"; 6 | import { HasManyMulti } from "../relations/has-many-multi.js"; 7 | import { HasManyThroughMulti } from "../relations/has-many-through-multi.js"; 8 | export declare abstract class OrmRelationBuilder extends QueryBuilder implements OrmRelationBuilderInterface { 9 | abstract db: IDBDatabase; 10 | abstract connector: Connector; 11 | /** 12 | * Returns has one relation 13 | * @param model 14 | * @param foreignKey 15 | * @param localKey 16 | * @param parentKeyName 17 | */ 18 | hasOne(model: ModelConstructorInterface, foreignKey: string, localKey?: string | undefined, parentKeyName?: string): HasOne; 19 | /** 20 | * Returns has many relation 21 | * @param model 22 | * @param foreignKey 23 | * @param localKey 24 | * @param parentKeyName 25 | */ 26 | hasMany(model: ModelConstructorInterface, foreignKey: string, localKey?: string | undefined, parentKeyName?: string): HasMany; 27 | /** 28 | * Returns has many multi entry relation 29 | * @param model 30 | * @param foreignKey 31 | * @param localKey 32 | * @param parentKeyName 33 | */ 34 | hasManyMultiEntry(model: ModelConstructorInterface, foreignKey: string, localKey?: string, parentKeyName?: string): HasManyMulti; 35 | /** 36 | * Returns relation has many through multi entry relation 37 | * @param model 38 | * @param foreignKey 39 | * @param localKey 40 | * @param parentKeyName 41 | */ 42 | hasManyThroughMultiEntry(model: ModelConstructorInterface, foreignKey: string, localKey?: string, parentKeyName?: string): HasManyThroughMulti; 43 | convertToRelation(modelConstructor: ModelConstructorInterface, type: RelationTypes, foreignKey: string): Relation; 44 | private newModel; 45 | } 46 | -------------------------------------------------------------------------------- /src/models/orm-relation-builder.ts: -------------------------------------------------------------------------------- 1 | import {QueryBuilder} from "./query-builder.js"; 2 | import {HasOne} from "../relations/has-one.js"; 3 | import { 4 | ModelConstructorInterface, 5 | ModelInterface, 6 | OrmRelationBuilderInterface, 7 | Relation, 8 | RelationTypes 9 | } from "./model.interface.js"; 10 | import {Connector} from "../connection/connector.js"; 11 | import {HasMany} from "../relations/has-many.js"; 12 | import {HasManyMulti} from "../relations/has-many-multi.js"; 13 | import {HasManyThroughMulti} from "../relations/has-many-through-multi.js"; 14 | 15 | export abstract class OrmRelationBuilder extends QueryBuilder implements OrmRelationBuilderInterface { 16 | 17 | public abstract db: IDBDatabase; 18 | 19 | public abstract connector: Connector; 20 | 21 | /** 22 | * Returns has one relation 23 | * @param model 24 | * @param foreignKey 25 | * @param localKey 26 | * @param parentKeyName 27 | */ 28 | hasOne(model: ModelConstructorInterface, foreignKey: string, localKey?: string | undefined, parentKeyName?: string): HasOne { 29 | const current: unknown = this; 30 | const relation = this.convertToRelation(model, RelationTypes.HasOne, foreignKey); 31 | 32 | if (localKey) { 33 | relation.localKey = localKey; 34 | } 35 | 36 | if (parentKeyName) { 37 | relation.attributeName = parentKeyName; 38 | } 39 | 40 | return new HasOne(this.db, this.connector, current, relation); 41 | } 42 | 43 | /** 44 | * Returns has many relation 45 | * @param model 46 | * @param foreignKey 47 | * @param localKey 48 | * @param parentKeyName 49 | */ 50 | hasMany(model: ModelConstructorInterface, foreignKey: string, localKey?: string | undefined, parentKeyName?: string): HasMany { 51 | const current: unknown = this; 52 | const relation = this.convertToRelation(model, RelationTypes.HasMany, foreignKey); 53 | 54 | if (localKey) { 55 | relation.localKey = localKey; 56 | } 57 | 58 | if (parentKeyName) { 59 | relation.attributeName = parentKeyName; 60 | } 61 | 62 | return new HasMany(this.db, this.connector, current, relation); 63 | } 64 | 65 | /** 66 | * Returns has many multi entry relation 67 | * @param model 68 | * @param foreignKey 69 | * @param localKey 70 | * @param parentKeyName 71 | */ 72 | hasManyMultiEntry(model: ModelConstructorInterface, foreignKey: string, localKey?: string, parentKeyName?: string): HasManyMulti { 73 | const current: unknown = this; 74 | const relation = this.convertToRelation(model, RelationTypes.HasManyMultiEntry, foreignKey); 75 | 76 | if (localKey) { 77 | relation.localKey = localKey; 78 | } 79 | 80 | if (parentKeyName) { 81 | relation.attributeName = parentKeyName; 82 | } 83 | 84 | return new HasManyMulti(this.db, this.connector, current, relation); 85 | } 86 | 87 | /** 88 | * Returns relation has many through multi entry relation 89 | * @param model 90 | * @param foreignKey 91 | * @param localKey 92 | * @param parentKeyName 93 | */ 94 | hasManyThroughMultiEntry(model: ModelConstructorInterface, foreignKey: string, localKey?: string, parentKeyName?: string): HasManyThroughMulti { 95 | const current: unknown = this; 96 | const relation = this.convertToRelation(model, RelationTypes.HasManyThroughMultiEntry, foreignKey); 97 | 98 | if (localKey) { 99 | relation.localKey = localKey; 100 | } 101 | 102 | if (parentKeyName) { 103 | relation.attributeName = parentKeyName; 104 | } 105 | 106 | return new HasManyThroughMulti(this.db, this.connector, current, relation); 107 | } 108 | 109 | public convertToRelation(modelConstructor: ModelConstructorInterface, type: RelationTypes, foreignKey: string): Relation { 110 | const model = this.newModel(modelConstructor); 111 | return {model, type, foreignKey}; 112 | } 113 | 114 | private newModel(modelConstructor: ModelConstructorInterface): ModelInterface { 115 | const table = this.connector.migrationSchema.tables.find(tableSchema => tableSchema.name === modelConstructor.TableName); 116 | 117 | if (!table) { 118 | throw new Error('Table schema not found'); 119 | } 120 | 121 | return new modelConstructor(this.db, table, this.connector); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/models/query-builder.d.ts: -------------------------------------------------------------------------------- 1 | import { Builder, CursorDirection, IndexBuilder, ModelInterface, QueryBuilderInterface } from "./model.interface.js"; 2 | import { RelationBuilder } from "./relation.builder.js"; 3 | export declare class QueryBuilder extends RelationBuilder implements QueryBuilderInterface { 4 | /** 5 | * Index filter setting 6 | */ 7 | indexBuilder: IndexBuilder | null; 8 | /** 9 | * Non indexed columns search settings 10 | */ 11 | builder: Builder[]; 12 | /** 13 | * Search direction and type 14 | */ 15 | cursor: CursorDirection | null; 16 | /** 17 | * Search on exact index value 18 | * @param indexName 19 | * @param value 20 | */ 21 | whereIndex(indexName: string, value: any): QueryBuilderInterface | ModelInterface; 22 | /** 23 | * Search on multiple indexed value 24 | * @param indexName 25 | * @param values 26 | */ 27 | whereIndexIn(indexName: string, values: any[]): QueryBuilderInterface | ModelInterface; 28 | /** 29 | * Search on MultiEntry index value 30 | * @param indexName 31 | * @param values 32 | * @param unique 33 | */ 34 | whereMultiIndexIn(indexName: string, values: any[], unique?: boolean): QueryBuilderInterface | ModelInterface; 35 | /** 36 | * Search index value where index greater then equal to value 37 | * @param indexName 38 | * @param value 39 | */ 40 | indexGte(indexName: string, value: any): QueryBuilderInterface | ModelInterface; 41 | /** 42 | * Search index where index greater than value 43 | * @param indexName 44 | * @param value 45 | */ 46 | indexGt(indexName: string, value: any): QueryBuilderInterface | ModelInterface; 47 | /** 48 | * Search index where index less than equal value 49 | * @param indexName 50 | * @param value 51 | */ 52 | indexLte(indexName: string, value: any): QueryBuilderInterface | ModelInterface; 53 | /** 54 | * Search index where index less than value 55 | * @param indexName 56 | * @param value 57 | */ 58 | indexLt(indexName: string, value: any): QueryBuilderInterface | ModelInterface; 59 | /** 60 | * Search index between values but not inclusive. 61 | * @param indexName 62 | * @param lower 63 | * @param upper 64 | */ 65 | indexBetween(indexName: string, lower: any, upper: any): QueryBuilderInterface | ModelInterface; 66 | /** 67 | * Search attribute where value is same 68 | * @param attributeName 69 | * @param value 70 | */ 71 | where(attributeName: string, value: any): QueryBuilderInterface | ModelInterface; 72 | /** 73 | * Search attribute where attribute value match one of the values 74 | * @param attributeName 75 | * @param values 76 | */ 77 | whereIn(attributeName: string, values: any[]): QueryBuilderInterface | ModelInterface; 78 | /** 79 | * Search attribute where attribute value is array type and matches one of the value 80 | * @param attributeName 81 | * @param values 82 | * @param unique 83 | */ 84 | whereInArray(attributeName: string, values: any[], unique?: boolean): QueryBuilderInterface | ModelInterface; 85 | /** 86 | * Search attribute value is greater then or equal value 87 | * @param attributeName 88 | * @param value 89 | */ 90 | gte(attributeName: string, value: any): QueryBuilderInterface | ModelInterface; 91 | /** 92 | * Search attribute value is greater than value 93 | * @param attributeName 94 | * @param value 95 | */ 96 | gt(attributeName: string, value: any): QueryBuilderInterface | ModelInterface; 97 | /** 98 | * Search attribute value is less than equal value 99 | * @param attributeName 100 | * @param value 101 | */ 102 | lte(attributeName: string, value: any): QueryBuilderInterface | ModelInterface; 103 | /** 104 | * Search attribute value is less than value 105 | * @param attributeName 106 | * @param value 107 | */ 108 | lt(attributeName: string, value: any): QueryBuilderInterface | ModelInterface; 109 | /** 110 | * Search attribute value between bound values. 111 | * @param attributeName 112 | * @param lower 113 | * @param upper 114 | */ 115 | between(attributeName: string, lower: any, upper: any): QueryBuilderInterface | ModelInterface; 116 | cursorDirection(direction: CursorDirection): QueryBuilderInterface | ModelInterface; 117 | /** 118 | * Returns IDBKeyRange on indexed filter 119 | * @param indexBuilder 120 | */ 121 | keyRange(indexBuilder: IndexBuilder): IDBKeyRange; 122 | /** 123 | * Checks if the attribute value is allowed to be processed according to attribute filters 124 | * @param result 125 | */ 126 | protected allowedToProcess(result: any): boolean; 127 | /** 128 | * Resets the builder values for filtering 129 | */ 130 | resetBuilder(): QueryBuilderInterface | ModelInterface; 131 | } 132 | -------------------------------------------------------------------------------- /src/models/relation.builder.d.ts: -------------------------------------------------------------------------------- 1 | import { ModelInterface, QueryBuilderInterface, Relation, RelationQueryBuilder, RelationTypes } from "./model.interface.js"; 2 | import { TableSchema } from "../migration/migration.interface.js"; 3 | export declare abstract class RelationBuilder implements RelationQueryBuilder { 4 | /** 5 | * Array of relations to be loaded 6 | */ 7 | relations: Relation[]; 8 | /** 9 | * Custom relations list 10 | */ 11 | customRelations: string[]; 12 | /** 13 | * Returns list of childRelation tables required by the model action 14 | * @param tables 15 | */ 16 | tableNames(tables: TableSchema[]): string[]; 17 | /** 18 | * Adds childRelation to be fetched 19 | * @param relations 20 | */ 21 | with(relations: Relation[]): RelationQueryBuilder | ModelInterface; 22 | /** 23 | * Adds childRelation to be fetched 24 | * 25 | * @deprecated 26 | * @param modelName 27 | * @param type 28 | * @param localKey 29 | * @param foreignKey 30 | * @param func 31 | */ 32 | relation(modelName: string, type: RelationTypes, localKey: string, foreignKey: string, func?: (builder: QueryBuilderInterface) => QueryBuilderInterface): RelationQueryBuilder | ModelInterface; 33 | /** 34 | * Adds custom relations 35 | * @param relations 36 | */ 37 | withCustom(relations: string[]): RelationQueryBuilder | ModelInterface; 38 | } 39 | -------------------------------------------------------------------------------- /src/models/relation.builder.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ModelInterface, 3 | QueryBuilderInterface, 4 | Relation, 5 | RelationQueryBuilder, 6 | RelationTypes 7 | } from "./model.interface.js"; 8 | import {Model} from "./model.js"; 9 | import {QueryBuilder} from "./query-builder.js"; 10 | import {Connector} from "../connection/connector.js"; 11 | import {TableSchema} from "../migration/migration.interface.js"; 12 | 13 | export abstract class RelationBuilder implements RelationQueryBuilder { 14 | 15 | /** 16 | * Array of relations to be loaded 17 | */ 18 | public relations: Relation[] = []; 19 | 20 | /** 21 | * Custom relations list 22 | */ 23 | public customRelations: string[] = []; 24 | 25 | /** 26 | * Returns list of childRelation tables required by the model action 27 | * @param tables 28 | */ 29 | public tableNames(tables: TableSchema[]): string[] { 30 | return tables.map(table => table.name); 31 | } 32 | 33 | /** 34 | * Adds childRelation to be fetched 35 | * @param relations 36 | */ 37 | public with(relations: Relation[]): RelationQueryBuilder | ModelInterface { 38 | // first filtering existing relations for same table 39 | 40 | const filteredRelations = this.relations.filter( 41 | relation => !relations.find( 42 | newRelation => newRelation.model === relation.model) 43 | ); 44 | this.relations = filteredRelations.concat(relations); 45 | 46 | return this; 47 | } 48 | 49 | /** 50 | * Adds childRelation to be fetched 51 | * 52 | * @deprecated 53 | * @param modelName 54 | * @param type 55 | * @param localKey 56 | * @param foreignKey 57 | * @param func 58 | */ 59 | public relation( 60 | modelName: string, type: RelationTypes, localKey: string, foreignKey: string, func?: (builder: QueryBuilderInterface) => QueryBuilderInterface 61 | ): RelationQueryBuilder | ModelInterface { 62 | 63 | const index = this.relations.findIndex(relation => relation.model === modelName); 64 | 65 | if (index !== -1) { 66 | this.relations.splice(index, 1); 67 | } 68 | 69 | this.relations.push({ 70 | model: modelName, 71 | type, 72 | localKey, 73 | foreignKey, 74 | func 75 | }); 76 | 77 | return this; 78 | } 79 | 80 | /** 81 | * Adds custom relations 82 | * @param relations 83 | */ 84 | public withCustom(relations: string[]): RelationQueryBuilder | ModelInterface { 85 | const filteredRelations = this.customRelations.filter( 86 | relation => !relations.find( 87 | newRelation => newRelation === relation) 88 | ); 89 | this.customRelations = filteredRelations.concat(relations); 90 | 91 | return this; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/models/search-actions.d.ts: -------------------------------------------------------------------------------- 1 | import { Aggregate } from "./aggregate.js"; 2 | import { BaseSearchActionsInterface } from "./model.interface.js"; 3 | export declare abstract class SearchActions extends Aggregate implements BaseSearchActionsInterface { 4 | protected abstract loadRelations(results: any[]): Promise[]; 5 | protected abstract loadCustomRelations(results: any[]): Promise[]; 6 | /** 7 | * Returns list of all matching records. 8 | */ 9 | all(): Promise; 10 | /** 11 | * Returns fist matching record 12 | */ 13 | first(): Promise; 14 | /** 15 | * Finds the record on primary key or returns null 16 | * @param id 17 | */ 18 | find(id: any): Promise; 19 | /** 20 | * Finds value at index. 21 | * @param indexName 22 | * @param id 23 | */ 24 | findIndex(indexName: string, id: any): Promise; 25 | /** 26 | * Finds all values for the index 27 | * 28 | * @param indexName 29 | * @param id 30 | */ 31 | findAllIndex(indexName: string, id: any): Promise; 32 | } 33 | -------------------------------------------------------------------------------- /src/models/search-actions.ts: -------------------------------------------------------------------------------- 1 | import {Aggregate} from "./aggregate.js"; 2 | import {BaseSearchActionsInterface, TransactionModes} from "./model.interface.js"; 3 | import {IDBResultEvent} from "../connection/idb-event.interface.js"; 4 | 5 | export abstract class SearchActions extends Aggregate implements BaseSearchActionsInterface { 6 | 7 | protected abstract loadRelations(results: any[]): Promise[]; 8 | 9 | protected abstract loadCustomRelations(results: any[]): Promise[]; 10 | 11 | /** 12 | * Returns list of all matching records. 13 | */ 14 | public all(): Promise; 15 | public all(): Promise { 16 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 17 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 18 | const objectStore = transaction.objectStore(this.table.name); 19 | const request = this.request(objectStore); 20 | 21 | return new Promise((resolve, reject) => { 22 | 23 | let results: any[] = []; 24 | request.addEventListener<'success'>("success", async (event) => { 25 | const cursor = (event).target.result as IDBCursorWithValue | undefined; 26 | 27 | if (cursor) { 28 | 29 | if (!this.allowedToProcess(cursor.value)) { 30 | return cursor.continue(); 31 | } 32 | results.push(cursor.value); 33 | return cursor.continue(); 34 | } 35 | 36 | if (results.length === 0 || this.relations.length === 0) { 37 | resolve(results); 38 | } 39 | 40 | const relations: Promise[] = this.loadRelations(results); 41 | 42 | await Promise.all(relations); 43 | 44 | resolve(results); 45 | }); 46 | 47 | request.addEventListener<'error'>("error", (error) => reject(error)); 48 | }); 49 | 50 | } 51 | 52 | /** 53 | * Returns fist matching record 54 | */ 55 | public first(): Promise; 56 | public first(): Promise { 57 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 58 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 59 | const objectStore = transaction.objectStore(this.table.name); 60 | const request = this.request(objectStore); 61 | 62 | return new Promise((resolve, reject) => { 63 | 64 | let result: any; 65 | request.addEventListener<'success'>("success", async (event) => { 66 | const cursor = (event).target.result as IDBCursorWithValue | undefined; 67 | 68 | if (cursor) { 69 | 70 | if (!this.allowedToProcess(cursor.value)) { 71 | return cursor.continue(); 72 | } 73 | result = cursor.value; 74 | } 75 | 76 | if (!result || this.relations.length === 0) { 77 | resolve(result || null); 78 | } 79 | 80 | const relations: Promise[] = this.loadRelations([result]); 81 | 82 | await Promise.all(relations); 83 | 84 | resolve(result); 85 | }); 86 | 87 | request.addEventListener<'error'>("error", (error) => reject(error)); 88 | }); 89 | } 90 | 91 | /** 92 | * Finds the record on primary key or returns null 93 | * @param id 94 | */ 95 | public find(id: any): Promise; 96 | public find(id: any): Promise { 97 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 98 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 99 | const objectStore = transaction.objectStore(this.table.name); 100 | const request = objectStore.get(id); 101 | 102 | return new Promise((resolve, reject) => { 103 | 104 | request.addEventListener<'success'>("success", async (event) => { 105 | const result = (event as IDBResultEvent).target.result; 106 | 107 | if (!result || this.relations.length === 0) { 108 | resolve(result || null); 109 | } 110 | 111 | const relations: Promise[] = this.loadRelations([result]); 112 | 113 | await Promise.all(relations); 114 | 115 | resolve(result || null); 116 | }); 117 | 118 | request.addEventListener<'error'>("error", (error) => reject(error)); 119 | }); 120 | } 121 | 122 | /** 123 | * Finds value at index. 124 | * @param indexName 125 | * @param id 126 | */ 127 | public findIndex(indexName: string, id: any): Promise; 128 | public findIndex(indexName: string, id: any): Promise { 129 | 130 | this.resetBuilder(); 131 | 132 | const tables = this.tableNames(this.connector.migrationSchema.tables).concat(this.table.name); 133 | const transaction = this.getTransaction(tables, TransactionModes.ReadOnly); 134 | const objectStore = transaction.objectStore(this.table.name); 135 | const request = objectStore.index(indexName).get(id); 136 | 137 | return new Promise((resolve, reject) => { 138 | 139 | request.addEventListener<'success'>("success", async (event) => { 140 | const result = (event as IDBResultEvent).target.result; 141 | 142 | if (!result || this.relations.length === 0) { 143 | resolve(result || null); 144 | } 145 | 146 | const relations: Promise[] = this.loadRelations([result]); 147 | 148 | await Promise.all(relations); 149 | 150 | resolve(result); 151 | }); 152 | 153 | request.addEventListener<'error'>("error", (error) => reject(error)); 154 | }); 155 | } 156 | 157 | /** 158 | * Finds all values for the index 159 | * 160 | * @param indexName 161 | * @param id 162 | */ 163 | public findAllIndex(indexName: string, id: any): Promise; 164 | public findAllIndex(indexName: string, id: any): Promise { 165 | this.resetBuilder(); 166 | this.whereIndex(indexName, id); 167 | return this.all(); 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /src/models/transaction-handling.d.ts: -------------------------------------------------------------------------------- 1 | import { TransactionModes } from "./model.interface.js"; 2 | import { OrmRelationBuilder } from "./orm-relation-builder.js"; 3 | export declare abstract class TransactionHandling extends OrmRelationBuilder implements TransactionHandling { 4 | protected transaction: IDBTransaction | null; 5 | /** 6 | * Retrieves current transaction and if ne transaction exists then creates new one. 7 | * 8 | * @param stores 9 | * @param mode 10 | * @param overwrite 11 | */ 12 | getTransaction(stores: string[], mode: TransactionModes, overwrite?: boolean): IDBTransaction; 13 | /** 14 | * Sets transaction for the model 15 | * @param transaction 16 | */ 17 | setTransaction(transaction: IDBTransaction): void; 18 | /** 19 | * Creates new transaction 20 | * @param stores 21 | * @param mode 22 | */ 23 | createTransaction(stores: string[], mode: TransactionModes): IDBTransaction; 24 | } 25 | -------------------------------------------------------------------------------- /src/models/transaction-handling.ts: -------------------------------------------------------------------------------- 1 | import {TransactionModes} from "./model.interface.js"; 2 | import {OrmRelationBuilder} from "./orm-relation-builder.js"; 3 | 4 | export abstract class TransactionHandling extends OrmRelationBuilder implements TransactionHandling { 5 | 6 | protected transaction: IDBTransaction | null = null; 7 | 8 | /** 9 | * Retrieves current transaction and if ne transaction exists then creates new one. 10 | * 11 | * @param stores 12 | * @param mode 13 | * @param overwrite 14 | */ 15 | public getTransaction(stores: string[], mode: TransactionModes, overwrite: boolean = false): IDBTransaction { 16 | if (this.transaction === null || overwrite) { 17 | this.transaction = this.createTransaction(stores, mode); 18 | } 19 | return this.transaction; 20 | } 21 | 22 | /** 23 | * Sets transaction for the model 24 | * @param transaction 25 | */ 26 | public setTransaction(transaction: IDBTransaction): void { 27 | this.transaction = transaction; 28 | } 29 | 30 | /** 31 | * Creates new transaction 32 | * @param stores 33 | * @param mode 34 | */ 35 | public createTransaction(stores: string[], mode: TransactionModes): IDBTransaction { 36 | const transaction = this.db.transaction(stores, mode); 37 | this.setTransaction(transaction); 38 | 39 | return transaction; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/relations/has-many-multi.d.ts: -------------------------------------------------------------------------------- 1 | import { Relations } from "./relations.js"; 2 | import { Connector } from "../connection/connector.js"; 3 | import { ModelInterface, Relation } from "../models/model.interface.js"; 4 | export declare class HasManyMulti extends Relations { 5 | db: IDBDatabase; 6 | connector: Connector; 7 | protected parentModel: ModelInterface; 8 | childRelation: Relation; 9 | constructor(db: IDBDatabase, connector: Connector, parentModel: ModelInterface, childRelation: Relation); 10 | fetch(results: any[]): Promise; 11 | bindResults(parentResults: any[], relationResults: any[], relation: Relation): Promise; 12 | } 13 | -------------------------------------------------------------------------------- /src/relations/has-many-multi.ts: -------------------------------------------------------------------------------- 1 | import {Relations} from "./relations.js"; 2 | import {Connector} from "../connection/connector.js"; 3 | import {ModelInterface, Relation} from "../models/model.interface.js"; 4 | 5 | export class HasManyMulti extends Relations { 6 | 7 | constructor( 8 | public db: IDBDatabase, 9 | public connector: Connector, 10 | protected parentModel: ModelInterface, 11 | public childRelation: Relation 12 | ) { 13 | super(); 14 | } 15 | 16 | public async fetch(results: any[]): Promise { 17 | let model = this.getRelationModel(this.childRelation); 18 | model = this.filteredModel(model, this.childRelation); 19 | 20 | const values = results.map(result => result[this.getLocalKey(this.parentModel, this.childRelation)]); 21 | model.whereMultiIndexIn(this.childRelation.foreignKey, values); 22 | 23 | const relationResults = await model.all(); 24 | 25 | return this.bindResults(results, relationResults, this.childRelation); 26 | } 27 | 28 | public bindResults(parentResults: any[], relationResults: any[], relation: Relation): Promise { 29 | const localKey = this.getLocalKey(this.parentModel, this.childRelation); 30 | 31 | parentResults.forEach(parentResult => { 32 | parentResult[this.getAttributeName(this.parentModel, relation)] = relationResults.filter( 33 | (relationResult: any) => !!relationResult[relation.foreignKey].find( 34 | (multiValue: any) => multiValue === parentResult[localKey] 35 | ) 36 | ); 37 | }); 38 | 39 | return Promise.resolve(parentResults); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/relations/has-many-through-multi.d.ts: -------------------------------------------------------------------------------- 1 | import { Relations } from "./relations.js"; 2 | import { ModelInterface, Relation } from "../models/model.interface.js"; 3 | import { Connector } from "../connection/connector.js"; 4 | export declare class HasManyThroughMulti extends Relations { 5 | db: IDBDatabase; 6 | connector: Connector; 7 | protected parentModel: ModelInterface; 8 | childRelation: Relation; 9 | constructor(db: IDBDatabase, connector: Connector, parentModel: ModelInterface, childRelation: Relation); 10 | fetch(results: any[]): Promise; 11 | bindResults(parentResults: any[], relationResults: any[], relation: Relation): Promise; 12 | } 13 | -------------------------------------------------------------------------------- /src/relations/has-many-through-multi.ts: -------------------------------------------------------------------------------- 1 | import {Relations} from "./relations.js"; 2 | import {ModelInterface, Relation} from "../models/model.interface.js"; 3 | import {Connector} from "../connection/connector.js"; 4 | 5 | export class HasManyThroughMulti extends Relations { 6 | constructor( 7 | public db: IDBDatabase, 8 | public connector: Connector, 9 | protected parentModel: ModelInterface, 10 | public childRelation: Relation 11 | ) { 12 | super(); 13 | } 14 | 15 | public async fetch(results: any[]): Promise { 16 | let model = this.getRelationModel(this.childRelation); 17 | model = this.filteredModel(model, this.childRelation); 18 | 19 | const values = results.reduce( 20 | (carry: any[], result) => carry.concat(result[this.getLocalKey(this.parentModel, this.childRelation)]), [] 21 | ); 22 | model.whereIndexIn(this.childRelation.foreignKey, values); 23 | 24 | const relationResults = await model.all(); 25 | 26 | return this.bindResults(results, relationResults, this.childRelation); 27 | } 28 | 29 | public bindResults(parentResults: any[], relationResults: any[], relation: Relation): Promise { 30 | const localKey = this.getLocalKey(this.parentModel, this.childRelation); 31 | 32 | parentResults.forEach(parentResult => { 33 | parentResult[this.getAttributeName(this.parentModel, relation)] = relationResults.filter( 34 | (relationResult: any) => !!parentResult[localKey].find( 35 | (multiValue: any) => multiValue === relationResult[relation.foreignKey] 36 | ) 37 | ); 38 | }); 39 | 40 | return Promise.resolve(parentResults); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/relations/has-many.d.ts: -------------------------------------------------------------------------------- 1 | import { Relations } from "./relations.js"; 2 | import { Connector } from "../connection/connector.js"; 3 | import { ModelInterface, Relation } from "../models/model.interface.js"; 4 | export declare class HasMany extends Relations { 5 | db: IDBDatabase; 6 | connector: Connector; 7 | protected parentModel: ModelInterface; 8 | childRelation: Relation; 9 | constructor(db: IDBDatabase, connector: Connector, parentModel: ModelInterface, childRelation: Relation); 10 | /** 11 | * Fetch relation results 12 | * @param results 13 | */ 14 | fetch(results: any[]): Promise; 15 | /** 16 | * Bind relation results to parent results 17 | * @param parentResults 18 | * @param relationResults 19 | * @param relation 20 | */ 21 | bindResults(parentResults: any[], relationResults: any, relation: Relation): Promise; 22 | } 23 | -------------------------------------------------------------------------------- /src/relations/has-many.ts: -------------------------------------------------------------------------------- 1 | import {Relations} from "./relations.js"; 2 | import {Connector} from "../connection/connector.js"; 3 | import {ModelInterface, Relation} from "../models/model.interface.js"; 4 | 5 | export class HasMany extends Relations { 6 | 7 | constructor( 8 | public db: IDBDatabase, 9 | public connector: Connector, 10 | protected parentModel: ModelInterface, 11 | public childRelation: Relation 12 | ) { 13 | super(); 14 | } 15 | 16 | /** 17 | * Fetch relation results 18 | * @param results 19 | */ 20 | public async fetch(results: any[]): Promise { 21 | let model = this.getRelationModel(this.childRelation); 22 | model = this.filteredModel(model, this.childRelation); 23 | 24 | const values = results.map(result => result[this.getLocalKey(this.parentModel, this.childRelation)]); 25 | model.whereIndexIn(this.childRelation.foreignKey, values); 26 | 27 | const relationResults = await model.all(); 28 | 29 | return this.bindResults(results, relationResults, this.childRelation); 30 | } 31 | 32 | /** 33 | * Bind relation results to parent results 34 | * @param parentResults 35 | * @param relationResults 36 | * @param relation 37 | */ 38 | public bindResults(parentResults: any[], relationResults: any, relation: Relation): Promise { 39 | const localKey = this.getLocalKey(this.parentModel, this.childRelation); 40 | parentResults.forEach(parentResult => { 41 | parentResult[this.getAttributeName(this.parentModel, relation)] = relationResults.filter( 42 | (relationResult: any) => relationResult[relation.foreignKey] === parentResult[localKey] 43 | ); 44 | }); 45 | 46 | return Promise.resolve(parentResults); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/relations/has-one.d.ts: -------------------------------------------------------------------------------- 1 | import { Relations } from "./relations.js"; 2 | import { Connector } from "../connection/connector.js"; 3 | import { ModelInterface, Relation } from "../models/model.interface.js"; 4 | export declare class HasOne extends Relations { 5 | db: IDBDatabase; 6 | connector: Connector; 7 | protected parentModel: ModelInterface; 8 | childRelation: Relation; 9 | constructor(db: IDBDatabase, connector: Connector, parentModel: ModelInterface, childRelation: Relation); 10 | fetch(results: any[]): Promise; 11 | bindResults(parentResults: any[], relationResults: any[], relation: Relation): Promise; 12 | } 13 | -------------------------------------------------------------------------------- /src/relations/has-one.ts: -------------------------------------------------------------------------------- 1 | import {Relations} from "./relations.js"; 2 | import {Connector} from "../connection/connector.js"; 3 | import {CursorDirection, ModelInterface, Relation} from "../models/model.interface.js"; 4 | 5 | export class HasOne extends Relations { 6 | 7 | constructor( 8 | public db: IDBDatabase, 9 | public connector: Connector, 10 | protected parentModel: ModelInterface, 11 | public childRelation: Relation 12 | ) { 13 | super(); 14 | } 15 | 16 | public async fetch(results: any[]): Promise { 17 | let model = this.getRelationModel(this.childRelation); 18 | model = this.filteredModel(model, this.childRelation); 19 | 20 | let relationResults: any[] = []; 21 | // optimizing query 22 | if (results.length === 1) { 23 | model.whereIndex(this.childRelation.foreignKey, results[0][this.getLocalKey(this.parentModel, this.childRelation)]); 24 | relationResults = [await model.first()]; 25 | 26 | } else { 27 | const values = results.map(result => result[this.getLocalKey(this.parentModel, this.childRelation)]); 28 | model.whereIndexIn(this.childRelation.foreignKey, values) 29 | .cursorDirection(CursorDirection.AscendingUnique); 30 | 31 | relationResults = await model.all(); 32 | } 33 | 34 | return this.bindResults(results, relationResults, this.childRelation); 35 | } 36 | 37 | public bindResults(parentResults: any[], relationResults: any[], relation: Relation): Promise { 38 | const localKey = this.getLocalKey(this.parentModel, this.childRelation); 39 | parentResults.forEach(result => { 40 | 41 | const mappedResult = relationResults.find(relationResult => relationResult[relation.foreignKey] === result[localKey]); 42 | result[this.getAttributeName(this.parentModel, relation)] = mappedResult || null; 43 | }); 44 | return Promise.resolve(parentResults); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/relations/relation.interface.d.ts: -------------------------------------------------------------------------------- 1 | import { Connector } from "../connection/connector.js"; 2 | import { ModelInterface, Relation } from "../models/model.interface.js"; 3 | export interface RelationInterface { 4 | db: IDBDatabase; 5 | connector: Connector; 6 | bindResults(parentResults: any | any[], relationResults: any[], relation: Relation): Promise; 7 | fetch(results: any[]): Promise; 8 | getLocalKey(model: ModelInterface, relation: Relation): string; 9 | getAttributeName(model: ModelInterface, relation: Relation): string; 10 | } 11 | -------------------------------------------------------------------------------- /src/relations/relation.interface.ts: -------------------------------------------------------------------------------- 1 | import {Connector} from "../connection/connector.js"; 2 | import {ModelInterface, Relation} from "../models/model.interface.js"; 3 | 4 | export interface RelationInterface { 5 | db: IDBDatabase; 6 | 7 | connector: Connector; 8 | 9 | bindResults(parentResults: any | any[], relationResults: any[], relation: Relation): Promise; 10 | 11 | fetch(results: any[]): Promise; 12 | 13 | getLocalKey(model: ModelInterface, relation: Relation): string; 14 | 15 | getAttributeName(model: ModelInterface, relation: Relation): string; 16 | } 17 | -------------------------------------------------------------------------------- /src/relations/relations.d.ts: -------------------------------------------------------------------------------- 1 | import { ModelInterface, QueryBuilderInterface, Relation } from "../models/model.interface.js"; 2 | import { QueryBuilder } from "../models/query-builder.js"; 3 | import { Connector } from "../connection/connector.js"; 4 | import { RelationInterface } from "./relation.interface.js"; 5 | export declare abstract class Relations extends QueryBuilder implements RelationInterface, QueryBuilderInterface { 6 | /** 7 | * IDBDatabase 8 | */ 9 | abstract db: IDBDatabase; 10 | /** 11 | * Connection instance 12 | */ 13 | abstract connector: Connector; 14 | /** 15 | * Binds childRelation result to parent result. 16 | * @param parentResults 17 | * @param relationResults 18 | * @param relation 19 | */ 20 | abstract bindResults(parentResults: any | any[], relationResults: any[], relation: Relation): Promise; 21 | /** 22 | * Fetches childRelation results 23 | * @param results 24 | */ 25 | abstract fetch(results: any[]): Promise; 26 | /** 27 | * Sets builder values created through callback function 28 | * @param model 29 | * @param relation 30 | */ 31 | filteredModel(model: ModelInterface, relation: Relation): ModelInterface; 32 | bindBuilder(model: ModelInterface): ModelInterface; 33 | /** 34 | * Retrieves th childRelation model instance 35 | * @param relation 36 | */ 37 | getRelationModel(relation: Relation): ModelInterface; 38 | /** 39 | * Retrieves the local key of parent model 40 | * @param model 41 | * @param relation 42 | */ 43 | getLocalKey(model: ModelInterface, relation: Relation): string; 44 | /** 45 | * Returns the attribute name by which childRelation is to be attached with parent model 46 | * @param model 47 | * @param relation 48 | */ 49 | getAttributeName(model: ModelInterface, relation: Relation): string; 50 | } 51 | -------------------------------------------------------------------------------- /src/relations/relations.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DEFAULT_PRIMARY_ID, ModelConstructorInterface, 3 | ModelInterface, 4 | QueryBuilderInterface, 5 | Relation, RelationTypes, 6 | } from "../models/model.interface.js"; 7 | import {Model} from "../models/model.js"; 8 | import {QueryBuilder} from "../models/query-builder.js"; 9 | import {Connector} from "../connection/connector.js"; 10 | import {RelationInterface} from "./relation.interface.js"; 11 | 12 | export abstract class Relations extends QueryBuilder implements RelationInterface, QueryBuilderInterface { 13 | 14 | /** 15 | * IDBDatabase 16 | */ 17 | public abstract db: IDBDatabase; 18 | 19 | /** 20 | * Connection instance 21 | */ 22 | public abstract connector: Connector; 23 | 24 | /** 25 | * Binds childRelation result to parent result. 26 | * @param parentResults 27 | * @param relationResults 28 | * @param relation 29 | */ 30 | public abstract bindResults(parentResults: any | any[], relationResults: any[], relation: Relation): Promise; 31 | 32 | /** 33 | * Fetches childRelation results 34 | * @param results 35 | */ 36 | public abstract fetch(results: any[]): Promise; 37 | 38 | /** 39 | * Sets builder values created through callback function 40 | * @param model 41 | * @param relation 42 | */ 43 | public filteredModel(model: ModelInterface, relation: Relation): ModelInterface { 44 | model = this.bindBuilder(model); 45 | const builder = new QueryBuilder(); 46 | 47 | if (relation.func) { 48 | const query = relation.func(builder); 49 | model.builder = model.builder.concat(query.builder); 50 | model.with(builder.relations); 51 | } 52 | 53 | return model; 54 | } 55 | 56 | public bindBuilder(model: ModelInterface): ModelInterface { 57 | model.builder = model.builder.concat(this.builder); 58 | model.with(this.relations); 59 | return model; 60 | } 61 | 62 | /** 63 | * Retrieves th childRelation model instance 64 | * @param relation 65 | */ 66 | public getRelationModel(relation: Relation): ModelInterface { 67 | let model: ModelInterface; 68 | 69 | if (typeof relation.model === "string") { 70 | const tableSchema = this.connector.migrationSchema.tables.find(table => table.name === relation.model); 71 | if (!tableSchema) { 72 | throw new Error('Table schema not found'); 73 | } 74 | 75 | model = new Model(this.db, tableSchema, this.connector); 76 | } else { 77 | model = relation.model; 78 | } 79 | 80 | return model; 81 | } 82 | 83 | /** 84 | * Retrieves the local key of parent model 85 | * @param model 86 | * @param relation 87 | */ 88 | public getLocalKey(model: ModelInterface, relation: Relation): string { 89 | const primaryKey = model.table.primary || DEFAULT_PRIMARY_ID; 90 | return relation.localKey ? relation.localKey : primaryKey; 91 | } 92 | 93 | /** 94 | * Returns the attribute name by which childRelation is to be attached with parent model 95 | * @param model 96 | * @param relation 97 | */ 98 | public getAttributeName(model: ModelInterface, relation: Relation): string { 99 | return relation.attributeName || model.table.name; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/utils.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Retrieves the nested attribute value using dot "." values 3 | * @param attributeString 4 | * @param value 5 | */ 6 | export declare function nestedAttributeValue(attributeString: string, value: any): any; 7 | /** 8 | * Deep merges two object taking first input as reference and second input being the properties to be merged to first. 9 | * @param object1 10 | * @param object2 11 | */ 12 | export declare function mergeDeep(object1: { 13 | [key: string]: any | any[]; 14 | }, object2: { 15 | [key: string]: any | any[]; 16 | }): { 17 | [key: string]: any | any[]; 18 | }; 19 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Retrieves the nested attribute value using dot "." values 3 | * @param attributeString 4 | * @param value 5 | */ 6 | export function nestedAttributeValue(attributeString: string, value: any): any { 7 | const attributes = attributeString.split('.'); 8 | let content = value; 9 | 10 | for (let index = 0; index < attributes.length; index++) { 11 | if (content[attributes[index]] === undefined) { 12 | return undefined; 13 | } 14 | 15 | content = content[attributes[index]]; 16 | } 17 | 18 | return content; 19 | } 20 | 21 | /** 22 | * Deep merges two object taking first input as reference and second input being the properties to be merged to first. 23 | * @param object1 24 | * @param object2 25 | */ 26 | export function mergeDeep( 27 | object1: { [key: string]: any | any[] }, 28 | object2: { [key: string]: any | any[] }): { [key: string]: any | any[] } { 29 | for (const key in object1) { 30 | if (object2.hasOwnProperty(key)) { 31 | if (object2[key] instanceof Object) { 32 | object1[key] = mergeDeep({}, object2[key]); 33 | } else { 34 | object1[key] = object2[key]; 35 | } 36 | } 37 | } 38 | 39 | for (const key in object2) { 40 | if (!object1.hasOwnProperty(key)) { 41 | object1[key] = object2[key]; 42 | } 43 | } 44 | 45 | return object1; 46 | } 47 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": true, 5 | "declarationMap": false, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "lib": [ 9 | "dom", 10 | "es7" 11 | ], 12 | "module": "es6", 13 | "moduleResolution": "classic", 14 | "sourceMap": true, 15 | "target": "es2017", 16 | "allowJs": false, 17 | "strict": true, 18 | "outDir": "dist/es2015", 19 | "declarationDir": "./src", 20 | "incremental": true 21 | }, 22 | "include": [ 23 | "src/**/*.ts" 24 | ], 25 | "exclude": [ 26 | "node_modules", 27 | "other" 28 | ], 29 | "compileOnSave": true 30 | } 31 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/vrsource-tslint-rules/rules", 4 | "node_modules/tslint-eslint-rules/dist/rules", 5 | "node_modules/tslint-no-toplevel-property-access/rules" 6 | ], 7 | "rules": { 8 | "no-console": [ 9 | true, 10 | "log" 11 | ], 12 | "no-duplicate-imports": true, 13 | "no-duplicate-variable": true, 14 | "no-jasmine-focus": true, 15 | "no-var-keyword": true, 16 | "require-internal-with-underscore": true, 17 | "no-toplevel-property-access": [ 18 | true, 19 | "packages/animations/src/", 20 | "packages/animations/browser/", 21 | "packages/common/src/", 22 | "packages/core/src/", 23 | "packages/elements/src/", 24 | "packages/forms/src/", 25 | "packages/http/src/", 26 | "packages/platform-browser/src/", 27 | "packages/router/src/" 28 | ], 29 | "semicolon": [ 30 | true 31 | ], 32 | "variable-name": [ 33 | true, 34 | "ban-keywords" 35 | ], 36 | "no-inner-declarations": [ 37 | true, 38 | "function" 39 | ], 40 | "no-debugger": true 41 | }, 42 | "jsRules": { 43 | "file-header": [ 44 | true, 45 | "Copyright Google Inc\\." 46 | ], 47 | "no-console": [ 48 | true, 49 | "log" 50 | ], 51 | "no-duplicate-imports": true, 52 | "no-duplicate-variable": true, 53 | "no-jasmine-focus": true, 54 | "require-internal-with-underscore": true, 55 | "semicolon": [ 56 | true 57 | ], 58 | "variable-name": [ 59 | true, 60 | "ban-keywords" 61 | ], 62 | "no-inner-declarations": [ 63 | true, 64 | "function" 65 | ], 66 | "quotemark": [true, "single"] 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require("webpack"); 3 | 4 | module.exports = { 5 | entry: './dist/es2015/index.js', 6 | output: { 7 | filename: './idb.js', 8 | }, 9 | optimization: { 10 | minimize: true 11 | }, 12 | module: { 13 | rules: [{ 14 | test: /\.m?js$/, 15 | exclude: /(node_modules|bower_components)/, 16 | use: { 17 | loader: 'babel-loader', 18 | }, 19 | }] 20 | }, 21 | devtool: "source-map" 22 | }; 23 | --------------------------------------------------------------------------------