create-izi-noir 0.2.0 → 0.2.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/dist/index.js +181 -35
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
7
|
import path2 from "path";
|
|
8
8
|
import { execSync } from "child_process";
|
|
9
|
-
import
|
|
9
|
+
import pc4 from "picocolors";
|
|
10
10
|
|
|
11
11
|
// src/prompts/project.ts
|
|
12
12
|
import prompts from "prompts";
|
|
@@ -153,6 +153,149 @@ function createSpinner(message) {
|
|
|
153
153
|
return new Spinner(message);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
// src/utils/progress.ts
|
|
157
|
+
import pc3 from "picocolors";
|
|
158
|
+
var THINKING_PHRASES = [
|
|
159
|
+
"Initializing ZK environment",
|
|
160
|
+
"Configuring proof system",
|
|
161
|
+
"Setting up circuit compiler",
|
|
162
|
+
"Preparing cryptographic primitives",
|
|
163
|
+
"Generating project scaffold",
|
|
164
|
+
"Configuring Noir integration",
|
|
165
|
+
"Setting up React components",
|
|
166
|
+
"Preparing WASM bindings"
|
|
167
|
+
];
|
|
168
|
+
var FILE_ICONS = {
|
|
169
|
+
".json": "\u{1F4E6}",
|
|
170
|
+
".ts": "\u{1F4DC}",
|
|
171
|
+
".tsx": "\u269B\uFE0F",
|
|
172
|
+
".css": "\u{1F3A8}",
|
|
173
|
+
".html": "\u{1F310}",
|
|
174
|
+
".md": "\u{1F4DD}",
|
|
175
|
+
".svg": "\u{1F5BC}\uFE0F",
|
|
176
|
+
default: "\u{1F4C4}"
|
|
177
|
+
};
|
|
178
|
+
function getFileIcon(filename) {
|
|
179
|
+
const ext = filename.slice(filename.lastIndexOf("."));
|
|
180
|
+
return FILE_ICONS[ext] || FILE_ICONS.default;
|
|
181
|
+
}
|
|
182
|
+
function sleep(ms) {
|
|
183
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
184
|
+
}
|
|
185
|
+
var ProgressReporter = class {
|
|
186
|
+
currentLine = "";
|
|
187
|
+
thinkingIndex = 0;
|
|
188
|
+
thinkingInterval = null;
|
|
189
|
+
async startThinking() {
|
|
190
|
+
process.stdout.write("\x1B[?25l");
|
|
191
|
+
this.showThinking();
|
|
192
|
+
}
|
|
193
|
+
showThinking() {
|
|
194
|
+
const frames2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
195
|
+
let frameIndex = 0;
|
|
196
|
+
let dotCount = 0;
|
|
197
|
+
this.thinkingInterval = setInterval(() => {
|
|
198
|
+
const frame = pc3.cyan(frames2[frameIndex]);
|
|
199
|
+
const phrase = THINKING_PHRASES[this.thinkingIndex % THINKING_PHRASES.length];
|
|
200
|
+
const dots = ".".repeat(dotCount % 4);
|
|
201
|
+
process.stdout.write(`\r${frame} ${pc3.dim(phrase)}${dots} `);
|
|
202
|
+
frameIndex = (frameIndex + 1) % frames2.length;
|
|
203
|
+
dotCount++;
|
|
204
|
+
if (dotCount % 12 === 0) {
|
|
205
|
+
this.thinkingIndex++;
|
|
206
|
+
}
|
|
207
|
+
}, 80);
|
|
208
|
+
}
|
|
209
|
+
stopThinking() {
|
|
210
|
+
if (this.thinkingInterval) {
|
|
211
|
+
clearInterval(this.thinkingInterval);
|
|
212
|
+
this.thinkingInterval = null;
|
|
213
|
+
}
|
|
214
|
+
process.stdout.write("\r\x1B[K");
|
|
215
|
+
}
|
|
216
|
+
async reportFile(filename, isLast = false) {
|
|
217
|
+
const icon = getFileIcon(filename);
|
|
218
|
+
const line = ` ${icon} ${pc3.dim("created")} ${pc3.white(filename)}`;
|
|
219
|
+
process.stdout.write(" " + icon + " " + pc3.dim("created") + " ");
|
|
220
|
+
for (const char of filename) {
|
|
221
|
+
process.stdout.write(pc3.white(char));
|
|
222
|
+
await sleep(8 + Math.random() * 12);
|
|
223
|
+
}
|
|
224
|
+
process.stdout.write("\n");
|
|
225
|
+
this.currentLine = line;
|
|
226
|
+
}
|
|
227
|
+
async reportDirectory(dirname) {
|
|
228
|
+
process.stdout.write(` \u{1F4C1} ${pc3.dim("mkdir")} ${pc3.blue(dirname)}/
|
|
229
|
+
`);
|
|
230
|
+
await sleep(30);
|
|
231
|
+
}
|
|
232
|
+
showSuccess(message) {
|
|
233
|
+
process.stdout.write("\x1B[?25h");
|
|
234
|
+
console.log();
|
|
235
|
+
console.log(pc3.green("\u2713") + " " + message);
|
|
236
|
+
}
|
|
237
|
+
showError(message) {
|
|
238
|
+
process.stdout.write("\x1B[?25h");
|
|
239
|
+
console.log();
|
|
240
|
+
console.log(pc3.red("\u2717") + " " + message);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
function createProgressReporter() {
|
|
244
|
+
return new ProgressReporter();
|
|
245
|
+
}
|
|
246
|
+
var InstallProgress = class {
|
|
247
|
+
interval = null;
|
|
248
|
+
progress = 0;
|
|
249
|
+
packages = [
|
|
250
|
+
"react",
|
|
251
|
+
"react-dom",
|
|
252
|
+
"vite",
|
|
253
|
+
"@izi-noir/sdk",
|
|
254
|
+
"@noir-lang/acvm_js",
|
|
255
|
+
"@noir-lang/noirc_abi",
|
|
256
|
+
"prism-react-renderer",
|
|
257
|
+
"typescript"
|
|
258
|
+
];
|
|
259
|
+
currentPackage = 0;
|
|
260
|
+
start() {
|
|
261
|
+
process.stdout.write("\x1B[?25l");
|
|
262
|
+
const barWidth = 30;
|
|
263
|
+
const frames2 = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
|
|
264
|
+
let frameIndex = 0;
|
|
265
|
+
this.interval = setInterval(() => {
|
|
266
|
+
const frame = pc3.cyan(frames2[frameIndex]);
|
|
267
|
+
const filled = Math.floor(this.progress / 100 * barWidth);
|
|
268
|
+
const empty = barWidth - filled;
|
|
269
|
+
const bar = pc3.green("\u2588".repeat(filled)) + pc3.dim("\u2591".repeat(empty));
|
|
270
|
+
const pkg = this.packages[this.currentPackage % this.packages.length];
|
|
271
|
+
process.stdout.write(
|
|
272
|
+
`\r${frame} Installing dependencies ${bar} ${pc3.dim(pkg)} `
|
|
273
|
+
);
|
|
274
|
+
frameIndex = (frameIndex + 1) % frames2.length;
|
|
275
|
+
if (this.progress < 95) {
|
|
276
|
+
this.progress += Math.random() * 3;
|
|
277
|
+
if (this.progress > (this.currentPackage + 1) * 12) {
|
|
278
|
+
this.currentPackage++;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}, 100);
|
|
282
|
+
}
|
|
283
|
+
stop(success = true) {
|
|
284
|
+
if (this.interval) {
|
|
285
|
+
clearInterval(this.interval);
|
|
286
|
+
this.interval = null;
|
|
287
|
+
}
|
|
288
|
+
process.stdout.write("\x1B[?25h");
|
|
289
|
+
process.stdout.write("\r\x1B[K");
|
|
290
|
+
const icon = success ? pc3.green("\u2713") : pc3.red("\u2717");
|
|
291
|
+
const message = success ? "Dependencies installed" : "Failed to install dependencies";
|
|
292
|
+
console.log(`${icon} ${message}`);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
function createInstallProgress() {
|
|
296
|
+
return new InstallProgress();
|
|
297
|
+
}
|
|
298
|
+
|
|
156
299
|
// src/generators/package-json.ts
|
|
157
300
|
function generatePackageJson(options) {
|
|
158
301
|
const isSolana = options.provider === "arkworks";
|
|
@@ -1410,28 +1553,31 @@ async function initCommand(projectName, options) {
|
|
|
1410
1553
|
});
|
|
1411
1554
|
}
|
|
1412
1555
|
if (!projectOptions) {
|
|
1413
|
-
console.log(
|
|
1556
|
+
console.log(pc4.yellow("\nOperation cancelled."));
|
|
1414
1557
|
process.exit(0);
|
|
1415
1558
|
}
|
|
1416
1559
|
const projectDir = path2.resolve(process.cwd(), projectOptions.projectName);
|
|
1417
1560
|
if (await directoryExists(projectDir)) {
|
|
1418
1561
|
if (!await isDirectoryEmpty(projectDir)) {
|
|
1419
1562
|
console.log(
|
|
1420
|
-
|
|
1563
|
+
pc4.red(`
|
|
1421
1564
|
Error: Directory "${projectOptions.projectName}" already exists and is not empty.`)
|
|
1422
1565
|
);
|
|
1423
1566
|
process.exit(1);
|
|
1424
1567
|
}
|
|
1425
1568
|
}
|
|
1426
1569
|
console.log();
|
|
1427
|
-
const
|
|
1428
|
-
spinner.start();
|
|
1570
|
+
const progress = createProgressReporter();
|
|
1429
1571
|
try {
|
|
1430
|
-
await
|
|
1431
|
-
|
|
1572
|
+
await progress.startThinking();
|
|
1573
|
+
await new Promise((r) => setTimeout(r, 800));
|
|
1574
|
+
progress.stopThinking();
|
|
1575
|
+
console.log(pc4.bold("\n Scaffolding your ZK project...\n"));
|
|
1576
|
+
await createProjectStructure(projectDir, projectOptions, progress);
|
|
1577
|
+
progress.showSuccess("Project structure created");
|
|
1432
1578
|
} catch (error) {
|
|
1433
|
-
|
|
1434
|
-
console.error(
|
|
1579
|
+
progress.showError("Failed to create project structure");
|
|
1580
|
+
console.error(pc4.red("\n"), error);
|
|
1435
1581
|
process.exit(1);
|
|
1436
1582
|
}
|
|
1437
1583
|
if (!projectOptions.skipGit) {
|
|
@@ -1442,28 +1588,28 @@ Error: Directory "${projectOptions.projectName}" already exists and is not empty
|
|
|
1442
1588
|
gitSpinner.stop(true);
|
|
1443
1589
|
} catch {
|
|
1444
1590
|
gitSpinner.stop(false);
|
|
1445
|
-
console.log(
|
|
1591
|
+
console.log(pc4.yellow(" Warning: Failed to initialize git repository"));
|
|
1446
1592
|
}
|
|
1447
1593
|
}
|
|
1448
1594
|
if (!projectOptions.skipInstall) {
|
|
1449
|
-
const
|
|
1450
|
-
|
|
1595
|
+
const installProgress = createInstallProgress();
|
|
1596
|
+
installProgress.start();
|
|
1451
1597
|
try {
|
|
1452
1598
|
execSync("npm install", { cwd: projectDir, stdio: "ignore" });
|
|
1453
|
-
|
|
1599
|
+
installProgress.stop(true);
|
|
1454
1600
|
} catch {
|
|
1455
|
-
|
|
1456
|
-
console.log(
|
|
1601
|
+
installProgress.stop(false);
|
|
1602
|
+
console.log(pc4.yellow(' Run "npm install" manually.'));
|
|
1457
1603
|
}
|
|
1458
1604
|
}
|
|
1459
1605
|
printSuccessMessage(projectOptions);
|
|
1460
1606
|
}
|
|
1461
|
-
async function createProjectStructure(projectDir, options) {
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1607
|
+
async function createProjectStructure(projectDir, options, progress) {
|
|
1608
|
+
const dirs = ["circuits", "src", "src/components", "src/lib", "public"];
|
|
1609
|
+
for (const dir of dirs) {
|
|
1610
|
+
await ensureDir(path2.join(projectDir, dir));
|
|
1611
|
+
await progress.reportDirectory(dir);
|
|
1612
|
+
}
|
|
1467
1613
|
const files = [
|
|
1468
1614
|
// Root config files
|
|
1469
1615
|
["package.json", generatePackageJson(options)],
|
|
@@ -1499,34 +1645,34 @@ async function createProjectStructure(projectDir, options) {
|
|
|
1499
1645
|
}
|
|
1500
1646
|
files.push(["circuits/index.ts", generateCircuitsIndex(options.template)]);
|
|
1501
1647
|
files.push(["circuits/types.d.ts", generateCircuitTypes()]);
|
|
1502
|
-
|
|
1503
|
-
files
|
|
1504
|
-
|
|
1505
|
-
)
|
|
1506
|
-
|
|
1648
|
+
for (let i = 0; i < files.length; i++) {
|
|
1649
|
+
const [relativePath, content] = files[i];
|
|
1650
|
+
await writeFile(path2.join(projectDir, relativePath), content);
|
|
1651
|
+
await progress.reportFile(relativePath, i === files.length - 1);
|
|
1652
|
+
}
|
|
1507
1653
|
}
|
|
1508
1654
|
function printSuccessMessage(options) {
|
|
1509
1655
|
console.log();
|
|
1510
|
-
console.log(
|
|
1656
|
+
console.log(pc4.green("\u2713") + " Project created successfully!");
|
|
1511
1657
|
console.log();
|
|
1512
1658
|
console.log("Next steps:");
|
|
1513
1659
|
console.log();
|
|
1514
|
-
console.log(
|
|
1660
|
+
console.log(pc4.cyan(` cd ${options.projectName}`));
|
|
1515
1661
|
if (options.skipInstall) {
|
|
1516
|
-
console.log(
|
|
1662
|
+
console.log(pc4.cyan(" npm install"));
|
|
1517
1663
|
}
|
|
1518
|
-
console.log(
|
|
1664
|
+
console.log(pc4.cyan(" npm run dev"));
|
|
1519
1665
|
console.log();
|
|
1520
|
-
console.log("Then open " +
|
|
1666
|
+
console.log("Then open " + pc4.blue("http://localhost:5173") + " in your browser.");
|
|
1521
1667
|
console.log();
|
|
1522
1668
|
console.log("To add circuits:");
|
|
1523
1669
|
console.log();
|
|
1524
|
-
console.log(
|
|
1525
|
-
console.log(
|
|
1526
|
-
console.log(
|
|
1670
|
+
console.log(pc4.dim(" 1. Create a new circuit in circuits/*.ts"));
|
|
1671
|
+
console.log(pc4.dim(" 2. Export it from circuits/index.ts"));
|
|
1672
|
+
console.log(pc4.dim(" 3. Add it to CIRCUITS array in src/App.tsx"));
|
|
1527
1673
|
console.log();
|
|
1528
1674
|
console.log(
|
|
1529
|
-
|
|
1675
|
+
pc4.dim("Learn more: ") + pc4.blue("https://github.com/izi-noir/izi-noir")
|
|
1530
1676
|
);
|
|
1531
1677
|
console.log();
|
|
1532
1678
|
}
|