@dungarees/bin-publish-lib-cli-yargs 0.11.4
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/feature.d.ts +6 -0
- package/feature.js +6 -0
- package/package.json +44 -0
- package/presenter.d.ts +3 -0
- package/presenter.js +14 -0
- package/presenter.test.d.ts +1 -0
- package/presenter.test.js +76 -0
- package/yargs-module.d.ts +6 -0
- package/yargs-module.js +14 -0
- package/yargs-module.test.d.ts +1 -0
- package/yargs-module.test.js +119 -0
package/feature.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PublishLibBehavior } from '@dungarees/bin-publish-lib-domain/behavior.ts';
|
|
2
|
+
import type { PublishLibEvent } from '@dungarees/bin-publish-lib-domain/events.ts';
|
|
3
|
+
import type { CliFeature } from '@dungarees/cli/feature.ts';
|
|
4
|
+
export declare const publishLibFeature: ({ publishLib, }: {
|
|
5
|
+
publishLib: PublishLibBehavior;
|
|
6
|
+
}) => CliFeature<PublishLibEvent>;
|
package/feature.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dungarees/bin-publish-lib-cli-yargs",
|
|
3
|
+
"engines": {
|
|
4
|
+
"node": ">=25.0.0"
|
|
5
|
+
},
|
|
6
|
+
"scripts": {
|
|
7
|
+
"type-check": "tsc --noEmit"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@dungarees/bin-publish-lib-domain": "*",
|
|
12
|
+
"@dungarees/cli": "*"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@dungarees/bin-fake-app-cli-yargs": "*",
|
|
16
|
+
"typescript": "^5.9.3",
|
|
17
|
+
"vitest": "^3.0.2"
|
|
18
|
+
},
|
|
19
|
+
"author": "info@productkind.com",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"version": "0.11.4",
|
|
22
|
+
"exports": {
|
|
23
|
+
"./feature.ts": {
|
|
24
|
+
"import": "./feature.js",
|
|
25
|
+
"types": "./feature.d.ts"
|
|
26
|
+
},
|
|
27
|
+
"./presenter.test.ts": {
|
|
28
|
+
"import": "./presenter.test.js",
|
|
29
|
+
"types": "./presenter.test.d.ts"
|
|
30
|
+
},
|
|
31
|
+
"./presenter.ts": {
|
|
32
|
+
"import": "./presenter.js",
|
|
33
|
+
"types": "./presenter.d.ts"
|
|
34
|
+
},
|
|
35
|
+
"./yargs-module.test.ts": {
|
|
36
|
+
"import": "./yargs-module.test.js",
|
|
37
|
+
"types": "./yargs-module.test.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./yargs-module.ts": {
|
|
40
|
+
"import": "./yargs-module.js",
|
|
41
|
+
"types": "./yargs-module.d.ts"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/presenter.d.ts
ADDED
package/presenter.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { exit, stderr, stdout } from '@dungarees/cli/utils.ts';
|
|
2
|
+
export const publishLibPresenter = {
|
|
3
|
+
'build-start': ({ srcDir, outDir, version }) => stdout(`Building package from ${srcDir} to ${outDir} with version: ${version ?? 'original version'}`),
|
|
4
|
+
'out-dir-created': ({ outDir }) => stdout(`Output directory created: ${outDir}`),
|
|
5
|
+
'package-json-written': ({ path, version }) => stdout(`Package.json written to ${path}/package.json with version: ${version}`),
|
|
6
|
+
'asset-copied': ({ path }) => stdout(`Asset copied to ${path}`),
|
|
7
|
+
'publish-succeeded': ({ packageDir, version, created }) => stdout(created
|
|
8
|
+
? `Created ${packageDir} on the registry at version ${version}`
|
|
9
|
+
: `Published ${packageDir} version ${version}`),
|
|
10
|
+
'publish-skipped': ({ packageDir, version }) => stdout(`Skipped ${packageDir}: version ${version} is already published`),
|
|
11
|
+
'publish-failed': ({ packageDir, exitCode, stderror }) => stderr(`Publish failed for ${packageDir} with exit code ${exitCode}, and error: ${stderror}`),
|
|
12
|
+
'publishes-failed': () => exit(1),
|
|
13
|
+
'all-published': () => stdout('All packages published successfully'),
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { publishLibPresenter } from './presenter.js';
|
|
2
|
+
import { expect, test } from 'vitest';
|
|
3
|
+
test('build-start maps to an info stdout message', () => {
|
|
4
|
+
expect(publishLibPresenter['build-start']({ srcDir: './src', outDir: './out', version: '1.0.0' })).toEqual({
|
|
5
|
+
type: 'stdout',
|
|
6
|
+
level: 'info',
|
|
7
|
+
message: 'Building package from ./src to ./out with version: 1.0.0',
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
test('build-start with no version says "original version"', () => {
|
|
11
|
+
expect(publishLibPresenter['build-start']({ srcDir: './src', outDir: './out', version: undefined })).toEqual({
|
|
12
|
+
type: 'stdout',
|
|
13
|
+
level: 'info',
|
|
14
|
+
message: 'Building package from ./src to ./out with version: original version',
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
test('out-dir-created maps to an info stdout message', () => {
|
|
18
|
+
expect(publishLibPresenter['out-dir-created']({ outDir: '/out' })).toEqual({
|
|
19
|
+
type: 'stdout',
|
|
20
|
+
level: 'info',
|
|
21
|
+
message: 'Output directory created: /out',
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
test('package-json-written maps to an info stdout message', () => {
|
|
25
|
+
expect(publishLibPresenter['package-json-written']({ path: '/out', version: '1.0.0' })).toEqual({
|
|
26
|
+
type: 'stdout',
|
|
27
|
+
level: 'info',
|
|
28
|
+
message: 'Package.json written to /out/package.json with version: 1.0.0',
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
test('publish-succeeded reports a new version of a known package', () => {
|
|
32
|
+
expect(publishLibPresenter['publish-succeeded']({
|
|
33
|
+
packageDir: 'lib-1',
|
|
34
|
+
version: '1.0.0',
|
|
35
|
+
created: false,
|
|
36
|
+
})).toEqual({
|
|
37
|
+
type: 'stdout',
|
|
38
|
+
level: 'info',
|
|
39
|
+
message: 'Published lib-1 version 1.0.0',
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
test('publish-succeeded says so when the package was created on the registry', () => {
|
|
43
|
+
expect(publishLibPresenter['publish-succeeded']({
|
|
44
|
+
packageDir: 'lib-1',
|
|
45
|
+
version: '1.0.0',
|
|
46
|
+
created: true,
|
|
47
|
+
})).toEqual({
|
|
48
|
+
type: 'stdout',
|
|
49
|
+
level: 'info',
|
|
50
|
+
message: 'Created lib-1 on the registry at version 1.0.0',
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
test('publish-failed names the package it failed for', () => {
|
|
54
|
+
expect(publishLibPresenter['publish-failed']({
|
|
55
|
+
packageDir: 'lib-1',
|
|
56
|
+
exitCode: 1,
|
|
57
|
+
stderror: 'Some error',
|
|
58
|
+
})).toEqual({
|
|
59
|
+
type: 'stderr',
|
|
60
|
+
level: 'error',
|
|
61
|
+
message: 'Publish failed for lib-1 with exit code 1, and error: Some error',
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
test('publishes-failed makes the run exit non-zero', () => {
|
|
65
|
+
expect(publishLibPresenter['publishes-failed']({ packageDirs: ['lib-1', 'lib-2'] })).toEqual({
|
|
66
|
+
type: 'exit',
|
|
67
|
+
code: 1,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
test('all-published maps to an info stdout message', () => {
|
|
71
|
+
expect(publishLibPresenter['all-published'](undefined)).toEqual({
|
|
72
|
+
type: 'stdout',
|
|
73
|
+
level: 'info',
|
|
74
|
+
message: 'All packages published successfully',
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PublishLibBehavior } from '@dungarees/bin-publish-lib-domain/behavior.ts';
|
|
2
|
+
import type { PublishLibEvent } from '@dungarees/bin-publish-lib-domain/events.ts';
|
|
3
|
+
import { type CommandFactory } from '@dungarees/cli/yargs-prompt-app.ts';
|
|
4
|
+
export declare const publishLibYargsModule: ({ publishLib }: {
|
|
5
|
+
publishLib: PublishLibBehavior;
|
|
6
|
+
}) => CommandFactory<PublishLibEvent>;
|
package/yargs-module.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createCommand } from '@dungarees/cli/yargs-prompt-app.ts';
|
|
2
|
+
export const publishLibYargsModule = ({ publishLib }) => (io) => createCommand({
|
|
3
|
+
command: 'publish-multi-lib [lib-path]',
|
|
4
|
+
describe: 'Publish a library',
|
|
5
|
+
builder: (yargs) => yargs
|
|
6
|
+
.positional('lib-path', {
|
|
7
|
+
type: 'string',
|
|
8
|
+
default: '.',
|
|
9
|
+
})
|
|
10
|
+
.option('registry', { type: 'string' }),
|
|
11
|
+
handler: ({ libPath, registry }) => {
|
|
12
|
+
io.registerEvents(publishLib.publishMultiLib({ dir: libPath, registry }).events$);
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { createTestApp } from '@dungarees/bin-fake-app-cli-yargs/test-app.ts';
|
|
2
|
+
import { renderCli } from '@dungarees/cli/test-renderer.ts';
|
|
3
|
+
import { expect, test } from 'vitest';
|
|
4
|
+
const srcFile1 = `
|
|
5
|
+
import { assertDefined } from '@org/lib-2/utils.ts'
|
|
6
|
+
|
|
7
|
+
export const fun1 = (input: string): string => {
|
|
8
|
+
return assertDefined(input + ' from file-1')
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
const srcFile2 = `
|
|
12
|
+
import { fun1 } from './file-1.ts';
|
|
13
|
+
|
|
14
|
+
export const fun2 = (input: string): string => {
|
|
15
|
+
return fun1(input + ' and file-2');
|
|
16
|
+
};
|
|
17
|
+
`;
|
|
18
|
+
const srcFile3 = `
|
|
19
|
+
import { fun2 } from './file-2.ts';
|
|
20
|
+
|
|
21
|
+
fun2('run')
|
|
22
|
+
`;
|
|
23
|
+
const srcFile4 = `
|
|
24
|
+
import { external } from '@external-org/external'
|
|
25
|
+
|
|
26
|
+
export const assertDefined = (input) => external(input)
|
|
27
|
+
`;
|
|
28
|
+
const REGISTRY = 'https://registry.test';
|
|
29
|
+
const PUBLISH_ARGS = ['publish', '--access', 'public'];
|
|
30
|
+
const PUBLISH_ARGS_WITH_REGISTRY = [...PUBLISH_ARGS, '--registry', REGISTRY];
|
|
31
|
+
const MULTI_LIB = {
|
|
32
|
+
'/multi-lib/config/version.json': JSON.stringify({ version: '1.0.0', type: 'module' }),
|
|
33
|
+
'/multi-lib/src/lib-1/package.json': JSON.stringify({
|
|
34
|
+
name: '@org/lib-1',
|
|
35
|
+
bin: { run: './run.ts' },
|
|
36
|
+
}),
|
|
37
|
+
'/multi-lib/src/lib-1/file-1.ts': srcFile1,
|
|
38
|
+
'/multi-lib/src/lib-1/file-2.ts': srcFile2,
|
|
39
|
+
'/multi-lib/src/lib-1/run.ts': srcFile3,
|
|
40
|
+
'/multi-lib/src/sub/lib-2/package.json': JSON.stringify({ name: '@org/lib-2', type: 'module' }),
|
|
41
|
+
'/multi-lib/src/sub/lib-2/utils.ts': srcFile4,
|
|
42
|
+
};
|
|
43
|
+
const notPublished = (name, registry) => ({
|
|
44
|
+
command: 'npm',
|
|
45
|
+
args: [
|
|
46
|
+
'view',
|
|
47
|
+
name,
|
|
48
|
+
'versions',
|
|
49
|
+
'--json',
|
|
50
|
+
...(registry === undefined ? [] : ['--registry', registry]),
|
|
51
|
+
],
|
|
52
|
+
stdout: '',
|
|
53
|
+
stderror: 'E404 Not found',
|
|
54
|
+
exitCode: 1,
|
|
55
|
+
});
|
|
56
|
+
const createDungareesApp = ({ npmPublishArgs, npmPublishExitCode = 0, npmPublishStdError, registry, }) => createTestApp({
|
|
57
|
+
files: MULTI_LIB,
|
|
58
|
+
commands: [
|
|
59
|
+
notPublished('@org/lib-1', registry),
|
|
60
|
+
notPublished('@org/lib-2', registry),
|
|
61
|
+
{
|
|
62
|
+
command: 'npm',
|
|
63
|
+
args: npmPublishArgs,
|
|
64
|
+
stdout: npmPublishExitCode === 0 ? 'Published successfully' : '',
|
|
65
|
+
...(npmPublishStdError === undefined ? {} : { stderror: npmPublishStdError }),
|
|
66
|
+
exitCode: npmPublishExitCode,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
const SUCCESS_TAIL = [
|
|
71
|
+
{ type: 'stdout', message: 'All packages published successfully', level: 'info' },
|
|
72
|
+
{ type: 'exit', code: 0 },
|
|
73
|
+
];
|
|
74
|
+
test('publish-multi-lib publishes the folder and reports success, then exits 0', async () => {
|
|
75
|
+
const { app, executedCommands } = createDungareesApp({
|
|
76
|
+
npmPublishArgs: PUBLISH_ARGS_WITH_REGISTRY,
|
|
77
|
+
registry: REGISTRY,
|
|
78
|
+
});
|
|
79
|
+
const { terminal } = renderCli(app, `dungarees publish-multi-lib /multi-lib --registry ${REGISTRY}`);
|
|
80
|
+
const output = await terminal.step();
|
|
81
|
+
expect(output.slice(-2)).toEqual(SUCCESS_TAIL);
|
|
82
|
+
expect(output).toContainEqual({
|
|
83
|
+
type: 'stdout',
|
|
84
|
+
message: 'Created lib-1 on the registry at version 1.0.0',
|
|
85
|
+
level: 'info',
|
|
86
|
+
});
|
|
87
|
+
expect(executedCommands).toContainEqual({
|
|
88
|
+
command: 'npm',
|
|
89
|
+
args: PUBLISH_ARGS_WITH_REGISTRY,
|
|
90
|
+
options: { cwd: '/multi-lib/dist/lib-1' },
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
test('publish-multi-lib omits the registry flag when none is given', async () => {
|
|
94
|
+
const { app, executedCommands } = createDungareesApp({ npmPublishArgs: PUBLISH_ARGS });
|
|
95
|
+
const { terminal } = renderCli(app, 'dungarees publish-multi-lib /multi-lib');
|
|
96
|
+
const output = await terminal.step();
|
|
97
|
+
expect(output.slice(-2)).toEqual(SUCCESS_TAIL);
|
|
98
|
+
expect(executedCommands).toContainEqual({
|
|
99
|
+
command: 'npm',
|
|
100
|
+
args: PUBLISH_ARGS,
|
|
101
|
+
options: { cwd: '/multi-lib/dist/lib-1' },
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
test('publish-multi-lib names each failed package and exits non-zero', async () => {
|
|
105
|
+
const { app } = createDungareesApp({
|
|
106
|
+
npmPublishArgs: PUBLISH_ARGS,
|
|
107
|
+
npmPublishExitCode: 1,
|
|
108
|
+
npmPublishStdError: 'You cannot publish over the previously published versions',
|
|
109
|
+
});
|
|
110
|
+
const { terminal } = renderCli(app, 'dungarees publish-multi-lib /multi-lib');
|
|
111
|
+
const output = await terminal.step();
|
|
112
|
+
expect(output.at(-1)).toEqual({ type: 'exit', code: 1 });
|
|
113
|
+
expect(output).not.toContainEqual({
|
|
114
|
+
type: 'stdout',
|
|
115
|
+
message: 'All packages published successfully',
|
|
116
|
+
level: 'info',
|
|
117
|
+
});
|
|
118
|
+
expect(output.filter((message) => message.type === 'stderr' && message.message.startsWith('Publish failed for'))).toHaveLength(2);
|
|
119
|
+
});
|