@versatiles/release-tool 1.0.3 → 1.2.0
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 +48 -0
- package/dist/{lib → commands}/command.js +4 -2
- package/dist/{lib → commands}/markdown.js +3 -10
- package/dist/commands/release.d.ts +2 -0
- package/dist/commands/release.js +124 -0
- package/dist/{lib → commands}/typedoc.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +14 -5
- package/dist/lib/git.d.ts +14 -0
- package/dist/lib/git.js +47 -0
- package/dist/lib/log.d.ts +5 -0
- package/dist/lib/log.js +28 -0
- package/dist/lib/shell.d.ts +12 -0
- package/dist/lib/shell.js +42 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +31 -2
- package/package.json +19 -7
- /package/dist/{lib → commands}/command.d.ts +0 -0
- /package/dist/{lib → commands}/markdown.d.ts +0 -0
- /package/dist/{lib → commands}/typedoc.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
[](https://codecov.io/gh/versatiles-org/node-release-tool)
|
|
2
|
+
[](https://github.com/versatiles-org/node-release-tool/actions/workflows/ci.yml)
|
|
3
|
+
|
|
1
4
|
# VersaTiles Release Tools
|
|
2
5
|
|
|
3
6
|
Tools used internally for:
|
|
@@ -6,6 +9,35 @@ Tools used internally for:
|
|
|
6
9
|
* creating Markdown documentation of executables: [`vrt cmd2md`](#subcommand-vrt-cmd2md)
|
|
7
10
|
* inserting Markdown into documents: [`vrt insertmd`](#subcommand-vrt-insertmd)
|
|
8
11
|
* updating "Table of Content" in Markdown files: [`vrt inserttoc`](#subcommand-vrt-inserttoc)
|
|
12
|
+
* releasing the current version as npm package: [`vrt release-npm`](#subcommand-vrt-release-npm)
|
|
13
|
+
|
|
14
|
+
# Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm i -D @versatiles/release-tool
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
# configure scripts
|
|
21
|
+
|
|
22
|
+
You need to configure the scripts in the package.json:
|
|
23
|
+
|
|
24
|
+
```JSON
|
|
25
|
+
{
|
|
26
|
+
"scripts": {
|
|
27
|
+
"check": "npm run lint && npm run build && npm run test",
|
|
28
|
+
"prepack": "npm run build && npm run doc",
|
|
29
|
+
"release": "vrt release-npm",
|
|
30
|
+
...
|
|
31
|
+
},
|
|
32
|
+
...
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
* `scripts.check` is **required** by the release command. Here you can lint, build and test your code.
|
|
37
|
+
* `scripts.prepack` is **recommended** to ensure that all files are up-to-date before releasing. Here you can build code and documentation.
|
|
38
|
+
* `scripts.release` is **recommended** to make it easy to release a new version.
|
|
39
|
+
|
|
40
|
+
Have a look at this [package.json](https://github.com/versatiles-org/node-release-tool/blob/main/package.json) as an example.
|
|
9
41
|
|
|
10
42
|
# Command `vrt`
|
|
11
43
|
|
|
@@ -25,6 +57,7 @@ Commands:
|
|
|
25
57
|
cmd2md <command> documents a runnable command and outputs it to stdout
|
|
26
58
|
insertmd <readme> [heading] [foldable] takes Markdown from stdin and insert it into a Markdown file
|
|
27
59
|
inserttoc <readme> [heading] updates the TOC in a Markdown file
|
|
60
|
+
release-npm [path] release a npm package
|
|
28
61
|
help [command] display help for command
|
|
29
62
|
```
|
|
30
63
|
|
|
@@ -91,3 +124,18 @@ Arguments:
|
|
|
91
124
|
Options:
|
|
92
125
|
-h, --help display help for command
|
|
93
126
|
```
|
|
127
|
+
|
|
128
|
+
## Subcommand: `vrt release-npm`
|
|
129
|
+
|
|
130
|
+
```console
|
|
131
|
+
$ vrt release-npm
|
|
132
|
+
Usage: vrt release-npm [options] [path]
|
|
133
|
+
|
|
134
|
+
release a npm package
|
|
135
|
+
|
|
136
|
+
Arguments:
|
|
137
|
+
path root path of the Node.js project
|
|
138
|
+
|
|
139
|
+
Options:
|
|
140
|
+
-h, --help display help for command
|
|
141
|
+
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import cp from 'child_process';
|
|
2
|
-
import { getErrorMessage } from '
|
|
2
|
+
import { getErrorMessage } from '../lib/utils.js';
|
|
3
3
|
/**
|
|
4
4
|
* Generates documentation for a CLI command and its subcommands.
|
|
5
5
|
* @param command The base CLI command to document.
|
|
@@ -31,8 +31,10 @@ export async function generateCommandDocumentation(command) {
|
|
|
31
31
|
*/
|
|
32
32
|
async function getCommandResults(command) {
|
|
33
33
|
return new Promise((resolve, reject) => {
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
35
|
+
const env = { ...process.env, NODE_ENV: undefined };
|
|
34
36
|
// Spawn a child process to run the command with the '--help' flag.
|
|
35
|
-
const childProcess = cp.spawn('npx', [...command.split(' '), '--help']);
|
|
37
|
+
const childProcess = cp.spawn('npx', [...command.split(' '), '--help'], { env });
|
|
36
38
|
let output = '';
|
|
37
39
|
// Collect output data from the process.
|
|
38
40
|
childProcess.stdout.on('data', data => output += String(data));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { remark } from 'remark';
|
|
2
2
|
import remarkGfm from 'remark-gfm';
|
|
3
|
-
import { getErrorMessage } from '
|
|
3
|
+
import { getErrorMessage } from '../lib/utils.js';
|
|
4
4
|
/**
|
|
5
5
|
* Injects a Markdown segment under a specified heading in a Markdown document.
|
|
6
6
|
* Optionally, the injected segment can be made foldable for better readability.
|
|
@@ -24,8 +24,7 @@ export function injectMarkdown(document, segment, heading, foldable) {
|
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
26
|
// Handle errors during the search for the start index.
|
|
27
|
-
|
|
28
|
-
throw error;
|
|
27
|
+
throw new Error(`Error while searching for segment "${heading}": ${getErrorMessage(error)}`);
|
|
29
28
|
}
|
|
30
29
|
// Get the depth of the specified heading to maintain the structure.
|
|
31
30
|
const depth = getHeadingDepth(documentAst, startIndex);
|
|
@@ -110,7 +109,7 @@ function findNextHeadingIndex(mainAst, startIndex, depth) {
|
|
|
110
109
|
for (let i = startIndex; i < mainAst.children.length; i++) {
|
|
111
110
|
const child = mainAst.children[i];
|
|
112
111
|
// Return the index of the next heading at the same depth.
|
|
113
|
-
if (child.type === 'heading' && child.depth
|
|
112
|
+
if (child.type === 'heading' && child.depth <= depth)
|
|
114
113
|
return i;
|
|
115
114
|
}
|
|
116
115
|
return mainAst.children.length;
|
|
@@ -269,10 +268,6 @@ export function nodeToHtml(node) {
|
|
|
269
268
|
return `<strong>${nodesToHtml(node.children)}</strong>`;
|
|
270
269
|
case 'link':
|
|
271
270
|
return `<a href="${node.url}"${node.title == null ? '' : ` title="${node.title}"`}>${nodesToHtml(node.children)}</a>`;
|
|
272
|
-
case 'linkReference':
|
|
273
|
-
throw new Error('"linkReference to html" not implemented');
|
|
274
|
-
case 'footnoteReference':
|
|
275
|
-
throw new Error('"footnoteReference to html" not implemented');
|
|
276
271
|
case 'image':
|
|
277
272
|
const attributes = [`src="${node.url}"`];
|
|
278
273
|
if (node.alt ?? '')
|
|
@@ -280,8 +275,6 @@ export function nodeToHtml(node) {
|
|
|
280
275
|
if (node.title ?? '')
|
|
281
276
|
attributes.push(`title="${node.title}"`);
|
|
282
277
|
return `<img ${attributes.join(' ')} />`;
|
|
283
|
-
case 'imageReference':
|
|
284
|
-
throw new Error('"imageReference to html" not implemented');
|
|
285
278
|
default:
|
|
286
279
|
console.log(node);
|
|
287
280
|
throw Error('unknown type');
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { check, info, panic, warn } from '../lib/log.js';
|
|
5
|
+
import { getShell } from '../lib/shell.js';
|
|
6
|
+
import { getGit } from '../lib/git.js';
|
|
7
|
+
import { resolve } from 'node:path';
|
|
8
|
+
export async function release(directory, branch = 'main') {
|
|
9
|
+
const shell = getShell(directory);
|
|
10
|
+
const { getCommitsBetween, getCurrentGitHubCommit, getLastGitHubTag } = getGit(directory);
|
|
11
|
+
info('starting release process');
|
|
12
|
+
// git: check if in the correct branch
|
|
13
|
+
const currentBranch = await check('get branch name', shell.stdout('git rev-parse --abbrev-ref HEAD'));
|
|
14
|
+
if (currentBranch !== branch)
|
|
15
|
+
panic(`current branch is "${currentBranch}" but should be "${branch}"`);
|
|
16
|
+
// git: check if no changes
|
|
17
|
+
await check('are all changes committed?', checkThatNoUncommittedChanges());
|
|
18
|
+
// git: pull
|
|
19
|
+
await check('git pull', shell.run('git pull -t'));
|
|
20
|
+
// check package.json
|
|
21
|
+
const pkg = JSON.parse(readFileSync(resolve(directory, 'package.json'), 'utf8'));
|
|
22
|
+
if (typeof pkg !== 'object' || pkg === null)
|
|
23
|
+
panic('package.json is not valid');
|
|
24
|
+
if (!('version' in pkg) || (typeof pkg.version !== 'string'))
|
|
25
|
+
panic('package.json is missing "version"');
|
|
26
|
+
if (!('scripts' in pkg) || (typeof pkg.scripts !== 'object') || (pkg.scripts == null))
|
|
27
|
+
panic('package.json is missing "scripts"');
|
|
28
|
+
if (!('check' in pkg.scripts))
|
|
29
|
+
panic('missing npm script "check" in package.json');
|
|
30
|
+
// get last version
|
|
31
|
+
const tag = await check('get last github tag', getLastGitHubTag());
|
|
32
|
+
const shaLast = tag?.sha;
|
|
33
|
+
const versionLastGithub = tag?.version;
|
|
34
|
+
const versionLastPackage = String(pkg.version);
|
|
35
|
+
if (versionLastPackage !== versionLastGithub)
|
|
36
|
+
warn(`versions differ in package.json (${versionLastPackage}) and last GitHub tag (${versionLastGithub})`);
|
|
37
|
+
// get current sha
|
|
38
|
+
const { sha: shaCurrent } = await check('get current github commit', getCurrentGitHubCommit());
|
|
39
|
+
// handle version
|
|
40
|
+
const nextVersion = await editVersion(versionLastPackage);
|
|
41
|
+
// prepare release notes
|
|
42
|
+
const releaseNotes = await check('prepare release notes', getReleaseNotes(nextVersion, shaLast, shaCurrent));
|
|
43
|
+
// update version
|
|
44
|
+
await check('update version', setNextVersion(nextVersion));
|
|
45
|
+
// test
|
|
46
|
+
await check('run checks', shell.run('npm run check'));
|
|
47
|
+
// npm publish
|
|
48
|
+
await check('npm publish', shell.run('npm publish --access public'));
|
|
49
|
+
// git push
|
|
50
|
+
await check('git add', shell.run('git add .'));
|
|
51
|
+
await check('git commit', shell.run(`git commit -m "v${nextVersion}"`, false));
|
|
52
|
+
await check('git tag', shell.run(`git tag -f -a "v${nextVersion}" -m "new release: v${nextVersion}"`));
|
|
53
|
+
await check('git push', shell.run('git push --no-verify --follow-tags'));
|
|
54
|
+
// github release
|
|
55
|
+
const releaseNotesPipe = `echo -e '${releaseNotes.replace(/[^a-z0-9,.?!:_<> -]/gi, c => '\\x' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))}'`;
|
|
56
|
+
if (await check('check github release', shell.ok('gh release view v' + nextVersion))) {
|
|
57
|
+
await check('edit release', shell.run(`${releaseNotesPipe} | gh release edit "v${nextVersion}" -F -`));
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
await check('create release', shell.run(`${releaseNotesPipe} | gh release create "v${nextVersion}" --draft --prerelease -F -`));
|
|
61
|
+
}
|
|
62
|
+
info('Finished');
|
|
63
|
+
return;
|
|
64
|
+
async function checkThatNoUncommittedChanges() {
|
|
65
|
+
if ((await shell.stdout('git status --porcelain')).length < 3)
|
|
66
|
+
return;
|
|
67
|
+
throw Error('please commit all changes before releasing');
|
|
68
|
+
}
|
|
69
|
+
async function setNextVersion(version) {
|
|
70
|
+
// set new version in package.json
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
72
|
+
const packageJSON = JSON.parse(readFileSync(resolve(directory, 'package.json'), 'utf8'));
|
|
73
|
+
packageJSON.version = version;
|
|
74
|
+
writeFileSync(resolve(directory, 'package.json'), JSON.stringify(packageJSON, null, ' ') + '\n');
|
|
75
|
+
// rebuild package.json
|
|
76
|
+
await shell.run('npm i --package-lock-only');
|
|
77
|
+
}
|
|
78
|
+
async function getReleaseNotes(version, hashLast, hashCurrent) {
|
|
79
|
+
const commits = await getCommitsBetween(hashLast, hashCurrent);
|
|
80
|
+
let notes = commits.reverse()
|
|
81
|
+
.map(commit => '- ' + commit.message.replace(/\s+/g, ' '))
|
|
82
|
+
.join('\n');
|
|
83
|
+
notes = `# Release v${version}\n\nchanges: \n${notes}\n\n`;
|
|
84
|
+
return notes;
|
|
85
|
+
}
|
|
86
|
+
async function editVersion(versionPackage) {
|
|
87
|
+
// ask for new version
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
89
|
+
const versionNew = (await inquirer.prompt({
|
|
90
|
+
message: 'What should be the new version?',
|
|
91
|
+
name: 'versionNew',
|
|
92
|
+
type: 'list',
|
|
93
|
+
choices: [versionPackage, bump(2), bump(1), bump(0)],
|
|
94
|
+
default: 1,
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
96
|
+
})).versionNew;
|
|
97
|
+
if (!versionNew)
|
|
98
|
+
throw Error();
|
|
99
|
+
return versionNew;
|
|
100
|
+
function bump(index) {
|
|
101
|
+
const p = versionPackage.split('.').map(v => parseInt(v, 10));
|
|
102
|
+
if (p.length !== 3)
|
|
103
|
+
throw Error();
|
|
104
|
+
switch (index) {
|
|
105
|
+
case 0:
|
|
106
|
+
p[0]++;
|
|
107
|
+
p[1] = 0;
|
|
108
|
+
p[2] = 0;
|
|
109
|
+
break;
|
|
110
|
+
case 1:
|
|
111
|
+
p[1]++;
|
|
112
|
+
p[2] = 0;
|
|
113
|
+
break;
|
|
114
|
+
case 2:
|
|
115
|
+
p[2]++;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
const name = p.map((n, i) => (i == index) ? `\x1b[1m${n}` : `${n}`).join('.') + '\x1b[22m';
|
|
119
|
+
const value = p.join('.');
|
|
120
|
+
return { name, value };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=release.js.map
|
|
@@ -206,10 +206,10 @@ function formatTypeDeclaration(someType) {
|
|
|
206
206
|
if (some.reflection)
|
|
207
207
|
result = `[${result}](#${createAnchorId(some.reflection)})`;
|
|
208
208
|
if (some.typeArguments?.length ?? 0)
|
|
209
|
-
result += '
|
|
209
|
+
result += '<'
|
|
210
210
|
+ (some.typeArguments ?? [])
|
|
211
211
|
.map(getTypeRec).join(',')
|
|
212
|
-
+ '
|
|
212
|
+
+ '>';
|
|
213
213
|
return result;
|
|
214
214
|
case 'reflection':
|
|
215
215
|
switch (some.declaration.kind) {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --enable-source-maps
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
-
import { generateTsMarkdownDoc } from './
|
|
5
|
-
import { injectMarkdown, updateTOC } from './
|
|
4
|
+
import { generateTsMarkdownDoc } from './commands/typedoc.js';
|
|
5
|
+
import { injectMarkdown, updateTOC } from './commands/markdown.js';
|
|
6
6
|
import { Command, InvalidArgumentError } from 'commander';
|
|
7
7
|
import { cwd } from 'node:process';
|
|
8
|
-
import { generateCommandDocumentation } from './
|
|
9
|
-
|
|
8
|
+
import { generateCommandDocumentation } from './commands/command.js';
|
|
9
|
+
import { release } from './commands/release.js';
|
|
10
|
+
export const program = new Command();
|
|
10
11
|
program
|
|
11
12
|
.name('vrt')
|
|
12
13
|
.description('versatiles release and documentaion tool');
|
|
@@ -48,7 +49,15 @@ program.command('inserttoc')
|
|
|
48
49
|
mdFile = updateTOC(mdFile, heading);
|
|
49
50
|
writeFileSync(mdFilename, mdFile);
|
|
50
51
|
});
|
|
51
|
-
program.
|
|
52
|
+
program.command('release-npm')
|
|
53
|
+
.description('release a npm package')
|
|
54
|
+
.argument('[path]', 'root path of the Node.js project')
|
|
55
|
+
.action((path) => {
|
|
56
|
+
void release(resolve(path ?? ',', process.cwd()), 'main');
|
|
57
|
+
});
|
|
58
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
59
|
+
await program.parseAsync();
|
|
60
|
+
}
|
|
52
61
|
function checkFilename(filename) {
|
|
53
62
|
const fullname = resolve(cwd(), filename);
|
|
54
63
|
if (!existsSync(fullname)) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Commit {
|
|
2
|
+
sha: string;
|
|
3
|
+
message: string;
|
|
4
|
+
tag?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface Git {
|
|
7
|
+
getLastGitHubTag: () => Promise<{
|
|
8
|
+
sha: string;
|
|
9
|
+
version: string;
|
|
10
|
+
} | undefined>;
|
|
11
|
+
getCurrentGitHubCommit: () => Promise<Commit>;
|
|
12
|
+
getCommitsBetween: (shaLast?: string, shaCurrent?: string) => Promise<Commit[]>;
|
|
13
|
+
}
|
|
14
|
+
export declare function getGit(cwd: string): Git;
|
package/dist/lib/git.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getShell } from './shell.js';
|
|
2
|
+
export function getGit(cwd) {
|
|
3
|
+
const shell = getShell(cwd);
|
|
4
|
+
return {
|
|
5
|
+
getLastGitHubTag,
|
|
6
|
+
getCurrentGitHubCommit,
|
|
7
|
+
getCommitsBetween,
|
|
8
|
+
};
|
|
9
|
+
async function getLastGitHubTag() {
|
|
10
|
+
const commits = await getAllCommits();
|
|
11
|
+
const result = commits
|
|
12
|
+
.map(commit => ({
|
|
13
|
+
sha: commit.sha,
|
|
14
|
+
version: commit.tag?.match(/^v(\d+\.\d+\.\d+)$/)?.[1],
|
|
15
|
+
}))
|
|
16
|
+
.find(r => r.version);
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
async function getAllCommits() {
|
|
20
|
+
const result = await shell.stdout('git log --pretty=format:\'⍃%H⍄%s⍄%D⍄\'');
|
|
21
|
+
return result
|
|
22
|
+
.split('⍃')
|
|
23
|
+
.filter(line => line.length > 2)
|
|
24
|
+
.map(line => {
|
|
25
|
+
const obj = line.split('⍄');
|
|
26
|
+
return {
|
|
27
|
+
sha: obj[0],
|
|
28
|
+
message: obj[1],
|
|
29
|
+
tag: /tag: ([a-z0-9.]+)/.exec(obj[2])?.[1],
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async function getCurrentGitHubCommit() {
|
|
34
|
+
return (await getAllCommits())[0];
|
|
35
|
+
}
|
|
36
|
+
async function getCommitsBetween(shaLast, shaCurrent) {
|
|
37
|
+
let commits = await getAllCommits();
|
|
38
|
+
const start = commits.findIndex(commit => commit.sha === shaCurrent);
|
|
39
|
+
if (start >= 0)
|
|
40
|
+
commits = commits.slice(start);
|
|
41
|
+
const end = commits.findIndex(commit => commit.sha === shaLast);
|
|
42
|
+
if (end >= 0)
|
|
43
|
+
commits = commits.slice(0, end);
|
|
44
|
+
return commits;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function panic(text: string): never;
|
|
2
|
+
export declare function warn(text: string): void;
|
|
3
|
+
export declare function info(text: string): void;
|
|
4
|
+
export declare function abort(): never;
|
|
5
|
+
export declare function check<T>(message: string, promise: Promise<T>): Promise<T>;
|
package/dist/lib/log.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function panic(text) {
|
|
2
|
+
process.stderr.write(`\x1b[1;31m! ERROR: ${text}\x1b[0m\n`);
|
|
3
|
+
abort();
|
|
4
|
+
}
|
|
5
|
+
export function warn(text) {
|
|
6
|
+
process.stderr.write(`\x1b[1;33m! warning: ${text}\x1b[0m\n`);
|
|
7
|
+
}
|
|
8
|
+
export function info(text) {
|
|
9
|
+
process.stderr.write(`\x1b[0mi ${text}\n`);
|
|
10
|
+
}
|
|
11
|
+
export function abort() {
|
|
12
|
+
info('abort');
|
|
13
|
+
process.exit();
|
|
14
|
+
}
|
|
15
|
+
export async function check(message, promise) {
|
|
16
|
+
process.stderr.write(`\x1b[0;90m\u2B95 ${message}\x1b[0m`);
|
|
17
|
+
try {
|
|
18
|
+
const result = await promise;
|
|
19
|
+
process.stderr.write(`\r\x1b[0;92m\u2714 ${message}\x1b[0m\n`);
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
process.stderr.write(`\r\x1b[0;91m\u2718 ${message}\x1b[0m\n`);
|
|
24
|
+
panic(error.message);
|
|
25
|
+
throw Error();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface Shell {
|
|
2
|
+
run: (command: string, errorOnCodeNonZero?: boolean) => Promise<{
|
|
3
|
+
code: number | null;
|
|
4
|
+
signal: string | null;
|
|
5
|
+
stdout: string;
|
|
6
|
+
stderr: string;
|
|
7
|
+
}>;
|
|
8
|
+
stderr: (command: string, errorOnCodeZero?: boolean) => Promise<string>;
|
|
9
|
+
stdout: (command: string, errorOnCodeZero?: boolean) => Promise<string>;
|
|
10
|
+
ok: (command: string) => Promise<boolean>;
|
|
11
|
+
}
|
|
12
|
+
export declare function getShell(cwd: string): Shell;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
export function getShell(cwd) {
|
|
3
|
+
async function run(command, errorOnCodeNonZero) {
|
|
4
|
+
try {
|
|
5
|
+
return await new Promise((resolve, reject) => {
|
|
6
|
+
const stdout = [];
|
|
7
|
+
const stderr = [];
|
|
8
|
+
const cp = spawn('bash', ['-c', command], { cwd })
|
|
9
|
+
.on('error', error => {
|
|
10
|
+
reject(error);
|
|
11
|
+
})
|
|
12
|
+
.on('close', (code, signal) => {
|
|
13
|
+
const result = {
|
|
14
|
+
code,
|
|
15
|
+
signal,
|
|
16
|
+
stdout: Buffer.concat(stdout).toString(),
|
|
17
|
+
stderr: Buffer.concat(stderr).toString(),
|
|
18
|
+
};
|
|
19
|
+
if ((errorOnCodeNonZero ?? true) && (code !== 0)) {
|
|
20
|
+
reject(result);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
resolve(result);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
cp.stdout.on('data', (chunk) => stdout.push(chunk));
|
|
27
|
+
cp.stderr.on('data', (chunk) => stderr.push(chunk));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error(error);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
run,
|
|
37
|
+
stderr: async (command, errorOnCodeZero) => (await run(command, errorOnCodeZero)).stderr.trim(),
|
|
38
|
+
stdout: async (command, errorOnCodeZero) => (await run(command, errorOnCodeZero)).stdout.trim(),
|
|
39
|
+
ok: async (command) => (await run(command, false)).code === 0,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=shell.js.map
|
package/dist/lib/utils.d.ts
CHANGED
package/dist/lib/utils.js
CHANGED
|
@@ -2,9 +2,38 @@ export function getErrorMessage(error) {
|
|
|
2
2
|
if (error == null)
|
|
3
3
|
return 'unknown';
|
|
4
4
|
if (typeof error === 'object') {
|
|
5
|
-
if ('message' in error)
|
|
6
|
-
|
|
5
|
+
if ('message' in error) {
|
|
6
|
+
if (typeof error.message === 'string')
|
|
7
|
+
return error.message;
|
|
8
|
+
return JSON.stringify(error.message);
|
|
9
|
+
}
|
|
7
10
|
}
|
|
8
11
|
return 'unknown';
|
|
9
12
|
}
|
|
13
|
+
export function prettyStyleJSON(inputData) {
|
|
14
|
+
return recursive(inputData);
|
|
15
|
+
function recursive(data, prefix = '', path = '') {
|
|
16
|
+
if (path.endsWith('.bounds'))
|
|
17
|
+
return singleLine(data);
|
|
18
|
+
//if (path.includes('.vector_layers[].')) return singleLine(data);
|
|
19
|
+
if (path.startsWith('.layers[].filter'))
|
|
20
|
+
return singleLine(data);
|
|
21
|
+
if (path.startsWith('.layers[].paint.'))
|
|
22
|
+
return singleLine(data);
|
|
23
|
+
if (path.startsWith('.layers[].layout.'))
|
|
24
|
+
return singleLine(data);
|
|
25
|
+
if (typeof data === 'object') {
|
|
26
|
+
if (Array.isArray(data)) {
|
|
27
|
+
return '[\n\t' + prefix + data.map((value) => recursive(value, prefix + '\t', path + '[]')).join(',\n\t' + prefix) + '\n' + prefix + ']';
|
|
28
|
+
}
|
|
29
|
+
if (data) {
|
|
30
|
+
return '{\n\t' + prefix + Object.entries(data).map(([key, value]) => '"' + key + '": ' + recursive(value, prefix + '\t', path + '.' + key)).join(',\n\t' + prefix) + '\n' + prefix + '}';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return singleLine(data);
|
|
34
|
+
}
|
|
35
|
+
function singleLine(data) {
|
|
36
|
+
return JSON.stringify(data, null, '\t').replace(/[\t\n]+/g, ' ');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
10
39
|
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versatiles/release-tool",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "VersaTiles release and documentation tools",
|
|
5
5
|
"bin": {
|
|
6
6
|
"vrt": "./dist/index.js"
|
|
@@ -11,11 +11,14 @@
|
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/index.js",
|
|
14
|
-
"check": "npm run lint && npm run
|
|
14
|
+
"check": "npm run lint && npm run build && npm run test",
|
|
15
15
|
"doc": "npx vrt cmd2md vrt | npx vrt insertmd README.md '# Command'",
|
|
16
16
|
"lint": "eslint . --color",
|
|
17
17
|
"prepack": "npm run build && npm run doc",
|
|
18
|
-
"
|
|
18
|
+
"release": "npx vrt release-npm",
|
|
19
|
+
"test-coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
20
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
21
|
+
"upgrade": "npm-check-updates -u && rm -f package-lock.json; rm -rf node_modules; npm i && npm update"
|
|
19
22
|
},
|
|
20
23
|
"author": "yetzt <node@yetzt.me>, Michael Kreil <versatiles@michael-kreil.de>",
|
|
21
24
|
"license": "Unlicense",
|
|
@@ -26,14 +29,23 @@
|
|
|
26
29
|
},
|
|
27
30
|
"homepage": "https://github.com/versatiles-org/node-versatiles/blob/main/versatiles-release-tool/README.md",
|
|
28
31
|
"devDependencies": {
|
|
29
|
-
"@types/
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
+
"@types/inquirer": "^9.0.7",
|
|
33
|
+
"@types/jest": "^29.5.11",
|
|
34
|
+
"@types/node": "^20.11.15",
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
|
36
|
+
"@typescript-eslint/parser": "^6.20.0",
|
|
37
|
+
"eslint": "^8.56.0",
|
|
38
|
+
"jest": "^29.7.0",
|
|
39
|
+
"ts-jest": "^29.1.2",
|
|
40
|
+
"ts-node": "^10.9.2",
|
|
41
|
+
"tsx": "^4.7.0",
|
|
42
|
+
"typescript": "^5.3.3"
|
|
32
43
|
},
|
|
33
44
|
"dependencies": {
|
|
34
45
|
"commander": "^11.1.0",
|
|
46
|
+
"inquirer": "^9.2.13",
|
|
35
47
|
"remark": "^15.0.1",
|
|
36
48
|
"remark-gfm": "^4.0.0",
|
|
37
|
-
"typedoc": "^0.25.
|
|
49
|
+
"typedoc": "^0.25.7"
|
|
38
50
|
}
|
|
39
51
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|