preflightlaunch 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
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
const require = createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
|
+
DEFAULT_API_URL,
|
|
5
6
|
apiRequest,
|
|
6
7
|
brand,
|
|
7
|
-
|
|
8
|
+
clearAuth,
|
|
9
|
+
confirm,
|
|
8
10
|
createSpinner,
|
|
9
11
|
critical,
|
|
10
12
|
error,
|
|
11
|
-
findProjectInDir,
|
|
12
|
-
findXcodeProjects,
|
|
13
13
|
getConfig,
|
|
14
14
|
handleUnknownCommand,
|
|
15
15
|
hasRunBefore,
|
|
@@ -22,13 +22,12 @@ import {
|
|
|
22
22
|
logout,
|
|
23
23
|
markAsRun,
|
|
24
24
|
ok,
|
|
25
|
-
|
|
25
|
+
renderHeader,
|
|
26
26
|
renderReport,
|
|
27
27
|
renderReportJson,
|
|
28
28
|
scanProject,
|
|
29
29
|
select,
|
|
30
30
|
setLastScannedPath,
|
|
31
|
-
showTagline,
|
|
32
31
|
source_default,
|
|
33
32
|
spinner,
|
|
34
33
|
submitCommand,
|
|
@@ -36,7 +35,7 @@ import {
|
|
|
36
35
|
success,
|
|
37
36
|
tip,
|
|
38
37
|
warning
|
|
39
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-PMKDGQCB.js";
|
|
40
39
|
import {
|
|
41
40
|
__commonJS,
|
|
42
41
|
__require,
|
|
@@ -5227,7 +5226,7 @@ async function loginCommand() {
|
|
|
5227
5226
|
const spinner2 = createSpinner("Opening browser for login...");
|
|
5228
5227
|
spinner2.start();
|
|
5229
5228
|
try {
|
|
5230
|
-
const result = await loginWithBrowser();
|
|
5229
|
+
const result = await loginWithBrowser("login");
|
|
5231
5230
|
if (result) {
|
|
5232
5231
|
spinner2.stop();
|
|
5233
5232
|
success(`Logged in as ${source_default.bold(result.email)}`);
|
|
@@ -5318,10 +5317,11 @@ async function scanCommand(path) {
|
|
|
5318
5317
|
const resolvedPath = await interactiveProjectSelect();
|
|
5319
5318
|
if (!resolvedPath) return;
|
|
5320
5319
|
path = resolvedPath;
|
|
5320
|
+
} else {
|
|
5321
|
+
intro("Scanning project");
|
|
5321
5322
|
}
|
|
5322
5323
|
const dir = resolve(path);
|
|
5323
5324
|
setLastScannedPath(dir);
|
|
5324
|
-
intro("Scanning project");
|
|
5325
5325
|
const s = spinner();
|
|
5326
5326
|
s.start("Looking for App Store files...");
|
|
5327
5327
|
const detected = scanProject(dir);
|
|
@@ -5380,12 +5380,12 @@ async function scanCommand(path) {
|
|
|
5380
5380
|
const next = await select({
|
|
5381
5381
|
message: "What next?",
|
|
5382
5382
|
options: [
|
|
5383
|
-
{ value: "submit", label: "Submit for full analysis", hint: "
|
|
5383
|
+
{ value: "submit", label: "Submit for full analysis", hint: "100 credits" },
|
|
5384
5384
|
{ value: "done", label: "Done for now" }
|
|
5385
5385
|
]
|
|
5386
5386
|
});
|
|
5387
5387
|
if (next === "submit") {
|
|
5388
|
-
const { submitCommand: submitCommand2 } = await import("./submit-
|
|
5388
|
+
const { submitCommand: submitCommand2 } = await import("./submit-HBKAOG3Y.js");
|
|
5389
5389
|
await submitCommand2(dir, {});
|
|
5390
5390
|
} else {
|
|
5391
5391
|
tip(`Run ${brand("preflight submit")} anytime to get AI-powered fix instructions.`);
|
|
@@ -5399,6 +5399,11 @@ async function statusCommand(id, options) {
|
|
|
5399
5399
|
error("Not logged in. Run `preflight login` first.");
|
|
5400
5400
|
process.exit(1);
|
|
5401
5401
|
}
|
|
5402
|
+
if (!id) {
|
|
5403
|
+
error("Please provide a submission ID. Run `preflight history` to find one.");
|
|
5404
|
+
process.exitCode = 1;
|
|
5405
|
+
return;
|
|
5406
|
+
}
|
|
5402
5407
|
if (options.watch) {
|
|
5403
5408
|
return watchStatus(id);
|
|
5404
5409
|
}
|
|
@@ -5480,8 +5485,13 @@ async function reportCommand(id, options) {
|
|
|
5480
5485
|
error("Not logged in. Run `preflight login` first.");
|
|
5481
5486
|
process.exit(1);
|
|
5482
5487
|
}
|
|
5488
|
+
if (!id) {
|
|
5489
|
+
error("Please provide a submission or report ID. Run `preflight history` to find one.");
|
|
5490
|
+
process.exitCode = 1;
|
|
5491
|
+
return;
|
|
5492
|
+
}
|
|
5483
5493
|
if (options.open) {
|
|
5484
|
-
await open_default(
|
|
5494
|
+
await open_default(`${DEFAULT_API_URL}/report/${id}`);
|
|
5485
5495
|
console.log(source_default.dim(" Opened report in browser"));
|
|
5486
5496
|
return;
|
|
5487
5497
|
}
|
|
@@ -5499,7 +5509,7 @@ async function reportCommand(id, options) {
|
|
|
5499
5509
|
renderReportJson(data.report, data.items);
|
|
5500
5510
|
} else {
|
|
5501
5511
|
renderReport(data.report, data.items);
|
|
5502
|
-
console.log(source_default.dim(` Full report:
|
|
5512
|
+
console.log(source_default.dim(` Full report: ${DEFAULT_API_URL}/report/${id}`));
|
|
5503
5513
|
console.log();
|
|
5504
5514
|
}
|
|
5505
5515
|
} catch (err) {
|
|
@@ -5564,64 +5574,163 @@ async function historyCommand(options) {
|
|
|
5564
5574
|
process.exit(1);
|
|
5565
5575
|
}
|
|
5566
5576
|
}
|
|
5577
|
+
async function interactiveHistory() {
|
|
5578
|
+
const s = spinner();
|
|
5579
|
+
s.start("Loading your reviews...");
|
|
5580
|
+
try {
|
|
5581
|
+
const res = await apiRequest("/api/submissions");
|
|
5582
|
+
const data = await res.json();
|
|
5583
|
+
s.stop("Reviews loaded");
|
|
5584
|
+
if (!res.ok) {
|
|
5585
|
+
log.error(data.message || "Failed to load reviews");
|
|
5586
|
+
return;
|
|
5587
|
+
}
|
|
5588
|
+
if (!data.data || data.data.length === 0) {
|
|
5589
|
+
log.info("No reviews yet. Start your first review from the main menu.");
|
|
5590
|
+
console.log();
|
|
5591
|
+
await confirm("Back to menu?", true);
|
|
5592
|
+
return;
|
|
5593
|
+
}
|
|
5594
|
+
const submissions = data.data;
|
|
5595
|
+
while (true) {
|
|
5596
|
+
const options = submissions.map((sub2) => {
|
|
5597
|
+
const date = new Date(sub2.created_at).toLocaleDateString("en-US", {
|
|
5598
|
+
month: "short",
|
|
5599
|
+
day: "numeric"
|
|
5600
|
+
});
|
|
5601
|
+
const statusLabel = sub2.status === "complete" ? "Ready" : sub2.status === "failed" ? "Failed" : sub2.status === "analyzing" ? "Analyzing..." : sub2.status;
|
|
5602
|
+
return {
|
|
5603
|
+
value: sub2.id,
|
|
5604
|
+
label: `${sub2.app_name || "Unknown"} - ${statusLabel} (${date})`,
|
|
5605
|
+
hint: sub2.status === "complete" ? "View report" : ""
|
|
5606
|
+
};
|
|
5607
|
+
});
|
|
5608
|
+
options.push({
|
|
5609
|
+
value: "__back__",
|
|
5610
|
+
label: "Back to menu",
|
|
5611
|
+
hint: ""
|
|
5612
|
+
});
|
|
5613
|
+
const selected = await select({
|
|
5614
|
+
message: "Your Reviews",
|
|
5615
|
+
options
|
|
5616
|
+
});
|
|
5617
|
+
if (selected === null || selected === "__back__") return;
|
|
5618
|
+
const sub = submissions.find((s2) => s2.id === selected);
|
|
5619
|
+
if (!sub) return;
|
|
5620
|
+
if (sub.status !== "complete" || !sub.report_id) {
|
|
5621
|
+
if (sub.status === "analyzing") {
|
|
5622
|
+
log.info("This review is still being analyzed. Check back in a few minutes.");
|
|
5623
|
+
} else if (sub.status === "failed") {
|
|
5624
|
+
log.warning("This review failed. Try submitting again.");
|
|
5625
|
+
} else {
|
|
5626
|
+
log.info(`Status: ${sub.status}`);
|
|
5627
|
+
}
|
|
5628
|
+
console.log();
|
|
5629
|
+
continue;
|
|
5630
|
+
}
|
|
5631
|
+
const reportSpinner = spinner();
|
|
5632
|
+
reportSpinner.start("Loading report...");
|
|
5633
|
+
try {
|
|
5634
|
+
const reportRes = await apiRequest(`/api/reports/${sub.report_id}`);
|
|
5635
|
+
const reportData = await reportRes.json();
|
|
5636
|
+
reportSpinner.stop("Report loaded");
|
|
5637
|
+
if (reportRes.ok) {
|
|
5638
|
+
renderReport(reportData.report, reportData.items);
|
|
5639
|
+
console.log(subtext(` Full report: https://preflightlaunch.com/report/${sub.report_id}`));
|
|
5640
|
+
console.log();
|
|
5641
|
+
} else {
|
|
5642
|
+
log.error("Could not load this report.");
|
|
5643
|
+
}
|
|
5644
|
+
} catch {
|
|
5645
|
+
reportSpinner.stop("Failed to load report");
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
} catch (err) {
|
|
5649
|
+
s.stop("Failed to load reviews");
|
|
5650
|
+
log.error(`Error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
5651
|
+
}
|
|
5652
|
+
}
|
|
5567
5653
|
|
|
5568
5654
|
// src/commands/setup.ts
|
|
5569
5655
|
init_esm_shims();
|
|
5570
5656
|
|
|
5571
5657
|
// src/commands/onboarding.ts
|
|
5572
5658
|
init_esm_shims();
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
log
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5659
|
+
async function showWelcomeScreen() {
|
|
5660
|
+
renderHeader();
|
|
5661
|
+
console.log(" Preflight scans your app for common issues that");
|
|
5662
|
+
console.log(" cause App Store rejections -- before you submit.");
|
|
5663
|
+
console.log();
|
|
5664
|
+
console.log(subtext(" How it works:"));
|
|
5665
|
+
console.log(subtext(" 1. Point us to your Xcode project"));
|
|
5666
|
+
console.log(subtext(" 2. We scan for 100+ rejection risks"));
|
|
5667
|
+
console.log(subtext(" 3. Get a detailed report with fixes"));
|
|
5668
|
+
console.log();
|
|
5669
|
+
const result = await select({
|
|
5670
|
+
message: "Ready?",
|
|
5671
|
+
options: [
|
|
5672
|
+
{ value: "start", label: "Get Started" }
|
|
5673
|
+
]
|
|
5674
|
+
});
|
|
5675
|
+
if (result === null) return false;
|
|
5676
|
+
markAsRun();
|
|
5677
|
+
return true;
|
|
5678
|
+
}
|
|
5679
|
+
async function showAuthScreen() {
|
|
5680
|
+
renderHeader();
|
|
5681
|
+
const authChoice = await select({
|
|
5682
|
+
message: "How would you like to get started?",
|
|
5683
|
+
options: [
|
|
5684
|
+
{ value: "signup", label: "Create a free account", hint: "Sign up with email, GitHub, or Google" },
|
|
5685
|
+
{ value: "login", label: "I already have an account", hint: "Log in with email, GitHub, or Google" }
|
|
5686
|
+
]
|
|
5687
|
+
});
|
|
5688
|
+
if (authChoice === null) return false;
|
|
5689
|
+
if (authChoice === "signup") {
|
|
5690
|
+
const s2 = spinner();
|
|
5691
|
+
s2.start("Opening signup page in browser...");
|
|
5692
|
+
try {
|
|
5693
|
+
await loginWithBrowser("signup");
|
|
5694
|
+
} catch {
|
|
5695
|
+
s2.stop("Could not open browser");
|
|
5696
|
+
}
|
|
5697
|
+
s2.stop("Signup page opened");
|
|
5698
|
+
log.info("Create your account in the browser, then come back here.");
|
|
5699
|
+
console.log();
|
|
5700
|
+
const ready = await confirm("Done signing up? Ready to log in?");
|
|
5701
|
+
if (ready === null || !ready) {
|
|
5702
|
+
log.info(subtext("Run `preflight` anytime to come back."));
|
|
5703
|
+
return false;
|
|
5593
5704
|
}
|
|
5594
|
-
} else {
|
|
5595
|
-
log.success("Already logged in. Skipping account setup.");
|
|
5596
5705
|
}
|
|
5597
|
-
const
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
const
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
label: "Skip - I'll scan later",
|
|
5609
|
-
hint: ""
|
|
5610
|
-
});
|
|
5611
|
-
const projectChoice = await select({
|
|
5612
|
-
message: "Step 2 of 2: Choose your Xcode project",
|
|
5613
|
-
options: choices
|
|
5614
|
-
});
|
|
5615
|
-
if (projectChoice === null) return;
|
|
5616
|
-
if (projectChoice !== "__skip__") {
|
|
5617
|
-
setLastScannedPath(projectChoice);
|
|
5618
|
-
log.success(`Project saved! Run ${brand("preflight scan")} to scan it.`);
|
|
5706
|
+
const s = spinner();
|
|
5707
|
+
s.start("Opening login page... Waiting for you to finish in browser.");
|
|
5708
|
+
try {
|
|
5709
|
+
const result = await loginWithBrowser("login");
|
|
5710
|
+
if (result) {
|
|
5711
|
+
s.stop(`Logged in as ${result.email}`);
|
|
5712
|
+
return true;
|
|
5713
|
+
} else {
|
|
5714
|
+
s.stop("Login timed out or was cancelled");
|
|
5715
|
+
log.warning("Run `preflight` anytime to try again.");
|
|
5716
|
+
return false;
|
|
5619
5717
|
}
|
|
5718
|
+
} catch {
|
|
5719
|
+
s.stop("Could not open browser");
|
|
5720
|
+
log.warning("Run `preflight login` to try from the command line.");
|
|
5721
|
+
return false;
|
|
5722
|
+
}
|
|
5723
|
+
}
|
|
5724
|
+
async function runOnboarding() {
|
|
5725
|
+
if (!isLoggedIn()) {
|
|
5726
|
+
const welcomed = await showWelcomeScreen();
|
|
5727
|
+
if (!welcomed) return;
|
|
5728
|
+
const authenticated = await showAuthScreen();
|
|
5729
|
+
if (!authenticated) return;
|
|
5620
5730
|
} else {
|
|
5621
|
-
|
|
5731
|
+
markAsRun();
|
|
5732
|
+
log.success("Already logged in.");
|
|
5622
5733
|
}
|
|
5623
|
-
markAsRun();
|
|
5624
|
-
outro("You're all set! Run " + brand("preflight") + " to get started.");
|
|
5625
5734
|
}
|
|
5626
5735
|
|
|
5627
5736
|
// src/commands/setup.ts
|
|
@@ -5631,7 +5740,7 @@ async function setupCommand() {
|
|
|
5631
5740
|
|
|
5632
5741
|
// src/index.ts
|
|
5633
5742
|
var program2 = new Command();
|
|
5634
|
-
program2.name("preflight").description("Preflight - App Store Review Scanner").version("0.2.
|
|
5743
|
+
program2.name("preflight").description("Preflight - App Store Review Scanner").version("0.2.1");
|
|
5635
5744
|
program2.command("login").description("Log in to Preflight (opens browser)").action(loginCommand);
|
|
5636
5745
|
program2.command("logout").description("Log out and clear stored credentials").action(logoutCommand);
|
|
5637
5746
|
program2.command("whoami").description("Show current user and credit balance").action(whoamiCommand);
|
|
@@ -5646,49 +5755,74 @@ program2.on("command:*", (operands) => {
|
|
|
5646
5755
|
handleUnknownCommand(operands[0]);
|
|
5647
5756
|
process.exitCode = 1;
|
|
5648
5757
|
});
|
|
5758
|
+
async function fetchCredits() {
|
|
5759
|
+
try {
|
|
5760
|
+
const res = await apiRequest("/api/credits");
|
|
5761
|
+
if (!res.ok) return void 0;
|
|
5762
|
+
const data = await res.json();
|
|
5763
|
+
return data.credits ?? void 0;
|
|
5764
|
+
} catch {
|
|
5765
|
+
return void 0;
|
|
5766
|
+
}
|
|
5767
|
+
}
|
|
5768
|
+
async function openUrl(url) {
|
|
5769
|
+
try {
|
|
5770
|
+
const open = (await import("./open-A77P4RC4.js")).default;
|
|
5771
|
+
await open(url);
|
|
5772
|
+
} catch {
|
|
5773
|
+
console.log(subtext(` Visit: ${url}`));
|
|
5774
|
+
}
|
|
5775
|
+
}
|
|
5649
5776
|
async function interactiveMenu() {
|
|
5650
5777
|
if (!hasRunBefore()) {
|
|
5651
|
-
await
|
|
5652
|
-
return;
|
|
5778
|
+
const welcomed = await showWelcomeScreen();
|
|
5779
|
+
if (!welcomed) return;
|
|
5653
5780
|
}
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
{
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5781
|
+
if (!isLoggedIn()) {
|
|
5782
|
+
const authenticated = await showAuthScreen();
|
|
5783
|
+
if (!authenticated) return;
|
|
5784
|
+
}
|
|
5785
|
+
let cachedCredits;
|
|
5786
|
+
cachedCredits = await fetchCredits();
|
|
5787
|
+
while (true) {
|
|
5788
|
+
const { email } = getConfig();
|
|
5789
|
+
renderHeader(email, cachedCredits);
|
|
5790
|
+
const choice = await select({
|
|
5791
|
+
message: "What would you like to do?",
|
|
5792
|
+
options: [
|
|
5793
|
+
{ value: "review", label: "New Review", hint: "Scan your app for App Store issues" },
|
|
5794
|
+
{ value: "history", label: "View Reviews", hint: "See your past review reports" },
|
|
5795
|
+
{ value: "buy", label: "Buy Credits", hint: "Get more credits at preflightlaunch.com" },
|
|
5796
|
+
{ value: "logout", label: "Log Out" }
|
|
5797
|
+
]
|
|
5798
|
+
});
|
|
5799
|
+
if (choice === null) {
|
|
5800
|
+
console.log();
|
|
5801
|
+
console.log(subtext(" See you next time!"));
|
|
5802
|
+
console.log();
|
|
5803
|
+
return;
|
|
5804
|
+
}
|
|
5805
|
+
switch (choice) {
|
|
5806
|
+
case "review":
|
|
5807
|
+
await submitCommand(void 0, {}, true);
|
|
5808
|
+
cachedCredits = await fetchCredits();
|
|
5809
|
+
break;
|
|
5810
|
+
case "history":
|
|
5811
|
+
await interactiveHistory();
|
|
5812
|
+
break;
|
|
5813
|
+
case "buy":
|
|
5814
|
+
await openUrl("https://preflightlaunch.com/pricing");
|
|
5815
|
+
log.info("Opened pricing page in browser.");
|
|
5816
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
5817
|
+
cachedCredits = await fetchCredits();
|
|
5818
|
+
break;
|
|
5819
|
+
case "logout":
|
|
5820
|
+
clearAuth();
|
|
5821
|
+
const authenticated = await showAuthScreen();
|
|
5822
|
+
if (!authenticated) return;
|
|
5823
|
+
cachedCredits = await fetchCredits();
|
|
5824
|
+
break;
|
|
5825
|
+
}
|
|
5692
5826
|
}
|
|
5693
5827
|
}
|
|
5694
5828
|
if (process.argv.length <= 2) {
|
|
@@ -3,9 +3,9 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
const require = createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
submitCommand
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PMKDGQCB.js";
|
|
7
7
|
import "./chunk-45JYNMSU.js";
|
|
8
8
|
export {
|
|
9
9
|
submitCommand
|
|
10
10
|
};
|
|
11
|
-
//# sourceMappingURL=submit-
|
|
11
|
+
//# sourceMappingURL=submit-HBKAOG3Y.js.map
|