@semaphore-protocol/cli 4.0.0-beta.1 → 4.0.0-beta.11
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 +18 -4
- package/dist/index.js +54 -17
- package/package.json +7 -4
- package/src/checkLatestVersion.ts +4 -4
- package/src/getGroupIds.ts +7 -3
- package/src/index.ts +19 -11
- package/src/inquirerPrompts.ts +20 -0
- package/src/spinner.ts +5 -0
package/README.md
CHANGED
|
@@ -46,23 +46,25 @@
|
|
|
46
46
|
</h4>
|
|
47
47
|
</div>
|
|
48
48
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
49
|
+
| Semaphore CLI simplifies the process of setting up Semaphore projects and retrieving on-chain group data, reducing setup time from minutes to seconds. |
|
|
50
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
51
51
|
|
|
52
52
|
## 🛠 Install
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
To install Semaphore CLI globally:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
npm i -g @semaphore-protocol/cli
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
Alternatively, you can use `npx` to run commands without installing the package globally:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
63
|
npx @semaphore-protocol/cli create my-app
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
This command sets up a new project in the `my-app` directory using the `monorepo-ethers` template.
|
|
67
|
+
|
|
66
68
|
## 📜 Usage
|
|
67
69
|
|
|
68
70
|
```
|
|
@@ -82,3 +84,15 @@ Commands:
|
|
|
82
84
|
get-proofs [options] [group-id] Get the proofs of a group from a supported network (e.g. sepolia or arbitrum).
|
|
83
85
|
help [command] Display help for a specific command.
|
|
84
86
|
```
|
|
87
|
+
|
|
88
|
+
## 🌐 Supported Networks
|
|
89
|
+
|
|
90
|
+
Semaphore CLI supports multiple Ethereum networks. Use the `get-groups` command to interact with groups on networks like Sepolia or Arbitrum.
|
|
91
|
+
|
|
92
|
+
## 📦 Supported Templates
|
|
93
|
+
|
|
94
|
+
When creating a new project, you can choose from several templates designed to integrate seamlessly with Semaphore's privacy protocols:
|
|
95
|
+
|
|
96
|
+
- **monorepo-ethers**: Hardhat + Next.js + SemaphoreEthers
|
|
97
|
+
- **monorepo-subgraph**: Hardhat + Next.js + SemaphoreSubgraph
|
|
98
|
+
- **contracts-hardhat**: Hardhat only, focused on smart contract development.
|
package/dist/index.js
CHANGED
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @module @semaphore-protocol/cli
|
|
5
|
-
* @version 4.0.0-beta.
|
|
5
|
+
* @version 4.0.0-beta.11
|
|
6
6
|
* @file A command line tool to set up your Semaphore project and get group data.
|
|
7
7
|
* @copyright Ethereum Foundation 2024
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @see [Github]{@link https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli}
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { SemaphoreSubgraph, SemaphoreEthers
|
|
12
|
+
import { SemaphoreSubgraph, SemaphoreEthers } from '@semaphore-protocol/data';
|
|
13
|
+
import { isSupportedNetwork, supportedNetworks } from '@semaphore-protocol/utils/networks';
|
|
13
14
|
import chalk from 'chalk';
|
|
14
15
|
import { program } from 'commander';
|
|
15
16
|
import decompress from 'decompress';
|
|
@@ -28,10 +29,10 @@ import inquirer from 'inquirer';
|
|
|
28
29
|
|
|
29
30
|
const cliRegistryURL = "https://registry.npmjs.org/-/package/@semaphore-protocol/cli/dist-tags";
|
|
30
31
|
/**
|
|
31
|
-
* Checks the
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* @param currentVersion The current version of the CLI.
|
|
32
|
+
* Checks for the latest version of the CLI tool against the registry. It first attempts to fetch the version directly
|
|
33
|
+
* via an API call. If this fails, possibly due to network restrictions, it falls back to using the `npm view` command.
|
|
34
|
+
* This method ensures that users behind a firewall or using a private registry can still check for updates.
|
|
35
|
+
* @param currentVersion The current version of the CLI being used.
|
|
35
36
|
*/
|
|
36
37
|
async function checkLatestVersion(currentVersion) {
|
|
37
38
|
let latestVersion;
|
|
@@ -54,6 +55,11 @@ async function checkLatestVersion(currentVersion) {
|
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
/**
|
|
59
|
+
* A utility class for managing a CLI spinner. This class encapsulates the functionality of the `ora` spinner,
|
|
60
|
+
* providing methods to start and stop the spinner. It is used to give visual feedback to the user during operations
|
|
61
|
+
* that have a noticeable delay, such as network requests.
|
|
62
|
+
*/
|
|
57
63
|
class Spinner {
|
|
58
64
|
constructor(text) {
|
|
59
65
|
this.ora = ora({
|
|
@@ -71,8 +77,11 @@ class Spinner {
|
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
80
|
+
* Retrieves all group IDs from the Semaphore protocol on a specified network. This function first attempts to
|
|
81
|
+
* fetch the group IDs using the SemaphoreSubgraph interface. If that fails, it tries the SemaphoreEthers interface
|
|
82
|
+
* as a fallback. This dual-method approach ensures higher reliability in fetching data across different network conditions.
|
|
83
|
+
* @param network The blockchain network from which to fetch the group IDs.
|
|
84
|
+
* @returns A promise that resolves to an array of group IDs or null if an error occurs.
|
|
76
85
|
*/
|
|
77
86
|
async function getGroupIds(network) {
|
|
78
87
|
let groupIds;
|
|
@@ -98,6 +107,10 @@ async function getGroupIds(network) {
|
|
|
98
107
|
return groupIds;
|
|
99
108
|
}
|
|
100
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Prompts the user to input the name of their project. Provides a default name of "my-app".
|
|
112
|
+
* @returns A promise that resolves to the user's input for the project name.
|
|
113
|
+
*/
|
|
101
114
|
async function getProjectName() {
|
|
102
115
|
const { projectName } = await inquirer.prompt({
|
|
103
116
|
name: "projectName",
|
|
@@ -107,6 +120,12 @@ async function getProjectName() {
|
|
|
107
120
|
});
|
|
108
121
|
return projectName;
|
|
109
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Prompts the user to select a template from a list of supported templates. Each template is presented
|
|
125
|
+
* with its value and name for better clarity.
|
|
126
|
+
* @param supportedTemplates An array of objects, each containing a 'value' and 'name' property for the template.
|
|
127
|
+
* @returns A promise that resolves to the selected template's value.
|
|
128
|
+
*/
|
|
110
129
|
async function getSupportedTemplate(supportedTemplates) {
|
|
111
130
|
const { selectedTemplate } = await inquirer.prompt({
|
|
112
131
|
name: "selectedTemplate",
|
|
@@ -120,6 +139,11 @@ async function getSupportedTemplate(supportedTemplates) {
|
|
|
120
139
|
});
|
|
121
140
|
return selectedTemplate;
|
|
122
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Prompts the user to select a network from a list of supported networks.
|
|
144
|
+
* @param supportedNetworks An array of strings representing the supported networks.
|
|
145
|
+
* @returns A promise that resolves to the selected network.
|
|
146
|
+
*/
|
|
123
147
|
async function getSupportedNetwork(supportedNetworks) {
|
|
124
148
|
const { selectedNetwork } = await inquirer.prompt({
|
|
125
149
|
name: "selectedNetwork",
|
|
@@ -130,6 +154,11 @@ async function getSupportedNetwork(supportedNetworks) {
|
|
|
130
154
|
});
|
|
131
155
|
return selectedNetwork;
|
|
132
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Prompts the user to select a group ID from a list of existing group IDs.
|
|
159
|
+
* @param groupIds An array of strings representing the group IDs.
|
|
160
|
+
* @returns A promise that resolves to the selected group ID.
|
|
161
|
+
*/
|
|
133
162
|
async function getGroupId(groupIds) {
|
|
134
163
|
const { selectedGroupId } = await inquirer.prompt({
|
|
135
164
|
name: "selectedGroupId",
|
|
@@ -141,9 +170,10 @@ async function getGroupId(groupIds) {
|
|
|
141
170
|
return selectedGroupId;
|
|
142
171
|
}
|
|
143
172
|
|
|
173
|
+
// Define the path to the package.json file to extract metadata for the CLI.
|
|
144
174
|
const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..`;
|
|
145
175
|
const { description, version } = JSON.parse(readFileSync(`${packagePath}/package.json`, "utf8"));
|
|
146
|
-
|
|
176
|
+
// List of supported templates for project creation.
|
|
147
177
|
const supportedTemplates = [
|
|
148
178
|
{
|
|
149
179
|
value: "monorepo-ethers",
|
|
@@ -158,6 +188,7 @@ const supportedTemplates = [
|
|
|
158
188
|
name: "Hardhat"
|
|
159
189
|
}
|
|
160
190
|
];
|
|
191
|
+
// Setup the CLI program with basic information and help text.
|
|
161
192
|
program
|
|
162
193
|
.name("semaphore")
|
|
163
194
|
.description(description)
|
|
@@ -171,6 +202,7 @@ program
|
|
|
171
202
|
console.info(`\n ${logSymbols.error}`, message);
|
|
172
203
|
}
|
|
173
204
|
});
|
|
205
|
+
// Define the 'create' command to scaffold new Semaphore projects.
|
|
174
206
|
program
|
|
175
207
|
.command("create")
|
|
176
208
|
.description("Create a Semaphore project with a supported template.")
|
|
@@ -196,15 +228,20 @@ program
|
|
|
196
228
|
}
|
|
197
229
|
spinner.start();
|
|
198
230
|
await checkLatestVersion(version);
|
|
231
|
+
// Extract the template package into the project directory.
|
|
199
232
|
await pacote.extract(`@semaphore-protocol/cli-template-${template}@${version}`, `${currentDirectory}/${projectDirectory}`);
|
|
233
|
+
// Decompress the template files after extraction.
|
|
200
234
|
await decompress(`${currentDirectory}/${projectDirectory}/files.tgz`, `${currentDirectory}/${projectDirectory}`);
|
|
235
|
+
// Clean up the compressed file after extraction.
|
|
201
236
|
unlinkSync(`${currentDirectory}/${projectDirectory}/files.tgz`);
|
|
237
|
+
// Copy the example environment file to the actual environment file.
|
|
202
238
|
copyFileSync(`${currentDirectory}/${projectDirectory}/.env.example`, `${currentDirectory}/${projectDirectory}/.env`);
|
|
203
239
|
spinner.stop();
|
|
204
240
|
console.info(`\n ${logSymbols.success}`, `Your project is ready!\n`);
|
|
205
241
|
console.info(` Please, install your dependencies by running:\n`);
|
|
206
242
|
console.info(` ${chalk.cyan("cd")} ${projectDirectory}`);
|
|
207
243
|
console.info(` ${chalk.cyan("yarn install")}\n`);
|
|
244
|
+
// Read the package.json to list available npm scripts.
|
|
208
245
|
const { scripts } = JSON.parse(readFileSync(`${currentDirectory}/${projectDirectory}/package.json`, "utf8"));
|
|
209
246
|
if (scripts) {
|
|
210
247
|
console.info(` Available scripts:\n`);
|
|
@@ -221,9 +258,9 @@ program
|
|
|
221
258
|
.allowExcessArguments(false)
|
|
222
259
|
.action(async ({ network }) => {
|
|
223
260
|
if (!network) {
|
|
224
|
-
network = await getSupportedNetwork(supportedNetworks);
|
|
261
|
+
network = await getSupportedNetwork(Object.keys(supportedNetworks));
|
|
225
262
|
}
|
|
226
|
-
if (!
|
|
263
|
+
if (!isSupportedNetwork(network)) {
|
|
227
264
|
console.info(`\n ${logSymbols.error}`, `error: the network '${network}' is not supported\n`);
|
|
228
265
|
return;
|
|
229
266
|
}
|
|
@@ -245,9 +282,9 @@ program
|
|
|
245
282
|
.allowExcessArguments(false)
|
|
246
283
|
.action(async (groupId, { network }) => {
|
|
247
284
|
if (!network) {
|
|
248
|
-
network = await getSupportedNetwork(supportedNetworks);
|
|
285
|
+
network = await getSupportedNetwork(Object.keys(supportedNetworks));
|
|
249
286
|
}
|
|
250
|
-
if (!
|
|
287
|
+
if (!isSupportedNetwork(network)) {
|
|
251
288
|
console.info(`\n ${logSymbols.error}`, `error: the network '${network}' is not supported\n`);
|
|
252
289
|
return;
|
|
253
290
|
}
|
|
@@ -299,9 +336,9 @@ program
|
|
|
299
336
|
.allowExcessArguments(false)
|
|
300
337
|
.action(async (groupId, { network }) => {
|
|
301
338
|
if (!network) {
|
|
302
|
-
network = await getSupportedNetwork(supportedNetworks);
|
|
339
|
+
network = await getSupportedNetwork(Object.keys(supportedNetworks));
|
|
303
340
|
}
|
|
304
|
-
if (!
|
|
341
|
+
if (!isSupportedNetwork(network)) {
|
|
305
342
|
console.info(`\n ${logSymbols.error}`, `error: the network '${network}' is not supported\n`);
|
|
306
343
|
return;
|
|
307
344
|
}
|
|
@@ -351,9 +388,9 @@ program
|
|
|
351
388
|
.allowExcessArguments(false)
|
|
352
389
|
.action(async (groupId, { network }) => {
|
|
353
390
|
if (!network) {
|
|
354
|
-
network = await getSupportedNetwork(supportedNetworks);
|
|
391
|
+
network = await getSupportedNetwork(Object.keys(supportedNetworks));
|
|
355
392
|
}
|
|
356
|
-
if (!
|
|
393
|
+
if (!isSupportedNetwork(network)) {
|
|
357
394
|
console.info(`\n ${logSymbols.error}`, `error: the network '${network}' is not supported\n`);
|
|
358
395
|
return;
|
|
359
396
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semaphore-protocol/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.0.0-beta.
|
|
4
|
+
"version": "4.0.0-beta.11",
|
|
5
5
|
"description": "A command line tool to set up your Semaphore project and get group data.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -31,15 +31,18 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
34
35
|
"@types/figlet": "^1.5.8",
|
|
35
36
|
"@types/inquirer": "^9.0.7",
|
|
36
37
|
"@types/pacote": "^11.1.8",
|
|
37
38
|
"@types/semver": "^7.5.8",
|
|
38
|
-
"
|
|
39
|
-
"rollup
|
|
39
|
+
"rimraf": "^5.0.5",
|
|
40
|
+
"rollup": "^4.12.0",
|
|
41
|
+
"rollup-plugin-cleanup": "^3.2.1"
|
|
40
42
|
},
|
|
41
43
|
"dependencies": {
|
|
42
|
-
"@semaphore-protocol/data": "4.0.0-beta.
|
|
44
|
+
"@semaphore-protocol/data": "4.0.0-beta.11",
|
|
45
|
+
"@semaphore-protocol/utils": "4.0.0-beta.11",
|
|
43
46
|
"axios": "^1.6.7",
|
|
44
47
|
"boxen": "^7.1.1",
|
|
45
48
|
"chalk": "^5.3.0",
|
|
@@ -7,10 +7,10 @@ import { lt as semverLt } from "semver"
|
|
|
7
7
|
const cliRegistryURL = "https://registry.npmjs.org/-/package/@semaphore-protocol/cli/dist-tags"
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Checks the
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @param currentVersion The current version of the CLI.
|
|
10
|
+
* Checks for the latest version of the CLI tool against the registry. It first attempts to fetch the version directly
|
|
11
|
+
* via an API call. If this fails, possibly due to network restrictions, it falls back to using the `npm view` command.
|
|
12
|
+
* This method ensures that users behind a firewall or using a private registry can still check for updates.
|
|
13
|
+
* @param currentVersion The current version of the CLI being used.
|
|
14
14
|
*/
|
|
15
15
|
export default async function checkLatestVersion(currentVersion: string) {
|
|
16
16
|
let latestVersion: string
|
package/src/getGroupIds.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { SemaphoreSubgraph, SemaphoreEthers } from "@semaphore-protocol/data"
|
|
2
|
+
import { SupportedNetwork } from "@semaphore-protocol/utils"
|
|
2
3
|
import logSymbols from "log-symbols"
|
|
3
4
|
import Spinner from "./spinner.js"
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Retrieves all group IDs from the Semaphore protocol on a specified network. This function first attempts to
|
|
8
|
+
* fetch the group IDs using the SemaphoreSubgraph interface. If that fails, it tries the SemaphoreEthers interface
|
|
9
|
+
* as a fallback. This dual-method approach ensures higher reliability in fetching data across different network conditions.
|
|
10
|
+
* @param network The blockchain network from which to fetch the group IDs.
|
|
11
|
+
* @returns A promise that resolves to an array of group IDs or null if an error occurs.
|
|
8
12
|
*/
|
|
9
|
-
export default async function getGroupIds(network): Promise<string[]> {
|
|
13
|
+
export default async function getGroupIds(network: SupportedNetwork): Promise<string[]> {
|
|
10
14
|
let groupIds: string[]
|
|
11
15
|
|
|
12
16
|
const spinner = new Spinner("Fetching groups")
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { GroupResponse, SemaphoreEthers, SemaphoreSubgraph
|
|
1
|
+
import { GroupResponse, SemaphoreEthers, SemaphoreSubgraph } from "@semaphore-protocol/data"
|
|
2
|
+
import { isSupportedNetwork, supportedNetworks } from "@semaphore-protocol/utils/networks"
|
|
2
3
|
import chalk from "chalk"
|
|
3
4
|
import { program } from "commander"
|
|
4
5
|
import decompress from "decompress"
|
|
@@ -13,11 +14,11 @@ import getGroupIds from "./getGroupIds.js"
|
|
|
13
14
|
import { getGroupId, getProjectName, getSupportedNetwork, getSupportedTemplate } from "./inquirerPrompts.js"
|
|
14
15
|
import Spinner from "./spinner.js"
|
|
15
16
|
|
|
17
|
+
// Define the path to the package.json file to extract metadata for the CLI.
|
|
16
18
|
const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..`
|
|
17
19
|
const { description, version } = JSON.parse(readFileSync(`${packagePath}/package.json`, "utf8"))
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
// List of supported templates for project creation.
|
|
21
22
|
const supportedTemplates = [
|
|
22
23
|
{
|
|
23
24
|
value: "monorepo-ethers",
|
|
@@ -33,6 +34,7 @@ const supportedTemplates = [
|
|
|
33
34
|
}
|
|
34
35
|
]
|
|
35
36
|
|
|
37
|
+
// Setup the CLI program with basic information and help text.
|
|
36
38
|
program
|
|
37
39
|
.name("semaphore")
|
|
38
40
|
.description(description)
|
|
@@ -47,6 +49,7 @@ program
|
|
|
47
49
|
}
|
|
48
50
|
})
|
|
49
51
|
|
|
52
|
+
// Define the 'create' command to scaffold new Semaphore projects.
|
|
50
53
|
program
|
|
51
54
|
.command("create")
|
|
52
55
|
.description("Create a Semaphore project with a supported template.")
|
|
@@ -79,15 +82,19 @@ program
|
|
|
79
82
|
|
|
80
83
|
await checkLatestVersion(version)
|
|
81
84
|
|
|
85
|
+
// Extract the template package into the project directory.
|
|
82
86
|
await pacote.extract(
|
|
83
87
|
`@semaphore-protocol/cli-template-${template}@${version}`,
|
|
84
88
|
`${currentDirectory}/${projectDirectory}`
|
|
85
89
|
)
|
|
86
90
|
|
|
91
|
+
// Decompress the template files after extraction.
|
|
87
92
|
await decompress(`${currentDirectory}/${projectDirectory}/files.tgz`, `${currentDirectory}/${projectDirectory}`)
|
|
88
93
|
|
|
94
|
+
// Clean up the compressed file after extraction.
|
|
89
95
|
unlinkSync(`${currentDirectory}/${projectDirectory}/files.tgz`)
|
|
90
96
|
|
|
97
|
+
// Copy the example environment file to the actual environment file.
|
|
91
98
|
copyFileSync(
|
|
92
99
|
`${currentDirectory}/${projectDirectory}/.env.example`,
|
|
93
100
|
`${currentDirectory}/${projectDirectory}/.env`
|
|
@@ -100,6 +107,7 @@ program
|
|
|
100
107
|
console.info(` ${chalk.cyan("cd")} ${projectDirectory}`)
|
|
101
108
|
console.info(` ${chalk.cyan("yarn install")}\n`)
|
|
102
109
|
|
|
110
|
+
// Read the package.json to list available npm scripts.
|
|
103
111
|
const { scripts } = JSON.parse(readFileSync(`${currentDirectory}/${projectDirectory}/package.json`, "utf8"))
|
|
104
112
|
|
|
105
113
|
if (scripts) {
|
|
@@ -122,10 +130,10 @@ program
|
|
|
122
130
|
.allowExcessArguments(false)
|
|
123
131
|
.action(async ({ network }) => {
|
|
124
132
|
if (!network) {
|
|
125
|
-
network = await getSupportedNetwork(supportedNetworks)
|
|
133
|
+
network = await getSupportedNetwork(Object.keys(supportedNetworks))
|
|
126
134
|
}
|
|
127
135
|
|
|
128
|
-
if (!
|
|
136
|
+
if (!isSupportedNetwork(network)) {
|
|
129
137
|
console.info(`\n ${logSymbols.error}`, `error: the network '${network}' is not supported\n`)
|
|
130
138
|
return
|
|
131
139
|
}
|
|
@@ -152,10 +160,10 @@ program
|
|
|
152
160
|
.allowExcessArguments(false)
|
|
153
161
|
.action(async (groupId, { network }) => {
|
|
154
162
|
if (!network) {
|
|
155
|
-
network = await getSupportedNetwork(supportedNetworks)
|
|
163
|
+
network = await getSupportedNetwork(Object.keys(supportedNetworks))
|
|
156
164
|
}
|
|
157
165
|
|
|
158
|
-
if (!
|
|
166
|
+
if (!isSupportedNetwork(network)) {
|
|
159
167
|
console.info(`\n ${logSymbols.error}`, `error: the network '${network}' is not supported\n`)
|
|
160
168
|
return
|
|
161
169
|
}
|
|
@@ -220,10 +228,10 @@ program
|
|
|
220
228
|
.allowExcessArguments(false)
|
|
221
229
|
.action(async (groupId, { network }) => {
|
|
222
230
|
if (!network) {
|
|
223
|
-
network = await getSupportedNetwork(supportedNetworks)
|
|
231
|
+
network = await getSupportedNetwork(Object.keys(supportedNetworks))
|
|
224
232
|
}
|
|
225
233
|
|
|
226
|
-
if (!
|
|
234
|
+
if (!isSupportedNetwork(network)) {
|
|
227
235
|
console.info(`\n ${logSymbols.error}`, `error: the network '${network}' is not supported\n`)
|
|
228
236
|
return
|
|
229
237
|
}
|
|
@@ -286,10 +294,10 @@ program
|
|
|
286
294
|
.allowExcessArguments(false)
|
|
287
295
|
.action(async (groupId, { network }) => {
|
|
288
296
|
if (!network) {
|
|
289
|
-
network = await getSupportedNetwork(supportedNetworks)
|
|
297
|
+
network = await getSupportedNetwork(Object.keys(supportedNetworks))
|
|
290
298
|
}
|
|
291
299
|
|
|
292
|
-
if (!
|
|
300
|
+
if (!isSupportedNetwork(network)) {
|
|
293
301
|
console.info(`\n ${logSymbols.error}`, `error: the network '${network}' is not supported\n`)
|
|
294
302
|
return
|
|
295
303
|
}
|
package/src/inquirerPrompts.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import inquirer from "inquirer"
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Prompts the user to input the name of their project. Provides a default name of "my-app".
|
|
5
|
+
* @returns A promise that resolves to the user's input for the project name.
|
|
6
|
+
*/
|
|
3
7
|
export async function getProjectName() {
|
|
4
8
|
const { projectName } = await inquirer.prompt({
|
|
5
9
|
name: "projectName",
|
|
@@ -10,6 +14,12 @@ export async function getProjectName() {
|
|
|
10
14
|
return projectName
|
|
11
15
|
}
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Prompts the user to select a template from a list of supported templates. Each template is presented
|
|
19
|
+
* with its value and name for better clarity.
|
|
20
|
+
* @param supportedTemplates An array of objects, each containing a 'value' and 'name' property for the template.
|
|
21
|
+
* @returns A promise that resolves to the selected template's value.
|
|
22
|
+
*/
|
|
13
23
|
export async function getSupportedTemplate(supportedTemplates: { value: string; name: string }[]) {
|
|
14
24
|
const { selectedTemplate } = await inquirer.prompt({
|
|
15
25
|
name: "selectedTemplate",
|
|
@@ -24,6 +34,11 @@ export async function getSupportedTemplate(supportedTemplates: { value: string;
|
|
|
24
34
|
return selectedTemplate
|
|
25
35
|
}
|
|
26
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Prompts the user to select a network from a list of supported networks.
|
|
39
|
+
* @param supportedNetworks An array of strings representing the supported networks.
|
|
40
|
+
* @returns A promise that resolves to the selected network.
|
|
41
|
+
*/
|
|
27
42
|
export async function getSupportedNetwork(supportedNetworks: string[]) {
|
|
28
43
|
const { selectedNetwork } = await inquirer.prompt({
|
|
29
44
|
name: "selectedNetwork",
|
|
@@ -35,6 +50,11 @@ export async function getSupportedNetwork(supportedNetworks: string[]) {
|
|
|
35
50
|
return selectedNetwork
|
|
36
51
|
}
|
|
37
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Prompts the user to select a group ID from a list of existing group IDs.
|
|
55
|
+
* @param groupIds An array of strings representing the group IDs.
|
|
56
|
+
* @returns A promise that resolves to the selected group ID.
|
|
57
|
+
*/
|
|
38
58
|
export async function getGroupId(groupIds: string[]) {
|
|
39
59
|
const { selectedGroupId } = await inquirer.prompt({
|
|
40
60
|
name: "selectedGroupId",
|
package/src/spinner.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import ora, { Ora } from "ora"
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* A utility class for managing a CLI spinner. This class encapsulates the functionality of the `ora` spinner,
|
|
5
|
+
* providing methods to start and stop the spinner. It is used to give visual feedback to the user during operations
|
|
6
|
+
* that have a noticeable delay, such as network requests.
|
|
7
|
+
*/
|
|
3
8
|
export default class Spinner {
|
|
4
9
|
private ora: Ora
|
|
5
10
|
|