Skip to content

Commit 26e0370

Browse files
authored
Merge pull request #3 from getoslash/gp/cliffy-migration
2 parents 87e8019 + 076bb57 commit 26e0370

File tree

8 files changed

+257
-173
lines changed

8 files changed

+257
-173
lines changed

.vscode/settings.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
"deno.unstable": false,
55
"deno.suggest.autoImports": true,
66
"deno.suggest.imports.hosts": {
7-
"https://deno.land/": true,
8-
"https://unpkg.com/": true
7+
"https://deno.land/": true
98
},
109
"editor.defaultFormatter": "denoland.vscode-deno",
1110
"[typescript]": {

README.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!-- deno-fmt-ignore-file -->
22
# Chrome Web Store CLI
33

4-
[![deno version](https://img.shields.io/badge/deno-^1.15.2-lightgrey?logo=deno)](https://github.com/denoland/deno)
4+
[![deno version](https://img.shields.io/badge/deno-^1.16.1-lightgrey?logo=deno)](https://github.com/denoland/deno)
55
[![GitHub Release](https://img.shields.io/github/release/getoslash/chrome-webstore-cli.svg)](https://github.com/getoslash/chrome-webstore-cli/releases)
66
[![Release](https://github.com/getoslash/chrome-webstore-cli/actions/workflows/release.yml/badge.svg)](https://github.com/getoslash/chrome-webstore-cli/actions/workflows/release.yml)
77
[![codecov](https://codecov.io/gh/getoslash/chrome-webstore-cli/branch/main/graph/badge.svg?token=???)](https://codecov.io/gh/getoslash/chrome-webstore-cli)
@@ -23,31 +23,32 @@ If you use Deno, you can also directly compile from source and install `cwc`
2323
using the command —
2424

2525
```
26-
deno install --quiet --allow-read --allow-write --allow-net=www.googleapis.com --allow-env --name cwc https://deno.land/x/cwc@1.0.0/mod.ts
26+
deno install --quiet --allow-read --allow-write --allow-net=www.googleapis.com --allow-env --name cwc https://deno.land/x/cwc@1.1.0/mod.ts
2727
```
2828

2929
## Usage
3030

3131
```
32-
cwc
32+
Usage: cwc
33+
Version: 1.1.0
3334
34-
Usage:
35-
$ cwc <command> [options]
35+
Description:
3636
37-
Commands:
38-
upload <source> Upload directory or ZIP file to Chrome Web Store
39-
publish Publish last upload to Chrome Web Store
37+
Upload & publish extensions and themes to the Chrome Web Store
4038
41-
For more info, run any command with the `--help` flag:
42-
$ cwc upload --help
43-
$ cwc publish --help
39+
Options:
4440
45-
Options:
46-
--extension-id <id> ID of the extension on the Chrome Web Store
47-
--client-id <client-id> Google API OAuth2 client ID
48-
--client-secret <client-secret> Google API OAuth2 client secret
49-
--refresh-token <refresh-token> Google API OAuth2 refresh token
50-
-h, --help Display this message
41+
-h, --help - Show this help.
42+
-V, --version - Show the version number for this program.
43+
-i, --id <id> - ID of the extension or theme on the Chrome Web Store (required)
44+
-c, --client-id <client-id> - Google API OAuth2 client ID (required)
45+
-s, --client-secret <client-secret> - Google API OAuth2 client secret (required)
46+
-r, --refresh-token <refresh-token> - Google API OAuth2 refresh token (required)
47+
48+
Commands:
49+
50+
upload - Upload directory or ZIP file to Chrome Web Store
51+
publish - Publish last upload to Chrome Web Store
5152
```
5253

5354
### 🗜 Auto-Zip support
@@ -83,7 +84,7 @@ The app needs a few permissions –
8384
<summary>Upload and auto-publish your extension</summary>
8485

8586
```
86-
cwc upload --source "<path-to-extension>" --extension-id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>" --auto-publish
87+
cwc upload --file "<path-to-extension>" --id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>" --auto-publish
8788
```
8889

8990
</details>
@@ -93,7 +94,7 @@ The app needs a few permissions –
9394
<summary>Publish the last uploaded version of your extension</summary>
9495

9596
```
96-
cwc publish --extension-id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>"
97+
cwc publish --id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>"
9798
```
9899

99100
</details>
@@ -103,7 +104,7 @@ The app needs a few permissions –
103104
<summary>Publish the last uploaded version of your extension but only to trusted testers</summary>
104105

105106
```
106-
cwc publish --extension-id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>" --trusted-testers
107+
cwc publish --id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>" --trusted-testers
107108
```
108109

109110
</details>

cli.ts

Lines changed: 154 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,168 @@
1-
import { cac, debugLog } from "./deps.ts";
1+
import { Command, debugLog } from "./deps.ts";
2+
import { version } from "./version.ts";
23
import { printErrorAndExit } from "./helpers/console.ts";
34
import { isPublishError, publish, upload } from "./helpers/api.ts";
45

5-
export const cli = cac("cwc");
6+
const cli = new Command()
7+
.name("cwc")
8+
.version(version)
9+
.allowEmpty(false)
10+
.throwErrors()
11+
.description("Upload & publish extensions and themes to the Chrome Web Store")
12+
.example(
13+
"Upload and auto-publish your extension",
14+
'cwc upload --file "<path-to-file-or-folder>" --id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>" --auto-publish',
15+
)
16+
.example(
17+
"Publish the last uploaded version of your extension",
18+
'cwc publish --id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>"',
19+
)
20+
.example(
21+
"Publish the last uploaded version of your extension but only to trusted testers",
22+
'cwc publish --id "<extension-id>" --client-id "<client-id>" --client-secret "<client-secret>" --refresh-token "<refresh-token>" --trusted-testers',
23+
)
24+
.option(
25+
"-i, --id <id>",
26+
"ID of the extension or theme on the Chrome Web Store",
27+
{
28+
required: true,
29+
requiredValue: true,
30+
global: true,
31+
},
32+
)
33+
.option("-c, --client-id <client-id>", "Google API OAuth2 client ID", {
34+
required: true,
35+
requiredValue: true,
36+
global: true,
37+
})
38+
.option(
39+
"-s, --client-secret <client-secret>",
40+
"Google API OAuth2 client secret",
41+
{
42+
required: true,
43+
requiredValue: true,
44+
global: true,
45+
},
46+
)
47+
.option(
48+
"-r, --refresh-token <refresh-token>",
49+
"Google API OAuth2 refresh token",
50+
{
51+
required: true,
52+
requiredValue: true,
53+
global: true,
54+
},
55+
)
56+
.command(
57+
"upload",
58+
new Command()
59+
.description("Upload directory or ZIP file to Chrome Web Store")
60+
.option(
61+
"-f, --file <file>",
62+
"Path of directory or ZIP file to upload",
63+
{
64+
required: true,
65+
requiredValue: true,
66+
},
67+
)
68+
.option(
69+
"-p, --auto-publish [auto-publish:boolean]",
70+
"Automatically publish after upload",
71+
)
72+
.action(
73+
async (
74+
entry: {
75+
file: string;
76+
id: string;
77+
clientId: string;
78+
clientSecret: string;
79+
refreshToken: string;
80+
autoPublish?: boolean;
81+
},
82+
): Promise<void> => {
83+
const debug = debugLog("cwc:upload");
84+
debug("parsed options %j", entry);
685

7-
cli.help();
86+
const uploadResult = await upload({
87+
source: entry.file,
88+
extensionId: entry.id,
89+
clientId: entry.clientId,
90+
clientSecret: entry.clientSecret,
91+
refreshToken: entry.refreshToken,
92+
autoPublish: entry.autoPublish || false,
93+
});
94+
debug("upload result %j", uploadResult);
895

9-
cli.option(
10-
"--extension-id <id>",
11-
"ID of the extension on the Chrome Web Store",
12-
);
13-
cli.option("--client-id <client-id>", "Google API OAuth2 client ID");
14-
cli.option(
15-
"--client-secret <client-secret>",
16-
"Google API OAuth2 client secret",
17-
);
18-
cli.option(
19-
"--refresh-token <refresh-token>",
20-
"Google API OAuth2 refresh token",
21-
);
96+
if (uploadResult.upload.uploadState === "SUCCESS") {
97+
console.log("Upload OK");
98+
} else {
99+
console.warn(`Upload ${uploadResult.upload.uploadState}`);
100+
if (uploadResult.upload.itemError?.[0]) {
101+
printErrorAndExit(
102+
`${uploadResult.upload.itemError[0].error_code}${
103+
uploadResult.upload.itemError[0].error_detail
104+
}`,
105+
);
106+
}
107+
}
22108

23-
cli.command("upload", "Upload directory or ZIP file to Chrome Web Store")
24-
.option("--source <input>", "Path of directory or ZIP file to upload")
25-
.option("--auto-publish", "Automatically publish after upload")
26-
.action(async (entry) => {
27-
const debug = debugLog("cwc:upload");
28-
debug("parsed options %j", entry);
109+
if (entry.autoPublish) {
110+
if (!isPublishError(uploadResult.publish)) {
111+
console.log(`Publish ${uploadResult.publish?.status}`);
112+
} else {
113+
printErrorAndExit(uploadResult.publish.error.message);
114+
}
115+
}
116+
},
117+
),
118+
)
119+
.command(
120+
"publish",
121+
new Command()
122+
.description("Publish last upload to Chrome Web Store")
123+
.option(
124+
"-t, --trusted-testers [trusted-testers:boolean]",
125+
"Publish only to trusted testers",
126+
)
127+
.action(
128+
async (
129+
entry: {
130+
id: string;
131+
clientId: string;
132+
clientSecret: string;
133+
refreshToken: string;
134+
trustedTesters?: boolean;
135+
},
136+
): Promise<void> => {
137+
const debug = debugLog("cwc:publish");
138+
debug("parsed options %j", entry);
139+
const publishResult = await publish({
140+
extensionId: entry.id,
141+
clientId: entry.clientId,
142+
clientSecret: entry.clientSecret,
143+
refreshToken: entry.refreshToken,
144+
trustedTesters: entry.trustedTesters || false,
145+
});
146+
debug("publish result %j", publishResult);
29147

30-
const uploadResult = await upload({
31-
source: entry.source,
32-
extensionId: entry.extensionId,
33-
clientId: entry.clientId,
34-
clientSecret: entry.clientSecret,
35-
refreshToken: entry.refreshToken,
36-
autoPublish: entry.autoPublish || false,
37-
});
38-
debug("upload result %j", uploadResult);
39-
40-
if (uploadResult.upload.uploadState === "SUCCESS") {
41-
console.log("Upload OK");
42-
} else {
43-
console.warn(`Upload ${uploadResult.upload.uploadState}`);
44-
if (uploadResult.upload.itemError?.[0]) {
45-
printErrorAndExit(
46-
`${uploadResult.upload.itemError[0].error_code}${
47-
uploadResult.upload.itemError[0].error_detail
48-
}`,
49-
);
50-
}
51-
}
52-
53-
if (entry.autoPublish) {
54-
if (!isPublishError(uploadResult.publish)) {
55-
console.log(`Publish ${uploadResult.publish?.status}`);
56-
} else {
57-
printErrorAndExit(uploadResult.publish.error.message);
58-
}
59-
}
60-
});
61-
62-
cli.command("publish", "Publish last upload to Chrome Web Store")
63-
.option("--trusted-testers", "Publish only to trusted testers")
64-
.action(async (entry) => {
65-
const debug = debugLog("cwc:publish");
66-
debug("parsed options %j", entry);
67-
const publishResult = await publish({
68-
extensionId: entry.extensionId,
69-
clientId: entry.clientId,
70-
clientSecret: entry.clientSecret,
71-
refreshToken: entry.refreshToken,
72-
trustedTesters: entry.trustedTesters || false,
73-
});
74-
debug("publish result %j", publishResult);
75-
76-
if (!isPublishError(publishResult)) {
77-
console.log(`Publish ${publishResult.status[0]}`);
78-
} else {
79-
printErrorAndExit(publishResult.error.message);
80-
}
81-
});
148+
if (!isPublishError(publishResult)) {
149+
console.log(`Publish ${publishResult.status[0]}`);
150+
} else {
151+
printErrorAndExit(publishResult.error.message);
152+
}
153+
},
154+
),
155+
);
82156

83157
if (import.meta.main) {
84158
try {
85-
const parsed = cli.parse([
86-
Deno.execPath(),
87-
import.meta.url,
88-
...Deno.args,
89-
], { run: false });
90-
if (!cli.matchedCommandName && !parsed.options.help) {
91-
throw new Error("No valid command found");
159+
const parsed = await cli.parse(Deno.args);
160+
if (parsed.args.length < 1 && Object.keys(parsed.options).length < 1) {
161+
throw new Error("No arguments provided!");
92162
}
93-
cli.runMatchedCommand();
94163
} catch (error) {
95-
cli.outputHelp();
96-
printErrorAndExit(error.message, 1);
164+
console.error("Error –", error.message);
165+
cli.showHelp();
166+
Deno.exit(1);
97167
}
98168
}

deps.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
export * as path from "https://deno.land/std@0.112.0/path/mod.ts";
2-
export { readableStreamFromReader } from "https://deno.land/std@0.112.0/io/mod.ts";
3-
export { cac } from "https://unpkg.com/[email protected]/mod.ts";
1+
export * as path from "https://deno.land/std@0.114.0/path/mod.ts";
2+
export { readableStreamFromReader } from "https://deno.land/std@0.114.0/io/mod.ts";
3+
export { Command } from "https://deno.land/x/[email protected]/command/command.ts";
44
export { JSZip } from "https://deno.land/x/[email protected]/mod.ts";
55
export { default as debugLog } from "https://deno.land/x/[email protected]/debug.ts";
6-
export { default as apiClient } from "https://deno.land/x/[email protected].0/mod.ts";
6+
export { default as apiClient } from "https://deno.land/x/[email protected].1/mod.ts";
77
export type {
88
GoogleAPIWebStoreItem,
99
GoogleAPIWebStorePublishFailure,
1010
GoogleAPIWebStorePublishResponse,
1111
GoogleAPIWebStorePublishSuccess,
12-
} from "https://deno.land/x/[email protected].0/types.ts";
12+
} from "https://deno.land/x/[email protected].1/types.ts";

dev_deps.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
export * as path from "https://deno.land/std@0.112.0/path/mod.ts";
1+
export * as path from "https://deno.land/std@0.114.0/path/mod.ts";
22
export {
33
assertEquals,
44
assertThrowsAsync,
5-
} from "https://deno.land/std@0.112.0/testing/asserts.ts";
6-
export { createHash } from "https://deno.land/std@0.112.0/hash/mod.ts";
7-
export { iterateReader } from "https://deno.land/std@0.112.0/streams/conversion.ts";
5+
} from "https://deno.land/std@0.114.0/testing/asserts.ts";
6+
export { createHash } from "https://deno.land/std@0.114.0/hash/mod.ts";
7+
export { iterateReader } from "https://deno.land/std@0.114.0/streams/conversion.ts";
88
export { stub } from "https://deno.land/x/[email protected]/mod.ts";
99
export type { Stub } from "https://deno.land/x/[email protected]/mod.ts";
10-
export type { SupportedAlgorithm } from "https://deno.land/std@0.112.0/hash/mod.ts";
10+
export type { SupportedAlgorithm } from "https://deno.land/std@0.114.0/hash/mod.ts";

helpers/api.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ export const publish = async (
102102
refreshToken: options.refreshToken,
103103
});
104104

105-
debug("publishing to chrome store");
105+
debug(
106+
`publishing to chrome store${
107+
options.trustedTesters ? " for only trusted testers" : ""
108+
}`,
109+
);
106110
const result = await api.publish(
107111
options.trustedTesters ? "trustedUsers" : undefined,
108112
);

0 commit comments

Comments
 (0)