w3wallets 0.3.0 → 0.4.1
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 +12 -1
- package/dist/index.d.mts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.js +93 -2
- package/dist/index.mjs +91 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ npm install -D w3wallets
|
|
|
18
18
|
The `Backpack` and the `Polkadot{.js}` wallets are currently supported.
|
|
19
19
|
|
|
20
20
|
<p align="center">
|
|
21
|
+
<img src="https://images.ctfassets.net/clixtyxoaeas/1ezuBGezqfIeifWdVtwU4c/d970d4cdf13b163efddddd5709164d2e/MetaMask-icon-Fox.svg" alt="Metamask Logo" width="60"/>
|
|
21
22
|
<img src="https://raw.githubusercontent.com/coral-xyz/backpack/refs/heads/master/assets/backpack.png" alt="Backpack Logo" width="60"/>
|
|
22
23
|
<img src="https://polkadot.js.org/logo.svg" alt="Polkadot JS Logo" width="60"/>
|
|
23
24
|
</p>
|
|
@@ -39,7 +40,11 @@ Install needed wallets into the chromium using `withWallets`.
|
|
|
39
40
|
import { withWallets } from "w3wallets";
|
|
40
41
|
import { test as base } from "@playwright/test";
|
|
41
42
|
|
|
42
|
-
export const test = withWallets(
|
|
43
|
+
export const test = withWallets(
|
|
44
|
+
base,
|
|
45
|
+
"backpack",
|
|
46
|
+
"polkadotJS",
|
|
47
|
+
).extend<BaseFixture>({
|
|
43
48
|
magic: (_, use) => use(42),
|
|
44
49
|
});
|
|
45
50
|
|
|
@@ -52,6 +57,12 @@ export { expect } from "@playwright/test";
|
|
|
52
57
|
|
|
53
58
|
#### 3. Use the installed wallets in tests
|
|
54
59
|
|
|
60
|
+
Most of the actions will use the following methods:
|
|
61
|
+
|
|
62
|
+
1. `onboard`: to set up your wallet
|
|
63
|
+
2. `approve`: for operations that confirm actions
|
|
64
|
+
3. `deny`: for actions that reject or cancel operations
|
|
65
|
+
|
|
55
66
|
```ts
|
|
56
67
|
import { test } from "./your-fixture";
|
|
57
68
|
|
package/dist/index.d.mts
CHANGED
|
@@ -6,7 +6,7 @@ import { Page, test, BrowserContext } from '@playwright/test';
|
|
|
6
6
|
*/
|
|
7
7
|
type BackPackNetwork = "Solana" | "Eclipse" | "Ethereum" | "Polygon" | "Base" | "Arbitrum" | "Optimism";
|
|
8
8
|
|
|
9
|
-
type WalletName = "backpack" | "polkadotJS";
|
|
9
|
+
type WalletName = "backpack" | "polkadotJS" | "metamask";
|
|
10
10
|
type NoDuplicates<T extends readonly unknown[], Acc extends readonly unknown[] = []> = T extends [infer Head, ...infer Tail] ? Head extends Acc[number] ? never : [Head, ...NoDuplicates<Tail, [...Acc, Head]>] : T;
|
|
11
11
|
interface IWallet {
|
|
12
12
|
gotoOnboardPage(): Promise<void>;
|
|
@@ -52,10 +52,32 @@ declare class PolkadotJS extends Wallet {
|
|
|
52
52
|
private _getLabeledInput;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
type NetworkSettings = {
|
|
56
|
+
name: string;
|
|
57
|
+
rpc: string;
|
|
58
|
+
chainId: number;
|
|
59
|
+
currencySymbol: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
declare class Metamask extends Wallet {
|
|
63
|
+
private defaultPassword;
|
|
64
|
+
gotoOnboardPage(): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param mnemonic 12-word mnemonic seed phrase
|
|
68
|
+
*/
|
|
69
|
+
onboard(mnemonic: string, password?: string): Promise<void>;
|
|
70
|
+
connectToNetwork(settings: NetworkSettings, switchNetwork?: boolean): Promise<void>;
|
|
71
|
+
approve(): Promise<void>;
|
|
72
|
+
deny(): Promise<void>;
|
|
73
|
+
private usingNotificationPage;
|
|
74
|
+
}
|
|
75
|
+
|
|
55
76
|
declare function withWallets<T extends readonly WalletName[]>(test: typeof test, ...config: NoDuplicates<T>): playwright_test.TestType<playwright_test.PlaywrightTestArgs & playwright_test.PlaywrightTestOptions & {
|
|
56
77
|
context: BrowserContext;
|
|
57
78
|
backpack: Backpack;
|
|
58
79
|
polkadotJS: PolkadotJS;
|
|
80
|
+
metamask: Metamask;
|
|
59
81
|
}, playwright_test.PlaywrightWorkerArgs & playwright_test.PlaywrightWorkerOptions>;
|
|
60
82
|
|
|
61
83
|
export { withWallets };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Page, test, BrowserContext } from '@playwright/test';
|
|
|
6
6
|
*/
|
|
7
7
|
type BackPackNetwork = "Solana" | "Eclipse" | "Ethereum" | "Polygon" | "Base" | "Arbitrum" | "Optimism";
|
|
8
8
|
|
|
9
|
-
type WalletName = "backpack" | "polkadotJS";
|
|
9
|
+
type WalletName = "backpack" | "polkadotJS" | "metamask";
|
|
10
10
|
type NoDuplicates<T extends readonly unknown[], Acc extends readonly unknown[] = []> = T extends [infer Head, ...infer Tail] ? Head extends Acc[number] ? never : [Head, ...NoDuplicates<Tail, [...Acc, Head]>] : T;
|
|
11
11
|
interface IWallet {
|
|
12
12
|
gotoOnboardPage(): Promise<void>;
|
|
@@ -52,10 +52,32 @@ declare class PolkadotJS extends Wallet {
|
|
|
52
52
|
private _getLabeledInput;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
type NetworkSettings = {
|
|
56
|
+
name: string;
|
|
57
|
+
rpc: string;
|
|
58
|
+
chainId: number;
|
|
59
|
+
currencySymbol: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
declare class Metamask extends Wallet {
|
|
63
|
+
private defaultPassword;
|
|
64
|
+
gotoOnboardPage(): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param mnemonic 12-word mnemonic seed phrase
|
|
68
|
+
*/
|
|
69
|
+
onboard(mnemonic: string, password?: string): Promise<void>;
|
|
70
|
+
connectToNetwork(settings: NetworkSettings, switchNetwork?: boolean): Promise<void>;
|
|
71
|
+
approve(): Promise<void>;
|
|
72
|
+
deny(): Promise<void>;
|
|
73
|
+
private usingNotificationPage;
|
|
74
|
+
}
|
|
75
|
+
|
|
55
76
|
declare function withWallets<T extends readonly WalletName[]>(test: typeof test, ...config: NoDuplicates<T>): playwright_test.TestType<playwright_test.PlaywrightTestArgs & playwright_test.PlaywrightTestOptions & {
|
|
56
77
|
context: BrowserContext;
|
|
57
78
|
backpack: Backpack;
|
|
58
79
|
polkadotJS: PolkadotJS;
|
|
80
|
+
metamask: Metamask;
|
|
59
81
|
}, playwright_test.PlaywrightWorkerArgs & playwright_test.PlaywrightWorkerOptions>;
|
|
60
82
|
|
|
61
83
|
export { withWallets };
|
package/dist/index.js
CHANGED
|
@@ -42,7 +42,7 @@ var import_fs = __toESM(require("fs"));
|
|
|
42
42
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
43
43
|
|
|
44
44
|
// src/withWallets.ts
|
|
45
|
-
var
|
|
45
|
+
var import_test4 = require("@playwright/test");
|
|
46
46
|
|
|
47
47
|
// src/backpack/backpack.ts
|
|
48
48
|
var import_test = require("@playwright/test");
|
|
@@ -188,13 +188,87 @@ var PolkadotJS = class extends Wallet {
|
|
|
188
188
|
}
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
+
// src/metamask/metamask.ts
|
|
192
|
+
var import_test3 = require("@playwright/test");
|
|
193
|
+
var Metamask = class extends Wallet {
|
|
194
|
+
defaultPassword = "11111111";
|
|
195
|
+
async gotoOnboardPage() {
|
|
196
|
+
await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
*
|
|
200
|
+
* @param mnemonic 12-word mnemonic seed phrase
|
|
201
|
+
*/
|
|
202
|
+
async onboard(mnemonic, password = this.defaultPassword) {
|
|
203
|
+
await this.page.getByTestId("onboarding-terms-checkbox").click();
|
|
204
|
+
await this.page.getByTestId("onboarding-import-wallet").click();
|
|
205
|
+
await this.page.getByTestId("metametrics-i-agree").click();
|
|
206
|
+
for (const [i, word] of mnemonic.split(" ").entries())
|
|
207
|
+
await this.page.getByTestId(`import-srp__srp-word-${i}`).fill(word);
|
|
208
|
+
await this.page.getByTestId("import-srp-confirm").click();
|
|
209
|
+
await this.page.getByTestId("create-password-new").fill(password);
|
|
210
|
+
await this.page.getByTestId("create-password-confirm").fill(password);
|
|
211
|
+
await this.page.getByTestId("create-password-terms").click();
|
|
212
|
+
await this.page.getByTestId("create-password-import").click();
|
|
213
|
+
await this.page.getByTestId("onboarding-complete-done").click();
|
|
214
|
+
await this.page.getByTestId("pin-extension-next").click();
|
|
215
|
+
await this.page.getByTestId("pin-extension-done").click();
|
|
216
|
+
}
|
|
217
|
+
async connectToNetwork(settings, switchNetwork = true) {
|
|
218
|
+
await this.page.locator(".mm-picker-network").click();
|
|
219
|
+
await this.page.getByRole("button", { name: "Add a custom network" }).click();
|
|
220
|
+
await this.page.getByTestId("network-form-network-name").fill(settings.name);
|
|
221
|
+
await this.page.getByTestId("network-form-chain-id").fill(settings.chainId.toString());
|
|
222
|
+
await this.page.getByTestId("network-form-ticker-input").fill(settings.currencySymbol);
|
|
223
|
+
await this.page.getByTestId("test-add-rpc-drop-down").click();
|
|
224
|
+
await this.page.getByRole("button", { name: "Add RPC URL" }).click();
|
|
225
|
+
await this.page.getByTestId("rpc-url-input-test").fill(settings.rpc);
|
|
226
|
+
await this.page.getByRole("button", { name: "Add URL" }).click();
|
|
227
|
+
await this.page.getByRole("button", { name: "Save" }).click();
|
|
228
|
+
if (switchNetwork) {
|
|
229
|
+
await this.page.locator(".mm-picker-network").click();
|
|
230
|
+
await this.page.getByTestId(settings.name).click();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// async approve() {
|
|
234
|
+
// return this.usingNotificationPage((p) =>
|
|
235
|
+
// p
|
|
236
|
+
// .locator(
|
|
237
|
+
// '[data-test-id="confirm-footer-button"], [data-test-id="confirm-btn"]',
|
|
238
|
+
// )
|
|
239
|
+
// .click(),
|
|
240
|
+
// );
|
|
241
|
+
// }
|
|
242
|
+
async approve() {
|
|
243
|
+
const p = await this.page.context().newPage();
|
|
244
|
+
await p.goto(`chrome-extension://${this.extensionId}/notification.html`);
|
|
245
|
+
await p.locator(
|
|
246
|
+
'[data-testid="confirm-footer-button"], [data-testid="confirm-btn"]'
|
|
247
|
+
).click();
|
|
248
|
+
await p.close();
|
|
249
|
+
}
|
|
250
|
+
async deny() {
|
|
251
|
+
return this.usingNotificationPage(
|
|
252
|
+
(p) => p.getByTestId("cancel-btn").click()
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
async usingNotificationPage(action) {
|
|
256
|
+
const p = await this.page.context().newPage();
|
|
257
|
+
await p.goto(`chrome-extension://${this.extensionId}/notification.html`);
|
|
258
|
+
await action(p);
|
|
259
|
+
await p.close();
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
191
263
|
// src/withWallets.ts
|
|
192
264
|
var w3walletsDir = ".w3wallets";
|
|
193
265
|
function withWallets(test, ...config) {
|
|
194
266
|
const withBackpack = config.includes("backpack");
|
|
195
267
|
const withPolkadotJS = config.includes("polkadotJS");
|
|
268
|
+
const withMetamask = config.includes("metamask");
|
|
196
269
|
const backpackPath = import_path.default.join(process.cwd(), w3walletsDir, "backpack");
|
|
197
270
|
const polkadotJSPath = import_path.default.join(process.cwd(), w3walletsDir, "polkadotJS");
|
|
271
|
+
const metamaskPath = import_path.default.join(process.cwd(), w3walletsDir, "metamask");
|
|
198
272
|
return test.extend({
|
|
199
273
|
/**
|
|
200
274
|
* Sets up a persistent browser context with the requested extensions loaded.
|
|
@@ -216,7 +290,11 @@ function withWallets(test, ...config) {
|
|
|
216
290
|
ensureWalletExtensionExists(polkadotJSPath, "polkadotJS");
|
|
217
291
|
extensionPaths.push(polkadotJSPath);
|
|
218
292
|
}
|
|
219
|
-
|
|
293
|
+
if (withMetamask) {
|
|
294
|
+
ensureWalletExtensionExists(metamaskPath, "metamask");
|
|
295
|
+
extensionPaths.push(metamaskPath);
|
|
296
|
+
}
|
|
297
|
+
const context = await import_test4.chromium.launchPersistentContext(userDataDir, {
|
|
220
298
|
headless: testInfo.project.use.headless ?? true,
|
|
221
299
|
channel: "chromium",
|
|
222
300
|
args: [
|
|
@@ -255,6 +333,19 @@ function withWallets(test, ...config) {
|
|
|
255
333
|
"Polkadot{.js} is not initialized"
|
|
256
334
|
);
|
|
257
335
|
await use(polkadotJS);
|
|
336
|
+
},
|
|
337
|
+
metamask: async ({ context }, use) => {
|
|
338
|
+
if (!withMetamask) {
|
|
339
|
+
throw Error(
|
|
340
|
+
"The Metamask wallet hasn't been loaded. Add it to the withWallets function."
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
const metamask = await initializeExtension(
|
|
344
|
+
context,
|
|
345
|
+
Metamask,
|
|
346
|
+
"Metamask is not initialized"
|
|
347
|
+
);
|
|
348
|
+
await use(metamask);
|
|
258
349
|
}
|
|
259
350
|
});
|
|
260
351
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -154,13 +154,87 @@ var PolkadotJS = class extends Wallet {
|
|
|
154
154
|
}
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
+
// src/metamask/metamask.ts
|
|
158
|
+
import "@playwright/test";
|
|
159
|
+
var Metamask = class extends Wallet {
|
|
160
|
+
defaultPassword = "11111111";
|
|
161
|
+
async gotoOnboardPage() {
|
|
162
|
+
await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
*
|
|
166
|
+
* @param mnemonic 12-word mnemonic seed phrase
|
|
167
|
+
*/
|
|
168
|
+
async onboard(mnemonic, password = this.defaultPassword) {
|
|
169
|
+
await this.page.getByTestId("onboarding-terms-checkbox").click();
|
|
170
|
+
await this.page.getByTestId("onboarding-import-wallet").click();
|
|
171
|
+
await this.page.getByTestId("metametrics-i-agree").click();
|
|
172
|
+
for (const [i, word] of mnemonic.split(" ").entries())
|
|
173
|
+
await this.page.getByTestId(`import-srp__srp-word-${i}`).fill(word);
|
|
174
|
+
await this.page.getByTestId("import-srp-confirm").click();
|
|
175
|
+
await this.page.getByTestId("create-password-new").fill(password);
|
|
176
|
+
await this.page.getByTestId("create-password-confirm").fill(password);
|
|
177
|
+
await this.page.getByTestId("create-password-terms").click();
|
|
178
|
+
await this.page.getByTestId("create-password-import").click();
|
|
179
|
+
await this.page.getByTestId("onboarding-complete-done").click();
|
|
180
|
+
await this.page.getByTestId("pin-extension-next").click();
|
|
181
|
+
await this.page.getByTestId("pin-extension-done").click();
|
|
182
|
+
}
|
|
183
|
+
async connectToNetwork(settings, switchNetwork = true) {
|
|
184
|
+
await this.page.locator(".mm-picker-network").click();
|
|
185
|
+
await this.page.getByRole("button", { name: "Add a custom network" }).click();
|
|
186
|
+
await this.page.getByTestId("network-form-network-name").fill(settings.name);
|
|
187
|
+
await this.page.getByTestId("network-form-chain-id").fill(settings.chainId.toString());
|
|
188
|
+
await this.page.getByTestId("network-form-ticker-input").fill(settings.currencySymbol);
|
|
189
|
+
await this.page.getByTestId("test-add-rpc-drop-down").click();
|
|
190
|
+
await this.page.getByRole("button", { name: "Add RPC URL" }).click();
|
|
191
|
+
await this.page.getByTestId("rpc-url-input-test").fill(settings.rpc);
|
|
192
|
+
await this.page.getByRole("button", { name: "Add URL" }).click();
|
|
193
|
+
await this.page.getByRole("button", { name: "Save" }).click();
|
|
194
|
+
if (switchNetwork) {
|
|
195
|
+
await this.page.locator(".mm-picker-network").click();
|
|
196
|
+
await this.page.getByTestId(settings.name).click();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// async approve() {
|
|
200
|
+
// return this.usingNotificationPage((p) =>
|
|
201
|
+
// p
|
|
202
|
+
// .locator(
|
|
203
|
+
// '[data-test-id="confirm-footer-button"], [data-test-id="confirm-btn"]',
|
|
204
|
+
// )
|
|
205
|
+
// .click(),
|
|
206
|
+
// );
|
|
207
|
+
// }
|
|
208
|
+
async approve() {
|
|
209
|
+
const p = await this.page.context().newPage();
|
|
210
|
+
await p.goto(`chrome-extension://${this.extensionId}/notification.html`);
|
|
211
|
+
await p.locator(
|
|
212
|
+
'[data-testid="confirm-footer-button"], [data-testid="confirm-btn"]'
|
|
213
|
+
).click();
|
|
214
|
+
await p.close();
|
|
215
|
+
}
|
|
216
|
+
async deny() {
|
|
217
|
+
return this.usingNotificationPage(
|
|
218
|
+
(p) => p.getByTestId("cancel-btn").click()
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
async usingNotificationPage(action) {
|
|
222
|
+
const p = await this.page.context().newPage();
|
|
223
|
+
await p.goto(`chrome-extension://${this.extensionId}/notification.html`);
|
|
224
|
+
await action(p);
|
|
225
|
+
await p.close();
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
157
229
|
// src/withWallets.ts
|
|
158
230
|
var w3walletsDir = ".w3wallets";
|
|
159
231
|
function withWallets(test, ...config) {
|
|
160
232
|
const withBackpack = config.includes("backpack");
|
|
161
233
|
const withPolkadotJS = config.includes("polkadotJS");
|
|
234
|
+
const withMetamask = config.includes("metamask");
|
|
162
235
|
const backpackPath = path.join(process.cwd(), w3walletsDir, "backpack");
|
|
163
236
|
const polkadotJSPath = path.join(process.cwd(), w3walletsDir, "polkadotJS");
|
|
237
|
+
const metamaskPath = path.join(process.cwd(), w3walletsDir, "metamask");
|
|
164
238
|
return test.extend({
|
|
165
239
|
/**
|
|
166
240
|
* Sets up a persistent browser context with the requested extensions loaded.
|
|
@@ -182,6 +256,10 @@ function withWallets(test, ...config) {
|
|
|
182
256
|
ensureWalletExtensionExists(polkadotJSPath, "polkadotJS");
|
|
183
257
|
extensionPaths.push(polkadotJSPath);
|
|
184
258
|
}
|
|
259
|
+
if (withMetamask) {
|
|
260
|
+
ensureWalletExtensionExists(metamaskPath, "metamask");
|
|
261
|
+
extensionPaths.push(metamaskPath);
|
|
262
|
+
}
|
|
185
263
|
const context = await chromium.launchPersistentContext(userDataDir, {
|
|
186
264
|
headless: testInfo.project.use.headless ?? true,
|
|
187
265
|
channel: "chromium",
|
|
@@ -221,6 +299,19 @@ function withWallets(test, ...config) {
|
|
|
221
299
|
"Polkadot{.js} is not initialized"
|
|
222
300
|
);
|
|
223
301
|
await use(polkadotJS);
|
|
302
|
+
},
|
|
303
|
+
metamask: async ({ context }, use) => {
|
|
304
|
+
if (!withMetamask) {
|
|
305
|
+
throw Error(
|
|
306
|
+
"The Metamask wallet hasn't been loaded. Add it to the withWallets function."
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
const metamask = await initializeExtension(
|
|
310
|
+
context,
|
|
311
|
+
Metamask,
|
|
312
|
+
"Metamask is not initialized"
|
|
313
|
+
);
|
|
314
|
+
await use(metamask);
|
|
224
315
|
}
|
|
225
316
|
});
|
|
226
317
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "w3wallets",
|
|
3
3
|
"description": "browser wallets for playwright",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.1",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"homepage": "https://github.com/Maksandre/w3wallets",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"e2e",
|
|
18
18
|
"playwright",
|
|
19
19
|
"backpack",
|
|
20
|
+
"metamask",
|
|
20
21
|
"testing",
|
|
21
22
|
"ethereum",
|
|
22
23
|
"polkadot",
|
|
@@ -32,8 +33,9 @@
|
|
|
32
33
|
"bin": "./src/scripts/download.js",
|
|
33
34
|
"scripts": {
|
|
34
35
|
"start:ui": "yarn workspace @w3wallets/test-app buildAndStart",
|
|
35
|
-
"download-wallets": "npx w3wallets backpack polkadotJS",
|
|
36
|
-
"test": "npx playwright test --project=
|
|
36
|
+
"download-wallets": "npx w3wallets backpack polkadotJS metamask",
|
|
37
|
+
"test": "npx playwright test --project=local --workers=2",
|
|
38
|
+
"test:ci": "npx playwright test --project=ci",
|
|
37
39
|
"build": "tsup",
|
|
38
40
|
"clean": "rm -rf dist",
|
|
39
41
|
"check-format": "prettier --check .",
|