dbdocs 0.5.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -1
- package/bin/run +0 -0
- package/oclif.manifest.json +1 -1
- package/package.json +6 -1
- package/src/commands/build.js +8 -18
- package/src/commands/ls.js +56 -0
- package/src/commands/validate.js +43 -0
- package/src/hooks/prerun/checkVersion.js +20 -0
- package/src/hooks/prerun/helper.js +37 -0
- package/src/utils/org.js +5 -0
- package/src/utils/parse.js +18 -0
- package/src/utils/parserWorker.js +20 -0
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ $ npm install -g dbdocs
|
|
|
19
19
|
$ dbdocs COMMAND
|
|
20
20
|
running command...
|
|
21
21
|
$ dbdocs (-v|--version|version)
|
|
22
|
-
dbdocs/0.
|
|
22
|
+
dbdocs/0.6.2 darwin-x64 node-v15.10.0
|
|
23
23
|
$ dbdocs --help [COMMAND]
|
|
24
24
|
USAGE
|
|
25
25
|
$ dbdocs COMMAND
|
|
@@ -32,9 +32,11 @@ USAGE
|
|
|
32
32
|
* [`dbdocs help [COMMAND]`](#dbdocs-help-command)
|
|
33
33
|
* [`dbdocs login`](#dbdocs-login)
|
|
34
34
|
* [`dbdocs logout`](#dbdocs-logout)
|
|
35
|
+
* [`dbdocs ls`](#dbdocs-ls)
|
|
35
36
|
* [`dbdocs password`](#dbdocs-password)
|
|
36
37
|
* [`dbdocs remove [PROJECT_NAME]`](#dbdocs-remove-project_name)
|
|
37
38
|
* [`dbdocs token`](#dbdocs-token)
|
|
39
|
+
* [`dbdocs validate [FILEPATH]`](#dbdocs-validate-filepath)
|
|
38
40
|
|
|
39
41
|
## `dbdocs build [FILEPATH]`
|
|
40
42
|
|
|
@@ -91,6 +93,18 @@ DESCRIPTION
|
|
|
91
93
|
clears local login credentials
|
|
92
94
|
```
|
|
93
95
|
|
|
96
|
+
## `dbdocs ls`
|
|
97
|
+
|
|
98
|
+
list projects
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
USAGE
|
|
102
|
+
$ dbdocs ls
|
|
103
|
+
|
|
104
|
+
DESCRIPTION
|
|
105
|
+
list all projects in your default organization
|
|
106
|
+
```
|
|
107
|
+
|
|
94
108
|
## `dbdocs password`
|
|
95
109
|
|
|
96
110
|
set password for your project or remove password
|
|
@@ -128,4 +142,16 @@ OPTIONS
|
|
|
128
142
|
-g, --generate generate authentication token
|
|
129
143
|
-r, --revoke revoke authentication token
|
|
130
144
|
```
|
|
145
|
+
|
|
146
|
+
## `dbdocs validate [FILEPATH]`
|
|
147
|
+
|
|
148
|
+
validate docs content
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
USAGE
|
|
152
|
+
$ dbdocs validate [FILEPATH]
|
|
153
|
+
|
|
154
|
+
ARGUMENTS
|
|
155
|
+
FILEPATH dbml file path
|
|
156
|
+
```
|
|
131
157
|
<!-- commandsstop -->
|
package/bin/run
CHANGED
|
File without changes
|
package/oclif.manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.
|
|
1
|
+
{"version":"0.6.2","commands":{"build":{"id":"build","description":"build docs","pluginName":"dbdocs","pluginType":"core","aliases":[],"flags":{"project":{"name":"project","type":"option","description":"project name"},"password":{"name":"password","type":"option","char":"p","description":"password for project"}},"args":[{"name":"filepath","description":"dbml file path"}]},"login":{"id":"login","description":"login to dbdocs\nlogin with your dbdocs credentials\n","pluginName":"dbdocs","pluginType":"core","aliases":[],"flags":{},"args":[]},"logout":{"id":"logout","description":"logout\nclears local login credentials\n","pluginName":"dbdocs","pluginType":"core","aliases":[],"flags":{},"args":[]},"ls":{"id":"ls","description":"list projects","pluginName":"dbdocs","pluginType":"core","aliases":[],"flags":{},"args":[]},"password":{"id":"password","description":"set password for your project or remove password","pluginName":"dbdocs","pluginType":"core","aliases":[],"flags":{"project":{"name":"project","type":"option","char":"p","description":"project name","helpValue":"project name"},"set":{"name":"set","type":"option","char":"s","description":"password for your project","helpValue":"password"},"remove":{"name":"remove","type":"boolean","char":"r","description":"remove password from your project","allowNo":false}},"args":[]},"remove":{"id":"remove","description":"remove docs","pluginName":"dbdocs","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"project_name","description":"name of the project which you want to remove"}]},"token":{"id":"token","description":"generate or revoke your authentication token","pluginName":"dbdocs","pluginType":"core","aliases":[],"flags":{"generate":{"name":"generate","type":"boolean","char":"g","description":"generate authentication token","allowNo":false},"revoke":{"name":"revoke","type":"boolean","char":"r","description":"revoke authentication token","allowNo":false}},"args":[]},"validate":{"id":"validate","description":"validate docs content","pluginName":"dbdocs","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"filepath","description":"dbml file path"}]}}}
|
package/package.json
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbdocs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"author": "@holistics",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dbdocs": "./bin/run"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
+
"@dbml/core": "^2.4.1",
|
|
9
10
|
"@oclif/command": "^1",
|
|
10
11
|
"@oclif/config": "^1",
|
|
11
12
|
"@oclif/plugin-help": "^2",
|
|
12
13
|
"axios": "^0.19.0",
|
|
13
14
|
"chalk": "^3.0.0",
|
|
15
|
+
"cli-ux": "^5.6.3",
|
|
14
16
|
"dotenv": "^8.2.0",
|
|
15
17
|
"inquirer": "^7.0.1",
|
|
16
18
|
"netrc-parser": "^3.1.6",
|
|
@@ -50,6 +52,9 @@
|
|
|
50
52
|
"init": [
|
|
51
53
|
"./src/hooks/init/checkUpdate",
|
|
52
54
|
"./src/hooks/init/loadEnv"
|
|
55
|
+
],
|
|
56
|
+
"prerun":[
|
|
57
|
+
"./src/hooks/prerun/checkVersion"
|
|
53
58
|
]
|
|
54
59
|
}
|
|
55
60
|
},
|
package/src/commands/build.js
CHANGED
|
@@ -10,14 +10,7 @@ const verifyToken = require('../utils/verifyToken');
|
|
|
10
10
|
const { getOrg } = require('../utils/org');
|
|
11
11
|
const { shouldAskForFeedback } = require('../utils/feedback');
|
|
12
12
|
const { isValidName } = require('../validators/projectName');
|
|
13
|
-
|
|
14
|
-
async function validate (content) {
|
|
15
|
-
const res = await axios.post(`${vars.apiUrl}/parse`, {
|
|
16
|
-
content,
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
return res.data.model;
|
|
20
|
-
}
|
|
13
|
+
const parse = require('../utils/parse');
|
|
21
14
|
|
|
22
15
|
async function build (project, authConfig) {
|
|
23
16
|
const res = await axios.post(`${vars.apiUrl}/projects`, project, authConfig);
|
|
@@ -57,20 +50,16 @@ class BuildCommand extends Command {
|
|
|
57
50
|
// validate dbml syntax, get project name if it's already defined in the file
|
|
58
51
|
spinner.text = 'Parsing file content';
|
|
59
52
|
spinner.start();
|
|
53
|
+
let model = null;
|
|
60
54
|
try {
|
|
61
|
-
|
|
55
|
+
model = await parse(content);
|
|
62
56
|
if (!project) {
|
|
63
|
-
project = model.
|
|
57
|
+
project = model.name;
|
|
64
58
|
}
|
|
65
59
|
spinner.succeed('Parsing file content');
|
|
66
|
-
} catch (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const { error } = err.response.data;
|
|
70
|
-
if (error.name === 'SyntaxError') {
|
|
71
|
-
message = `You have syntax error in ${path.basename(filepath)} line ${error.location.start.line} column ${error.location.start.column}. ${error.message}`;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (!error.location) throw error;
|
|
62
|
+
const message = `You have syntax error in ${path.basename(filepath)} line ${error.location.start.line} column ${error.location.start.column}. ${error.message}`;
|
|
74
63
|
throw new Error(message);
|
|
75
64
|
}
|
|
76
65
|
|
|
@@ -95,6 +84,7 @@ class BuildCommand extends Command {
|
|
|
95
84
|
doc: {
|
|
96
85
|
content,
|
|
97
86
|
},
|
|
87
|
+
shallowSchema: model.schemas,
|
|
98
88
|
}, authConfig);
|
|
99
89
|
if (!newProject.isPublic) {
|
|
100
90
|
if (isCreated || password) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const { Command } = require('@oclif/command');
|
|
2
|
+
const { cli } = require('cli-ux');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const { vars } = require('../vars');
|
|
5
|
+
const verifyToken = require('../utils/verifyToken');
|
|
6
|
+
const { getProjectsByOrg } = require('../utils/org');
|
|
7
|
+
const { getOrg } = require('../utils/org');
|
|
8
|
+
|
|
9
|
+
class LsCommand extends Command {
|
|
10
|
+
async run () {
|
|
11
|
+
try {
|
|
12
|
+
const authConfig = await verifyToken();
|
|
13
|
+
const org = await getOrg(authConfig);
|
|
14
|
+
const projects = await getProjectsByOrg(org.name, authConfig);
|
|
15
|
+
this.log(chalk.bold(org.name));
|
|
16
|
+
|
|
17
|
+
const [maxUrlWidth, maxUpdatedAtWidth] = projects.reduce((accumulator, project) => {
|
|
18
|
+
const url = `${vars.hostUrl}/${org.name}/${project.urlName}`;
|
|
19
|
+
const updatedAt = (new Date(project.updatedAt)).toLocaleString();
|
|
20
|
+
return [
|
|
21
|
+
accumulator[0] > url.length ? accumulator[0] : url.length,
|
|
22
|
+
accumulator[1] > updatedAt.length ? accumulator[1] : updatedAt.length,
|
|
23
|
+
];
|
|
24
|
+
}, [3, 12]);
|
|
25
|
+
|
|
26
|
+
cli.table(projects, {
|
|
27
|
+
name: {
|
|
28
|
+
minWidth: 20,
|
|
29
|
+
},
|
|
30
|
+
isPublic: {
|
|
31
|
+
minWidth: 12,
|
|
32
|
+
header: 'Password',
|
|
33
|
+
// eslint-disable-next-line no-confusing-arrow
|
|
34
|
+
get: (project) => project.isPublic ? 'No' : 'Yes',
|
|
35
|
+
},
|
|
36
|
+
url: {
|
|
37
|
+
minWidth: maxUrlWidth + 2,
|
|
38
|
+
get: (project) => chalk.cyan(`${vars.hostUrl}/${org.name}/${project.urlName}`),
|
|
39
|
+
},
|
|
40
|
+
updatedAt: {
|
|
41
|
+
minWidth: maxUpdatedAtWidth + 2,
|
|
42
|
+
header: 'Last updated',
|
|
43
|
+
get: (project) => (new Date(project.updatedAt)).toLocaleString(),
|
|
44
|
+
},
|
|
45
|
+
}, {
|
|
46
|
+
printLine: this.log,
|
|
47
|
+
});
|
|
48
|
+
} catch (err) {
|
|
49
|
+
this.error(err);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
LsCommand.description = 'list projects';
|
|
55
|
+
|
|
56
|
+
module.exports = LsCommand;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const { Command, flags } = require('@oclif/command');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const ora = require('ora');
|
|
5
|
+
const parse = require('../utils/parse');
|
|
6
|
+
|
|
7
|
+
class ValidateCommand extends Command {
|
|
8
|
+
async run () {
|
|
9
|
+
const spinner = ora({});
|
|
10
|
+
let filepath = null;
|
|
11
|
+
try {
|
|
12
|
+
const { args } = this.parse(ValidateCommand);
|
|
13
|
+
filepath = args.filepath;
|
|
14
|
+
let content = '';
|
|
15
|
+
content = fs.readFileSync(path.resolve(process.cwd(), filepath), 'utf-8');
|
|
16
|
+
|
|
17
|
+
spinner.text = 'Validating file content';
|
|
18
|
+
spinner.start();
|
|
19
|
+
|
|
20
|
+
await parse(content);
|
|
21
|
+
spinner.succeed('Validating file content');
|
|
22
|
+
spinner.succeed('Done. Parse succeeded without errors.');
|
|
23
|
+
} catch (error) {
|
|
24
|
+
let message = error.message || 'Something wrong :( Please try again.';
|
|
25
|
+
if (filepath && error.location) message = `You have syntax error in ${path.basename(filepath)} line ${error.location.start.line} column ${error.location.start.column}. ${error.message}`;
|
|
26
|
+
if (spinner.isSpinning) {
|
|
27
|
+
spinner.fail(`Failed: ${message}`);
|
|
28
|
+
} else {
|
|
29
|
+
this.error(message);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
ValidateCommand.description = 'validate docs content';
|
|
36
|
+
|
|
37
|
+
ValidateCommand.flags = {};
|
|
38
|
+
|
|
39
|
+
ValidateCommand.args = [
|
|
40
|
+
{ name: 'filepath', description: 'dbml file path' },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
module.exports = ValidateCommand;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const { getVersion, getPackageVersion, compareVersion } = require('./helper');
|
|
2
|
+
|
|
3
|
+
module.exports = async function () {
|
|
4
|
+
let shouldExit = false;
|
|
5
|
+
try {
|
|
6
|
+
const localVersion = getPackageVersion();
|
|
7
|
+
const remoteVersion = await getVersion();
|
|
8
|
+
const mustUpgrade = compareVersion(localVersion, remoteVersion.required) === -1;
|
|
9
|
+
if (mustUpgrade) {
|
|
10
|
+
shouldExit = true;
|
|
11
|
+
this.error('Your CLI version is no longer supported, please upgrade with "npm i -g dbdocs"');
|
|
12
|
+
}
|
|
13
|
+
const shouldUpgrade = compareVersion(localVersion, remoteVersion.current) === -1;
|
|
14
|
+
if (shouldUpgrade) this.warn('A new version is available, use "npm i -g dbdocs" to upgrade to the latest version');
|
|
15
|
+
} catch (err) {
|
|
16
|
+
const message = err.message || 'Something goes wrong when checking version';
|
|
17
|
+
if (shouldExit) this.error(message);
|
|
18
|
+
this.warn(message);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const { vars } = require('../../vars');
|
|
3
|
+
const pkg = require('../../../package.json');
|
|
4
|
+
|
|
5
|
+
const getVersion = async () => {
|
|
6
|
+
const res = await axios.get(`${vars.apiUrl}/version/cli`);
|
|
7
|
+
return res.data;
|
|
8
|
+
};
|
|
9
|
+
const getPackageVersion = () => {
|
|
10
|
+
const ver = pkg.version;
|
|
11
|
+
const [major, minor, patch] = ver.split('.');
|
|
12
|
+
return { major, minor, patch };
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {{major: number, minor: number, patch: number}} a: version to compare
|
|
17
|
+
* @param {{major: number, minor: number, patch: number}} b: version to compare to
|
|
18
|
+
* @returns {number}
|
|
19
|
+
* 0: a = b;
|
|
20
|
+
* 1: a > b;
|
|
21
|
+
* -1: a < b;
|
|
22
|
+
*/
|
|
23
|
+
const compareVersion = (a, b) => {
|
|
24
|
+
if (a.major > b.major) return 1;
|
|
25
|
+
if (a.major < b.major) return -1;
|
|
26
|
+
if (a.minor > b.minor) return 1;
|
|
27
|
+
if (a.minor < b.minor) return -1;
|
|
28
|
+
if (a.patch > b.patch) return 1;
|
|
29
|
+
if (a.patch < b.patch) return -1;
|
|
30
|
+
return 0;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
module.exports = {
|
|
34
|
+
getVersion,
|
|
35
|
+
getPackageVersion,
|
|
36
|
+
compareVersion,
|
|
37
|
+
};
|
package/src/utils/org.js
CHANGED
|
@@ -5,7 +5,12 @@ async function getOrg (authConfig) {
|
|
|
5
5
|
const { data: { orgs } } = await axios.get(`${vars.apiUrl}/orgs`, authConfig);
|
|
6
6
|
return orgs[0];
|
|
7
7
|
}
|
|
8
|
+
async function getProjectsByOrg (orgName, authConfig) {
|
|
9
|
+
const { data: { org: { projects } } } = await axios.get(`${vars.apiUrl}/orgs/${orgName}/projects`, authConfig);
|
|
10
|
+
return projects;
|
|
11
|
+
}
|
|
8
12
|
|
|
9
13
|
module.exports = {
|
|
10
14
|
getOrg,
|
|
15
|
+
getProjectsByOrg,
|
|
11
16
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const { Worker } = require('worker_threads');
|
|
2
|
+
|
|
3
|
+
const parse = (content) => {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const workerPath = `${__dirname}/parserWorker.js`;
|
|
6
|
+
|
|
7
|
+
const worker = new Worker(workerPath, {
|
|
8
|
+
workerData: { content },
|
|
9
|
+
});
|
|
10
|
+
worker.on('message', resolve);
|
|
11
|
+
worker.on('error', reject);
|
|
12
|
+
worker.on('exit', (code) => {
|
|
13
|
+
if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
module.exports = parse;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const { parentPort, workerData } = require("worker_threads");
|
|
2
|
+
const { Parser } = require("@dbml/core");
|
|
3
|
+
|
|
4
|
+
function parse (content) {
|
|
5
|
+
const databaseObject = Parser.parse(content, 'dbml');
|
|
6
|
+
const schemas = databaseObject.schemas.map((schema) => {
|
|
7
|
+
return {
|
|
8
|
+
name: schema.name,
|
|
9
|
+
tables: schema.tables.map((table) => table.name),
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
name: databaseObject.name,
|
|
14
|
+
schemas,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { content } = workerData;
|
|
19
|
+
const result = parse(content);
|
|
20
|
+
parentPort.postMessage(result);
|