create-fhevm-playground-pro 1.0.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 +11 -0
- package/README.package.md +11 -0
- package/base-template/README.md +11 -0
- package/base-template/contracts/SimpleCounterPremium.sol +14 -0
- package/base-template/hardhat.config.ts +13 -0
- package/base-template/package.json +14 -0
- package/base-template/scripts/deploy.ts +10 -0
- package/base-template/test/simple-counter.test.ts +7 -0
- package/dist/create-example.js +147 -0
- package/dist/index.js +18 -0
- package/dist/scaffolder.js +51 -0
- package/dist/templates-index.js +30 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# create-fhevm-playground-pro
|
|
2
|
+
|
|
3
|
+
Premium scaffolding CLI for fhEVM Playground Pro ā Zama bounty (Dec 2025).
|
|
4
|
+
|
|
5
|
+
Install and run the guided onboarding with:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-fhevm-playground-pro guided
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
See the full project site and GitHub repository for more details.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# create-fhevm-playground-pro (npm package)
|
|
2
|
+
|
|
3
|
+
Lightweight CLI to scaffold fhEVM example projects and run an interactive guided onboarding.
|
|
4
|
+
|
|
5
|
+
Install and run the guided onboarding:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-fhevm-playground-pro guided
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
After publishing, the package exposes a single binary: `create-fhevm-playground-pro`.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.24;
|
|
3
|
+
|
|
4
|
+
contract SimpleCounterPremium {
|
|
5
|
+
uint256 private count;
|
|
6
|
+
|
|
7
|
+
function increment() public {
|
|
8
|
+
count += 1;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getCount() public view returns (uint256) {
|
|
12
|
+
return count;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HardhatUserConfig } from 'hardhat/config';
|
|
2
|
+
import '@nomicfoundation/hardhat-toolbox';
|
|
3
|
+
|
|
4
|
+
const config: HardhatUserConfig = {
|
|
5
|
+
solidity: '0.8.24',
|
|
6
|
+
paths: {
|
|
7
|
+
sources: './contracts',
|
|
8
|
+
tests: './test',
|
|
9
|
+
artifacts: './artifacts'
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default config;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fhEVM-example-template",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Base template for fhEVM example projects",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Run Hardhat tests\" && exit 0",
|
|
7
|
+
"compile": "hardhat compile"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"hardhat": "^2.19.4",
|
|
11
|
+
"typescript": "^5.5.0",
|
|
12
|
+
"ts-node": "^10.9.1"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
/**
|
|
8
|
+
* CLI entry for create-fhevm-playground-pro
|
|
9
|
+
* Provides `create` and `guided` commands.
|
|
10
|
+
*/
|
|
11
|
+
const commander_1 = require("commander");
|
|
12
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
13
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
14
|
+
const scaffolder_js_1 = require("./scaffolder.js");
|
|
15
|
+
const templates_index_js_1 = require("./templates-index.js");
|
|
16
|
+
const program = new commander_1.Command();
|
|
17
|
+
program
|
|
18
|
+
.name('create-fhevm-playground-pro')
|
|
19
|
+
.description('Premium CLI scaffolding tool for fhEVM examples')
|
|
20
|
+
.version('1.0.0');
|
|
21
|
+
program
|
|
22
|
+
.command('create')
|
|
23
|
+
.description('Create a new fhEVM example project')
|
|
24
|
+
.requiredOption('-n, --name <name>', 'Project name (e.g., my-counter)')
|
|
25
|
+
.requiredOption('-c, --category <category>', `Category: ${templates_index_js_1.CATEGORIES.map((c) => c.id).join(', ')}`)
|
|
26
|
+
.option('-p, --pro', 'Create PRO bonus example (unlocks pro categories)')
|
|
27
|
+
.action(async (options) => {
|
|
28
|
+
try {
|
|
29
|
+
console.log(chalk_1.default.cyan.bold('\nš fhEVM Playground Pro - Project Generator\n'));
|
|
30
|
+
if (!templates_index_js_1.CATEGORIES.find((cat) => cat.id === options.category)) {
|
|
31
|
+
console.error(chalk_1.default.red(`ā Unknown category: ${options.category}`));
|
|
32
|
+
console.log(chalk_1.default.yellow(`Available categories:\n${templates_index_js_1.CATEGORIES.map((c) => c.id).join(', ')}`));
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
const category = templates_index_js_1.CATEGORIES.find((cat) => cat.id === options.category);
|
|
36
|
+
if (category?.isPro && !options.pro) {
|
|
37
|
+
console.error(chalk_1.default.red(`ā Category "${options.category}" is PRO only. Add --pro flag.`));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
await (0, scaffolder_js_1.createExample)({ name: options.name, category: options.category, isPro: !!options.pro });
|
|
41
|
+
console.log(chalk_1.default.green.bold('\nā
Project created successfully!\n'));
|
|
42
|
+
console.log(chalk_1.default.cyan('Next steps:'));
|
|
43
|
+
console.log(chalk_1.default.white(` cd ${options.name}`));
|
|
44
|
+
console.log(chalk_1.default.white(' npm install'));
|
|
45
|
+
console.log(chalk_1.default.white(' npm run test\n'));
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error(chalk_1.default.red(`\nā Error: ${error instanceof Error ? error.message : String(error)}\n`));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
// Guided command per specification
|
|
53
|
+
program
|
|
54
|
+
.command('guided')
|
|
55
|
+
.description('Interactive guided onboarding for fhEVM Playground Pro')
|
|
56
|
+
.action(async () => {
|
|
57
|
+
try {
|
|
58
|
+
console.clear();
|
|
59
|
+
console.log(chalk_1.default.cyan.bold('š Welcome to fhEVM Playground Pro š'));
|
|
60
|
+
// Exact educational paragraph
|
|
61
|
+
console.log(chalk_1.default.white("Fully Homomorphic Encryption (FHE) enables computation on encrypted data without decryption ā a breakthrough for blockchain privacy. Zama's fhEVM brings this power to Ethereum-compatible chains, allowing confidential balances, private voting, blind auctions, MEV-resistant DeFi, and more, all while preserving verifiability. fhEVM Playground Pro is the premium, fully automated example hub built for Zama's December 2025 bounty: 12 core concept examples covering every fundamental + 7 innovative real-world Pro applications in confidential finance, governance, and gaming. Let's dive in and build something private!"));
|
|
62
|
+
// Ask which path
|
|
63
|
+
const { pathChoice } = await inquirer_1.default.prompt([
|
|
64
|
+
{
|
|
65
|
+
type: 'list',
|
|
66
|
+
name: 'pathChoice',
|
|
67
|
+
message: 'What would you like to explore first?',
|
|
68
|
+
choices: [
|
|
69
|
+
'1. Core Concepts (Master fhEVM fundamentals ā 12 examples)',
|
|
70
|
+
'2. Innovative Pro Apps (Real-world confidential apps ā 7 examples)'
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
]);
|
|
74
|
+
const coreList = [
|
|
75
|
+
{ title: 'Basic Counter ā Encrypted increment & view', id: 'basic-counter' },
|
|
76
|
+
{ title: 'Arithmetic Operations ā Add, sub, mul on encrypted values', id: 'arithmetic' },
|
|
77
|
+
{ title: 'Comparisons & Inequalities ā eq, gt, lt on encrypted data', id: 'comparisons' },
|
|
78
|
+
{ title: 'Encryption & Decryption ā Single/multiple values', id: 'single-encryption' },
|
|
79
|
+
{ title: 'Access Control ā FHE.allow & allowTransient', id: 'access-control' },
|
|
80
|
+
{ title: 'Input Proofs ā Why and how to verify client inputs', id: 'input-verification-proofs' },
|
|
81
|
+
{ title: 'Anti-Patterns & Edge Cases ā Common mistakes to avoid', id: 'anti-patterns-guide' },
|
|
82
|
+
{ title: 'Handles & Lifecycle ā Symbolic execution and management', id: 'handles-lifecycle' },
|
|
83
|
+
{ title: 'OpenZeppelin ERC7984 ā Confidential tokens standard', id: 'oz-erc7984-basic' },
|
|
84
|
+
{ title: 'OZ Wrappers & Swaps ā ERC20 ā Confidential conversions', id: 'oz-erc20-wrapper' },
|
|
85
|
+
{ title: 'Confidential Vesting Wallet', id: 'vesting' },
|
|
86
|
+
{ title: 'Blind Auction Pro ā Sealed encrypted bids', id: 'blind-auction' }
|
|
87
|
+
];
|
|
88
|
+
const proList = [
|
|
89
|
+
{ title: 'Confidential DAO Voting ā Private votes, homomorphic tally', id: 'dao-voting-pro' },
|
|
90
|
+
{ title: 'Private Lending Pool ā Encrypted loans & collateral', id: 'private-lending-pro' },
|
|
91
|
+
{ title: 'Blind DEX Order Book ā MEV-resistant private trades', id: 'blind-dex-pro' },
|
|
92
|
+
{ title: 'Encrypted Poker Game ā Hidden hands, fair on-chain play', id: 'poker-game-pro' },
|
|
93
|
+
{ title: 'Private Yield Farming ā Confidential positions & rewards', id: 'yield-farming-pro' },
|
|
94
|
+
{ title: 'MEV-Resistant Arbitrage ā Blind opportunity execution', id: 'mev-arbitrage-pro' },
|
|
95
|
+
{ title: 'Confidential Stablecoin ā Private mint/burn with compliance', id: 'confidential-stablecoin-pro' }
|
|
96
|
+
];
|
|
97
|
+
const chosenList = pathChoice.startsWith('1') ? coreList : proList;
|
|
98
|
+
console.log('\n');
|
|
99
|
+
chosenList.forEach((item, idx) => {
|
|
100
|
+
const num = (idx + 1).toString();
|
|
101
|
+
console.log(`${chalk_1.default.cyan(num + '.')} ${chalk_1.default.white(item.title)}`);
|
|
102
|
+
});
|
|
103
|
+
const { selection } = await inquirer_1.default.prompt([
|
|
104
|
+
{
|
|
105
|
+
type: 'input',
|
|
106
|
+
name: 'selection',
|
|
107
|
+
message: 'Type the number of the example you want to create:',
|
|
108
|
+
validate: (input) => {
|
|
109
|
+
const n = Number(input);
|
|
110
|
+
if (!Number.isInteger(n) || n < 1 || n > chosenList.length) {
|
|
111
|
+
return `Please enter a number between 1 and ${chosenList.length}`;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
]);
|
|
117
|
+
const idx = Number(selection) - 1;
|
|
118
|
+
const chosen = chosenList[idx];
|
|
119
|
+
if (!chosen) {
|
|
120
|
+
console.error(chalk_1.default.red('\nā Invalid selection. Exiting.'));
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
const projectName = `${chosen.id.replace(/[^a-z0-9-]/g, '')}-example`;
|
|
124
|
+
const isPro = pathChoice.startsWith('2');
|
|
125
|
+
console.log(chalk_1.default.cyan(`\nCreating example: ${chosen.title}`));
|
|
126
|
+
try {
|
|
127
|
+
await (0, scaffolder_js_1.createExample)({ name: projectName, category: chosen.id, isPro });
|
|
128
|
+
console.log(chalk_1.default.green.bold(`\nā
Created ${projectName}`));
|
|
129
|
+
console.log(chalk_1.default.cyan('\nNext steps:'));
|
|
130
|
+
console.log(chalk_1.default.white(` cd ${projectName}`));
|
|
131
|
+
console.log(chalk_1.default.white(' npm install'));
|
|
132
|
+
console.log(chalk_1.default.white(' npm test (use MOCK=true for mocked mode)'));
|
|
133
|
+
console.log(chalk_1.default.white('\n To run with a real fhEVM node, see the project README or run the provided Docker script.'));
|
|
134
|
+
console.log(chalk_1.default.white('\nRun `npx create-fhevm-playground-pro guided` again to create another example.'));
|
|
135
|
+
console.log(chalk_1.default.white('\nProject site: https://example.com/fhevm-playground-pro (placeholder)\n'));
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
console.error(chalk_1.default.red.bold(`\nā Creation failed: ${err?.message || String(err)}`));
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
console.error(chalk_1.default.red(`\nā Error: ${err?.message || String(err)}`));
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
program.parse();
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Re-export for ESM/CJS compatibility; not used directly but keeps imports stable
|
|
18
|
+
__exportStar(require("./create-example"), exports);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createExample = createExample;
|
|
7
|
+
/**
|
|
8
|
+
* Minimal scaffolder used by the CLI.
|
|
9
|
+
* Copies `base-template/` into a new project folder, updates package.json and README.
|
|
10
|
+
*/
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
|
+
const child_process_1 = require("child_process");
|
|
14
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
15
|
+
async function createExample(options) {
|
|
16
|
+
const projectDir = path_1.default.resolve(process.cwd(), options.name);
|
|
17
|
+
if (fs_extra_1.default.existsSync(projectDir)) {
|
|
18
|
+
throw new Error(`Directory ${options.name} already exists`);
|
|
19
|
+
}
|
|
20
|
+
const srcTemplate = path_1.default.resolve(__dirname, '..', 'base-template');
|
|
21
|
+
if (!fs_extra_1.default.existsSync(srcTemplate)) {
|
|
22
|
+
throw new Error('base-template not found in package. Ensure base-template/ is published.');
|
|
23
|
+
}
|
|
24
|
+
// Copy template
|
|
25
|
+
fs_extra_1.default.copySync(srcTemplate, projectDir);
|
|
26
|
+
// Update package.json name and description
|
|
27
|
+
const pkgPath = path_1.default.join(projectDir, 'package.json');
|
|
28
|
+
if (fs_extra_1.default.existsSync(pkgPath)) {
|
|
29
|
+
const pkg = fs_extra_1.default.readJsonSync(pkgPath);
|
|
30
|
+
pkg.name = options.name;
|
|
31
|
+
pkg.description = `${options.category} - fhEVM example (scaffolded)`;
|
|
32
|
+
fs_extra_1.default.writeJsonSync(pkgPath, pkg, { spaces: 2 });
|
|
33
|
+
}
|
|
34
|
+
// Update README to mention category
|
|
35
|
+
const readmePath = path_1.default.join(projectDir, 'README.md');
|
|
36
|
+
if (fs_extra_1.default.existsSync(readmePath)) {
|
|
37
|
+
let r = fs_extra_1.default.readFileSync(readmePath, 'utf-8');
|
|
38
|
+
r = `# ${options.name}\n\nCategory: ${options.category}\n\n` + r;
|
|
39
|
+
fs_extra_1.default.writeFileSync(readmePath, r, 'utf-8');
|
|
40
|
+
}
|
|
41
|
+
// Initialize git if available
|
|
42
|
+
try {
|
|
43
|
+
(0, child_process_1.execSync)('git init', { cwd: projectDir, stdio: 'ignore' });
|
|
44
|
+
(0, child_process_1.execSync)('git add .', { cwd: projectDir, stdio: 'ignore' });
|
|
45
|
+
(0, child_process_1.execSync)('git commit -m "Initial commit: fhEVM example"', { cwd: projectDir, stdio: 'ignore' });
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
// ignore git errors
|
|
49
|
+
}
|
|
50
|
+
console.log(chalk_1.default.green(`Project scaffolded at ${projectDir}`));
|
|
51
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CATEGORIES = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Minimal templates index used by the CLI to display available categories.
|
|
6
|
+
* This mirrors the central-repo categories minimally for CLI prompts.
|
|
7
|
+
*/
|
|
8
|
+
exports.CATEGORIES = [
|
|
9
|
+
// Core (non-pro) categories (short list used for validation)
|
|
10
|
+
{ id: 'basic-counter', name: 'Basic Counter', isPro: false },
|
|
11
|
+
{ id: 'arithmetic', name: 'Arithmetic Operations', isPro: false },
|
|
12
|
+
{ id: 'comparisons', name: 'Comparisons', isPro: false },
|
|
13
|
+
{ id: 'single-encryption', name: 'Single Encryption', isPro: false },
|
|
14
|
+
{ id: 'access-control', name: 'Access Control', isPro: false },
|
|
15
|
+
{ id: 'input-verification-proofs', name: 'Input Proofs', isPro: false },
|
|
16
|
+
{ id: 'anti-patterns-guide', name: 'Anti-Patterns Guide', isPro: false },
|
|
17
|
+
{ id: 'handles-lifecycle', name: 'Handles Lifecycle', isPro: false },
|
|
18
|
+
{ id: 'oz-erc7984-basic', name: 'OpenZeppelin ERC7984 Basic', isPro: false },
|
|
19
|
+
{ id: 'oz-erc20-wrapper', name: 'OZ ERC20 Wrapper', isPro: false },
|
|
20
|
+
{ id: 'vesting', name: 'Vesting', isPro: false },
|
|
21
|
+
{ id: 'blind-auction', name: 'Blind Auction', isPro: false },
|
|
22
|
+
// Pro categories
|
|
23
|
+
{ id: 'dao-voting-pro', name: 'DAO Voting Pro', isPro: true },
|
|
24
|
+
{ id: 'private-lending-pro', name: 'Private Lending Pro', isPro: true },
|
|
25
|
+
{ id: 'blind-dex-pro', name: 'Blind DEX Pro', isPro: true },
|
|
26
|
+
{ id: 'poker-game-pro', name: 'Poker Game Pro', isPro: true },
|
|
27
|
+
{ id: 'yield-farming-pro', name: 'Yield Farming Pro', isPro: true },
|
|
28
|
+
{ id: 'mev-arbitrage-pro', name: 'MEV Arbitrage Pro', isPro: true },
|
|
29
|
+
{ id: 'confidential-stablecoin-pro', name: 'Confidential Stablecoin Pro', isPro: true }
|
|
30
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-fhevm-playground-pro",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Premium scaffolding CLI for fhEVM Playground Pro ā Zama bounty",
|
|
5
|
+
"main": "dist/create-example.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-fhevm-playground-pro": "./dist/create-example.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/",
|
|
11
|
+
"base-template/"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"keywords": ["fhEVM","FHE","scaffold","cli","zama"],
|
|
18
|
+
"author": "",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"commander": "^11.0.0",
|
|
22
|
+
"chalk": "^5.3.0",
|
|
23
|
+
"inquirer": "^9.2.7",
|
|
24
|
+
"fs-extra": "^11.1.1"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"typescript": "^5.5.0",
|
|
28
|
+
"@types/node": "^20.5.0",
|
|
29
|
+
"@types/inquirer": "^9.0.6",
|
|
30
|
+
"@types/fs-extra": "^11.0.1"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
35
|
+
}
|