Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Commit

Permalink
feat: implement cli for generate couchdb's design documents
Browse files Browse the repository at this point in the history
  • Loading branch information
fox1t committed Mar 4, 2020
1 parent 3711fc2 commit 9c7e36c
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 7 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
ignorePatterns: ['bin'],
extends: [
'plugin:@typescript-eslint/recommended',
'prettier',
Expand Down
82 changes: 82 additions & 0 deletions bin/ddoc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env node
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const util_1 = require("util");
const sade_1 = __importDefault(require("sade"));
const typescript_1 = __importDefault(require("typescript"));
const require_from_string_1 = __importDefault(require("require-from-string"));
const glob_1 = __importDefault(require("glob"));
const mkdirp_1 = __importDefault(require("mkdirp"));
const stat = util_1.promisify(fs_1.default.stat);
const readFile = util_1.promisify(fs_1.default.readFile);
const writeFile = util_1.promisify(fs_1.default.writeFile);
const glob = util_1.promisify(glob_1.default);
const prog = sade_1.default('ddoc');
prog.version('0.1.0');
prog
.command('build <src>', 'Build design document(s) from TypeScript soruce directory or file.', {
default: true,
})
.option('-c, --config', 'Provide path to custom tsconfig.json', './tsconfig.json')
.example('build src/db/designs')
.example('build src/db/designs/patient.ts -c src/db/tsconfig.json')
.action(async (src, opts) => {
var _a;
try {
const cwd = process.cwd();
const tsconfigPath = path_1.default.isAbsolute(opts.config) ? opts.config : path_1.default.join(cwd, opts.config);
console.log(`> using ${tsconfigPath} config`);
const tsconfig = require(tsconfigPath);
src = path_1.default.isAbsolute(src) ? path_1.default.normalize(src) : path_1.default.join(cwd, src);
const srcStats = await stat(src);
let dest = ((_a = tsconfig === null || tsconfig === void 0 ? void 0 : tsconfig.compilerOptions) === null || _a === void 0 ? void 0 : _a.outDir) ? path_1.default.join(path_1.default.dirname(tsconfigPath), tsconfig.compilerOptions.outDir)
: '';
let ddocs;
if (srcStats.isDirectory()) {
dest = dest || src;
ddocs = await glob(path_1.default.join(src, '**/*.ts'));
}
else {
dest = dest || path_1.default.dirname(src);
ddocs = [src];
}
console.log(`> src directory is ${src}`);
await mkdirp_1.default(dest);
console.log(`> destination directory is ${dest}`);
const errors = [];
await Promise.all(ddocs.map(async (srcPath) => {
try {
const sourceFile = (await readFile(srcPath)).toString();
const output = typescript_1.default.transpileModule(sourceFile, tsconfig);
const ddoc = require_from_string_1.default(output.outputText);
const filename = path_1.default.basename(srcPath, '.ts');
const stringifiedDesign = JSON.stringify(ddoc, (_, val) => {
if (typeof val === 'function') {
return val.toString();
}
return val;
}, 1);
await writeFile(path_1.default.join(dest, `${filename}.json`), stringifiedDesign);
}
catch (err) {
errors.push(err);
}
}));
if (errors.length > 0) {
errors.forEach(err => {
console.error(err);
});
throw new Error(`Compilation failed. Resolve errors in your code and try again.`);
}
}
catch (err) {
console.error(err);
process.exit(1);
}
});
prog.parse(process.argv);
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
"url": "https://github.com/HospitalRun/hospitalrun-server.git"
},
"scripts": {
"ddoc": "npm run build:bin && node bin/ddoc",
"commit": "npx git-cz",
"build": "npm run clean && tsc -p ./tsconfig.json && npm run build:designs",
"build:designs": "tsc -p ./src/db/tsconfig.json",
"build:bin": "rimraf bin && tsc -p ./src/bin/tsconfig.json",
"start": "node dist",
"clean": "rimraf dist",
"dev:db": "pouchdb-server --config ./db/config.json",
Expand All @@ -30,7 +32,6 @@
"author": "Maksim Sinik <[email protected]>",
"license": "MIT",
"dependencies": {
"cross-env": "~7.0.0",
"fastify": "~2.12.0",
"fastify-autoload": "~1.2.2",
"fastify-blipp": "~2.1.0",
Expand All @@ -41,14 +42,18 @@
"fastify-plugin": "~1.6.1",
"make-promises-safe": "~5.1.0",
"nano": "~8.2.1",
"qs": "~6.9.1"
"qs": "~6.9.1",
"require-from-string": "~2.0.2"
},
"devDependencies": {
"@commitlint/cli": "8.3.5",
"@commitlint/config-conventional": "8.3.4",
"@commitlint/prompt": "8.3.5",
"@types/mkdirp": "~1.0.0",
"@types/node": "~13.7.0",
"@types/qs": "~6.9.0",
"@types/require-from-string": "~1.2.0",
"@types/sade": "~1.6.0",
"@typescript-eslint/eslint-plugin": "~2.21.0",
"@typescript-eslint/parser": "~2.21.0",
"commitizen": "~4.0.3",
Expand All @@ -61,14 +66,17 @@
"eslint-config-prettier": "~6.10.0",
"eslint-plugin-import": "~2.20.0",
"eslint-plugin-prettier": "~3.1.0",
"glob": "~7.1.6",
"husky": "~4.2.0",
"lint-staged": "~10.0.7",
"mkdirp": "~1.0.3",
"nodemon": "~2.0.0",
"npm-run-all": "~4.1.5",
"pino-colada": "~1.5.0",
"pouchdb-server": "~4.2.0",
"prettier": "~1.19.1",
"rimraf": "~3.0.0",
"sade": "~1.7.3",
"source-map-support": "~0.5.16",
"tap": "~14.10.5",
"tap-mocha-reporter": "~5.0.0",
Expand Down
93 changes: 93 additions & 0 deletions src/bin/ddoc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/usr/bin/env node

import path from 'path'
import fs from 'fs'
import { promisify } from 'util'
import sade from 'sade'
import ts from 'typescript'
import requireFromString from 'require-from-string'
import originalGlob from 'glob'
import mkdirp from 'mkdirp'

const stat = promisify(fs.stat)
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const glob = promisify(originalGlob)

const prog = sade('ddoc')

prog.version('0.1.0')

prog
.command('build <src>', 'Build design document(s) from TypeScript soruce directory or file.', {
default: true,
})
// .describe('Build design documents from TypeScript soruce directory or file.')
.option('-c, --config', 'Provide path to custom tsconfig.json', './tsconfig.json')
.example('build src/db/designs')
.example('build src/db/designs/patient.ts -c src/db/tsconfig.json')
.action(async (src, opts) => {
try {
const cwd = process.cwd()
const tsconfigPath = path.isAbsolute(opts.config) ? opts.config : path.join(cwd, opts.config)

console.log(`> using ${tsconfigPath} config`)
const tsconfig = require(tsconfigPath) // eslint-disable-line

src = path.isAbsolute(src) ? path.normalize(src) : path.join(cwd, src) // eslint-disable-line

const srcStats = await stat(src)
// use outDir if specified inside tsconfig, otherwise build json alongside ts files
let dest: string = tsconfig?.compilerOptions?.outDir
? path.join(path.dirname(tsconfigPath), tsconfig.compilerOptions.outDir)
: ''
let ddocs: string[]
if (srcStats.isDirectory()) {
dest = dest || src
ddocs = await glob(path.join(src, '**/*.ts'))
} else {
dest = dest || path.dirname(src)
ddocs = [src]
}

console.log(`> src directory is ${src}`)
await mkdirp(dest)
console.log(`> destination directory is ${dest}`)

const errors: Error[] = []
await Promise.all(
ddocs.map(async srcPath => {
try {
const sourceFile = (await readFile(srcPath)).toString()
const output = ts.transpileModule(sourceFile, tsconfig)
const ddoc = requireFromString(output.outputText)
const filename = path.basename(srcPath, '.ts')
const stringifiedDesign = JSON.stringify(
ddoc,
(_, val) => {
if (typeof val === 'function') {
return val.toString()
}
return val
},
1,
)
await writeFile(path.join(dest, `${filename}.json`), stringifiedDesign)
} catch (err) {
errors.push(err)
}
}),
)
if (errors.length > 0) {
errors.forEach(err => {
console.error(err)
})
throw new Error(`Compilation failed. Resolve errors in your code and try again.`)
}
} catch (err) {
console.error(err)
process.exit(1)
}
})

prog.parse(process.argv)
14 changes: 14 additions & 0 deletions src/bin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// we need this custom tsconfig.json to handle CouchDB Javascript Context locally to this folder
{
"extends": "../../tsconfig.json",
"include": [
"."
],
"exclude": [
"node_modules",
],
"compilerOptions": {
"outDir": "../../bin",
"sourceMap": false
}
}
1 change: 0 additions & 1 deletion src/db/designs/index.ts

This file was deleted.

7 changes: 3 additions & 4 deletions src/db/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
// we need this custom tsconfig.json to handle CouchDB Javascript Context locally to this folder
{
"extends": "../../tsconfig.json",
"include": [
"."
],
"exclude": [
"node_modules",
"node_modules"
],
"compilerOptions": {
"typeRoots": [
"../../node_modules/@types",
"./design-functions-context.d.ts"
],
"outDir": "../../dist/db",
"outDir": "../../db/designs",
"sourceMap": false
}
}

0 comments on commit 9c7e36c

Please sign in to comment.