Skip to content

Commit c46e343

Browse files
Birkbjoamcgee
authored andcommitted
feat: schema differ (#43)
* feat: dhis-schema differ * fix: remove parse from entrypoint-call * fix: missed a .parse() * fix: array to object, fixing diff bug. refactor to 3 args * refactor(schema): format and output switch * perf(schema): generate html, reduce html size by 90% * chore: add utils package.json to greenkeeper * chore: update dependencies for default 🌴 (#51) * chore(package): update dependencies * chore(package): update dependencies * chore(package): update dependencies * chore(package): update dependencies * chore(package): update lockfile yarn.lock * chore: regenerate yarn.lock * feat(schema-fetch): add support for fetching schemas. refactoring * fix: missing require, remove absolute-url check * chore: merge yarn.lock * feat: add link to report meta-info * feat: add deep linking. Handle missing rev * feat: add option to sort arrays * docs(schema): wip docs and examples for schema diff * fix: add missing formatter-file * fix: support for ommiting protocol. Remove -b as flag * feat(schemadiff): support for auth through config * feat(schema-fetch): support multiple urls and baseurl * fix(schema-fetch): fix baseurl * docs(schema): fetch docs * fix(schema): fallback to prompt if no config
1 parent 200eda8 commit c46e343

14 files changed

Lines changed: 842 additions & 13 deletions

File tree

packages/cluster/src/commands/restart.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ module.exports = {
5454
builder: {
5555
port: {
5656
alias: 'p',
57-
desc: `Specify the port on which to expose the DHIS2 instance (default: ${
58-
defaults.port
59-
})`,
57+
desc: `Specify the port on which to expose the DHIS2 instance (default: ${defaults.port})`,
6058
type: 'integer',
6159
},
6260
},

packages/cluster/src/commands/up.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,7 @@ module.exports = {
9595
builder: {
9696
port: {
9797
alias: 'p',
98-
desc: `Specify the port on which to expose the DHIS2 instance (default: ${
99-
defaults.port
100-
})`,
98+
desc: `Specify the port on which to expose the DHIS2 instance (default: ${defaults.port})`,
10199
type: 'integer',
102100
},
103101
seed: {
@@ -129,9 +127,7 @@ module.exports = {
129127
type: 'string',
130128
},
131129
channel: {
132-
desc: `Set the release channel to use (default: ${
133-
defaults.channel
134-
})`,
130+
desc: `Set the release channel to use (default: ${defaults.channel})`,
135131
type: 'string',
136132
},
137133
customContext: {

packages/utils/bin/d2-utils

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@ const { makeEntryPoint, notifyOfUpdates } = require('@dhis2/cli-helpers-engine')
33

44
const pkgJson = require('../package.json')
55
const command = require(`..`)
6-
76
notifyOfUpdates(pkgJson)
87
makeEntryPoint(command)

packages/utils/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
"@semantic-release/npm": "^5.1.15",
2222
"@semantic-release/release-notes-generator": "^7.3.0",
2323
"dhis2-uid": "^0.1.2",
24+
"ejs": "^2.6.1",
25+
"inquirer": "^6.3.1",
26+
"jsondiffpatch": "^0.3.11",
2427
"semantic-release": "^15.13.24"
2528
},
2629
"publishConfig": {

packages/utils/src/cmds/schema.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const { namespace } = require('@dhis2/cli-helpers-engine')
2+
3+
const command = namespace('schema', {
4+
desc: 'Utils for schema operations',
5+
builder: yargs =>
6+
yargs
7+
.option('force', {
8+
type: 'boolean',
9+
describe:
10+
'By default each schema is cached, identified by the version and revision. Use this flag to disable caching and download the schemas.',
11+
})
12+
.option('auth', {
13+
type: 'boolean',
14+
default: false,
15+
describe: `Force prompt for credentials for each server. If false, credentials will be read from the config-file.`,
16+
})
17+
.commandDir('schema'),
18+
})
19+
20+
module.exports = command
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Schema
2+
3+
> A part of the [@dhis2/cli](https://github.com/dhis2/cli)
4+
> commandline interface.
5+
6+
Utility tools that operate on DHIS2-schemas.
7+
8+
## Diff
9+
10+
Diffs DHIS2-schemas. Can use running DHIS2 instances as input, which will download the schemas and diff these, providing a a variety of [formats](#--format). This is useful to show changes between versions / revisions. Can also use files from the [*fetch*](#fetch)-command.
11+
12+
### Usage
13+
14+
#### Examples
15+
**Note** that these examples assume that you have setup the [configuration](#configuration)-file with `baseUrl: https://play.dhis2.org`
16+
17+
Basic usage; downloads schemas from the [play](https://play.dhis2.org/)-server and outputs a format akin to `git diff` to the terminal.
18+
```bash
19+
d2 utils schema diff /2.31 /2.32dev
20+
```
21+
Output a html file with the version and revision in the filename to the current working directory. Open the file in the browser, using OSX's [open](https://ss64.com/osx/open.html). See [xdg-open](https://linux.die.net/man/1/xdg-open) for a linux equivalent.
22+
```bash
23+
d2 utils schema diff /2.31 /2.32dev --format html -o | xargs open
24+
```
25+
26+
**Note** that to use relative urls they must start with `/`. If not, the url will be assumed to be absolute and the request will fail
27+
28+
Use absolute URLs. Output html-file to home/Documents directory.
29+
```bash
30+
d2 utils schema diff https://birk.dev/master https://play.dhis2.org/dev/ --format html -o ~/Documents/
31+
```
32+
33+
### Options
34+
35+
##### --auth
36+
If true a prompt will ask for username and password for each server.
37+
Note that you can still provide authentication from `config.js`. If the flag is omitted or `--auth=false` credentials from `config.js` will be read. Note that the prompt is shown if no credentials can be resolved from the [configuration](#configuration)-file.
38+
39+
##### --output, -o
40+
Specify the location of the output. If used as a flag (no arguments) a
41+
file relative to current working directory is generated with the name
42+
"LEFT-version_revision__RIGHT-version_revision.html".
43+
If the location is a directory, the default filename is
44+
used and output to location.
45+
The output of the program changes to this path-location, so it can be combined with pipe. Eg
46+
`d2 utils schema diff /2.31 /2.32 --format html -o | xargs open`
47+
will pass the path to `xargs open`, and open the html-diff in your browser.
48+
49+
##### --format
50+
Specify the format of the output. Can be one of `["html", "json", "console"]`.
51+
52+
JSON is the raw output of [jsondiffpatch](https://github.com/benjamine/jsondiffpatch/blob/master/docs/arrays.md), see the [delta format](https://github.com/benjamine/jsondiffpatch/blob/master/docs/deltas.md) for information about this format.
53+
54+
Default: console.
55+
56+
##### --base-url, -b
57+
Base-Url to use for downloading schemas. If this is set leftServer and rightServer should be relative to this url, eg. /dev. Note the leading slash for the relative urls.
58+
59+
##### --ignore-array-order
60+
The server returns non-deterministic ordering of arrays. Enabling this will prevent most internal array moves, which are probably irrelevant anyway.
61+
62+
### Configuration
63+
64+
Many of the above options may be provided through the `d2` configuration file, which by default is located at `~/.config/d2/config.js`. This is especially useful for credentials. The file is namespaced by command, an example of such a file:
65+
```
66+
module.exports = {
67+
utils: {
68+
schema: {
69+
username: 'admin',
70+
password: 'district',
71+
baseUrl: 'https://play.dhis2.org',
72+
rightServer: {
73+
username: 'system',
74+
password: 'System123',
75+
},
76+
}
77+
},
78+
}
79+
```
80+
81+
Authorization is handled in the following way:
82+
- Per-server configuration (e.g. leftServer) is read first, if either password or username are non-existant or blank, the `schema`-level are used.
83+
- If `schema`-level configuration is blank, an interactive prompt for username and password will be shown.
84+
85+
In the example configuration file above, `leftServer` will use schema-level credentials (admin, district), while `rightServer` will use `john, district`,
86+
87+
## Fetch
88+
89+
Fetches schemas from a _running_ DHIS2 instance. The schemas are compatible with the *diff*-command.
90+
91+
92+
### Usage
93+
94+
```
95+
d2-utils schema fetch <urls...> [opts]
96+
```
97+
98+
Fetch supports multiple urls at the same time. These can be a combination of relative and absolute urls if baseUrl is set. Note that `--output` will in this case always resolve to the directory part of the output-path.
99+
100+
#### Examples
101+
102+
Downloads schemas relative to working directory with auto-generated name.
103+
```
104+
d2 utils schema fetch https://play.dhis2.org/dev -o
105+
```
106+
107+
Combination of relative and absolute urls. Note that the protocol is not needed. `https` is prepended if the urls does *not* start with `/`. This is the reason why it's important to start relative urls with `/`.
108+
109+
```
110+
d2 utils schema fetch https://play.dhis2.org/dev birk.dev/master /2.32 --base-url play.dhis2.org -o
111+
```
112+
113+
##### With Diff command
114+
115+
It's possible to use a one-liner to download the schemas and pipe this file location to the [diff](#diff)-command. The following example will download the schemas to the current working directory, while downloading `2.31` schemas and diffing these. Output is an html file in the current directory.
116+
```
117+
d2 utils schema fetch https://play.dhis2.org/dev -o | xargs d2 utils schema diff /2.31 -o --format html
118+
```
119+
120+
121+
### Configuration
122+
123+
Configuration is mostly identical to the Diff command. However, options are only read from the `schema`-object. This is mostly useful for credentials and `base-url`.
124+
125+
126+
### Options
127+
128+
##### --auth
129+
See [auth](#--auth)
130+
131+
##### --output, -o
132+
See [output](#--output). In addition, if multiple urls are given, the path will be resolved to the [directory-path](https://nodejs.org/api/path.html#path_path_dirname_path).
133+
134+
##### --base-url, -b
135+
Base-Url to use for downloading schemas. If this is set, urls that are relative (starts with `/`) will be appended to this url. eg. /dev. Note the leading slash for the relative urls.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const { builder, handler } = require('./diff/index.js')
2+
3+
module.exports = {
4+
command: 'diff <leftUrl> <rightUrl>',
5+
desc: 'Generate a diff of schemas between DHIS2 versions',
6+
builder,
7+
handler,
8+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<!DOCTYPE html>
2+
<meta charset="UTF-8">
3+
<html>
4+
<head>
5+
<link rel="stylesheet" href="data:text/css;base64,<%= jsondiffpatchCSS %>">
6+
7+
<style>
8+
th {
9+
text-align: left
10+
}
11+
.left {
12+
background-color: #fbb
13+
}
14+
.right {
15+
background-color: #bfb
16+
}
17+
.jsondiffpatch-property-name a {
18+
color: inherit;
19+
text-decoration: none;
20+
}
21+
</style>
22+
<%
23+
const metaPropsToShow = ['contextPath', 'version', 'revision', 'buildTime']
24+
const commitBaseUrl = 'https://github.com/dhis2/dhis2-core/commit/'
25+
const linkWrap = (url, label) => `<a href="${url}">${label}</a>`
26+
const format = (key, val) => {
27+
if(key === 'contextPath') {
28+
return linkWrap(val, val)
29+
} else if(key === 'revision') {
30+
return val === 'REV-NA' ? 'N/A' : linkWrap(commitBaseUrl.concat(val), val)
31+
}
32+
return val;
33+
}
34+
%>
35+
</head>
36+
<body>
37+
<div>
38+
<div id="info">
39+
<div>
40+
<table style="width:100%">
41+
<tr>
42+
<th></th>
43+
<th class='left'>Left</th>
44+
<th class='right'>Right</th>
45+
</tr>
46+
<% metaPropsToShow.forEach(key => { %>
47+
<tr>
48+
<td><%= key %></td>
49+
<td><%- format(key, meta.left[key]) %></td>
50+
<td><%- format(key, meta.right[key]) %></td>
51+
</tr>
52+
<% }) %>
53+
</table>
54+
</div>
55+
</div>
56+
<div id="visual">
57+
<%- formatted %>
58+
</div>
59+
</div>
60+
</body>
61+
</html>

0 commit comments

Comments
 (0)