-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
552 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"presets": ["es2015"], | ||
"plugins": ["transform-runtime"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules/** | ||
dist/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module.exports = { | ||
root: true, | ||
parserOptions: { | ||
sourceType: 'module', | ||
ecmaFeatures: { | ||
experimentalObjectRestSpread: true | ||
} | ||
}, | ||
env: { | ||
browser: true, | ||
node: true | ||
}, | ||
extends: 'standard', | ||
'rules': { | ||
// allow paren-less arrow functions | ||
'arrow-parens': 0, | ||
// allow async-await | ||
'generator-star-spacing': 0, | ||
// allow debugger during development | ||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DS_Store | ||
node_modules | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,110 @@ | ||
# dexie-relationships | ||
Dexie relationship plugin | ||
Dexie.js relationship plugin | ||
======== | ||
|
||
Dexie.js is a wrapper library for indexedDB - the standard database in the browser. | ||
|
||
Dexie relationship plugin provides an API to ease the loading of relational data from foreign tables | ||
|
||
Installation | ||
======== | ||
|
||
npm: | ||
``` | ||
npm install dexie-relationships --save | ||
``` | ||
|
||
bower: | ||
``` | ||
bower install dexie-relationships --save | ||
``` | ||
|
||
API Example | ||
======== | ||
|
||
#### Schema | ||
Note the use of `->` which sets the foreign keys. | ||
|
||
```javascript | ||
db.version(1).stores({ | ||
projects: '++id', | ||
project_settings: '++id, project_id -> projects.id', | ||
project_members: '++id, project_id -> projects.id' | ||
}) | ||
``` | ||
|
||
#### Seed the data | ||
|
||
```javascript | ||
db.projects.add({name: 'Project #1'}) | ||
db.projects.add({name: 'Project #2'}) | ||
|
||
db.project_settings.add({name: 'Setting #1', project_id: 1}) | ||
db.project_settings.add({name: 'Setting #2', project_id: 2}) | ||
db.project_settings.add({name: 'Setting #3', project_id: 1}) | ||
|
||
db.project_members.add({name: 'Member #1', project_id: 1}) | ||
db.project_members.add({name: 'Member #2', project_id: 2}) | ||
db.project_members.add({name: 'Member #3', project_id: 1}) | ||
``` | ||
|
||
#### Usage | ||
|
||
```javascript | ||
db.with({ | ||
'settings': 'project_settings', | ||
'members': 'project_members' | ||
}).then(rows => console.log(rows)) | ||
``` | ||
|
||
#### Result | ||
|
||
```json | ||
[ | ||
{ | ||
"name":"Project #1", | ||
"id":1, | ||
"settings":[ | ||
{ | ||
"name":"Setting #1", | ||
"project_id":1, | ||
"id":1 | ||
}, | ||
{ | ||
"name":"Setting #3", | ||
"project_id":1, | ||
"id":3 | ||
} | ||
], | ||
"members":[ | ||
{ | ||
"name":"Member #1", | ||
"project_id":1, | ||
"id":1 | ||
}, | ||
{ | ||
"name":"Member #3", | ||
"project_id":1, | ||
"id":3 | ||
} | ||
] | ||
}, | ||
{ | ||
"name":"Project #2", | ||
"id":2, | ||
"settings":[ | ||
{ | ||
"name":"Setting #2", | ||
"project_id":2, | ||
"id":2 | ||
} | ||
], | ||
"members":[ | ||
{ | ||
"name":"Member #2", | ||
"project_id":2, | ||
"id":2 | ||
} | ||
] | ||
} | ||
] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "dexie-relationships", | ||
"description": "Dexie relationship plugin", | ||
"main": "dist/dexie-relationships.js", | ||
"authors": [ | ||
"Ignas Bernotas" | ||
], | ||
"license": "MIT", | ||
"keywords": [ | ||
"dexie", | ||
"relationships", | ||
"plugin" | ||
], | ||
"homepage": "https://github.com/ignasbernotas/dexie-relationships" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
'use strict'; | ||
|
||
var _promise = require('babel-runtime/core-js/promise'); | ||
|
||
var _promise2 = _interopRequireDefault(_promise); | ||
|
||
var _keys = require('babel-runtime/core-js/object/keys'); | ||
|
||
var _keys2 = _interopRequireDefault(_keys); | ||
|
||
var _dexie = require('dexie'); | ||
|
||
var _dexie2 = _interopRequireDefault(_dexie); | ||
|
||
var _schemaParser = require('./schema-parser'); | ||
|
||
var _schemaParser2 = _interopRequireDefault(_schemaParser); | ||
|
||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
|
||
var Relationships = function Relationships(db) { | ||
/** | ||
* Iterate through all items and collect related records | ||
* | ||
* @param relationships | ||
* | ||
* @returns {Dexie.Promise} | ||
*/ | ||
db.Table.prototype.with = function (relationships) { | ||
return this.toCollection().with(relationships); | ||
}; | ||
|
||
/** | ||
* Iterate through all items and collect related records | ||
* | ||
* @param relationships | ||
* | ||
* @returns {Dexie.Promise} | ||
*/ | ||
db.Collection.prototype.with = function (relationships) { | ||
var self = this; | ||
var baseTable = this._ctx.table.name; | ||
var databaseTables = db._allTables; | ||
|
||
// this holds tables that have foreign keys pointing at the current table | ||
var usableForeignTables = {}; | ||
|
||
// validate target tables and add them into our usable tables object | ||
(0, _keys2.default)(relationships).forEach(function (column) { | ||
var table = relationships[column]; | ||
|
||
if (!databaseTables.hasOwnProperty(table)) { | ||
throw new Error('Relationship table ' + table + ' doesn\'t exist.'); | ||
} | ||
|
||
if (!databaseTables[table].schema.hasOwnProperty('foreignKeys')) { | ||
throw new Error('Relationship table ' + table + ' doesn\'t have foreign keys set.'); | ||
} | ||
|
||
// remove the foreign keys that don't link to the base table | ||
var columns = databaseTables[table].schema.foreignKeys.filter(function (column) { | ||
return column.targetTable === baseTable; | ||
}); | ||
|
||
if (columns.length > 0) { | ||
usableForeignTables[table] = { | ||
column: column, | ||
foreign: columns[0] | ||
}; | ||
} | ||
}); | ||
|
||
return new _dexie2.default.Promise(function (resolve) { | ||
self.toArray().then(function (rows) { | ||
var queue = []; | ||
|
||
// loop through all rows and collect all data from the related table | ||
rows.forEach(function (row) { | ||
var tables = (0, _keys2.default)(usableForeignTables); | ||
|
||
tables.forEach(function (table) { | ||
var relatedTable = usableForeignTables[table]; | ||
|
||
var promise = databaseTables[table].where(relatedTable.foreign.index).equals(row[relatedTable.foreign.targetIndex]).toArray().then(function (relations) { | ||
row[relatedTable.column] = relations; | ||
}); | ||
|
||
queue.push(promise); | ||
}); | ||
}); | ||
|
||
// we need to wait until all data is retrieved | ||
// once it's there we can resolve the promise | ||
_promise2.default.all(queue).then(function () { | ||
resolve(rows); | ||
}); | ||
}); | ||
}); | ||
}; | ||
|
||
db.Version.prototype._parseStoresSpec = _dexie2.default.override(db.Version.prototype._parseStoresSpec, function (parseStoresSpec) { | ||
return function (storesSpec, outDbSchema) { | ||
var parser = new _schemaParser2.default(storesSpec); | ||
|
||
var foreignKeys = parser.getForeignKeys(); | ||
// call the original method | ||
var rv = parseStoresSpec.call(this, parser.getCleanedSchema(), outDbSchema); | ||
|
||
// set foreign keys into database table objects | ||
// to use later in 'with' method | ||
(0, _keys2.default)(outDbSchema).forEach(function (table) { | ||
if (foreignKeys.hasOwnProperty(table)) { | ||
outDbSchema[table].foreignKeys = foreignKeys[table]; | ||
} | ||
}); | ||
|
||
return rv; | ||
}; | ||
}); | ||
}; | ||
|
||
_dexie2.default.addons.push(Relationships); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
{ | ||
"name": "dexie-relationships", | ||
"version": "1.0.0", | ||
"description": "Dexie relationship plugin", | ||
"main": "dist/dexie-relationships.js", | ||
"directories": { | ||
"test": "tests" | ||
}, | ||
"dependencies": { | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.16.0", | ||
"babel-loader": "^6.2.5", | ||
"babel-preset-es2015": "^6.16.0", | ||
"chai": "^3.5.0", | ||
"eslint": "^3.8.1", | ||
"eslint-config-standard": "^6.2.0", | ||
"eslint-plugin-promise": "^3.3.0", | ||
"eslint-plugin-standard": "^2.0.1", | ||
"mocha": "^3.1.2", | ||
"webpack": "^1.13.2" | ||
}, | ||
"scripts": { | ||
"build": "babel --presets es2015 src/index.js -o dist/dexie-relationships.js", | ||
"test": "npm run eslint && npm run mocha", | ||
"eslint": "eslint src", | ||
"mocha": "./node_modules/.bin/mocha --compilers js:babel-core/register --reporter spec" | ||
}, | ||
"babel": { | ||
"presets": ["es2015"] | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ignasbernotas/dexie-relationships.git" | ||
}, | ||
"keywords": [ | ||
"dexie", | ||
"relationships", | ||
"plugin" | ||
], | ||
"author": "Ignas Bernotas", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/ignasbernotas/dexie-relationships/issues" | ||
}, | ||
"homepage": "https://github.com/ignasbernotas/dexie-relationships#readme" | ||
} |
Oops, something went wrong.