couch-init2
Advanced tools
Comparing version 4.0.1 to 4.1.0
const fetch = require('node-fetch') | ||
const couchdbError = require('./couchdb_error') | ||
@@ -14,2 +15,3 @@ module.exports = async (dbUrl, dbName) => { | ||
if (res.status >= 400) { | ||
throw (await couchdbError(res)) | ||
const body = await res.text() | ||
@@ -16,0 +18,0 @@ throw new Error(`${res.status}: ${res.statusText} ${body}`) |
const { readFile, writeFile } = require('fs').promises | ||
const fetch = require('node-fetch') | ||
const promiseProps = require('./promise_props') | ||
const couchdbError = require('./couchdb_error') | ||
@@ -16,7 +17,13 @@ // This verifies that the database design documents are up-to-date | ||
const syncDesignDoc = async (designDocFolder, dbUrl, designDocName) => { | ||
const jsDesignDoc = designDocName.endsWith('.js') | ||
if (jsDesignDoc) designDocName = designDocName.replace(/\.js$/, '') | ||
const designDocId = `_design/${designDocName}` | ||
const designDocUrl = `${dbUrl}/${designDocId}` | ||
const designDocFile = await getDesignDocFile(designDocFolder, designDocName) | ||
let currentDesignDoc | ||
let created | ||
let designDocFile | ||
if (jsDesignDoc) { | ||
designDocFile = await getJsDesignDoc(designDocFolder, designDocName) | ||
} else { | ||
designDocFile = await getJsonDesignDoc(designDocFolder, designDocName) | ||
} | ||
let currentDesignDoc, created | ||
const res = await fetch(designDocUrl) | ||
@@ -32,3 +39,3 @@ if (res.status === 200) { | ||
} | ||
const op = await updateDesignDoc(designDocId, designDocFile, currentDesignDoc, designDocUrl) | ||
const op = await updateDesignDoc(designDocFile, currentDesignDoc, designDocUrl) | ||
if (created) return { created } | ||
@@ -38,5 +45,41 @@ else return op | ||
const getDesignDocFile = async (designDocFolder, designDocName) => { | ||
const designDocPath = `${designDocFolder}/${designDocName}.json` | ||
const getJsDesignDoc = async (designDocFolder, designDocName) => { | ||
const designDocPath = `${designDocFolder}/${designDocName}.js` | ||
try { | ||
let jsDesignDoc = require(designDocPath) | ||
// Allow to pass just the view object | ||
if (!jsDesignDoc._id) { | ||
jsDesignDoc = { | ||
_id: `_design/${designDocName}`, | ||
language: 'javascript', | ||
views: jsDesignDoc, | ||
} | ||
} | ||
stringifyJsDesignDoc(jsDesignDoc.views) | ||
return JSON.stringify(jsDesignDoc) | ||
} catch (err) { | ||
if (err.code !== 'MODULE_NOT_FOUND') throw err | ||
// Initialize the design doc if none is found | ||
// Return a stringify version to keep consistency | ||
// with what would the normal readFile | ||
const emptyDesignDoc = `module.exports = {}` | ||
// Initializing the missing design doc file | ||
await writeFile(designDocPath, emptyDesignDoc) | ||
return {} | ||
} | ||
} | ||
const stringifyJsDesignDoc = views => { | ||
for (const view of Object.values(views)) { | ||
if (view.map) view.map = view.map.toString().trim() | ||
if (view.reduce) view.reduce = view.reduce.toString().trim() | ||
} | ||
} | ||
const getJsonDesignDoc = async (designDocFolder, designDocName) => { | ||
try { | ||
const designDocPath = `${designDocFolder}/${designDocName}.json` | ||
return await readFile(designDocPath, { encoding: 'utf-8' }) | ||
@@ -49,12 +92,12 @@ } catch (err) { | ||
// with what would the normal readFile | ||
const initDoc = JSON.stringify(emtpyDesignDoc(designDocName), null, 4) | ||
const emptyDesignDoc = JSON.stringify(emtpyDesignDoc(designDocName), null, 4) | ||
// Initializing the missing design doc file | ||
await writeFile(designDocPath, initDoc) | ||
await writeFile(designDocPath, emptyDesignDoc) | ||
return initDoc | ||
return {} | ||
} | ||
} | ||
const updateDesignDoc = async (designDocId, designDocFile, currentDesignDoc, designDocUrl) => { | ||
const updateDesignDoc = async (designDocFile, currentDesignDoc, designDocUrl) => { | ||
const rev = currentDesignDoc && currentDesignDoc._rev | ||
@@ -79,3 +122,5 @@ | ||
if (res.status !== 201) throw new Error(`${res.status}: ${res.statusText}`) | ||
if (res.status !== 201) { | ||
throw (await couchdbError(res)) | ||
} | ||
@@ -82,0 +127,0 @@ return { updated: true } |
{ | ||
"name": "couch-init2", | ||
"version": "4.0.1", | ||
"version": "4.1.0", | ||
"description": "Opiniated CouchDB databases initializer", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -51,2 +51,42 @@ # couch-init2 | ||
### Design docs formats | ||
#### json | ||
The JSON format is identical to the document in database, minus the `_rev` id. | ||
```json | ||
{ | ||
"_id": "_design/example", | ||
"language": "javascript", | ||
"views": { | ||
"byFoo": { | ||
"map": "function (doc) {\n if (doc.foo) emit(doc.foo, 1)\n}" | ||
} | ||
} | ||
} | ||
``` | ||
#### js | ||
The JS format allows to use a JS module that exports just the `views` object, the `_id` being deduced from the filename (ex: if the file is named `foo.js`, the `_id` will be `_design/foo`) | ||
```js | ||
module.exports = { | ||
byFoo: { | ||
map: function (doc) { | ||
if (doc.foo) emit(doc.foo, 1) | ||
}, | ||
reduce: function(keys, values) { | ||
return values.reduce((a, b) => a + b, 0) | ||
}, | ||
}, | ||
byBar: { | ||
// The function stringification won't be able to detect variables in scope. | ||
// In this case, you have to pass the function and its dependencies as a string. | ||
map: ` | ||
const double = num => num * 2 | ||
function (doc) { | ||
if (doc.foo) emit(doc.foo, double(1)) | ||
}`, | ||
}, | ||
} | ||
``` | ||
### What it does | ||
@@ -53,0 +93,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14280
10
289
99
2