craft-native 0.0.247 → 0.0.249
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/android/src/index.d.ts +2 -0
- package/dist/android/src/index.js +22 -18
- package/dist/android/templates/CraftNative.kt.template +17 -0
- package/dist/android/templates/CraftNativeFlatList.kt.template +115 -40
- package/dist/android/templates/CraftNativeMapGoogle.kt.template +92 -5
- package/dist/android/templates/CraftNativeMapLibre.kt.template +90 -3
- package/dist/android/templates/CraftNativeMutation.kt.template +32 -0
- package/dist/android/templates/CraftNativeRefreshableFlatList.kt.template +7 -2
- package/dist/android/templates/CraftNativeServices.kt.template +25 -0
- package/dist/android/templates/CraftNativeShell.kt.template +41 -9
- package/dist/android/templates/MainActivityNative.kt.template +369 -69
- package/dist/android/templates/build.gradle.kts.project.template +1 -1
- package/dist/api/mobile.d.ts +37 -1
- package/dist/browser.js +9 -9
- package/dist/cli.js +90 -673
- package/dist/components/index.d.ts +50 -9
- package/dist/index.cjs +394 -438
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +446 -493
- package/dist/ios/src/index.d.ts +2 -0
- package/dist/ios/src/index.js +54 -53
- package/dist/ios/templates/CraftApp.swift +44 -3
- package/dist/ios/templates/CraftHealth.swift +217 -0
- package/dist/ios/templates/CraftHeartRate.swift +6 -3
- package/dist/ios/templates/CraftHybrid.swift +30 -22
- package/dist/ios/templates/CraftLiveActivities.swift +1 -1
- package/dist/ios/templates/CraftNativeActions.swift +87 -8
- package/dist/ios/templates/CraftNativeFiles.swift +15 -3
- package/dist/ios/templates/CraftNativeFlatList.swift +18 -1
- package/dist/ios/templates/CraftNativeMutation.swift +36 -0
- package/dist/ios/templates/CraftNativeScreen.swift +826 -69
- package/dist/ios/templates/CraftNativeServices.swift +4 -2
- package/dist/ios/templates/CraftNativeUI.swift +10 -2
- package/dist/ios/templates/testing/DriverTests.swift.template +1 -0
- package/dist/ios/templates/testing/HostApp.swift +9 -2
- package/dist/macos/templates/CraftNativeMutation.swift +36 -0
- package/dist/macos/templates/native_layout.zig +226 -2
- package/dist/mobile-testing.js +2 -2
- package/dist/mobile.js +101 -63
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
configurable: true,
|
|
14
|
-
set: __exportSetter.bind(all, name)
|
|
15
|
-
});
|
|
3
|
+
var __esm = (fn, res, err) => () => {
|
|
4
|
+
if (fn)
|
|
5
|
+
try {
|
|
6
|
+
res = fn(fn = 0);
|
|
7
|
+
} catch (e) {
|
|
8
|
+
err = [e];
|
|
9
|
+
}
|
|
10
|
+
if (err)
|
|
11
|
+
throw err[0];
|
|
12
|
+
return res;
|
|
16
13
|
};
|
|
17
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
18
|
-
var __require = import.meta.require;
|
|
19
14
|
|
|
20
15
|
// src/temp-dir.ts
|
|
21
16
|
import { existsSync as existsSync3, mkdtempSync, readdirSync, rmSync, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -88,17 +83,17 @@ function sweepOrphanedTempDirs(options = {}) {
|
|
|
88
83
|
const pid = Number(match[1]);
|
|
89
84
|
if (pid === process.pid || isAlive(pid))
|
|
90
85
|
continue;
|
|
91
|
-
const
|
|
86
|
+
const path = join(root, name);
|
|
92
87
|
try {
|
|
93
|
-
if (now - statSync(
|
|
88
|
+
if (now - statSync(path).mtimeMs < minAge)
|
|
94
89
|
continue;
|
|
95
|
-
if (existsSync3(join(
|
|
90
|
+
if (existsSync3(join(path, KEEP_MARKER)))
|
|
96
91
|
continue;
|
|
97
92
|
} catch {
|
|
98
93
|
continue;
|
|
99
94
|
}
|
|
100
|
-
removeQuietly(
|
|
101
|
-
removed.push(
|
|
95
|
+
removeQuietly(path);
|
|
96
|
+
removed.push(path);
|
|
102
97
|
}
|
|
103
98
|
return removed;
|
|
104
99
|
}
|
|
@@ -131,30 +126,6 @@ var init_temp_dir = __esm(() => {
|
|
|
131
126
|
});
|
|
132
127
|
|
|
133
128
|
// src/package.ts
|
|
134
|
-
var exports_package = {};
|
|
135
|
-
__export(exports_package, {
|
|
136
|
-
windowsNotificationAppId: () => windowsNotificationAppId,
|
|
137
|
-
windowsExecutableName: () => windowsExecutableName,
|
|
138
|
-
windowsArchitecture: () => windowsArchitecture,
|
|
139
|
-
urlTypesEntry: () => urlTypesEntry,
|
|
140
|
-
shouldRetryHdiutil: () => shouldRetryHdiutil,
|
|
141
|
-
renderWixSource: () => renderWixSource,
|
|
142
|
-
productbuildArguments: () => productbuildArguments,
|
|
143
|
-
pkgbuildComponentPlist: () => pkgbuildComponentPlist,
|
|
144
|
-
pkgbuildArguments: () => pkgbuildArguments,
|
|
145
|
-
packageApp: () => packageApp,
|
|
146
|
-
pack: () => pack,
|
|
147
|
-
notarytoolArguments: () => notarytoolArguments,
|
|
148
|
-
macOSInfoPlist: () => macOSInfoPlist,
|
|
149
|
-
linuxDesktopEntry: () => linuxDesktopEntry,
|
|
150
|
-
formatPackagingCommandError: () => formatPackagingCommandError,
|
|
151
|
-
dmgCreateArguments: () => dmgCreateArguments,
|
|
152
|
-
dmgCapacityMegabytes: () => dmgCapacityMegabytes,
|
|
153
|
-
codesignArguments: () => codesignArguments,
|
|
154
|
-
candleArguments: () => candleArguments,
|
|
155
|
-
WINDOWS_NOTIFICATION_ID_FILE: () => WINDOWS_NOTIFICATION_ID_FILE,
|
|
156
|
-
DEFAULT_DEB_DEPENDENCIES: () => DEFAULT_DEB_DEPENDENCIES
|
|
157
|
-
});
|
|
158
129
|
import { spawn } from "child_process";
|
|
159
130
|
import { createHash } from "crypto";
|
|
160
131
|
import {
|
|
@@ -238,8 +209,8 @@ function buildZip(entries) {
|
|
|
238
209
|
eocd.writeUInt16LE(0, 20);
|
|
239
210
|
return Buffer.concat([...locals, centralBuf, eocd]);
|
|
240
211
|
}
|
|
241
|
-
function formatPackagingCommandError(tool, code,
|
|
242
|
-
const detail = `${
|
|
212
|
+
function formatPackagingCommandError(tool, code, stdout, stderr) {
|
|
213
|
+
const detail = `${stdout}${stderr}`.trim();
|
|
243
214
|
return `${tool} exited with code ${code}${detail ? `: ${detail}` : ""}`;
|
|
244
215
|
}
|
|
245
216
|
async function packageApp(config) {
|
|
@@ -269,13 +240,13 @@ async function packageApp(config) {
|
|
|
269
240
|
}
|
|
270
241
|
async function packageMacOS(config, outDir) {
|
|
271
242
|
const results = [];
|
|
272
|
-
const { name, version
|
|
243
|
+
const { name, version, bundleId = `com.myapp.${name.toLowerCase()}` } = config;
|
|
273
244
|
const opts = config.macos || {};
|
|
274
245
|
const hardenedRuntime = !opts.appStore;
|
|
275
246
|
const appBundlePath = join2(outDir, `${name}.app`);
|
|
276
247
|
const appBundle = createMacOSAppBundle({
|
|
277
248
|
name,
|
|
278
|
-
version
|
|
249
|
+
version,
|
|
279
250
|
bundleId,
|
|
280
251
|
buildNumber: opts.buildNumber,
|
|
281
252
|
category: opts.category,
|
|
@@ -319,7 +290,7 @@ async function packageMacOS(config, outDir) {
|
|
|
319
290
|
}
|
|
320
291
|
results.push({ success: true, platform: "macos", format: "app", outputPath: appBundlePath });
|
|
321
292
|
if (opts.dmg !== false) {
|
|
322
|
-
const outputPath = join2(outDir, `${name}-${
|
|
293
|
+
const outputPath = join2(outDir, `${name}-${version}.dmg`);
|
|
323
294
|
const dmgResult = await createDMG({ appBundlePath, outputPath, volumeName: name });
|
|
324
295
|
results.push({
|
|
325
296
|
success: dmgResult.success,
|
|
@@ -332,12 +303,12 @@ async function packageMacOS(config, outDir) {
|
|
|
332
303
|
results.push(...await notarizeIfRequested(opts, outputPath, "dmg"));
|
|
333
304
|
}
|
|
334
305
|
if (opts.pkg || opts.appStore) {
|
|
335
|
-
const outputPath = join2(outDir, `${name}-${
|
|
306
|
+
const outputPath = join2(outDir, `${name}-${version}.pkg`);
|
|
336
307
|
const pkgResult = await createPKG({
|
|
337
308
|
appBundlePath,
|
|
338
309
|
outputPath,
|
|
339
310
|
identifier: bundleId,
|
|
340
|
-
version
|
|
311
|
+
version,
|
|
341
312
|
appStore: opts.appStore === true,
|
|
342
313
|
installerIdentity: opts.installerIdentity
|
|
343
314
|
});
|
|
@@ -383,14 +354,14 @@ async function notarizeIfRequested(opts, artifactPath, format) {
|
|
|
383
354
|
}
|
|
384
355
|
async function packageWindows(config, outDir) {
|
|
385
356
|
const results = [];
|
|
386
|
-
const { name, version
|
|
357
|
+
const { name, version } = config;
|
|
387
358
|
const opts = config.windows || {};
|
|
388
359
|
if (opts.msi !== false) {
|
|
389
360
|
const msiResult = await createMSI({
|
|
390
361
|
name,
|
|
391
|
-
version
|
|
362
|
+
version,
|
|
392
363
|
binaryPath: config.binaryPath,
|
|
393
|
-
outputPath: join2(outDir, `${name}-${
|
|
364
|
+
outputPath: join2(outDir, `${name}-${version}.msi`),
|
|
394
365
|
manufacturer: config.author || "Unknown",
|
|
395
366
|
architecture: opts.architecture || windowsArchitecture(process.arch),
|
|
396
367
|
additionalFiles: opts.additionalFiles,
|
|
@@ -410,11 +381,11 @@ async function packageWindows(config, outDir) {
|
|
|
410
381
|
if (opts.zip || opts.msi === false) {
|
|
411
382
|
const zipResult = await createZIP({
|
|
412
383
|
name,
|
|
413
|
-
version
|
|
384
|
+
version,
|
|
414
385
|
manufacturer: config.author || "Unknown",
|
|
415
386
|
binaryPath: config.binaryPath,
|
|
416
387
|
additionalFiles: opts.additionalFiles,
|
|
417
|
-
outputPath: join2(outDir, `${name}-${
|
|
388
|
+
outputPath: join2(outDir, `${name}-${version}-windows.zip`)
|
|
418
389
|
});
|
|
419
390
|
results.push({
|
|
420
391
|
success: zipResult.success,
|
|
@@ -428,14 +399,14 @@ async function packageWindows(config, outDir) {
|
|
|
428
399
|
}
|
|
429
400
|
async function packageLinux(config, outDir) {
|
|
430
401
|
const results = [];
|
|
431
|
-
const { name, version
|
|
402
|
+
const { name, version } = config;
|
|
432
403
|
const opts = config.linux || {};
|
|
433
404
|
if (opts.deb !== false) {
|
|
434
405
|
const debResult = await createDEB({
|
|
435
406
|
name,
|
|
436
|
-
version
|
|
407
|
+
version,
|
|
437
408
|
binaryPath: config.binaryPath,
|
|
438
|
-
outputPath: join2(outDir, `${name}_${
|
|
409
|
+
outputPath: join2(outDir, `${name}_${version}_amd64.deb`),
|
|
439
410
|
description: config.description || "",
|
|
440
411
|
maintainer: config.author || "Unknown",
|
|
441
412
|
dependencies: opts.debDependencies || [...DEFAULT_DEB_DEPENDENCIES],
|
|
@@ -453,9 +424,9 @@ async function packageLinux(config, outDir) {
|
|
|
453
424
|
if (opts.rpm) {
|
|
454
425
|
const rpmResult = await createRPM({
|
|
455
426
|
name,
|
|
456
|
-
version
|
|
427
|
+
version,
|
|
457
428
|
binaryPath: config.binaryPath,
|
|
458
|
-
outputPath: join2(outDir, `${name}-${
|
|
429
|
+
outputPath: join2(outDir, `${name}-${version}-1.x86_64.rpm`),
|
|
459
430
|
description: config.description || "",
|
|
460
431
|
requires: opts.rpmDependencies || ["gtk3", "webkit2gtk3"]
|
|
461
432
|
});
|
|
@@ -470,9 +441,9 @@ async function packageLinux(config, outDir) {
|
|
|
470
441
|
if (opts.appImage) {
|
|
471
442
|
const appImageResult = await createAppImage({
|
|
472
443
|
name,
|
|
473
|
-
version
|
|
444
|
+
version,
|
|
474
445
|
binaryPath: config.binaryPath,
|
|
475
|
-
outputPath: join2(outDir, `${name}-${
|
|
446
|
+
outputPath: join2(outDir, `${name}-${version}-x86_64.AppImage`),
|
|
476
447
|
iconPath: config.iconPath
|
|
477
448
|
});
|
|
478
449
|
results.push({
|
|
@@ -647,11 +618,11 @@ function createMacOSAppBundle(opts) {
|
|
|
647
618
|
return { success: false, error: error.message };
|
|
648
619
|
}
|
|
649
620
|
}
|
|
650
|
-
function pathContentBytes(
|
|
651
|
-
const stat = lstatSync(
|
|
621
|
+
function pathContentBytes(path) {
|
|
622
|
+
const stat = lstatSync(path);
|
|
652
623
|
if (!stat.isDirectory())
|
|
653
624
|
return stat.size;
|
|
654
|
-
return readdirSync2(
|
|
625
|
+
return readdirSync2(path).reduce((total, entry) => total + pathContentBytes(join2(path, entry)), 0);
|
|
655
626
|
}
|
|
656
627
|
function dmgCapacityMegabytes(contentBytes) {
|
|
657
628
|
if (!Number.isSafeInteger(contentBytes) || contentBytes < 0)
|
|
@@ -682,10 +653,10 @@ function shouldRetryHdiutil(error, attempt, maxAttempts = HDIUTIL_MAX_ATTEMPTS)
|
|
|
682
653
|
function runTool(tool, args) {
|
|
683
654
|
return new Promise((resolve) => {
|
|
684
655
|
const proc = spawn(tool, args);
|
|
685
|
-
let
|
|
656
|
+
let stdout = "";
|
|
686
657
|
let stderr = "";
|
|
687
658
|
proc.stdout?.on("data", (chunk) => {
|
|
688
|
-
|
|
659
|
+
stdout += chunk.toString();
|
|
689
660
|
});
|
|
690
661
|
proc.stderr?.on("data", (chunk) => {
|
|
691
662
|
stderr += chunk.toString();
|
|
@@ -694,7 +665,7 @@ function runTool(tool, args) {
|
|
|
694
665
|
if (code === 0)
|
|
695
666
|
resolve({ success: true });
|
|
696
667
|
else
|
|
697
|
-
resolve({ success: false, error: formatPackagingCommandError(tool, code,
|
|
668
|
+
resolve({ success: false, error: formatPackagingCommandError(tool, code, stdout, stderr) });
|
|
698
669
|
});
|
|
699
670
|
proc.on("error", (err) => resolve({ success: false, error: err.message }));
|
|
700
671
|
});
|
|
@@ -879,16 +850,16 @@ ${schemes.map((_, index) => ` <ComponentRef Id="${id}Protocol${index}" />`)
|
|
|
879
850
|
}
|
|
880
851
|
function windowsCompanionFiles(paths, executableName) {
|
|
881
852
|
const seen = new Set([executableName.toLowerCase(), WINDOWS_NOTIFICATION_ID_FILE.toLowerCase()]);
|
|
882
|
-
return (paths || []).map((
|
|
883
|
-
const name = basename(
|
|
853
|
+
return (paths || []).map((path) => {
|
|
854
|
+
const name = basename(path);
|
|
884
855
|
if (!name || /[<>:"/\\|?*\u0000-\u001F]/.test(name) || /[. ]$/.test(name) || /^(?:CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(?:\.|$)/i.test(name))
|
|
885
856
|
throw new Error(`Invalid Windows companion file name: ${JSON.stringify(name)}`);
|
|
886
857
|
if (seen.has(name.toLowerCase()))
|
|
887
858
|
throw new Error(`Duplicate Windows package file: ${name}`);
|
|
888
859
|
seen.add(name.toLowerCase());
|
|
889
|
-
if (!existsSync4(
|
|
890
|
-
throw new Error(`Windows companion file not found: ${
|
|
891
|
-
return { path
|
|
860
|
+
if (!existsSync4(path) || lstatSync(path).isDirectory())
|
|
861
|
+
throw new Error(`Windows companion file not found: ${path}`);
|
|
862
|
+
return { path, name };
|
|
892
863
|
});
|
|
893
864
|
}
|
|
894
865
|
function windowsExecutableName(name) {
|
|
@@ -1236,12 +1207,6 @@ function detectPlatform() {
|
|
|
1236
1207
|
return "linux";
|
|
1237
1208
|
}
|
|
1238
1209
|
}
|
|
1239
|
-
async function pack(options) {
|
|
1240
|
-
return packageApp({
|
|
1241
|
-
...options,
|
|
1242
|
-
platforms: [detectPlatform()]
|
|
1243
|
-
});
|
|
1244
|
-
}
|
|
1245
1210
|
var DEFAULT_DEB_DEPENDENCIES, CRC32_TABLE, URL_SCHEME, MEBIBYTE, HDIUTIL_MAX_ATTEMPTS = 3, runHdiutil = (args) => runTool("hdiutil", args), WINDOWS_NOTIFICATION_ID_FILE = "craft-notification-id.txt";
|
|
1246
1211
|
var init_package = __esm(() => {
|
|
1247
1212
|
init_temp_dir();
|
|
@@ -1274,8 +1239,6 @@ import process4 from "process";
|
|
|
1274
1239
|
import process7 from "process";
|
|
1275
1240
|
import tty from "tty";
|
|
1276
1241
|
import process8, { stdin, stdout } from "process";
|
|
1277
|
-
import process9, { stdin as stdin2, stdout as stdout2 } from "process";
|
|
1278
|
-
import readline2 from "readline";
|
|
1279
1242
|
class Telemetry {
|
|
1280
1243
|
configPath;
|
|
1281
1244
|
config = null;
|
|
@@ -2762,553 +2725,8 @@ var settings = {
|
|
|
2762
2725
|
error: "Something went wrong"
|
|
2763
2726
|
}
|
|
2764
2727
|
};
|
|
2765
|
-
function isActionKey(key, action) {
|
|
2766
|
-
if (typeof key === "string") {
|
|
2767
|
-
return settings.aliases.get(key) === action;
|
|
2768
|
-
}
|
|
2769
|
-
for (const value of key) {
|
|
2770
|
-
if (value === undefined)
|
|
2771
|
-
continue;
|
|
2772
|
-
if (isActionKey(value, action)) {
|
|
2773
|
-
return true;
|
|
2774
|
-
}
|
|
2775
|
-
}
|
|
2776
|
-
return false;
|
|
2777
|
-
}
|
|
2778
|
-
function diffLines(a, b) {
|
|
2779
|
-
if (a === b)
|
|
2780
|
-
return [];
|
|
2781
|
-
const aLines = a.split(`
|
|
2782
|
-
`);
|
|
2783
|
-
const bLines = b.split(`
|
|
2784
|
-
`);
|
|
2785
|
-
const diff = [];
|
|
2786
|
-
for (let i = 0;i < Math.max(aLines.length, bLines.length); i++) {
|
|
2787
|
-
if (aLines[i] !== bLines[i])
|
|
2788
|
-
diff.push(i);
|
|
2789
|
-
}
|
|
2790
|
-
return diff;
|
|
2791
|
-
}
|
|
2792
2728
|
var isWindows = process8.platform.startsWith("win");
|
|
2793
2729
|
var CANCEL_SYMBOL = Symbol("clapp:cancel");
|
|
2794
|
-
function setRawMode(input, value) {
|
|
2795
|
-
const i = input;
|
|
2796
|
-
if (i.isTTY)
|
|
2797
|
-
i.setRawMode(value);
|
|
2798
|
-
}
|
|
2799
|
-
function stripAnsi(str) {
|
|
2800
|
-
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
2801
|
-
}
|
|
2802
|
-
function stringWidth(str) {
|
|
2803
|
-
return stripAnsi(str).length;
|
|
2804
|
-
}
|
|
2805
|
-
function wrapAnsi(text, columns, options) {
|
|
2806
|
-
if (!columns || columns < 1)
|
|
2807
|
-
return text;
|
|
2808
|
-
const hard = options?.hard ?? false;
|
|
2809
|
-
const trim = options?.trim ?? true;
|
|
2810
|
-
const lines = text.split(`
|
|
2811
|
-
`);
|
|
2812
|
-
const result = [];
|
|
2813
|
-
for (const line of lines) {
|
|
2814
|
-
if (stringWidth(line) <= columns) {
|
|
2815
|
-
result.push(trim ? line.trimEnd() : line);
|
|
2816
|
-
continue;
|
|
2817
|
-
}
|
|
2818
|
-
if (hard) {
|
|
2819
|
-
let current = "";
|
|
2820
|
-
let currentWidth = 0;
|
|
2821
|
-
let i = 0;
|
|
2822
|
-
while (i < line.length) {
|
|
2823
|
-
const ansiMatch = line.slice(i).match(/^\x1b\[[0-9;]*m/);
|
|
2824
|
-
if (ansiMatch) {
|
|
2825
|
-
current += ansiMatch[0];
|
|
2826
|
-
i += ansiMatch[0].length;
|
|
2827
|
-
continue;
|
|
2828
|
-
}
|
|
2829
|
-
if (currentWidth >= columns) {
|
|
2830
|
-
result.push(trim ? current.trimEnd() : current);
|
|
2831
|
-
current = "";
|
|
2832
|
-
currentWidth = 0;
|
|
2833
|
-
}
|
|
2834
|
-
current += line[i];
|
|
2835
|
-
currentWidth++;
|
|
2836
|
-
i++;
|
|
2837
|
-
}
|
|
2838
|
-
if (current) {
|
|
2839
|
-
result.push(trim ? current.trimEnd() : current);
|
|
2840
|
-
}
|
|
2841
|
-
} else {
|
|
2842
|
-
result.push(trim ? line.trimEnd() : line);
|
|
2843
|
-
}
|
|
2844
|
-
}
|
|
2845
|
-
return result.join(`
|
|
2846
|
-
`);
|
|
2847
|
-
}
|
|
2848
|
-
|
|
2849
|
-
class Prompt {
|
|
2850
|
-
input;
|
|
2851
|
-
output;
|
|
2852
|
-
_abortSignal;
|
|
2853
|
-
rl;
|
|
2854
|
-
opts;
|
|
2855
|
-
_render;
|
|
2856
|
-
_track = false;
|
|
2857
|
-
_prevFrame = "";
|
|
2858
|
-
_subscribers = new Map;
|
|
2859
|
-
_cursor = 0;
|
|
2860
|
-
_manualLine = "";
|
|
2861
|
-
state = "initial";
|
|
2862
|
-
error = "";
|
|
2863
|
-
value;
|
|
2864
|
-
userInput = "";
|
|
2865
|
-
constructor(options, trackValue = true) {
|
|
2866
|
-
const { input = stdin2, output = stdout2, render, signal, ...opts } = options;
|
|
2867
|
-
this.opts = opts;
|
|
2868
|
-
this.onKeypress = this.onKeypress.bind(this);
|
|
2869
|
-
this.close = this.close.bind(this);
|
|
2870
|
-
this.render = this.render.bind(this);
|
|
2871
|
-
this._render = render.bind(this);
|
|
2872
|
-
this._track = trackValue;
|
|
2873
|
-
this._abortSignal = signal;
|
|
2874
|
-
this.input = input;
|
|
2875
|
-
this.output = output;
|
|
2876
|
-
}
|
|
2877
|
-
unsubscribe() {
|
|
2878
|
-
this._subscribers.clear();
|
|
2879
|
-
}
|
|
2880
|
-
setSubscriber(event, opts) {
|
|
2881
|
-
const params = this._subscribers.get(event) ?? [];
|
|
2882
|
-
params.push(opts);
|
|
2883
|
-
this._subscribers.set(event, params);
|
|
2884
|
-
}
|
|
2885
|
-
on(event, cb) {
|
|
2886
|
-
this.setSubscriber(event, { cb });
|
|
2887
|
-
return this;
|
|
2888
|
-
}
|
|
2889
|
-
once(event, cb) {
|
|
2890
|
-
this.setSubscriber(event, { cb, once: true });
|
|
2891
|
-
return this;
|
|
2892
|
-
}
|
|
2893
|
-
emit(event, ...data) {
|
|
2894
|
-
const cbs = this._subscribers.get(event) ?? [];
|
|
2895
|
-
const cleanup = [];
|
|
2896
|
-
for (const subscriber of cbs) {
|
|
2897
|
-
subscriber.cb(...data);
|
|
2898
|
-
if (subscriber.once) {
|
|
2899
|
-
cleanup.push(() => cbs.splice(cbs.indexOf(subscriber), 1));
|
|
2900
|
-
}
|
|
2901
|
-
}
|
|
2902
|
-
for (const cb of cleanup) {
|
|
2903
|
-
cb();
|
|
2904
|
-
}
|
|
2905
|
-
return this;
|
|
2906
|
-
}
|
|
2907
|
-
prompt() {
|
|
2908
|
-
return new Promise((resolve) => {
|
|
2909
|
-
if (this._abortSignal) {
|
|
2910
|
-
if (this._abortSignal.aborted) {
|
|
2911
|
-
this.state = "cancel";
|
|
2912
|
-
this.close();
|
|
2913
|
-
return resolve(CANCEL_SYMBOL);
|
|
2914
|
-
}
|
|
2915
|
-
this._abortSignal.addEventListener("abort", () => {
|
|
2916
|
-
this.state = "cancel";
|
|
2917
|
-
this.close();
|
|
2918
|
-
}, { once: true });
|
|
2919
|
-
}
|
|
2920
|
-
this.rl = readline2.createInterface({
|
|
2921
|
-
input: this.input,
|
|
2922
|
-
tabSize: 2,
|
|
2923
|
-
prompt: "",
|
|
2924
|
-
escapeCodeTimeout: 50,
|
|
2925
|
-
terminal: true
|
|
2926
|
-
});
|
|
2927
|
-
this.rl.prompt();
|
|
2928
|
-
if (this.opts.initialUserInput !== undefined) {
|
|
2929
|
-
this._setUserInput(this.opts.initialUserInput, true);
|
|
2930
|
-
}
|
|
2931
|
-
this.input.on("keypress", this.onKeypress);
|
|
2932
|
-
setRawMode(this.input, true);
|
|
2933
|
-
this.output.on("resize", this.render);
|
|
2934
|
-
this.render();
|
|
2935
|
-
this.once("submit", () => {
|
|
2936
|
-
this.output.write(cursor.show);
|
|
2937
|
-
this.output.off("resize", this.render);
|
|
2938
|
-
setRawMode(this.input, false);
|
|
2939
|
-
resolve(this.value);
|
|
2940
|
-
});
|
|
2941
|
-
this.once("cancel", () => {
|
|
2942
|
-
this.output.write(cursor.show);
|
|
2943
|
-
this.output.off("resize", this.render);
|
|
2944
|
-
setRawMode(this.input, false);
|
|
2945
|
-
resolve(CANCEL_SYMBOL);
|
|
2946
|
-
});
|
|
2947
|
-
});
|
|
2948
|
-
}
|
|
2949
|
-
_isActionKey(char, _key) {
|
|
2950
|
-
return char === "\t";
|
|
2951
|
-
}
|
|
2952
|
-
_setValue(value) {
|
|
2953
|
-
this.value = value;
|
|
2954
|
-
this.emit("value", this.value);
|
|
2955
|
-
}
|
|
2956
|
-
_setUserInput(value, write) {
|
|
2957
|
-
this.userInput = value ?? "";
|
|
2958
|
-
this.emit("userInput", this.userInput);
|
|
2959
|
-
if (write && this._track && this.rl) {
|
|
2960
|
-
this.rl.write(this.userInput);
|
|
2961
|
-
this._cursor = this.rl.cursor;
|
|
2962
|
-
}
|
|
2963
|
-
}
|
|
2964
|
-
onKeypress(char, key) {
|
|
2965
|
-
if (this._track && key.name !== "return") {
|
|
2966
|
-
if (key.name && this._isActionKey(char, key)) {
|
|
2967
|
-
this.rl?.write(null, { ctrl: true, name: "h" });
|
|
2968
|
-
}
|
|
2969
|
-
this._cursor = this.rl?.cursor ?? 0;
|
|
2970
|
-
const isSpecialKey = key.name === "tab" || key.name === "escape" || key.name === "backspace" || key.name === "delete" || key.name === "enter" || key.name === "return" || key.name && ["up", "down", "left", "right"].includes(key.name);
|
|
2971
|
-
if (char && !isSpecialKey && char.length === 1 && char >= " ") {
|
|
2972
|
-
this._manualLine += char;
|
|
2973
|
-
} else if (key.name === "backspace" && this._manualLine.length > 0) {
|
|
2974
|
-
this._manualLine = this._manualLine.slice(0, -1);
|
|
2975
|
-
}
|
|
2976
|
-
const effectiveLine = this._manualLine.length >= (this.rl?.line?.length || 0) ? this._manualLine : this.rl?.line;
|
|
2977
|
-
this._setUserInput(effectiveLine);
|
|
2978
|
-
}
|
|
2979
|
-
if (this.state === "error") {
|
|
2980
|
-
this.state = "active";
|
|
2981
|
-
this.error = "";
|
|
2982
|
-
}
|
|
2983
|
-
if (key?.name) {
|
|
2984
|
-
if (!this._track && settings.aliases.has(key.name)) {
|
|
2985
|
-
this.emit("cursor", settings.aliases.get(key.name));
|
|
2986
|
-
}
|
|
2987
|
-
if (settings.actions.has(key.name)) {
|
|
2988
|
-
this.emit("cursor", key.name);
|
|
2989
|
-
}
|
|
2990
|
-
}
|
|
2991
|
-
if (char && (char.toLowerCase() === "y" || char.toLowerCase() === "n")) {
|
|
2992
|
-
this.emit("confirm", char.toLowerCase() === "y");
|
|
2993
|
-
}
|
|
2994
|
-
this.emit("key", char?.toLowerCase(), key);
|
|
2995
|
-
if (key?.name === "return") {
|
|
2996
|
-
if (this.opts.validate) {
|
|
2997
|
-
const problem = this.opts.validate(this.value);
|
|
2998
|
-
if (problem) {
|
|
2999
|
-
this.error = problem instanceof Error ? problem.message : problem;
|
|
3000
|
-
this.state = "error";
|
|
3001
|
-
}
|
|
3002
|
-
}
|
|
3003
|
-
if (this.state !== "error") {
|
|
3004
|
-
this.state = "submit";
|
|
3005
|
-
}
|
|
3006
|
-
}
|
|
3007
|
-
if (isActionKey([char, key?.name, key?.sequence], "cancel")) {
|
|
3008
|
-
this.state = "cancel";
|
|
3009
|
-
}
|
|
3010
|
-
if (this.state === "submit" || this.state === "cancel") {
|
|
3011
|
-
this.emit("finalize");
|
|
3012
|
-
}
|
|
3013
|
-
this.render();
|
|
3014
|
-
if (this.state === "submit" || this.state === "cancel") {
|
|
3015
|
-
this.close();
|
|
3016
|
-
}
|
|
3017
|
-
}
|
|
3018
|
-
close() {
|
|
3019
|
-
this.input.unpipe();
|
|
3020
|
-
this.input.removeListener("keypress", this.onKeypress);
|
|
3021
|
-
this.output.write(`
|
|
3022
|
-
`);
|
|
3023
|
-
setRawMode(this.input, false);
|
|
3024
|
-
this.rl?.close();
|
|
3025
|
-
this.rl = undefined;
|
|
3026
|
-
this.emit(`${this.state}`, this.value);
|
|
3027
|
-
if (this.state === "cancel") {
|
|
3028
|
-
setTimeout(() => {
|
|
3029
|
-
this.unsubscribe();
|
|
3030
|
-
}, 10);
|
|
3031
|
-
} else {
|
|
3032
|
-
this.unsubscribe();
|
|
3033
|
-
}
|
|
3034
|
-
}
|
|
3035
|
-
restoreCursor() {
|
|
3036
|
-
const lines = wrapAnsi(this._prevFrame, process9.stdout.columns, { hard: true, trim: false }).split(`
|
|
3037
|
-
`).length - 1;
|
|
3038
|
-
this.output.write(cursor.move(-999, lines * -1));
|
|
3039
|
-
}
|
|
3040
|
-
render() {
|
|
3041
|
-
const frame = wrapAnsi(this._render(this) ?? "", process9.stdout.columns, {
|
|
3042
|
-
hard: true,
|
|
3043
|
-
trim: false
|
|
3044
|
-
});
|
|
3045
|
-
if (frame === this._prevFrame) {
|
|
3046
|
-
return;
|
|
3047
|
-
}
|
|
3048
|
-
if (this.state === "initial") {
|
|
3049
|
-
this.output.write(cursor.hide);
|
|
3050
|
-
} else {
|
|
3051
|
-
const diff = diffLines(this._prevFrame, frame);
|
|
3052
|
-
this.restoreCursor();
|
|
3053
|
-
if (diff && diff?.length === 1) {
|
|
3054
|
-
const diffLine = diff[0];
|
|
3055
|
-
this.output.write(cursor.move(0, diffLine));
|
|
3056
|
-
this.output.write(erase.lines(1));
|
|
3057
|
-
const lines = frame.split(`
|
|
3058
|
-
`);
|
|
3059
|
-
this.output.write(lines[diffLine]);
|
|
3060
|
-
this._prevFrame = frame;
|
|
3061
|
-
this.output.write(cursor.move(0, lines.length - diffLine - 1));
|
|
3062
|
-
return;
|
|
3063
|
-
}
|
|
3064
|
-
if (diff && diff?.length > 1) {
|
|
3065
|
-
const diffLine = diff[0];
|
|
3066
|
-
this.output.write(cursor.move(0, diffLine));
|
|
3067
|
-
this.output.write(erase.down());
|
|
3068
|
-
const lines = frame.split(`
|
|
3069
|
-
`);
|
|
3070
|
-
const newLines = lines.slice(diffLine);
|
|
3071
|
-
this.output.write(newLines.join(`
|
|
3072
|
-
`));
|
|
3073
|
-
this._prevFrame = frame;
|
|
3074
|
-
return;
|
|
3075
|
-
}
|
|
3076
|
-
this.output.write(erase.down());
|
|
3077
|
-
}
|
|
3078
|
-
this.output.write(frame);
|
|
3079
|
-
if (this.state === "initial") {
|
|
3080
|
-
this.state = "active";
|
|
3081
|
-
}
|
|
3082
|
-
this._prevFrame = frame;
|
|
3083
|
-
}
|
|
3084
|
-
}
|
|
3085
|
-
function getCursorForValue(selected, items) {
|
|
3086
|
-
if (selected === undefined) {
|
|
3087
|
-
return 0;
|
|
3088
|
-
}
|
|
3089
|
-
const currLength = items.length;
|
|
3090
|
-
if (currLength === 0) {
|
|
3091
|
-
return 0;
|
|
3092
|
-
}
|
|
3093
|
-
const index = items.findIndex((item) => item.value === selected);
|
|
3094
|
-
return index !== -1 ? index : 0;
|
|
3095
|
-
}
|
|
3096
|
-
function defaultFilter(input, option) {
|
|
3097
|
-
const label = option.label ?? String(option.value);
|
|
3098
|
-
return label.toLowerCase().includes(input.toLowerCase());
|
|
3099
|
-
}
|
|
3100
|
-
function normalisedValue(multiple, values) {
|
|
3101
|
-
if (!values) {
|
|
3102
|
-
return;
|
|
3103
|
-
}
|
|
3104
|
-
if (multiple) {
|
|
3105
|
-
return values;
|
|
3106
|
-
}
|
|
3107
|
-
return values[0];
|
|
3108
|
-
}
|
|
3109
|
-
|
|
3110
|
-
class AutocompletePrompt extends Prompt {
|
|
3111
|
-
filteredOptions;
|
|
3112
|
-
multiple;
|
|
3113
|
-
isNavigating = false;
|
|
3114
|
-
selectedValues = [];
|
|
3115
|
-
focusedValue;
|
|
3116
|
-
#cursor = 0;
|
|
3117
|
-
#lastUserInput = "";
|
|
3118
|
-
#filterFn;
|
|
3119
|
-
#options;
|
|
3120
|
-
get cursor() {
|
|
3121
|
-
return this.#cursor;
|
|
3122
|
-
}
|
|
3123
|
-
get userInputWithCursor() {
|
|
3124
|
-
if (!this.userInput) {
|
|
3125
|
-
return colors_default.inverse(colors_default.hidden("_"));
|
|
3126
|
-
}
|
|
3127
|
-
if (this._cursor >= this.userInput.length) {
|
|
3128
|
-
return `${this.userInput}\u2588`;
|
|
3129
|
-
}
|
|
3130
|
-
const s1 = this.userInput.slice(0, this._cursor);
|
|
3131
|
-
const [s2, ...s3] = this.userInput.slice(this._cursor);
|
|
3132
|
-
return `${s1}${colors_default.inverse(s2)}${s3.join("")}`;
|
|
3133
|
-
}
|
|
3134
|
-
get options() {
|
|
3135
|
-
if (typeof this.#options === "function") {
|
|
3136
|
-
return this.#options();
|
|
3137
|
-
}
|
|
3138
|
-
return this.#options;
|
|
3139
|
-
}
|
|
3140
|
-
constructor(opts) {
|
|
3141
|
-
super(opts);
|
|
3142
|
-
this.#options = opts.options;
|
|
3143
|
-
const options = this.options;
|
|
3144
|
-
this.filteredOptions = [...options];
|
|
3145
|
-
this.multiple = opts.multiple === true;
|
|
3146
|
-
this.#filterFn = opts.filter ?? defaultFilter;
|
|
3147
|
-
let initialValues;
|
|
3148
|
-
if (opts.initialValue && Array.isArray(opts.initialValue)) {
|
|
3149
|
-
if (this.multiple) {
|
|
3150
|
-
initialValues = opts.initialValue;
|
|
3151
|
-
} else {
|
|
3152
|
-
initialValues = opts.initialValue.slice(0, 1);
|
|
3153
|
-
}
|
|
3154
|
-
} else {
|
|
3155
|
-
if (!this.multiple && this.options.length > 0) {
|
|
3156
|
-
initialValues = [this.options[0].value];
|
|
3157
|
-
}
|
|
3158
|
-
}
|
|
3159
|
-
if (initialValues) {
|
|
3160
|
-
for (const selectedValue of initialValues) {
|
|
3161
|
-
const selectedIndex = options.findIndex((opt) => opt.value === selectedValue);
|
|
3162
|
-
if (selectedIndex !== -1) {
|
|
3163
|
-
this.toggleSelected(selectedValue);
|
|
3164
|
-
this.#cursor = selectedIndex;
|
|
3165
|
-
}
|
|
3166
|
-
}
|
|
3167
|
-
}
|
|
3168
|
-
this.focusedValue = this.options[this.#cursor]?.value;
|
|
3169
|
-
this.on("key", (char, key) => this.#onKey(char, key));
|
|
3170
|
-
this.on("userInput", (value) => this.#onUserInputChanged(value));
|
|
3171
|
-
}
|
|
3172
|
-
_isActionKey(char, key) {
|
|
3173
|
-
return char === "\t" || this.multiple && this.isNavigating && key.name === "space" && char !== undefined && char !== "";
|
|
3174
|
-
}
|
|
3175
|
-
#onKey(_char, key) {
|
|
3176
|
-
const isUpKey = key.name === "up";
|
|
3177
|
-
const isDownKey = key.name === "down";
|
|
3178
|
-
const isReturnKey = key.name === "return";
|
|
3179
|
-
if (isUpKey || isDownKey) {
|
|
3180
|
-
this.#cursor = Math.max(0, Math.min(this.#cursor + (isUpKey ? -1 : 1), this.filteredOptions.length - 1));
|
|
3181
|
-
this.focusedValue = this.filteredOptions[this.#cursor]?.value;
|
|
3182
|
-
if (!this.multiple) {
|
|
3183
|
-
this.selectedValues = [this.focusedValue];
|
|
3184
|
-
}
|
|
3185
|
-
this.isNavigating = true;
|
|
3186
|
-
} else if (isReturnKey) {
|
|
3187
|
-
this.value = normalisedValue(this.multiple, this.selectedValues);
|
|
3188
|
-
} else {
|
|
3189
|
-
if (this.multiple) {
|
|
3190
|
-
if (this.focusedValue !== undefined && (key.name === "tab" || this.isNavigating && key.name === "space")) {
|
|
3191
|
-
this.toggleSelected(this.focusedValue);
|
|
3192
|
-
} else {
|
|
3193
|
-
this.isNavigating = false;
|
|
3194
|
-
}
|
|
3195
|
-
} else {
|
|
3196
|
-
if (this.focusedValue) {
|
|
3197
|
-
this.selectedValues = [this.focusedValue];
|
|
3198
|
-
}
|
|
3199
|
-
this.isNavigating = false;
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
}
|
|
3203
|
-
deselectAll() {
|
|
3204
|
-
this.selectedValues = [];
|
|
3205
|
-
}
|
|
3206
|
-
toggleSelected(value) {
|
|
3207
|
-
if (this.filteredOptions.length === 0) {
|
|
3208
|
-
return;
|
|
3209
|
-
}
|
|
3210
|
-
if (this.multiple) {
|
|
3211
|
-
if (this.selectedValues.includes(value)) {
|
|
3212
|
-
this.selectedValues = this.selectedValues.filter((v) => v !== value);
|
|
3213
|
-
} else {
|
|
3214
|
-
this.selectedValues = [...this.selectedValues, value];
|
|
3215
|
-
}
|
|
3216
|
-
} else {
|
|
3217
|
-
this.selectedValues = [value];
|
|
3218
|
-
}
|
|
3219
|
-
}
|
|
3220
|
-
#onUserInputChanged(value) {
|
|
3221
|
-
if (value !== this.#lastUserInput) {
|
|
3222
|
-
this.#lastUserInput = value;
|
|
3223
|
-
const options = this.options;
|
|
3224
|
-
if (value) {
|
|
3225
|
-
this.filteredOptions = options.filter((opt) => this.#filterFn(value, opt));
|
|
3226
|
-
} else {
|
|
3227
|
-
this.filteredOptions = [...options];
|
|
3228
|
-
}
|
|
3229
|
-
this.#cursor = getCursorForValue(this.focusedValue, this.filteredOptions);
|
|
3230
|
-
this.focusedValue = this.filteredOptions[this.#cursor]?.value;
|
|
3231
|
-
if (!this.multiple) {
|
|
3232
|
-
if (this.focusedValue !== undefined) {
|
|
3233
|
-
this.toggleSelected(this.focusedValue);
|
|
3234
|
-
} else {
|
|
3235
|
-
this.deselectAll();
|
|
3236
|
-
}
|
|
3237
|
-
}
|
|
3238
|
-
}
|
|
3239
|
-
}
|
|
3240
|
-
}
|
|
3241
|
-
class GroupMultiSelectPrompt extends Prompt {
|
|
3242
|
-
options;
|
|
3243
|
-
cursor = 0;
|
|
3244
|
-
#selectableGroups;
|
|
3245
|
-
getGroupItems(group) {
|
|
3246
|
-
return this.options.filter((o) => o.group === group);
|
|
3247
|
-
}
|
|
3248
|
-
isGroupSelected(group) {
|
|
3249
|
-
const items = this.getGroupItems(group);
|
|
3250
|
-
const value = this.value;
|
|
3251
|
-
if (value === undefined) {
|
|
3252
|
-
return false;
|
|
3253
|
-
}
|
|
3254
|
-
return items.every((i) => value.includes(i.value));
|
|
3255
|
-
}
|
|
3256
|
-
toggleValue() {
|
|
3257
|
-
const item = this.options[this.cursor];
|
|
3258
|
-
if (this.value === undefined) {
|
|
3259
|
-
this.value = [];
|
|
3260
|
-
}
|
|
3261
|
-
if (item.group === true) {
|
|
3262
|
-
const group = String(item.value);
|
|
3263
|
-
const groupedItems = this.getGroupItems(group);
|
|
3264
|
-
if (this.isGroupSelected(group)) {
|
|
3265
|
-
this.value = this.value.filter((v) => groupedItems.findIndex((i) => i.value === v) === -1);
|
|
3266
|
-
} else {
|
|
3267
|
-
this.value = [...this.value, ...groupedItems.map((i) => i.value)];
|
|
3268
|
-
}
|
|
3269
|
-
this.value = Array.from(new Set(this.value));
|
|
3270
|
-
} else {
|
|
3271
|
-
const selected = this.value.includes(item.value);
|
|
3272
|
-
this.value = selected ? this.value.filter((v) => v !== item.value) : [...this.value, item.value];
|
|
3273
|
-
}
|
|
3274
|
-
}
|
|
3275
|
-
constructor(opts) {
|
|
3276
|
-
super(opts, false);
|
|
3277
|
-
const { options } = opts;
|
|
3278
|
-
this.#selectableGroups = opts.selectableGroups !== false;
|
|
3279
|
-
this.options = Object.entries(options).flatMap(([key, option]) => [
|
|
3280
|
-
{ value: key, group: true, label: key },
|
|
3281
|
-
...option.map((opt) => ({ ...opt, group: key }))
|
|
3282
|
-
]);
|
|
3283
|
-
this.value = [...opts.initialValues ?? []];
|
|
3284
|
-
this.cursor = Math.max(this.options.findIndex(({ value }) => value === opts.cursorAt), this.#selectableGroups ? 0 : 1);
|
|
3285
|
-
this.on("cursor", (key) => {
|
|
3286
|
-
switch (key) {
|
|
3287
|
-
case "left":
|
|
3288
|
-
case "up": {
|
|
3289
|
-
this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
|
|
3290
|
-
const currentIsGroup = this.options[this.cursor]?.group === true;
|
|
3291
|
-
if (!this.#selectableGroups && currentIsGroup) {
|
|
3292
|
-
this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
|
|
3293
|
-
}
|
|
3294
|
-
break;
|
|
3295
|
-
}
|
|
3296
|
-
case "down":
|
|
3297
|
-
case "right": {
|
|
3298
|
-
this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
|
|
3299
|
-
const currentIsGroup = this.options[this.cursor]?.group === true;
|
|
3300
|
-
if (!this.#selectableGroups && currentIsGroup) {
|
|
3301
|
-
this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
|
|
3302
|
-
}
|
|
3303
|
-
break;
|
|
3304
|
-
}
|
|
3305
|
-
case "space":
|
|
3306
|
-
this.toggleValue();
|
|
3307
|
-
break;
|
|
3308
|
-
}
|
|
3309
|
-
});
|
|
3310
|
-
}
|
|
3311
|
-
}
|
|
3312
2730
|
var unicode = isUnicodeSupported();
|
|
3313
2731
|
var unicodeOr = (c, fallback) => unicode ? c : fallback;
|
|
3314
2732
|
var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
|
|
@@ -3424,7 +2842,7 @@ function pinCraftNativeDependency(packagePath, craftVersion) {
|
|
|
3424
2842
|
`);
|
|
3425
2843
|
}
|
|
3426
2844
|
// package.json
|
|
3427
|
-
var version = "0.0.
|
|
2845
|
+
var version = "0.0.249";
|
|
3428
2846
|
|
|
3429
2847
|
// bin/cli.ts
|
|
3430
2848
|
var spawnedFrom = process6.env[CRAFT_CLI_SPAWN_MARKER];
|
|
@@ -3538,8 +2956,8 @@ cli.command("build", "Build the Craft application").option("--release", "Build i
|
|
|
3538
2956
|
console.log(`Platforms: ${platforms.join(", ")}`);
|
|
3539
2957
|
console.log(`Mode: ${options?.release ? "Release" : "Debug"}
|
|
3540
2958
|
`);
|
|
3541
|
-
const { existsSync
|
|
3542
|
-
const { spawn
|
|
2959
|
+
const { existsSync } = await import("fs");
|
|
2960
|
+
const { spawn } = await import("child_process");
|
|
3543
2961
|
for (const platform of platforms) {
|
|
3544
2962
|
console.log(`\uD83D\uDCE6 Building for ${platform}...`);
|
|
3545
2963
|
try {
|
|
@@ -3549,10 +2967,10 @@ cli.command("build", "Build the Craft application").option("--release", "Build i
|
|
|
3549
2967
|
continue;
|
|
3550
2968
|
}
|
|
3551
2969
|
const iosDir = "./ios";
|
|
3552
|
-
if (
|
|
2970
|
+
if (existsSync(iosDir)) {
|
|
3553
2971
|
const buildType = options?.release ? "Release" : "Debug";
|
|
3554
2972
|
await new Promise((resolve, reject) => {
|
|
3555
|
-
const proc =
|
|
2973
|
+
const proc = spawn("xcodebuild", [
|
|
3556
2974
|
"-project",
|
|
3557
2975
|
`${iosDir}/App.xcodeproj`,
|
|
3558
2976
|
"-scheme",
|
|
@@ -3572,10 +2990,10 @@ cli.command("build", "Build the Craft application").option("--release", "Build i
|
|
|
3572
2990
|
}
|
|
3573
2991
|
} else if (platform === "android") {
|
|
3574
2992
|
const androidDir = "./android";
|
|
3575
|
-
if (
|
|
2993
|
+
if (existsSync(androidDir)) {
|
|
3576
2994
|
const task = options?.release ? "assembleRelease" : "assembleDebug";
|
|
3577
2995
|
await new Promise((resolve, reject) => {
|
|
3578
|
-
const proc =
|
|
2996
|
+
const proc = spawn("./gradlew", [task], {
|
|
3579
2997
|
cwd: androidDir,
|
|
3580
2998
|
stdio: "inherit"
|
|
3581
2999
|
});
|
|
@@ -3587,13 +3005,13 @@ cli.command("build", "Build the Craft application").option("--release", "Build i
|
|
|
3587
3005
|
console.log(` \u26A0\uFE0F No Android project found. Run: craft android init`);
|
|
3588
3006
|
}
|
|
3589
3007
|
} else if (platform === "macos" || platform === "windows" || platform === "linux") {
|
|
3590
|
-
const zigDir =
|
|
3008
|
+
const zigDir = existsSync("./packages/zig") ? "./packages/zig" : ".";
|
|
3591
3009
|
const optimizeFlag = options?.release ? "-Doptimize=ReleaseSafe" : "";
|
|
3592
3010
|
await new Promise((resolve, reject) => {
|
|
3593
3011
|
const args = ["build"];
|
|
3594
3012
|
if (optimizeFlag)
|
|
3595
3013
|
args.push(optimizeFlag);
|
|
3596
|
-
const proc =
|
|
3014
|
+
const proc = spawn("zig", args, {
|
|
3597
3015
|
cwd: zigDir,
|
|
3598
3016
|
stdio: "inherit"
|
|
3599
3017
|
});
|
|
@@ -3632,8 +3050,7 @@ cli.command("dev [url]", "Launch in development mode with hot reload").option("-
|
|
|
3632
3050
|
}
|
|
3633
3051
|
});
|
|
3634
3052
|
cli.command("package", "Create installers for your Craft application").option("--name <name>", "Application name").option("--version <version>", "Application version").option("--binary <path>", "Path to application binary").option("--description <text>", "Application description").option("--author <name>", "Author/Maintainer name").option("--bundle-id <id>", "Bundle identifier (macOS/iOS)").option("--out <dir>", "Output directory (default: ./dist)").option("--icon <path>", "Application icon path").option("--platforms <list>", "Comma-separated platforms (macos,windows,linux)").option("--config <path>", "Load config from JSON file").option("--dmg", "Create DMG installer (macOS)").option("--pkg", "Create PKG installer (macOS)").option("--msi", "Create MSI installer (Windows)").option("--zip", "Create ZIP archive (Windows)").option("--deb", "Create DEB package (Linux)").option("--rpm", "Create RPM package (Linux)").option("--appimage", "Create AppImage (Linux)").example('craft package --name "My App" --version "1.0.0" --binary ./build/myapp').example("craft package --config package.json").example('craft package --name "My App" --version "1.0.0" --binary ./build/myapp --platforms macos,windows,linux').action(async (options) => {
|
|
3635
|
-
const packageModule = await Promise.resolve().then(() => (init_package(),
|
|
3636
|
-
const { packageApp: packageApp2 } = packageModule;
|
|
3053
|
+
const packageModule = await Promise.resolve().then(() => (init_package(), {}));
|
|
3637
3054
|
let config;
|
|
3638
3055
|
if (options?.config) {
|
|
3639
3056
|
if (!existsSync5(options.config)) {
|
|
@@ -3692,7 +3109,7 @@ cli.command("package", "Create installers for your Craft application").option("-
|
|
|
3692
3109
|
console.log(`Platforms: ${(config.platforms || ["current"]).join(", ")}
|
|
3693
3110
|
`);
|
|
3694
3111
|
try {
|
|
3695
|
-
const results = await
|
|
3112
|
+
const results = await packageApp(config);
|
|
3696
3113
|
console.log(`
|
|
3697
3114
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`);
|
|
3698
3115
|
console.log(`\uD83D\uDCCA Packaging Results
|
|
@@ -3824,8 +3241,8 @@ cli.command("android run", "Build and run on Android device or emulator").option
|
|
|
3824
3241
|
output: options?.output || "./android"
|
|
3825
3242
|
});
|
|
3826
3243
|
});
|
|
3827
|
-
cli.command("preview [path]", "Preview app in browser before building native").option("-p, --port <port>", "Port to serve on", { default: 3456 }).option("--host <host>", "Host to bind to", { default: "localhost" }).example("craft preview ./dist").example("craft preview ./index.html --port 8080").action(async (
|
|
3828
|
-
const servePath =
|
|
3244
|
+
cli.command("preview [path]", "Preview app in browser before building native").option("-p, --port <port>", "Port to serve on", { default: 3456 }).option("--host <host>", "Host to bind to", { default: "localhost" }).example("craft preview ./dist").example("craft preview ./index.html --port 8080").action(async (path, options) => {
|
|
3245
|
+
const servePath = path || ".";
|
|
3829
3246
|
const port = options?.port || 3456;
|
|
3830
3247
|
const host = options?.host || "localhost";
|
|
3831
3248
|
console.log(`
|
|
@@ -3833,27 +3250,27 @@ cli.command("preview [path]", "Preview app in browser before building native").o
|
|
|
3833
3250
|
console.log(` Path: ${servePath}`);
|
|
3834
3251
|
console.log(` URL: http://${host}:${port}
|
|
3835
3252
|
`);
|
|
3836
|
-
const { spawn
|
|
3837
|
-
const proc =
|
|
3253
|
+
const { spawn } = await import("child_process");
|
|
3254
|
+
const proc = spawn("bunx", ["--bun", "serve", "-p", String(port), servePath], {
|
|
3838
3255
|
stdio: "inherit"
|
|
3839
3256
|
});
|
|
3840
3257
|
proc.on("error", () => {
|
|
3841
3258
|
console.log("Falling back to python http.server...");
|
|
3842
|
-
|
|
3259
|
+
spawn("python3", ["-m", "http.server", String(port), "--directory", servePath], {
|
|
3843
3260
|
stdio: "inherit"
|
|
3844
3261
|
});
|
|
3845
3262
|
});
|
|
3846
3263
|
});
|
|
3847
3264
|
cli.command("publish", "Publish app to App Store or Play Store").option("--ios", "Publish to App Store (TestFlight)").option("--android", "Publish to Play Store").option("--api-key <path>", "App Store Connect API key path").option("--service-account <path>", "Google Play service account JSON").option("-o, --output <dir>", "Project directory", { default: "." }).example("craft publish --ios").example("craft publish --android").action(async (options) => {
|
|
3848
|
-
const { existsSync
|
|
3849
|
-
const { join
|
|
3265
|
+
const { existsSync } = await import("fs");
|
|
3266
|
+
const { join } = await import("path");
|
|
3850
3267
|
const { $ } = await Promise.resolve(globalThis.Bun);
|
|
3851
3268
|
if (options?.ios) {
|
|
3852
3269
|
console.log(`
|
|
3853
3270
|
\uD83D\uDCF1 Publishing to App Store (TestFlight)...
|
|
3854
3271
|
`);
|
|
3855
|
-
const iosDir =
|
|
3856
|
-
if (!
|
|
3272
|
+
const iosDir = join(options?.output || ".", "ios");
|
|
3273
|
+
if (!existsSync(iosDir)) {
|
|
3857
3274
|
console.error("\u274C No iOS project found. Run: craft ios init");
|
|
3858
3275
|
process6.exit(1);
|
|
3859
3276
|
}
|
|
@@ -3882,8 +3299,8 @@ cli.command("publish", "Publish app to App Store or Play Store").option("--ios",
|
|
|
3882
3299
|
console.log(`
|
|
3883
3300
|
\uD83E\uDD16 Publishing to Play Store...
|
|
3884
3301
|
`);
|
|
3885
|
-
const androidDir =
|
|
3886
|
-
if (!
|
|
3302
|
+
const androidDir = join(options?.output || ".", "android");
|
|
3303
|
+
if (!existsSync(androidDir)) {
|
|
3887
3304
|
console.error("\u274C No Android project found. Run: craft android init");
|
|
3888
3305
|
process6.exit(1);
|
|
3889
3306
|
}
|
|
@@ -3891,7 +3308,7 @@ cli.command("publish", "Publish app to App Store or Play Store").option("--ios",
|
|
|
3891
3308
|
try {
|
|
3892
3309
|
await $`cd ${androidDir} && ./gradlew bundleRelease`;
|
|
3893
3310
|
console.log("\u2705 AAB created");
|
|
3894
|
-
const aabPath =
|
|
3311
|
+
const aabPath = join(androidDir, "app/build/outputs/bundle/release/app-release.aab");
|
|
3895
3312
|
if (options?.serviceAccount) {
|
|
3896
3313
|
console.log("2. Uploading to Play Store...");
|
|
3897
3314
|
console.log("\u26A0\uFE0F Automatic Play Store upload requires fastlane or Google Play API integration.");
|
|
@@ -3930,31 +3347,31 @@ cli.command("init <name>", "Initialize a new Craft project").option("--template
|
|
|
3930
3347
|
`);
|
|
3931
3348
|
const bundleId = options?.bundleId || `com.example.${name.toLowerCase().replace(/[^a-z0-9]/g, "")}`;
|
|
3932
3349
|
const appNameSlug = name.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
3933
|
-
const { mkdirSync
|
|
3934
|
-
const { join
|
|
3350
|
+
const { mkdirSync, writeFileSync, existsSync, readdirSync, readFileSync, cpSync } = await import("fs");
|
|
3351
|
+
const { join, dirname } = await import("path");
|
|
3935
3352
|
const replaceVars = (content) => {
|
|
3936
3353
|
return content.replace(/\{\{APP_NAME\}\}/g, name).replace(/\{\{APP_NAME_SLUG\}\}/g, appNameSlug).replace(/\{\{BUNDLE_ID\}\}/g, bundleId).replace(/\{\{AUTHOR\}\}/g, "Developer");
|
|
3937
3354
|
};
|
|
3938
3355
|
const copyTemplate = async (templateName, destDir) => {
|
|
3939
|
-
const templateDir =
|
|
3940
|
-
if (!
|
|
3356
|
+
const templateDir = join(import.meta.dir, "templates/projects", templateName);
|
|
3357
|
+
if (!existsSync(templateDir)) {
|
|
3941
3358
|
console.log(` \u26A0\uFE0F Template '${templateName}' not found, using blank template`);
|
|
3942
3359
|
return false;
|
|
3943
3360
|
}
|
|
3944
3361
|
const copyRecursive = (src, dest) => {
|
|
3945
|
-
if (!
|
|
3946
|
-
|
|
3362
|
+
if (!existsSync(dest)) {
|
|
3363
|
+
mkdirSync(dest, { recursive: true });
|
|
3947
3364
|
}
|
|
3948
|
-
const entries =
|
|
3365
|
+
const entries = readdirSync(src, { withFileTypes: true });
|
|
3949
3366
|
for (const entry of entries) {
|
|
3950
|
-
const srcPath =
|
|
3951
|
-
const destPath =
|
|
3367
|
+
const srcPath = join(src, entry.name);
|
|
3368
|
+
const destPath = join(dest, entry.name);
|
|
3952
3369
|
if (entry.isDirectory()) {
|
|
3953
3370
|
copyRecursive(srcPath, destPath);
|
|
3954
3371
|
} else {
|
|
3955
|
-
const content =
|
|
3372
|
+
const content = readFileSync(srcPath, "utf-8");
|
|
3956
3373
|
const processedContent = replaceVars(content);
|
|
3957
|
-
|
|
3374
|
+
writeFileSync(destPath, processedContent);
|
|
3958
3375
|
}
|
|
3959
3376
|
}
|
|
3960
3377
|
};
|
|
@@ -3963,13 +3380,13 @@ cli.command("init <name>", "Initialize a new Craft project").option("--template
|
|
|
3963
3380
|
};
|
|
3964
3381
|
if (["blank", "tabs", "drawer", "dashboard"].includes(template)) {
|
|
3965
3382
|
console.log(`\uD83D\uDCC1 Creating ${template} project from template...`);
|
|
3966
|
-
if (!
|
|
3967
|
-
|
|
3383
|
+
if (!existsSync(name)) {
|
|
3384
|
+
mkdirSync(name, { recursive: true });
|
|
3968
3385
|
}
|
|
3969
3386
|
const copied = await copyTemplate(template, name);
|
|
3970
3387
|
if (!copied) {
|
|
3971
|
-
|
|
3972
|
-
|
|
3388
|
+
mkdirSync(join(name, "src"), { recursive: true });
|
|
3389
|
+
writeFileSync(join(name, "index.html"), replaceVars(`<!DOCTYPE html>
|
|
3973
3390
|
<html lang="en">
|
|
3974
3391
|
<head>
|
|
3975
3392
|
<meta charset="UTF-8">
|
|
@@ -3983,7 +3400,7 @@ cli.command("init <name>", "Initialize a new Craft project").option("--template
|
|
|
3983
3400
|
</div>
|
|
3984
3401
|
</body>
|
|
3985
3402
|
</html>`));
|
|
3986
|
-
|
|
3403
|
+
writeFileSync(join(name, "package.json"), replaceVars(JSON.stringify({
|
|
3987
3404
|
name: "{{APP_NAME_SLUG}}",
|
|
3988
3405
|
version: "1.0.0",
|
|
3989
3406
|
private: true,
|
|
@@ -3997,13 +3414,13 @@ cli.command("init <name>", "Initialize a new Craft project").option("--template
|
|
|
3997
3414
|
}
|
|
3998
3415
|
}, null, 2)));
|
|
3999
3416
|
}
|
|
4000
|
-
pinCraftNativeDependency(
|
|
3417
|
+
pinCraftNativeDependency(join(name, "package.json"), version);
|
|
4001
3418
|
console.log(`\u2705 ${template} project created`);
|
|
4002
3419
|
}
|
|
4003
3420
|
if (template === "desktop" || template === "all") {
|
|
4004
3421
|
console.log("\uD83D\uDCC1 Creating desktop project structure...");
|
|
4005
|
-
if (!
|
|
4006
|
-
|
|
3422
|
+
if (!existsSync(name)) {
|
|
3423
|
+
mkdirSync(name, { recursive: true });
|
|
4007
3424
|
}
|
|
4008
3425
|
const configContent = `import type { CraftConfig } from 'craft-native'
|
|
4009
3426
|
|
|
@@ -4017,7 +3434,7 @@ export default {
|
|
|
4017
3434
|
},
|
|
4018
3435
|
} satisfies CraftConfig
|
|
4019
3436
|
`;
|
|
4020
|
-
|
|
3437
|
+
writeFileSync(`${name}/craft.config.ts`, configContent);
|
|
4021
3438
|
const htmlContent = `<!DOCTYPE html>
|
|
4022
3439
|
<html lang="en">
|
|
4023
3440
|
<head>
|
|
@@ -4048,7 +3465,7 @@ export default {
|
|
|
4048
3465
|
</body>
|
|
4049
3466
|
</html>
|
|
4050
3467
|
`;
|
|
4051
|
-
|
|
3468
|
+
writeFileSync(`${name}/index.html`, htmlContent);
|
|
4052
3469
|
const packageJson = {
|
|
4053
3470
|
name: appNameSlug,
|
|
4054
3471
|
version: "0.1.0",
|
|
@@ -4064,7 +3481,7 @@ export default {
|
|
|
4064
3481
|
"craft-native": `^${version}`
|
|
4065
3482
|
}
|
|
4066
3483
|
};
|
|
4067
|
-
|
|
3484
|
+
writeFileSync(`${name}/package.json`, JSON.stringify(packageJson, null, 2));
|
|
4068
3485
|
pinCraftNativeDependency(`${name}/package.json`, version);
|
|
4069
3486
|
console.log("\u2705 Desktop project created");
|
|
4070
3487
|
}
|