create-fhevm-example 1.1.5 → 1.2.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 CHANGED
@@ -48,19 +48,24 @@ npx create-fhevm-example --example fhe-counter --output ./my-project --install
48
48
 
49
49
  **Concepts**: `fhe-access-control`, `fhe-input-proof`, `fhe-handles`, `fhe-anti-patterns`
50
50
 
51
+ **Gaming**: `rock-paper-scissors`, `encrypted-lottery`, `encrypted-poker`
52
+
51
53
  **OpenZeppelin**: `erc7984`, `erc7984-erc20-wrapper`, `swap-erc7984-to-erc20`, `swap-erc7984-to-erc7984`, `vesting-wallet`
52
54
 
53
- **Advanced**: `blind-auction`, `hidden-voting`
55
+ **Advanced**: `blind-auction`, `hidden-voting`, `private-payroll`, `encrypted-escrow`, `private-kyc`
54
56
 
55
57
  ## Available Categories
56
58
 
57
59
  | Category | Description |
58
60
  |----------|-------------|
59
- | `basic` | Encryption, decryption, basic operations (9 contracts) |
60
- | `concepts` | Access control, proofs, handles (4 contracts) |
61
- | `operations` | Arithmetic, comparison operations (4 contracts) |
62
- | `openzeppelin` | ERC7984, wrappers, swaps (5 contracts) |
63
- | `advanced` | Blind auction, voting (2 contracts) |
61
+ | `basic` | Basic encryption and counter examples (1 contract) |
62
+ | `basicencryption` | Single and multiple value encryption (2 contracts) |
63
+ | `basicdecryption` | Public and user decryption examples (4 contracts) |
64
+ | `basicfheoperations` | FHE arithmetic and comparison (4 contracts) |
65
+ | `concepts` | Access control, proofs, handles, anti-patterns (4 contracts) |
66
+ | `gaming` | Rock-paper-scissors, lottery, poker (3 contracts) |
67
+ | `openzeppelin` | ERC7984, wrappers, swaps, vesting (5 contracts) |
68
+ | `advanced` | Blind auction, voting, payroll, escrow, KYC (5 contracts) |
64
69
 
65
70
  ## What Gets Created
66
71
 
@@ -89,6 +94,35 @@ npx create-fhevm-example --example fhe-counter --output ./my-project --install
89
94
 
90
95
  >This section is for contributors and maintainers of the package.
91
96
 
97
+ ### File Structure
98
+
99
+ The package follows a modular structure similar to the main project's `scripts/` directory:
100
+
101
+ ```
102
+ src/
103
+ ├── index.ts # Main entry point + CLI modes (~320 lines)
104
+ ├── builders.ts # createSingleExample, createCategoryProject (~250 lines)
105
+ ├── ui.ts # Interactive prompts + install/test commands (~180 lines)
106
+ ├── utils.ts # Utilities + constants + validation + logging (~350 lines)
107
+ ├── config.ts # Auto-generated examples & categories (~440 lines)
108
+ └── add-mode.ts # Add FHEVM to existing projects (~370 lines)
109
+ ```
110
+
111
+ **Key Components:**
112
+ - `index.ts` - Main CLI entry point, handles interactive and direct modes
113
+ - `builders.ts` - Project creation logic (single example, category project)
114
+ - `ui.ts` - User interface (prompts + commands, replaces old prompts.ts + commands.ts)
115
+ - `utils.ts` - File operations, constants, validation, logging utilities
116
+ - `config.ts` - Auto-generated configuration from monorepo contracts
117
+ - `add-mode.ts` - Add FHEVM to existing Hardhat projects
118
+
119
+ **Design Principles:**
120
+ - **Modular**: Each file has a single responsibility
121
+ - **Aligned**: Mirrors main project's `scripts/` structure
122
+ - **Maintainable**: Easy to understand and update
123
+ - **Type-safe**: Full TypeScript coverage
124
+ - **Consistent**: Standardized logging, error handling, validation
125
+
92
126
  ### Configuration
93
127
 
94
128
  The CLI uses a configuration file that defines all available examples and categories. This file is **auto-generated** by scanning the monorepo's contracts directory.
@@ -153,10 +187,10 @@ npm unlink -g create-fhevm-example
153
187
 
154
188
  ### Scripts
155
189
 
156
- - `npm run build` - Compile TypeScript
157
- - `npm run dev` - Watch mode
158
- - `npm run update:config` - Update config from monorepo contracts
159
- - `npm run prepublishOnly` - Auto-runs update:config + build before publish
190
+ - `npm run build` - Compile TypeScript to `dist/`
191
+ - `npm run dev` - Watch mode for development
192
+ - `npm run update:config` - Regenerate config from monorepo contracts
193
+ - `npm run prepublishOnly` - Auto-runs before publish (update:config + build)
160
194
 
161
195
  ---
162
196
 
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Project Builders
3
+ *
4
+ * Creates single example and category projects from templates.
5
+ * Similar to main project's create-example.ts and create-category.ts
6
+ */
7
+ /**
8
+ * Cleans up template-specific files after copying
9
+ * Similar to cleanupTemplate() in main project's shared/utils.ts
10
+ */
11
+ export declare function cleanupTemplate(outputDir: string): void;
12
+ /**
13
+ * Creates a single example project from the template
14
+ *
15
+ * Steps:
16
+ * 1. Copy template directory and clean up
17
+ * 2. Download contract and test files from GitHub
18
+ * 3. Update package.json and deploy scripts
19
+ */
20
+ export declare function createSingleExample(exampleName: string, outputDir: string, tempRepoPath: string): Promise<void>;
21
+ /**
22
+ * Creates a category project with multiple examples
23
+ *
24
+ * Steps:
25
+ * 1. Copy template directory and clean up
26
+ * 2. Download all contracts and tests for the category
27
+ * 3. Update package.json
28
+ */
29
+ export declare function createCategoryProject(categoryName: string, outputDir: string, tempRepoPath: string): Promise<void>;
30
+ //# sourceMappingURL=builders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkBH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAmDvD;AAoED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAgDf;AAMD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CA4Df"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Project Builders
3
+ *
4
+ * Creates single example and category projects from templates.
5
+ * Similar to main project's create-example.ts and create-category.ts
6
+ */
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import { EXAMPLES, CATEGORIES } from "./config.js";
10
+ import { copyDirectoryRecursive, getContractName, downloadFileFromGitHub, runCommand, generateDeployScript, } from "./utils.js";
11
+ import { TEST_TYPES_CONTENT } from "./utils.js";
12
+ // =============================================================================
13
+ // Template Cleanup
14
+ // =============================================================================
15
+ /**
16
+ * Cleans up template-specific files after copying
17
+ * Similar to cleanupTemplate() in main project's shared/utils.ts
18
+ */
19
+ export function cleanupTemplate(outputDir) {
20
+ // Remove .git directory
21
+ const gitDir = path.join(outputDir, ".git");
22
+ if (fs.existsSync(gitDir)) {
23
+ fs.rmSync(gitDir, { recursive: true, force: true });
24
+ }
25
+ // Remove FHECounter.sol (template example)
26
+ const templateContract = path.join(outputDir, "contracts", "FHECounter.sol");
27
+ if (fs.existsSync(templateContract)) {
28
+ fs.unlinkSync(templateContract);
29
+ }
30
+ // Remove .gitkeep files
31
+ const contractsGitkeep = path.join(outputDir, "contracts", ".gitkeep");
32
+ if (fs.existsSync(contractsGitkeep)) {
33
+ fs.unlinkSync(contractsGitkeep);
34
+ }
35
+ // Clear test directory (remove template tests)
36
+ const testDir = path.join(outputDir, "test");
37
+ if (fs.existsSync(testDir)) {
38
+ fs.readdirSync(testDir).forEach((file) => {
39
+ if (file.endsWith(".ts") || file === ".gitkeep") {
40
+ fs.unlinkSync(path.join(testDir, file));
41
+ }
42
+ });
43
+ }
44
+ // Remove FHECounter task import from hardhat.config.ts
45
+ const configPath = path.join(outputDir, "hardhat.config.ts");
46
+ if (fs.existsSync(configPath)) {
47
+ let configContent = fs.readFileSync(configPath, "utf-8");
48
+ configContent = configContent.replace(/import "\.\/tasks\/FHECounter";\n?/g, "");
49
+ fs.writeFileSync(configPath, configContent);
50
+ }
51
+ // Remove FHECounter task file
52
+ const oldTaskFile = path.join(outputDir, "tasks", "FHECounter.ts");
53
+ if (fs.existsSync(oldTaskFile)) {
54
+ fs.unlinkSync(oldTaskFile);
55
+ }
56
+ // Create test/types.ts for type safety
57
+ fs.writeFileSync(path.join(outputDir, "test", "types.ts"), TEST_TYPES_CONTENT);
58
+ }
59
+ // =============================================================================
60
+ // Helper Functions
61
+ // =============================================================================
62
+ /**
63
+ * Downloads contract dependencies to the output directory
64
+ */
65
+ async function downloadDependencies(dependencies, outputDir) {
66
+ for (const depPath of dependencies) {
67
+ const relativePath = depPath.replace(/^contracts\//, "");
68
+ const depDestPath = path.join(outputDir, "contracts", relativePath);
69
+ const depDestDir = path.dirname(depDestPath);
70
+ if (!fs.existsSync(depDestDir)) {
71
+ fs.mkdirSync(depDestDir, { recursive: true });
72
+ }
73
+ await downloadFileFromGitHub(depPath, depDestPath);
74
+ }
75
+ }
76
+ /**
77
+ * Updates package.json with project name, description, and npm dependencies
78
+ */
79
+ function updatePackageJson(outputDir, projectName, description, npmDependencies) {
80
+ const packageJsonPath = path.join(outputDir, "package.json");
81
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
82
+ packageJson.name = projectName;
83
+ if (description) {
84
+ packageJson.description = description;
85
+ }
86
+ if (npmDependencies && Object.keys(npmDependencies).length > 0) {
87
+ if (!packageJson.dependencies) {
88
+ packageJson.dependencies = {};
89
+ }
90
+ Object.assign(packageJson.dependencies, npmDependencies);
91
+ }
92
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
93
+ }
94
+ /**
95
+ * Initializes git repository (optional, fails silently)
96
+ */
97
+ async function initGitRepo(outputDir) {
98
+ try {
99
+ await runCommand("git", ["init"], outputDir);
100
+ }
101
+ catch (error) {
102
+ // Git init is optional
103
+ }
104
+ }
105
+ // =============================================================================
106
+ // Single Example Builder
107
+ // =============================================================================
108
+ /**
109
+ * Creates a single example project from the template
110
+ *
111
+ * Steps:
112
+ * 1. Copy template directory and clean up
113
+ * 2. Download contract and test files from GitHub
114
+ * 3. Update package.json and deploy scripts
115
+ */
116
+ export async function createSingleExample(exampleName, outputDir, tempRepoPath) {
117
+ const example = EXAMPLES[exampleName];
118
+ if (!example) {
119
+ throw new Error(`Unknown example: ${exampleName}`);
120
+ }
121
+ const templateDir = path.join(tempRepoPath, "fhevm-hardhat-template");
122
+ const contractName = getContractName(example.contract);
123
+ if (!contractName) {
124
+ throw new Error("Could not extract contract name");
125
+ }
126
+ // Step 1: Copy template and clean up
127
+ copyDirectoryRecursive(templateDir, outputDir);
128
+ cleanupTemplate(outputDir);
129
+ // Step 2: Download example contract
130
+ await downloadFileFromGitHub(example.contract, path.join(outputDir, "contracts", `${contractName}.sol`));
131
+ // Download contract dependencies if specified
132
+ if (example.dependencies) {
133
+ await downloadDependencies(example.dependencies, outputDir);
134
+ }
135
+ // Step 3: Download test file
136
+ await downloadFileFromGitHub(example.test, path.join(outputDir, "test", path.basename(example.test)));
137
+ // Step 4: Update deploy script and package.json
138
+ fs.writeFileSync(path.join(outputDir, "deploy", "deploy.ts"), generateDeployScript(contractName));
139
+ updatePackageJson(outputDir, `fhevm-example-${exampleName}`, example.description, example.npmDependencies);
140
+ // Initialize git repository
141
+ await initGitRepo(outputDir);
142
+ }
143
+ // =============================================================================
144
+ // Category Project Builder
145
+ // =============================================================================
146
+ /**
147
+ * Creates a category project with multiple examples
148
+ *
149
+ * Steps:
150
+ * 1. Copy template directory and clean up
151
+ * 2. Download all contracts and tests for the category
152
+ * 3. Update package.json
153
+ */
154
+ export async function createCategoryProject(categoryName, outputDir, tempRepoPath) {
155
+ const category = CATEGORIES[categoryName];
156
+ if (!category) {
157
+ throw new Error(`Unknown category: ${categoryName}`);
158
+ }
159
+ const templateDir = path.join(tempRepoPath, "fhevm-hardhat-template");
160
+ // Step 1: Copy template and clean up
161
+ copyDirectoryRecursive(templateDir, outputDir);
162
+ cleanupTemplate(outputDir);
163
+ // Step 2: Download all contracts and tests
164
+ for (const item of category.contracts) {
165
+ const contractName = getContractName(item.sol);
166
+ if (contractName) {
167
+ await downloadFileFromGitHub(item.sol, path.join(outputDir, "contracts", `${contractName}.sol`));
168
+ }
169
+ if (item.test) {
170
+ await downloadFileFromGitHub(item.test, path.join(outputDir, "test", path.basename(item.test)));
171
+ }
172
+ }
173
+ // Collect dependencies from all examples in this category
174
+ const allDependencies = new Set();
175
+ const allNpmDependencies = {};
176
+ for (const [exampleName, exampleConfig] of Object.entries(EXAMPLES)) {
177
+ if (exampleConfig.category === category.name.replace(" Examples", "")) {
178
+ if (exampleConfig.dependencies) {
179
+ exampleConfig.dependencies.forEach((dep) => allDependencies.add(dep));
180
+ }
181
+ if (exampleConfig.npmDependencies) {
182
+ Object.assign(allNpmDependencies, exampleConfig.npmDependencies);
183
+ }
184
+ }
185
+ }
186
+ // Download all collected dependencies
187
+ if (allDependencies.size > 0) {
188
+ await downloadDependencies(Array.from(allDependencies), outputDir);
189
+ }
190
+ // Step 3: Update package.json
191
+ updatePackageJson(outputDir, `fhevm-examples-${categoryName}`, undefined, allNpmDependencies);
192
+ // Initialize git repository
193
+ await initGitRepo(outputDir);
194
+ }
195
+ //# sourceMappingURL=builders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builders.js","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Command Execution & Install/Test
3
+ *
4
+ * Runs npm install, compile, and test commands.
5
+ * Similar to main project's shared/commands.ts
6
+ */
7
+ /**
8
+ * Runs npm install, compile, and test in the project directory
9
+ */
10
+ export declare function runInstallAndTest(projectPath: string): Promise<void>;
11
+ /**
12
+ * Shows quick start commands for the created project
13
+ */
14
+ export declare function showQuickStart(relativePath: string): void;
15
+ /**
16
+ * Asks user if they want to install and test, then runs or shows quick start
17
+ */
18
+ export declare function askInstallAndTest(resolvedOutput: string, relativePath: string): Promise<void>;
19
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiD1E;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAOzD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAiBf"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Command Execution & Install/Test
3
+ *
4
+ * Runs npm install, compile, and test commands.
5
+ * Similar to main project's shared/commands.ts
6
+ */
7
+ import * as p from "@clack/prompts";
8
+ import pc from "picocolors";
9
+ import { runCommand, extractTestResults } from "./utils.js";
10
+ // =============================================================================
11
+ // Install & Test
12
+ // =============================================================================
13
+ /**
14
+ * Runs npm install, compile, and test in the project directory
15
+ */
16
+ export async function runInstallAndTest(projectPath) {
17
+ const steps = [
18
+ {
19
+ name: "Installing dependencies",
20
+ cmd: "npm",
21
+ args: ["install"],
22
+ showOutput: false,
23
+ },
24
+ {
25
+ name: "Compiling contracts",
26
+ cmd: "npm",
27
+ args: ["run", "compile"],
28
+ showOutput: false,
29
+ },
30
+ {
31
+ name: "Running tests",
32
+ cmd: "npm",
33
+ args: ["run", "test"],
34
+ showOutput: true,
35
+ },
36
+ ];
37
+ for (const step of steps) {
38
+ const s = p.spinner();
39
+ s.start(step.name + "...");
40
+ try {
41
+ const output = await runCommand(step.cmd, step.args, projectPath);
42
+ if (step.showOutput) {
43
+ const testResults = extractTestResults(output);
44
+ s.stop(testResults
45
+ ? pc.green(`✓ ${step.name} - ${testResults}`)
46
+ : pc.green(`✓ ${step.name} completed`));
47
+ }
48
+ else {
49
+ s.stop(pc.green(`✓ ${step.name} completed`));
50
+ }
51
+ }
52
+ catch (error) {
53
+ s.stop(pc.red(`✗ ${step.name} failed`));
54
+ if (error instanceof Error) {
55
+ p.log.error(error.message);
56
+ }
57
+ throw new Error(`${step.name} failed`);
58
+ }
59
+ }
60
+ p.log.success(pc.green("All steps completed successfully!"));
61
+ }
62
+ // =============================================================================
63
+ // Quick Start Display
64
+ // =============================================================================
65
+ /**
66
+ * Shows quick start commands for the created project
67
+ */
68
+ export function showQuickStart(relativePath) {
69
+ p.note(`${pc.dim("$")} cd ${relativePath}\n${pc.dim("$")} npm install\n${pc.dim("$")} npm run compile\n${pc.dim("$")} npm run test`, "🚀 Quick Start");
70
+ }
71
+ /**
72
+ * Asks user if they want to install and test, then runs or shows quick start
73
+ */
74
+ export async function askInstallAndTest(resolvedOutput, relativePath) {
75
+ const shouldInstall = await p.confirm({
76
+ message: "Install dependencies and run tests?",
77
+ initialValue: false,
78
+ });
79
+ if (p.isCancel(shouldInstall)) {
80
+ showQuickStart(relativePath);
81
+ return;
82
+ }
83
+ if (shouldInstall) {
84
+ p.log.message("");
85
+ await runInstallAndTest(resolvedOutput);
86
+ }
87
+ else {
88
+ showQuickStart(relativePath);
89
+ }
90
+ }
91
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Shared constants for the CLI
3
+ */
4
+ /**
5
+ * Simple folder icon for all categories
6
+ */
7
+ export declare const CATEGORY_ICON = "\uD83D\uDCC1";
8
+ /**
9
+ * Display order for example categories in the interactive prompt
10
+ */
11
+ export declare const CATEGORY_ORDER: string[];
12
+ /**
13
+ * Content for test/types.ts file
14
+ */
15
+ export declare const TEST_TYPES_CONTENT = "import type { HardhatEthersSigner } from \"@nomicfoundation/hardhat-ethers/signers\";\n\n/**\n * Common signers interface used across test files\n */\nexport interface Signers {\n owner: HardhatEthersSigner;\n alice: HardhatEthersSigner;\n}\n";
16
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;GAEG;AACH,eAAO,MAAM,aAAa,iBAAO,CAAC;AAElC;;GAEG;AACH,eAAO,MAAM,cAAc,UAS1B,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,kBAAkB,yPAS9B,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Shared constants for the CLI
3
+ */
4
+ // =============================================================================
5
+ // Category Display
6
+ // =============================================================================
7
+ /**
8
+ * Simple folder icon for all categories
9
+ */
10
+ export const CATEGORY_ICON = "📁";
11
+ /**
12
+ * Display order for example categories in the interactive prompt
13
+ */
14
+ export const CATEGORY_ORDER = [
15
+ "Basic",
16
+ "Basic - Encryption",
17
+ "Basic - Decryption",
18
+ "Basic - FHE Operations",
19
+ "Concepts",
20
+ "Gaming",
21
+ "Openzeppelin",
22
+ "Advanced",
23
+ ];
24
+ // =============================================================================
25
+ // Template Content
26
+ // =============================================================================
27
+ /**
28
+ * Content for test/types.ts file
29
+ */
30
+ export const TEST_TYPES_CONTENT = `import type { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
31
+
32
+ /**
33
+ * Common signers interface used across test files
34
+ */
35
+ export interface Signers {
36
+ owner: HardhatEthersSigner;
37
+ alice: HardhatEthersSigner;
38
+ }
39
+ `;
40
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,OAAO;IACP,oBAAoB;IACpB,oBAAoB;IACpB,wBAAwB;IACxB,UAAU;IACV,QAAQ;IACR,cAAc;IACd,UAAU;CACX,CAAC;AAEF,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;CASjC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -6,17 +6,15 @@
6
6
  * npx create-fhevm-example # Interactive mode
7
7
  * npx create-fhevm-example --example <name> # Create single example
8
8
  * npx create-fhevm-example --category <name> # Create category project
9
+ * npx create-fhevm-example --add # Add to existing project
9
10
  *
10
- * FILE STRUCTURE:
11
- * ================
12
- * 1. IMPORTS
13
- * 2. CONSTANTS - Category icons, order, etc.
14
- * 3. PROJECT BUILDERS - createSingleExample, createCategoryProject
15
- * 4. PROMPT HELPERS - Category/example selection prompts
16
- * 5. INSTALL & TEST - Build and test utilities
17
- * 6. INTERACTIVE MODE - Main interactive flow
18
- * 7. DIRECT MODE - CLI argument handling
19
- * 8. MAIN ENTRY POINT
11
+ * This is the main entry point - similar to scripts/create.ts in main project.
12
+ * Actual logic is split into:
13
+ * - builders.ts (createSingleExample, createCategoryProject)
14
+ * - ui.ts (prompts + commands)
15
+ * - utils.ts (file operations + constants + utilities)
16
+ * - config.ts (examples & categories)
17
+ * - add-mode.ts (add to existing project)
20
18
  */
21
19
  export {};
22
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;GAkBG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;GAgBG"}