diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..7100dc2
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,36 @@
+
+module.exports = {
+ root: true,
+ parserOptions: {
+// ecmaVersion: 2017,
+ sourceType: 'module',
+// project: "./tsconfig.json",
+ tsconfigRootDir: __dirname,
+ project: ['./test.tsconfig.json'],
+ },
+ parser: '@typescript-eslint/parser',
+ plugins: [
+ '@typescript-eslint',
+ ],
+ extends: [
+// 'eslint:recommended',
+// 'plugin:@typescript-eslint/eslint-recommended',
+// 'plugin:@typescript-eslint/recommended',
+// "plugin:@typescript-eslint/recommended-requiring-type-checking",
+ ],
+ env: {
+ browser: true,
+ node: true,
+ es6: true,
+ },
+// plugins: [
+// "promise"
+// ],
+ rules: {
+ "@typescript-eslint/no-floating-promises": "error",
+// "await-promise": 2,
+// "no-debugger": 0,
+// "no-console": 0,
+// "no-mixed-spaces-and-tabs": 0,
+ }
+};
diff --git a/.gitignore b/.gitignore
index 318b19e..1f8ddf2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,6 @@ coverage
test/test-bundle.js
npm-debug.log
dist
+/.nyc_output
+/lib
+/dist
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100755
index 2f0446d..0000000
--- a/.jshintrc
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "curly": true,
- "eqeqeq": true,
- "immed": true,
- "newcap": true,
- "noarg": true,
- "sub": true,
- "undef": true,
- "unused": true,
- "eqnull": true,
- "browser": true,
- "node": true,
- "strict": true,
- "globalstrict": true,
- "globals": {
- "Pouch": true,
- "blobUtil": true
- },
- "white": true,
- "indent": 2,
- "maxlen": 100,
- "predef": [
- "process",
- "global",
- "require",
- "console",
- "describe",
- "beforeEach",
- "afterEach",
- "it",
- "emit"
- ]
-}
\ No newline at end of file
diff --git a/README.md b/README.md
index 80ce7b3..076ea98 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ Then include it after `pouchdb.js` in your HTML page:
```html
-
+
```
### In Node.js
@@ -55,6 +55,31 @@ PouchDB.plugin(require('relational-pouch'));
PouchDB.plugin(require('pouchdb-find'));
```
+#### Typescript
+
+This package contains its own type definitions. Due to the nature of setSchema, which alters the database on which it is called, typescript needs to know about these changes. This is done by returning a new type. So working with this plugin should look something like this:
+
+```js
+import Pouch from 'pouchdb-core';
+//import some adapter
+import find from 'pouchdb-find';
+import rel from 'relational-pouch';
+
+Pouch
+ //.plugin(someadapter)
+ .plugin(find)
+ .plugin(rel);
+
+const baseDB = new Pouch(...);//adapter options
+const relDB = baseDB.setSchema(...);//schema options
+
+let relDoc = await relDB.rel.find('sometype', 'someid');
+
+//non relation pouch API is still available
+let doc = await relDB.get('someid');
+```
+
+
API
----------
@@ -167,14 +192,8 @@ Result:
```js
{
- "posts": [
- {
- "title": "Rails is Omakase",
- "text": "There are a lot of a-la-carte software...",
- "id": "14760983-285C-6D1F-9813-D82E08F1AC29",
- "rev": "1-84df2c73028e5b8d0ae1cbb401959370"
- }
- ]
+ "id": "14760983-285C-6D1F-9813-D82E08F1AC29",
+ "rev": "1-84df2c73028e5b8d0ae1cbb401959370"
}
```
@@ -192,14 +211,8 @@ Result:
```js
{
- "posts": [
- {
- "title": "Rails is Unagi",
- "text": "Delicious unagi. Mmmmmm.",
- "id": 1,
- "rev": "1-0ae315ee597b22cc4b1acf9e0edc35ba"
- }
- ]
+ "id": 1,
+ "rev": "1-0ae315ee597b22cc4b1acf9e0edc35ba"
}
```
@@ -359,25 +372,10 @@ var attachment = new Blob(['Is there life on Mars?']);
db.rel.putAttachment('post', {id:1, rev:"1-..."}, 'file', attachment, 'text/plain');
```
-Result:
+This returns the new rev:
```js
-{
- "posts": [
- {
- "attachments": {
- "file": {
- "content_type": "text/plain",
- "digest": "md5-1cz9JKh0i+1OLJonmitgiQ==",
- "length": 22,
- // ... http://pouchdb.com/guides/attachments.html
- }
- },
- "id": 1,
- "rev": "2-...."
- }
- ]
-}
+"2-...."
```
### db.rel.getAttachment(type, id, attachmentId)
@@ -409,17 +407,10 @@ Or continuing from the `putAttachment` example:
db.rel.removeAttachment('post', {id: 1, rev:"2-09d5c5bd86fc170c064b296773044ea9"} , 'file');
```
-Result:
+This returns the new rev:
```js
-{
- "posts": [
- {
- "id": 1,
- "rev": "3-...."
- }
- ]
-}
+"3-...."
```
### db.rel.parseDocID(docID)
@@ -1118,10 +1109,14 @@ Testing
### In Node
-This will run the tests in Node using LevelDB:
+This will run the tests in Node using memory and http adapter:
npm test
+if you don't have a admin party setup you can specify admin credentials in the RELATIONAL_POUCH_DB_AUTH environment variable like this:
+
+ RELATIONAL_POUCH_DB_AUTH=user:password@
+
You can also check for 100% code coverage using:
npm run coverage
@@ -1150,3 +1145,20 @@ You can run e.g.
CLIENT=selenium:phantomjs npm test
This will run the tests automatically and the process will exit with a 0 or a 1 when it's done. Firefox uses IndexedDB, and PhantomJS uses WebSQL.
+
+## Changelog
+
+### 4.0.0
+
+- Breaking change: To prevent us from having to do cloning of input documents, we have changed the `save`, `putAttachment` and `removeAttachment` API. These functions no longer return the complete document. The attachment functions only return the new `rev` value, while the save will also return the `id`. So after these promises resolve you have to manually update your in app data to reflect this new revision (and possibly id) if you want to update the document later. You can use something like the following:
+ ```js
+ let updatedData = await db.rel.save('post', post);
+ Object.assign(post, updatedData);
+ ```
+ or
+ ```js
+ post.rev = await db.rel.putAttachment('post', post, 'file', fileData);
+ ```
+- This library now uses Typescript, Webpack and Babel in its build setup. The build creates files in 2 output directories: lib and dist.
+ - The lib directory will contain the output of `tsc` in esnext mode. So this can be used by Webpack and other module aware systems. These will require Babel transformations if you want to use them, but this way you can specify your own target.
+ - The dist directory contains 2 files, pouchdb.relational-pouch.browser.js and pouchdb.relational-pouch.node.js. These are compiled by webpack with targets ">2%, not ie 11" and "node 10". This should be sufficient for now, but otherwise you can build your own with Webpack.
\ No newline at end of file
diff --git a/bin/dev-server.js b/bin/dev-server.js
index d7bbaed..3ab3ad1 100755
--- a/bin/dev-server.js
+++ b/bin/dev-server.js
@@ -5,6 +5,8 @@
var COUCH_HOST = process.env.COUCH_HOST || 'http://127.0.0.1:5984';
var HTTP_PORT = 8001;
+const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
+
var Promise = require('bluebird');
var request = require('request');
var http_server = require("http-server");
@@ -12,39 +14,87 @@ var fs = require('fs');
var indexfile = "./test/test.js";
var dotfile = "./test/.test-bundle.js";
var outfile = "./test/test-bundle.js";
-var watchify = require("watchify");
-var browserify = require('browserify');
-var b = browserify(indexfile, {
- cache: {},
- packageCache: {},
- plugin: [watchify]
-})
+var webpack = require('webpack');
+var path = require('path');
-b.on('update', bundle);
-bundle();
+var b = webpack({
+ target: "web",
+ entry: "./test/test.ts",
+ mode: 'development',
+ devtool: 'source-map',
+ output: {
+ path: path.resolve(__dirname, '../test'),
+ filename: 'test-bundle.js',
+ libraryTarget: 'umd',
+ },
+ plugins: [
+ new ForkTsCheckerWebpackPlugin({eslint: true, tsconfig: "test.tsconfig.json"}),
+ new webpack.EnvironmentPlugin(['RELATIONAL_POUCH_DB_AUTH']),
+ ],
+ module: {
+ rules: [
+// {
+// enforce: 'pre',
+// test: /\.[tj]s$/,
+// exclude: /node_modules/,
+// loader: 'eslint-loader',
+// },
+ {
+ test: /\.[tj]s$/,
+ exclude: /(node_modules|bower_components)/,
+ use: [
+ {
+ loader: 'babel-loader',
+ options: {
+ presets: [
+ ['@babel/preset-env',
+ {
+ "targets": "last 1 Chrome versions",
+ "modules": false,
+ useBuiltIns: "usage",
+ corejs: 3,
+ }],
+ ],
+ },
+ },
+ {
+ loader: 'ts-loader',
+ options: {
+ transpileOnly: true,
+ experimentalWatchApi: true,
+ context: path.resolve(__dirname, '../'),
+ configFile: "test.tsconfig.json",
+ },
+ },
+ ],
+ }
+ ]
+ },
+ resolve: {
+ extensions: ['tsx', '.ts', '.js', '.json'],
+ },
+}).watch({}, (error, stats) => {
+ if (error) {
+ console.error(error);
+ return;
+ }
+
+ let logOptions = {all: false, colors: true, assets: true, errors: true, errorDetails: true, warnings: true, errorStack: true};
+ if (!stats.hasErrors()) {
+ console.log('Updated');
+ console.log(stats.toString(logOptions));
+ filesWritten = true;
+ checkReady();
+ } else {
+ const info = stats.toJson();
+ console.error(stats.toString(logOptions));//children: false, entrypoints: false, hash: false, modules: false, , chunks: false
+ }
+});
var filesWritten = false;
var serverStarted = false;
var readyCallback;
-function bundle() {
- var wb = b.bundle();
- wb.on('error', function (err) {
- console.error(String(err));
- });
- wb.on("end", end);
- wb.pipe(fs.createWriteStream(dotfile));
-
- function end() {
- fs.rename(dotfile, outfile, function (err) {
- if (err) { return console.error(err); }
- console.log('Updated:', outfile);
- filesWritten = true;
- checkReady();
- });
- }
-}
-
function startServers(callback) {
readyCallback = callback;
// enable CORS globally, because it's easier this way
diff --git a/bower.json b/bower.json
index 630201f..aea6b59 100644
--- a/bower.json
+++ b/bower.json
@@ -1,12 +1,12 @@
{
"name": "relational-pouch",
- "version": "3.2.0",
+ "version": "4.0.0",
"description": "PouchDB, relational-style",
"homepage": "https://github.com/pouchdb-community/relational-pouch",
"authors": [
"Nolan Lawson "
],
- "main": "dist/pouchdb.relational-pouch.js",
+ "main": "dist/pouchdb.relational-pouch.browser.js",
"moduleType": [
"node"
],
@@ -23,6 +23,7 @@
"bower_components",
"test",
"tests",
- "vendor"
+ "vendor",
+ "lib"
]
}
diff --git a/dist/pouchdb.relational-pouch.js b/dist/pouchdb.relational-pouch.js
deleted file mode 100644
index d560abb..0000000
--- a/dist/pouchdb.relational-pouch.js
+++ /dev/null
@@ -1,1561 +0,0 @@
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.RelationalPouch = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; i--) {
- var relatedId = relatedIds[i];
- if (foundObjects.has(relatedType) &&
- foundObjects.get(relatedType).has(JSON.stringify(relatedId))) {
- delete relatedIds[i];
- }
- }
- relatedIds = relatedIds.filter(function (relatedId) {
- return typeof relatedId !== 'undefined';
- });
-
- // just return the ids and the types. We'll find them all
- // in a single bulk operation in order to minimize HTTP requests
- if (relatedIds.length) {
- return {
- relatedType: relatedType,
- relatedIds: relatedIds
- };
- }
- }));
- }
- }
- });
- return Promise.all(subTasks);
- });
- return Promise.all(tasks);
- }).then(function (listsOfFetchTasks) {
- // fetch in as few http requests as possible
- var typesToIds = {};
- listsOfFetchTasks.forEach(function (fetchTasks) {
- fetchTasks.forEach(function (fetchTask) {
- if (!fetchTask) {
- return;
- }
- typesToIds[fetchTask.relatedType] =
- (typesToIds[fetchTask.relatedType] || []).concat(fetchTask.relatedIds);
- });
- });
-
- return utils.series(Object.keys(typesToIds).map(function (relatedType) {
- var relatedIds = uniq(typesToIds[relatedType]);
- return function () {return _find(relatedType, relatedIds, foundObjects); };
- })).then(function () {
- var res = {};
- foundObjects.forEach(function (found, type) {
- var typeInfo = getTypeInfo(type);
- var list = res[typeInfo.plural] = [];
- found.forEach(function (obj) {
- list.push(obj);
- });
- //list.sort(lexCompare);
- });
- return res;
- });
- });
- }
-
- function putAttachment(type, obj, attachmentId, attachment, attachmentType) {
- var dbDocId = serialize(type, obj.id);
- var typeInfo = getTypeInfo(type);
- return Promise.resolve().then(function () {
- return db.putAttachment(dbDocId, attachmentId, obj.rev, attachment, attachmentType);
- }).then(function (pouchRes) {
- var res = {};
- res[typeInfo.plural] = [extend(true, obj, {
- id: deserialize(pouchRes.id),
- rev: pouchRes.rev
- })];
- return res;
- });
- }
-
- function removeAttachment(type, obj, attachmentId) {
- var dbDocId = serialize(type, obj.id);
- var typeInfo = getTypeInfo(type);
- return Promise.resolve().then(function () {
- return db.removeAttachment(dbDocId, attachmentId, obj.rev);
- }).then(function (pouchRes) {
- var res = {};
- res[typeInfo.plural] = [extend(true, obj, {
- id: deserialize(pouchRes.id),
- rev: pouchRes.rev
- })];
- return res;
- });
- }
-
- function getAttachment(type, id, attachmentId, options) {
- options = options || {};
- return Promise.resolve().then(function () {
- return db.getAttachment(serialize(type, id), attachmentId, options);
- });
- }
-
- function save(type, obj) {
- return Promise.resolve().then(function () {
- return _save(type, obj);
- });
- }
-
- function find(type, idOrIds) {
- return Promise.resolve().then(function () {
- return _find(getTypeInfo(type).singular, idOrIds, new collections.Map());
- });
- }
-
- function _findHasMany(type, belongsToKey, belongsToId, foundObjects) {
- var selector = {
- '_id': {
- '$gt': makeDocID({type: type}),
- '$lt': makeDocID({type: type, id: {}})
- }
- };
- selector['data.' + belongsToKey] = belongsToId;
-
- //only use opts for return ids or whole doc? returning normal documents is not really good
- return db.find({ selector: selector }).then(function(findRes) {
- return _parseRelDocs(type, foundObjects, findRes.docs);
- });
- }
-
- function findHasMany(type, belongsToKey, belongsToId) {
- return _findHasMany(type, belongsToKey, belongsToId, new collections.Map());
- }
-
- function del(type, obj) {
- return Promise.resolve().then(function () {
- return _del(type, obj);
- });
- }
-
- function parseDocID(str) {
- var idx = str.indexOf('_');
- var type = str.substring(0, idx);
- var relId = deserialize(str);
-
- var defaultType = keysToSchemas.get(type);
- if (!defaultType) {
- var matchingSchemaTypes = schema.filter(
- function (schemaType) { return schemaType.documentType === type; });
- if (matchingSchemaTypes.length > 0) {
- type = matchingSchemaTypes[0].singular;
- }
- }
-
- return {
- type: type,
- id: relId
- };
- }
-
- function makeDocID(obj) {
- var type = obj.type;
-
- var typeInfo = keysToSchemas.get(type);
- if (typeInfo) {
- type = typeInfo.documentType;
- }
-
- return serialize(type, obj.id);
- }
-
- db.rel = {
- save: save,
- find: find,
- findHasMany: findHasMany,
- del: del,
- getAttachment: getAttachment,
- putAttachment: putAttachment,
- removeAttachment: removeAttachment,
- parseDocID: parseDocID,
- makeDocID: makeDocID,
- parseRelDocs: parseRelDocs,
- isDeleted: isDeleted,
- uuid: uuid
- };
-};
-
-/* istanbul ignore next */
-if (typeof window !== 'undefined' && window.PouchDB) {
- window.PouchDB.plugin(exports);
-}
-
-},{"./collections":1,"./pouch-utils":3,"./uuid":4,"uniq":11}],3:[function(require,module,exports){
-(function (process){
-'use strict';
-
-var Promise = require('pouchdb-promise');
-/* istanbul ignore next */
-exports.once = function (fun) {
- var called = false;
- return exports.getArguments(function (args) {
- if (called) {
- console.trace();
- throw new Error('once called more than once');
- } else {
- called = true;
- fun.apply(this, args);
- }
- });
-};
-/* istanbul ignore next */
-exports.getArguments = function (fun) {
- return function () {
- var len = arguments.length;
- var args = new Array(len);
- var i = -1;
- while (++i < len) {
- args[i] = arguments[i];
- }
- return fun.call(this, args);
- };
-};
-/* istanbul ignore next */
-exports.toPromise = function (func) {
- //create the function we will be returning
- return exports.getArguments(function (args) {
- var self = this;
- var tempCB = (typeof args[args.length - 1] === 'function') ? args.pop() : false;
- // if the last argument is a function, assume its a callback
- var usedCB;
- if (tempCB) {
- // if it was a callback, create a new callback which calls it,
- // but do so async so we don't trap any errors
- usedCB = function (err, resp) {
- process.nextTick(function () {
- tempCB(err, resp);
- });
- };
- }
- var promise = new Promise(function (fulfill, reject) {
- try {
- var callback = exports.once(function (err, mesg) {
- if (err) {
- reject(err);
- } else {
- fulfill(mesg);
- }
- });
- // create a callback for this invocation
- // apply the function in the orig context
- args.push(callback);
- func.apply(self, args);
- } catch (e) {
- reject(e);
- }
- });
- // if there is a callback, call it back
- if (usedCB) {
- promise.then(function (result) {
- usedCB(null, result);
- }, usedCB);
- }
- promise.cancel = function () {
- return this;
- };
- return promise;
- });
-};
-
-// execute some promises in a chain
-exports.series = function (promiseFactories) {
- var chain = exports.Promise.resolve();
- var overallRes = new Array(promiseFactories.length);
- promiseFactories.forEach(function (promiseFactory, i) {
- chain = chain.then(promiseFactories[i]).then(function (res) {
- overallRes[i] = res;
- });
- });
- return chain.then(function () {
- return overallRes;
- });
-};
-
-exports.inherits = require('inherits');
-exports.Promise = Promise;
-exports.extend = require('pouchdb-extend');
-
-}).call(this,require('_process'))
-},{"_process":10,"inherits":6,"pouchdb-extend":7,"pouchdb-promise":8}],4:[function(require,module,exports){
-"use strict";
-
-// BEGIN Math.uuid.js
-
-/*!
-Math.uuid.js (v1.4)
-http://www.broofa.com
-mailto:robert@broofa.com
-
-Copyright (c) 2010 Robert Kieffer
-Dual licensed under the MIT and GPL licenses.
-*/
-
-/*
- * Generate a random uuid.
- *
- * USAGE: Math.uuid(length, radix)
- * length - the desired number of characters
- * radix - the number of allowable values for each character.
- *
- * EXAMPLES:
- * // No arguments - returns RFC4122, version 4 ID
- * >>> Math.uuid()
- * "92329D39-6F5C-4520-ABFC-AAB64544E172"
- *
- * // One argument - returns ID of the specified length
- * >>> Math.uuid(15) // 15 character ID (default base=62)
- * "VcydxgltxrVZSTV"
- *
- * // Two arguments - returns ID of the specified length, and radix.
- * // (Radix must be <= 62)
- * >>> Math.uuid(8, 2) // 8 character ID (base=2)
- * "01001010"
- * >>> Math.uuid(8, 10) // 8 character ID (base=10)
- * "47473046"
- * >>> Math.uuid(8, 16) // 8 character ID (base=16)
- * "098F4D35"
- */
-var chars = (
- '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
- 'abcdefghijklmnopqrstuvwxyz'
-).split('');
-function getValue(radix) {
- return 0 | Math.random() * radix;
-}
-function uuid(len, radix) {
- radix = radix || chars.length;
- var out = '';
- var i = -1;
-
- /* istanbul ignore next */
- if (len) {
- // Compact form
- while (++i < len) {
- out += chars[getValue(radix)];
- }
- return out;
- }
- // rfc4122, version 4 form
- // Fill in random data. At i==19 set the high bits of clock sequence as
- // per rfc4122, sec. 4.1.5
- while (++i < 36) {
- switch (i) {
- case 8:
- case 13:
- case 18:
- case 23:
- out += '-';
- break;
- case 19:
- out += chars[(getValue(16) & 0x3) | 0x8];
- break;
- default:
- out += chars[getValue(16)];
- }
- }
-
- return out;
-}
-
-
-
-module.exports = uuid;
-
-
-},{}],5:[function(require,module,exports){
-(function (global){
-'use strict';
-var Mutation = global.MutationObserver || global.WebKitMutationObserver;
-
-var scheduleDrain;
-
-{
- if (Mutation) {
- var called = 0;
- var observer = new Mutation(nextTick);
- var element = global.document.createTextNode('');
- observer.observe(element, {
- characterData: true
- });
- scheduleDrain = function () {
- element.data = (called = ++called % 2);
- };
- } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {
- var channel = new global.MessageChannel();
- channel.port1.onmessage = nextTick;
- scheduleDrain = function () {
- channel.port2.postMessage(0);
- };
- } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {
- scheduleDrain = function () {
-
- // Create a
-
diff --git a/test/test.js b/test/test.ts
similarity index 89%
rename from test/test.js
rename to test/test.ts
index e63b6b3..4d25339 100644
--- a/test/test.js
+++ b/test/test.ts
@@ -1,26 +1,32 @@
-/*jshint expr:true */
-'use strict';
+import {createBlob} from 'blob-util';
-var Pouch = require('pouchdb-memory');
+import Pouch from 'pouchdb-core';
+import memory from 'pouchdb-adapter-memory';
+import http from 'pouchdb-adapter-http';
+import mapreduce from 'pouchdb-mapreduce';
+import find from 'pouchdb-find';
-//
-// your plugin goes here
-//
-var plugin = require('../lib');
-Pouch.plugin(plugin)
- .plugin(require('pouchdb-find'));
+import rel from '../src/';
+
+import * as chai from 'chai';
+import * as chaiAsPromised from 'chai-as-promised';
-var chai = require('chai');
-chai.use(require("chai-as-promised"));
+Pouch
+ .plugin(memory)
+ .plugin(http)
+ .plugin(mapreduce)
+ .plugin(find)
+ .plugin(rel);
+
+chai.use(chaiAsPromised);
//
// more variables you might want
//
-var should = chai.should(); // var should = chai.should();
-var Promise = require('bluebird'); // var Promise = require('bluebird');
+var should = chai.should();
var dbs = 'testdb' + Math.random() +
- ',http://localhost:5984/testdb' + Math.round(Math.random() * 100000);
+ ',http://' + (process.env.RELATIONAL_POUCH_DB_AUTH || '') + 'localhost:5984/testdb' + Math.round(Math.random() * 100000);
dbs.split(',').forEach(function (db) {
var dbType = /^http/.test(db) ? 'http' : 'local';
@@ -28,22 +34,22 @@ dbs.split(',').forEach(function (db) {
});
function tests(dbName, dbType) {
- var db;
+ var rootdb:PouchDB.Database;
beforeEach(function () {
- db = new Pouch(dbName);
- return db;
+ rootdb = new Pouch(dbName);
+ return rootdb;
});
afterEach(function () {
- return db.getIndexes().then(function(data) {
+ return rootdb.getIndexes().then(function(data) {
var deleteIndexPromises = data.indexes.map(function(index) {
- return index.ddoc ? (db.deleteIndex(index)) : (Promise.resolve());
- });
+ return index.ddoc ? (rootdb.deleteIndex(index)) : null;
+ });
return Promise.all(deleteIndexPromises);
}).catch(function() {
- //may fail on http
+ //may fail on http
}).then(function() {
- return db.destroy();
+ return rootdb.destroy();
});
});
@@ -51,7 +57,7 @@ function tests(dbName, dbType) {
this.timeout(30000);
it('should barf on bad types', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -64,7 +70,7 @@ function tests(dbName, dbType) {
});
it('makeDocID and parseDocID produce symmetrical return vals', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -77,20 +83,19 @@ function tests(dbName, dbType) {
});
it('allows makeDocID for an unknown type', function () {
- db.setSchema([]);
+ let db = rootdb.setSchema([]);
db.rel.makeDocID({ type: 'something', id: 'quux' }).should.equal('something_2_quux');
});
it('allows parseDocID for an unknown type', function () {
- db.setSchema([]);
+ let db = rootdb.setSchema([]);
db.rel.parseDocID('something_2_bar').should.deep.equal({ type: 'something', id: 'bar' });
});
it('should store blog posts', function () {
-
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -103,22 +108,13 @@ function tests(dbName, dbType) {
text: text
}).then(function (res) {
should.exist(res);
- res.posts.should.have.length(1);
- res.posts[0].id.should.be.a('string');
- res.posts[0].rev.should.be.a('string');
- var id = res.posts[0].id;
- var rev = res.posts[0].rev;
- res.posts[0].should.deep.equal({
- id: id,
- rev: rev,
- title: title,
- text: text
- });
+ res.id.should.be.a('string');
+ res.rev.should.be.a('string');
});
});
it('should store blog posts with an id', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -133,23 +129,15 @@ function tests(dbName, dbType) {
id: id
}).then(function (res) {
should.exist(res);
- res.posts.should.have.length(1);
- res.posts[0].id.should.be.a('string');
- res.posts[0].rev.should.be.a('string');
- var id = res.posts[0].id;
- var rev = res.posts[0].rev;
- res.posts[0].should.deep.equal({
- id: id,
- rev: rev,
- title: title,
- text: text
- });
+ res.id.should.be.a('string');
+ res.rev.should.be.a('string');
+ res.id.should.equal(id);
});
});
it('should store blog posts with an int id', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -164,23 +152,15 @@ function tests(dbName, dbType) {
id: id
}).then(function (res) {
should.exist(res);
- res.posts.should.have.length(1);
- res.posts[0].id.should.be.a('number');
- res.posts[0].rev.should.be.a('string');
- var id = res.posts[0].id;
- var rev = res.posts[0].rev;
- res.posts[0].should.deep.equal({
- id: id,
- rev: rev,
- title: title,
- text: text
- });
+ res.id.should.be.a('number');
+ res.rev.should.be.a('string');
+ res.id.should.equal(id);
});
});
it('should update blog posts', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -188,30 +168,48 @@ function tests(dbName, dbType) {
var title = 'Rails is Omakase';
var text = 'There are a lot of ala carte blah blah blah';
var id = 1;
-
- return db.rel.save('post', {
+ var post:any = {
title: title,
text: text,
id: id
- }).then(function (res) {
+ };
+
+ return db.rel.save('post', post).then(function (res) {
should.exist(res);
- var post = res.posts[0];
+ res.rev.should.be.a('string');
+ res.id.should.be.a('number');
+ res.id.should.equal(id);
+ Object.assign(post, res);
post.title = 'Rails is Unagi';
return db.rel.save('post', post);
}).then(function (res) {
- var rev = res.posts[0].rev;
- res.posts.should.deep.equal([{
- id: id,
- rev: rev,
- title: 'Rails is Unagi',
- text: text
- }]);
+ res.rev.should.be.a('string');
+ res.id.should.be.a('number');
+ res.id.should.equal(id);
+ res.rev.should.not.equal(post.rev);
});
});
+
+ it('fails on a rev conflict', function () {
+ let db = rootdb.setSchema([{
+ singular: 'post',
+ plural: 'posts'
+ }]);
+
+ var post:any = {
+ title: "Some title",
+ id: "postid"
+ };
+
+ return db.rel.save('post', post).then(function (res) {
+ return db.rel.save('post', post);
+ }).should.be.rejected;
+ });
+
it('should find blog posts', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -253,7 +251,7 @@ function tests(dbName, dbType) {
it('should orders correctly', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -306,7 +304,7 @@ function tests(dbName, dbType) {
it('should find empty blog posts', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -320,7 +318,7 @@ function tests(dbName, dbType) {
it('should find stuff that doesnt exist', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -339,7 +337,7 @@ function tests(dbName, dbType) {
it('should separate independent types', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'post',
plural: 'posts'
@@ -366,7 +364,7 @@ function tests(dbName, dbType) {
it('should find a single thing', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'post',
plural: 'posts'
@@ -401,7 +399,7 @@ function tests(dbName, dbType) {
it('should find multiple things', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'post',
plural: 'posts'
@@ -442,7 +440,7 @@ function tests(dbName, dbType) {
});
it('should find using a documentType if provided', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'postSummary',
plural: 'postSummaries',
@@ -462,7 +460,7 @@ function tests(dbName, dbType) {
});
it('should save using a documentType if provided', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'postSummary',
plural: 'postSummary',
@@ -484,7 +482,7 @@ function tests(dbName, dbType) {
});
it('should use the documentType for makeDocID', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'post',
plural: 'posts'
@@ -500,7 +498,7 @@ function tests(dbName, dbType) {
});
it('should use the default documentType for parseDocID, if present', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'post',
plural: 'posts'
@@ -516,7 +514,7 @@ function tests(dbName, dbType) {
});
it('should use a type with a matching documentType for parseDocID, if no default', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'postSummary',
plural: 'postSummaries',
@@ -526,10 +524,32 @@ function tests(dbName, dbType) {
db.rel.parseDocID('post_2_bar').should.deep.equal({ type: 'postSummary', id: 'bar' });
});
+
+ it('should save a snapshot, so changes after rel.save should be ignored', function () {
+ let db = rootdb.setSchema([{
+ singular: 'post',
+ plural: 'posts'
+ }]);
+
+ let titleBeforeSaving = "Title before saving";
+ let post = {
+ title: titleBeforeSaving,
+ id: 'snapshot'
+ };
+
+ let savePromise = db.rel.save('post', post);
+ post.title = "Title after saving";
+
+ return savePromise.then(function () {
+ return db.rel.find('post', post.id);
+ }).then(function (res) {
+ res.posts[0].title.should.equal(titleBeforeSaving);
+ });
+ });
it('can delete', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'post',
plural: 'posts'
@@ -574,7 +594,7 @@ function tests(dbName, dbType) {
it('Adds attachment information', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -587,10 +607,10 @@ function tests(dbName, dbType) {
return db.get("post_2_with_attachment");
}).then(function (res) {
var attachment;
- if (process.browser) {
- attachment = blobUtil.createBlob(['Is there life on Mars?']);
+ if (typeof window !== 'undefined') {
+ attachment = createBlob(['Is there life on Mars?']);
} else {
- attachment = new Buffer('Is there life on Mars?');
+ attachment = Buffer.from('Is there life on Mars?');
}
return db.putAttachment(res._id, "file", res._rev, attachment, 'text/plain');
}).then(function () {
@@ -602,16 +622,16 @@ function tests(dbName, dbType) {
});
it('When saving the new document, saves the attachment', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
var attachment;
- if (process.browser) {
- attachment = blobUtil.createBlob(['Is there life on Mars?']);
+ if (typeof window !== 'undefined') {
+ attachment = createBlob(['Is there life on Mars?']);
} else {
- attachment = new Buffer('Is there life on Mars?');
+ attachment = Buffer.from('Is there life on Mars?');
}
return db.rel.save('post', {
@@ -635,16 +655,16 @@ function tests(dbName, dbType) {
});
it('When updating the existing document, keeps the attachment', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
var attachment;
- if (process.browser) {
- attachment = blobUtil.createBlob(['Is there life on Mars?']);
+ if (typeof window !== 'undefined') {
+ attachment = createBlob(['Is there life on Mars?']);
} else {
- attachment = new Buffer('Is there life on Mars?');
+ attachment = Buffer.from('Is there life on Mars?');
}
return db.rel.save('post', {
@@ -676,16 +696,16 @@ function tests(dbName, dbType) {
});
it('Removes the attachment through removal of attachments field', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
var attachment;
- if (process.browser) {
- attachment = blobUtil.createBlob(['Is there life on Mars?']);
+ if (typeof window !== 'undefined') {
+ attachment = createBlob(['Is there life on Mars?']);
} else {
- attachment = new Buffer('Is there life on Mars?');
+ attachment = Buffer.from('Is there life on Mars?');
}
return db.rel.save('post', {
@@ -714,7 +734,7 @@ function tests(dbName, dbType) {
});
it('Adds attachments through rel.putAttachment', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -723,13 +743,15 @@ function tests(dbName, dbType) {
title: "Files are cool",
text: "In order to have nice blog posts we need to be able to add files",
id: 'with_attachment'
+ }).then(function() {
+ return db.rel.find('post', 'with_attachment');
}).then(function (res) {
var attachment;
var post = res.posts[0];
- if (process.browser) {
- attachment = blobUtil.createBlob(['Is there life on Mars?']);
+ if (typeof window !== 'undefined') {
+ attachment = createBlob(['Is there life on Mars?']);
} else {
- attachment = new Buffer('Is there life on Mars?');
+ attachment = Buffer.from('Is there life on Mars?');
}
return db.rel.putAttachment('post', post, "file", attachment, 'text/plain');
}).then(function () {
@@ -742,7 +764,7 @@ function tests(dbName, dbType) {
});
it('Get attachments through rel.getAttachment', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -751,24 +773,26 @@ function tests(dbName, dbType) {
title: "Files are cool",
text: "In order to have nice blog posts we need to be able to add files",
id: 'with_attachment'
+ }).then(function() {
+ return db.rel.find('post', 'with_attachment');
}).then(function (res) {
var attachment;
var post = res.posts[0];
- if (process.browser) {
- attachment = blobUtil.createBlob(['Is there life on Mars?']);
+ if (typeof window !== 'undefined') {
+ attachment = createBlob(['Is there life on Mars?']);
} else {
- attachment = new Buffer('Is there life on Mars?');
+ attachment = Buffer.from('Is there life on Mars?');
}
return db.rel.putAttachment('post', post, "file", attachment, 'text/plain');
}).then(function () {
return db.rel.getAttachment('post', 'with_attachment', 'file');
}).then(function (attachment) {
- if (process.browser) {
+ if (typeof window !== 'undefined') {
var reader = new FileReader();
reader.onloadend = function () {
var binary = "";
- var bytes = new Uint8Array(this.result || '');
+ var bytes = new Uint8Array(this.result as ArrayBuffer);
var length = bytes.byteLength;
for (var i = 0; i < length; i++) {
@@ -777,7 +801,7 @@ function tests(dbName, dbType) {
binary.should.equal('Is there life on Mars?');
};
- reader.readAsArrayBuffer(attachment);
+ reader.readAsArrayBuffer(attachment as Blob);
} else {
attachment.toString('ascii').should.equal('Is there life on Mars?');
}
@@ -785,7 +809,7 @@ function tests(dbName, dbType) {
});
it('Removes attachments through rel.removeAttachment', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -794,13 +818,15 @@ function tests(dbName, dbType) {
title: "Files are cool",
text: "In order to have nice blog posts we need to be able to add files",
id: 'with_attachment'
+ }).then(function() {
+ return db.rel.find('post', 'with_attachment');
}).then(function (res) {
var attachment;
var post = res.posts[0];
- if (process.browser) {
- attachment = blobUtil.createBlob(['Is there life on Mars?']);
+ if (typeof window !== 'undefined') {
+ attachment = createBlob(['Is there life on Mars?']);
} else {
- attachment = new Buffer('Is there life on Mars?');
+ attachment = Buffer.from('Is there life on Mars?');
}
return db.rel.putAttachment('post', post, "file", attachment, 'text/plain');
}).then(function () {
@@ -823,7 +849,7 @@ function tests(dbName, dbType) {
it('fails if you include no relations', function () {
return Promise.resolve().then(function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'foo',
plural: 'foos',
relations: {}
@@ -837,7 +863,7 @@ function tests(dbName, dbType) {
it('fails if you include empty relationship definition', function () {
return Promise.resolve().then(function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'foo',
plural: 'foos',
relations: {
@@ -853,7 +879,7 @@ function tests(dbName, dbType) {
it('fails for unknown entity types', function () {
return Promise.resolve().then(function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'foo',
plural: 'foos',
relations: {
@@ -869,7 +895,7 @@ function tests(dbName, dbType) {
it('fails for unknown relation types', function () {
return Promise.resolve().then(function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'foo',
plural: 'foos',
@@ -894,7 +920,7 @@ function tests(dbName, dbType) {
this.timeout(30000);
it('does one-to-one', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -949,7 +975,7 @@ function tests(dbName, dbType) {
});
it('does one-to-many with empty dependents', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -989,7 +1015,7 @@ function tests(dbName, dbType) {
});
it('does one-to-many with several entities', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1082,7 +1108,7 @@ function tests(dbName, dbType) {
});
});
it('does many-to-many with recursive relationship', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1306,7 +1332,7 @@ function tests(dbName, dbType) {
if (dbType === 'local') { //pouchdb-find only supported on cloudant and couch >= 2.0
it('does parseRelDocs', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1324,7 +1350,7 @@ function tests(dbName, dbType) {
]);
return db.createIndex({index: { fields: ['data.name'] }}).then(function() {
- return db.rel.save('author', {
+ return db.rel.save('author', {
name: 'Stephen King',
id: 19,
books: [1]
@@ -1336,10 +1362,10 @@ function tests(dbName, dbType) {
author: 19
});
}).then(function () {
- //not a rel.find
- return db.find({selector: {'data.name': 'Stephen King'}}).then(function(findRes) {
- return db.rel.parseRelDocs('author', findRes.docs);
- });
+ //not a rel.find
+ return db.find({selector: {'data.name': 'Stephen King'}});
+ }).then(function(findRes) {
+ return db.rel.parseRelDocs('author', findRes.docs);
}).then(function (res) {
['authors', 'books'].forEach(function (type) {
res[type].forEach(function (obj) {
@@ -1367,7 +1393,7 @@ function tests(dbName, dbType) {
});
it('does one-to-many without saving hasMany side', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1385,7 +1411,7 @@ function tests(dbName, dbType) {
]);
return db.createIndex({index: { fields: ['data.author', '_id'] }}).then(function() {
- return db.rel.save('author', {
+ return db.rel.save('author', {
name: 'Stephen King',
id: 19,
});
@@ -1423,12 +1449,12 @@ function tests(dbName, dbType) {
});
it('does findHasMany', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
relations: {
- //omit relation should also work
+ //omit relation should also work
'books': {hasMany: { type: 'book', options: {async: true, queryInverse: 'author'}}}
}
},
@@ -1442,7 +1468,7 @@ function tests(dbName, dbType) {
]);
return db.createIndex({index: { fields: ['data.author', '_id'] }}).then(function() {
- return db.rel.save('author', {
+ return db.rel.save('author', {
name: 'Stephen King',
id: 19,
});
@@ -1472,7 +1498,7 @@ function tests(dbName, dbType) {
return db.rel.findHasMany('book', 'author', 19);
}).then(function(res) {
- ['books'].forEach(function (type) {
+ ['books'].forEach(function (type) {
res[type].forEach(function (obj) {
obj.rev.should.be.a('string');
delete obj.rev;
@@ -1492,7 +1518,7 @@ function tests(dbName, dbType) {
}
it('does many-to-many with several entities', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1594,7 +1620,7 @@ function tests(dbName, dbType) {
});
it('should fetch all authors even with empty relations', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1665,7 +1691,7 @@ function tests(dbName, dbType) {
});
it('does one-to-many', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1764,7 +1790,7 @@ function tests(dbName, dbType) {
});
it('does one-to-many with embedded relations', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1866,7 +1892,7 @@ function tests(dbName, dbType) {
});
});
it('does one-to-many and keeps the right order', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -1965,7 +1991,7 @@ function tests(dbName, dbType) {
});
it('does sideload if async option is false', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -2040,7 +2066,7 @@ function tests(dbName, dbType) {
});
});
it('does not sideload if async option is true', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -2100,7 +2126,7 @@ function tests(dbName, dbType) {
});
it('fromRawDoc works with changes', function () {
- db.setSchema([
+ let db = rootdb.setSchema([
{
singular: 'author',
plural: 'authors',
@@ -2155,7 +2181,7 @@ function tests(dbName, dbType) {
it('should pass along options', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -2192,7 +2218,7 @@ function tests(dbName, dbType) {
it('should pass along options, including startkey', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -2233,7 +2259,7 @@ function tests(dbName, dbType) {
it('should pass along options, including endkey', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -2273,7 +2299,7 @@ function tests(dbName, dbType) {
it('should pass along options, including kip', function () {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
@@ -2313,7 +2339,7 @@ function tests(dbName, dbType) {
});
it('isDeleted should work', function() {
- db.setSchema([{
+ let db = rootdb.setSchema([{
singular: 'post',
plural: 'posts'
}]);
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..6be7314
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "lib": ["es5", "es2015", "dom", "scripthost"],
+ "target": "esnext",
+ "declaration": true,
+ "outDir": "./lib",
+ "strict": false,
+ "allowSyntheticDefaultImports": true,
+ "baseUrl": "./src",
+ /*"paths": {
+ "*": ["@types/*"]
+ },*/
+ "moduleResolution": "node",
+ "typeRoots": ["@types", "node_modules/@types"],
+ },
+ "include": ["src"],
+ "exclude": ["node_modules"]
+}
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..01b79c1
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,131 @@
+
+let webpack = require('webpack');
+//let deepScope = require('webpack-deep-scope-plugin').default;
+
+let path = require('path');
+let package = require('./package.json');
+
+module.exports = (env, argv) => {
+let nodeTarget = {
+ target: "node",
+ entry: "./src/index.ts",
+ mode: argv.mode || 'development',
+ output: {
+ path: path.resolve(__dirname, 'dist'),
+ filename: 'pouchdb.relational-pouch.node.js',
+ libraryTarget: 'commonjs2',
+ libraryExport: 'default',
+ },
+ externals: Object.keys(package.dependencies),
+ plugins: [
+ ],
+ module: {
+ rules: [
+ {
+ test: /\.m?[jt]s$/,
+ exclude: /(node_modules|bower_components)/,
+ use: [
+ {
+ loader: 'babel-loader',
+ options: {
+ presets: [
+ ['@babel/preset-env',
+ {
+ "targets": {
+ "node": "10"
+ },
+ "modules": false,
+ useBuiltIns: "usage",
+ corejs: 3,
+ }],
+ ],
+ },
+ },
+ {
+ loader: 'ts-loader',
+ options: {
+ transpileOnly: true,
+ experimentalWatchApi: true,
+ },
+ },
+ ],
+ }
+ ]
+ },
+ resolve: {
+ extensions: ['tsx', '.ts', '.js', '.json'],
+ },
+// externals: [
+// function(context, request, callback) {
+// if (/^http-debug$/.test(request)){
+// return callback(null, 'commonjs ' + request);
+// }
+// callback();
+// },
+// ],
+};
+
+let webTarget = {
+ target: "web",
+ entry: "./src/browser.ts",//TODO: this file could be exluded in tsc to not generate dist/browser.*
+ mode: argv.mode || 'development',
+// stats: 'verbose',
+ output: {
+ path: path.resolve(__dirname, 'dist'),
+ filename: 'pouchdb.relational-pouch.browser.js',
+ libraryTarget: 'umd',
+ },
+ plugins: [
+ ],
+ module: {
+ rules: [
+ {
+ test: /\.m?[jt]s$/,
+ exclude: /(node_modules|bower_components)/,
+ use: [
+ {
+ loader: 'babel-loader',
+ options: {
+ presets: [
+ ['@babel/preset-env',
+ {
+ "targets": ">2%, not ie 11",
+ "modules": false,
+ useBuiltIns: "usage",
+ corejs: 3,
+ }],
+ ],
+ },
+ },
+ {
+ loader: 'ts-loader',
+ options: {
+ transpileOnly: true,
+ experimentalWatchApi: true,
+ },
+ },
+ ],
+ }
+ ]
+ },
+ resolve: {
+ extensions: ['tsx', '.ts', '.js', '.json'],
+ },
+// externals: [
+// function(context, request, callback) {
+// if (/^http-debug$/.test(request)){
+// return callback(null, 'commonjs ' + request);
+// }
+// callback();
+// },
+// ],
+};
+
+var doSourcemapping = argv.mode != 'production';//also needs a change in run.js
+if (doSourcemapping) {
+ webTarget.devtool = 'source-map';//'inline-source-map',
+ nodeTarget.devtool = 'source-map';
+}
+
+return [webTarget, nodeTarget,];
+};
diff --git a/webpack.test.node.config.js b/webpack.test.node.config.js
new file mode 100644
index 0000000..eefcbf3
--- /dev/null
+++ b/webpack.test.node.config.js
@@ -0,0 +1,75 @@
+
+let webpack = require('webpack');
+const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
+
+let path = require('path');
+let package = require('./package.json');
+
+let babelLoader = {
+ loader: 'babel-loader',
+ options: {
+ presets: [
+ ['@babel/preset-env',
+ {
+ "targets": {
+ "node": "current"
+ },
+ "modules": false,
+ useBuiltIns: "usage",
+ corejs: 3,
+ }],
+ ],
+ plugins: ["istanbul"],
+ },
+};
+
+module.exports = (env, argv) => {
+let nodeTarget = {
+ stats: 'errors-only',
+ target: "node",
+ entry: "./test/test.ts",
+ mode: argv.mode || 'development',
+ externals: Object.keys(package.dependencies),
+ output: {
+ path: path.resolve(__dirname, 'test'),
+ filename: 'test-node.js',
+ libraryTarget: 'commonjs2',
+ },
+ plugins: [
+ new ForkTsCheckerWebpackPlugin(),
+ ],
+ module: {
+ rules: [
+ {
+ test: /\.[tj]s$/,
+ exclude: /(node_modules|bower_components)/,
+ use: [
+ babelLoader,
+ {
+ loader: 'ts-loader',
+ options: {
+ transpileOnly: true,
+ experimentalWatchApi: true,
+ },
+ },
+ ],
+ },
+// {
+// test: /\.m?js$/,
+// exclude: /(node_modules|bower_components)/,
+// use: babelLoader,
+// },
+ ]
+ },
+ resolve: {
+ extensions: ['tsx', '.ts', '.js', '.json'],
+ },
+};
+
+var doSourcemapping = argv.mode != 'production';//also needs a change in run.js
+if (doSourcemapping) {
+ nodeTarget.devtool = 'source-map';
+}
+
+return [nodeTarget,];
+};