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.
|
@@ -3,6 +3,7 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
const require = createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
__commonJS,
|
|
6
|
+
__require,
|
|
6
7
|
__toESM,
|
|
7
8
|
init_esm_shims,
|
|
8
9
|
open_default
|
|
@@ -2980,7 +2981,7 @@ var require_compile = __commonJS({
|
|
|
2980
2981
|
const schOrFunc = root.refs[ref];
|
|
2981
2982
|
if (schOrFunc)
|
|
2982
2983
|
return schOrFunc;
|
|
2983
|
-
let _sch =
|
|
2984
|
+
let _sch = resolve4.call(this, root, ref);
|
|
2984
2985
|
if (_sch === void 0) {
|
|
2985
2986
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2986
2987
|
const { schemaId } = this.opts;
|
|
@@ -3007,7 +3008,7 @@ var require_compile = __commonJS({
|
|
|
3007
3008
|
function sameSchemaEnv(s1, s2) {
|
|
3008
3009
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3009
3010
|
}
|
|
3010
|
-
function
|
|
3011
|
+
function resolve4(root, ref) {
|
|
3011
3012
|
let sch;
|
|
3012
3013
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3013
3014
|
ref = sch;
|
|
@@ -3585,7 +3586,7 @@ var require_fast_uri = __commonJS({
|
|
|
3585
3586
|
}
|
|
3586
3587
|
return uri;
|
|
3587
3588
|
}
|
|
3588
|
-
function
|
|
3589
|
+
function resolve4(baseURI, relativeURI, options) {
|
|
3589
3590
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3590
3591
|
const resolved = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3591
3592
|
schemelessOptions.skipEscape = true;
|
|
@@ -3812,7 +3813,7 @@ var require_fast_uri = __commonJS({
|
|
|
3812
3813
|
var fastUri = {
|
|
3813
3814
|
SCHEMES,
|
|
3814
3815
|
normalize,
|
|
3815
|
-
resolve:
|
|
3816
|
+
resolve: resolve4,
|
|
3816
3817
|
resolveComponent,
|
|
3817
3818
|
equal,
|
|
3818
3819
|
serialize,
|
|
@@ -10245,7 +10246,7 @@ var require_compile2 = __commonJS({
|
|
|
10245
10246
|
const schOrFunc = root.refs[ref];
|
|
10246
10247
|
if (schOrFunc)
|
|
10247
10248
|
return schOrFunc;
|
|
10248
|
-
let _sch =
|
|
10249
|
+
let _sch = resolve4.call(this, root, ref);
|
|
10249
10250
|
if (_sch === void 0) {
|
|
10250
10251
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
10251
10252
|
const { schemaId } = this.opts;
|
|
@@ -10272,7 +10273,7 @@ var require_compile2 = __commonJS({
|
|
|
10272
10273
|
function sameSchemaEnv(s1, s2) {
|
|
10273
10274
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
10274
10275
|
}
|
|
10275
|
-
function
|
|
10276
|
+
function resolve4(root, ref) {
|
|
10276
10277
|
let sch;
|
|
10277
10278
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
10278
10279
|
ref = sch;
|
|
@@ -17430,8 +17431,8 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
17430
17431
|
var source_default = chalk;
|
|
17431
17432
|
|
|
17432
17433
|
// src/commands/submit.ts
|
|
17433
|
-
import { readFileSync, statSync as
|
|
17434
|
-
import { basename as basename3, resolve as
|
|
17434
|
+
import { readFileSync, statSync as statSync3 } from "fs";
|
|
17435
|
+
import { basename as basename3, resolve as resolve3 } from "path";
|
|
17435
17436
|
|
|
17436
17437
|
// src/lib/scanner.ts
|
|
17437
17438
|
init_esm_shims();
|
|
@@ -17867,7 +17868,7 @@ var retryifyAsync = (fn, options) => {
|
|
|
17867
17868
|
throw error2;
|
|
17868
17869
|
const delay = Math.round(interval * Math.random());
|
|
17869
17870
|
if (delay > 0) {
|
|
17870
|
-
const delayPromise = new Promise((
|
|
17871
|
+
const delayPromise = new Promise((resolve4) => setTimeout(resolve4, delay));
|
|
17871
17872
|
return delayPromise.then(() => attempt.apply(void 0, args));
|
|
17872
17873
|
} else {
|
|
17873
17874
|
return attempt.apply(void 0, args);
|
|
@@ -18669,8 +18670,8 @@ var Conf = class {
|
|
|
18669
18670
|
}
|
|
18670
18671
|
try {
|
|
18671
18672
|
const initializationVector = data.slice(0, 16);
|
|
18672
|
-
const
|
|
18673
|
-
const decipher = crypto2.createDecipheriv(encryptionAlgorithm,
|
|
18673
|
+
const password2 = crypto2.pbkdf2Sync(this.#encryptionKey, initializationVector.toString(), 1e4, 32, "sha512");
|
|
18674
|
+
const decipher = crypto2.createDecipheriv(encryptionAlgorithm, password2, initializationVector);
|
|
18674
18675
|
const slice = data.slice(17);
|
|
18675
18676
|
const dataUpdate = typeof slice === "string" ? stringToUint8Array(slice) : slice;
|
|
18676
18677
|
return uint8ArrayToString(concatUint8Arrays([decipher.update(dataUpdate), decipher.final()]));
|
|
@@ -18714,8 +18715,8 @@ var Conf = class {
|
|
|
18714
18715
|
let data = this._serialize(value);
|
|
18715
18716
|
if (this.#encryptionKey) {
|
|
18716
18717
|
const initializationVector = crypto2.randomBytes(16);
|
|
18717
|
-
const
|
|
18718
|
-
const cipher = crypto2.createCipheriv(encryptionAlgorithm,
|
|
18718
|
+
const password2 = crypto2.pbkdf2Sync(this.#encryptionKey, initializationVector.toString(), 1e4, 32, "sha512");
|
|
18719
|
+
const cipher = crypto2.createCipheriv(encryptionAlgorithm, password2, initializationVector);
|
|
18719
18720
|
data = concatUint8Arrays([initializationVector, stringToUint8Array(":"), cipher.update(stringToUint8Array(data)), cipher.final()]);
|
|
18720
18721
|
}
|
|
18721
18722
|
if (process8.env.SNAP) {
|
|
@@ -18821,24 +18822,37 @@ var Conf = class {
|
|
|
18821
18822
|
}
|
|
18822
18823
|
};
|
|
18823
18824
|
|
|
18825
|
+
// src/lib/constants.ts
|
|
18826
|
+
init_esm_shims();
|
|
18827
|
+
var SUPABASE_URL = "https://cfqzdyktjhkalfrmcgmw.supabase.co";
|
|
18828
|
+
var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNmcXpkeWt0amhrYWxmcm1jZ213Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjkyNzM4MjYsImV4cCI6MjA4NDg0OTgyNn0.O1bPUNHw7kzpWecAyT4Pizh2ITRSal3PJsrUIkZY04o";
|
|
18829
|
+
var CALLBACK_PORT = 54321;
|
|
18830
|
+
var DEFAULT_API_URL = "https://preflightlaunch.com";
|
|
18831
|
+
|
|
18824
18832
|
// src/lib/config.ts
|
|
18825
18833
|
var config = new Conf({
|
|
18826
18834
|
projectName: "preflight",
|
|
18827
18835
|
schema: {
|
|
18828
18836
|
accessToken: { type: "string" },
|
|
18829
18837
|
refreshToken: { type: "string" },
|
|
18830
|
-
apiUrl: { type: "string", default:
|
|
18838
|
+
apiUrl: { type: "string", default: DEFAULT_API_URL },
|
|
18831
18839
|
userId: { type: "string" },
|
|
18832
18840
|
email: { type: "string" },
|
|
18833
18841
|
hasRunBefore: { type: "boolean", default: false },
|
|
18834
18842
|
lastScannedPath: { type: "string" }
|
|
18835
18843
|
}
|
|
18836
18844
|
});
|
|
18845
|
+
try {
|
|
18846
|
+
if (config.get("apiUrl") === "https://preflight.dev") {
|
|
18847
|
+
config.set("apiUrl", DEFAULT_API_URL);
|
|
18848
|
+
}
|
|
18849
|
+
} catch {
|
|
18850
|
+
}
|
|
18837
18851
|
function getConfig() {
|
|
18838
18852
|
return {
|
|
18839
18853
|
accessToken: config.get("accessToken"),
|
|
18840
18854
|
refreshToken: config.get("refreshToken"),
|
|
18841
|
-
apiUrl: config.get("apiUrl") ||
|
|
18855
|
+
apiUrl: config.get("apiUrl") || DEFAULT_API_URL,
|
|
18842
18856
|
userId: config.get("userId"),
|
|
18843
18857
|
email: config.get("email"),
|
|
18844
18858
|
hasRunBefore: config.get("hasRunBefore") || false,
|
|
@@ -18899,11 +18913,11 @@ function __rest(s, e) {
|
|
|
18899
18913
|
}
|
|
18900
18914
|
function __awaiter(thisArg, _arguments, P3, generator) {
|
|
18901
18915
|
function adopt(value) {
|
|
18902
|
-
return value instanceof P3 ? value : new P3(function(
|
|
18903
|
-
|
|
18916
|
+
return value instanceof P3 ? value : new P3(function(resolve4) {
|
|
18917
|
+
resolve4(value);
|
|
18904
18918
|
});
|
|
18905
18919
|
}
|
|
18906
|
-
return new (P3 || (P3 = Promise))(function(
|
|
18920
|
+
return new (P3 || (P3 = Promise))(function(resolve4, reject) {
|
|
18907
18921
|
function fulfilled(value) {
|
|
18908
18922
|
try {
|
|
18909
18923
|
step(generator.next(value));
|
|
@@ -18919,7 +18933,7 @@ function __awaiter(thisArg, _arguments, P3, generator) {
|
|
|
18919
18933
|
}
|
|
18920
18934
|
}
|
|
18921
18935
|
function step(result) {
|
|
18922
|
-
result.done ?
|
|
18936
|
+
result.done ? resolve4(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
18923
18937
|
}
|
|
18924
18938
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18925
18939
|
});
|
|
@@ -21472,15 +21486,15 @@ var RealtimeChannel = class _RealtimeChannel {
|
|
|
21472
21486
|
}
|
|
21473
21487
|
}
|
|
21474
21488
|
} else {
|
|
21475
|
-
return new Promise((
|
|
21489
|
+
return new Promise((resolve4) => {
|
|
21476
21490
|
var _a2, _b2, _c;
|
|
21477
21491
|
const push = this._push(args.type, args, opts.timeout || this.timeout);
|
|
21478
21492
|
if (args.type === "broadcast" && !((_c = (_b2 = (_a2 = this.params) === null || _a2 === void 0 ? void 0 : _a2.config) === null || _b2 === void 0 ? void 0 : _b2.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) {
|
|
21479
|
-
|
|
21493
|
+
resolve4("ok");
|
|
21480
21494
|
}
|
|
21481
|
-
push.receive("ok", () =>
|
|
21482
|
-
push.receive("error", () =>
|
|
21483
|
-
push.receive("timeout", () =>
|
|
21495
|
+
push.receive("ok", () => resolve4("ok"));
|
|
21496
|
+
push.receive("error", () => resolve4("error"));
|
|
21497
|
+
push.receive("timeout", () => resolve4("timed out"));
|
|
21484
21498
|
});
|
|
21485
21499
|
}
|
|
21486
21500
|
}
|
|
@@ -21508,16 +21522,16 @@ var RealtimeChannel = class _RealtimeChannel {
|
|
|
21508
21522
|
};
|
|
21509
21523
|
this.joinPush.destroy();
|
|
21510
21524
|
let leavePush = null;
|
|
21511
|
-
return new Promise((
|
|
21525
|
+
return new Promise((resolve4) => {
|
|
21512
21526
|
leavePush = new Push(this, CHANNEL_EVENTS.leave, {}, timeout);
|
|
21513
21527
|
leavePush.receive("ok", () => {
|
|
21514
21528
|
onClose();
|
|
21515
|
-
|
|
21529
|
+
resolve4("ok");
|
|
21516
21530
|
}).receive("timeout", () => {
|
|
21517
21531
|
onClose();
|
|
21518
|
-
|
|
21532
|
+
resolve4("timed out");
|
|
21519
21533
|
}).receive("error", () => {
|
|
21520
|
-
|
|
21534
|
+
resolve4("error");
|
|
21521
21535
|
});
|
|
21522
21536
|
leavePush.send();
|
|
21523
21537
|
if (!this._canPush()) {
|
|
@@ -23217,7 +23231,7 @@ var _getRequestParams = (method, options, parameters, body) => {
|
|
|
23217
23231
|
return _objectSpread2(_objectSpread2({}, params), parameters);
|
|
23218
23232
|
};
|
|
23219
23233
|
async function _handleRequest(fetcher, method, url, options, parameters, body, namespace) {
|
|
23220
|
-
return new Promise((
|
|
23234
|
+
return new Promise((resolve4, reject) => {
|
|
23221
23235
|
fetcher(url, _getRequestParams(method, options, parameters, body)).then((result) => {
|
|
23222
23236
|
if (!result.ok) throw result;
|
|
23223
23237
|
if (options === null || options === void 0 ? void 0 : options.noResolveJson) return result;
|
|
@@ -23227,7 +23241,7 @@ async function _handleRequest(fetcher, method, url, options, parameters, body, n
|
|
|
23227
23241
|
if (!contentType || !contentType.includes("application/json")) return {};
|
|
23228
23242
|
}
|
|
23229
23243
|
return result.json();
|
|
23230
|
-
}).then((data) =>
|
|
23244
|
+
}).then((data) => resolve4(data)).catch((error2) => handleError(error2, reject, options, namespace));
|
|
23231
23245
|
});
|
|
23232
23246
|
}
|
|
23233
23247
|
function createFetchApi(namespace = "storage") {
|
|
@@ -27724,7 +27738,7 @@ var GoTrueClient = class _GoTrueClient {
|
|
|
27724
27738
|
try {
|
|
27725
27739
|
let res;
|
|
27726
27740
|
if ("email" in credentials) {
|
|
27727
|
-
const { email, password, options } = credentials;
|
|
27741
|
+
const { email, password: password2, options } = credentials;
|
|
27728
27742
|
let codeChallenge = null;
|
|
27729
27743
|
let codeChallengeMethod = null;
|
|
27730
27744
|
if (this.flowType === "pkce") {
|
|
@@ -27736,7 +27750,7 @@ var GoTrueClient = class _GoTrueClient {
|
|
|
27736
27750
|
redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
|
|
27737
27751
|
body: {
|
|
27738
27752
|
email,
|
|
27739
|
-
password,
|
|
27753
|
+
password: password2,
|
|
27740
27754
|
data: (_a = options === null || options === void 0 ? void 0 : options.data) !== null && _a !== void 0 ? _a : {},
|
|
27741
27755
|
gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
|
|
27742
27756
|
code_challenge: codeChallenge,
|
|
@@ -27745,12 +27759,12 @@ var GoTrueClient = class _GoTrueClient {
|
|
|
27745
27759
|
xform: _sessionResponse
|
|
27746
27760
|
});
|
|
27747
27761
|
} else if ("phone" in credentials) {
|
|
27748
|
-
const { phone, password, options } = credentials;
|
|
27762
|
+
const { phone, password: password2, options } = credentials;
|
|
27749
27763
|
res = await _request(this.fetch, "POST", `${this.url}/signup`, {
|
|
27750
27764
|
headers: this.headers,
|
|
27751
27765
|
body: {
|
|
27752
27766
|
phone,
|
|
27753
|
-
password,
|
|
27767
|
+
password: password2,
|
|
27754
27768
|
data: (_b = options === null || options === void 0 ? void 0 : options.data) !== null && _b !== void 0 ? _b : {},
|
|
27755
27769
|
channel: (_c = options === null || options === void 0 ? void 0 : options.channel) !== null && _c !== void 0 ? _c : "sms",
|
|
27756
27770
|
gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }
|
|
@@ -27792,23 +27806,23 @@ var GoTrueClient = class _GoTrueClient {
|
|
|
27792
27806
|
try {
|
|
27793
27807
|
let res;
|
|
27794
27808
|
if ("email" in credentials) {
|
|
27795
|
-
const { email, password, options } = credentials;
|
|
27809
|
+
const { email, password: password2, options } = credentials;
|
|
27796
27810
|
res = await _request(this.fetch, "POST", `${this.url}/token?grant_type=password`, {
|
|
27797
27811
|
headers: this.headers,
|
|
27798
27812
|
body: {
|
|
27799
27813
|
email,
|
|
27800
|
-
password,
|
|
27814
|
+
password: password2,
|
|
27801
27815
|
gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }
|
|
27802
27816
|
},
|
|
27803
27817
|
xform: _sessionResponsePassword
|
|
27804
27818
|
});
|
|
27805
27819
|
} else if ("phone" in credentials) {
|
|
27806
|
-
const { phone, password, options } = credentials;
|
|
27820
|
+
const { phone, password: password2, options } = credentials;
|
|
27807
27821
|
res = await _request(this.fetch, "POST", `${this.url}/token?grant_type=password`, {
|
|
27808
27822
|
headers: this.headers,
|
|
27809
27823
|
body: {
|
|
27810
27824
|
phone,
|
|
27811
|
-
password,
|
|
27825
|
+
password: password2,
|
|
27812
27826
|
gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }
|
|
27813
27827
|
},
|
|
27814
27828
|
xform: _sessionResponsePassword
|
|
@@ -30308,13 +30322,6 @@ function shouldShowDeprecationWarning() {
|
|
|
30308
30322
|
}
|
|
30309
30323
|
if (shouldShowDeprecationWarning()) console.warn("\u26A0\uFE0F Node.js 18 and below are deprecated and will no longer be supported in future versions of @supabase/supabase-js. Please upgrade to Node.js 20 or later. For more information, visit: https://github.com/orgs/supabase/discussions/37217");
|
|
30310
30324
|
|
|
30311
|
-
// src/lib/constants.ts
|
|
30312
|
-
init_esm_shims();
|
|
30313
|
-
var SUPABASE_URL = "https://cfqzdyktjhkalfrmcgmw.supabase.co";
|
|
30314
|
-
var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNmcXpkeWt0amhrYWxmcm1jZ213Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjkyNzM4MjYsImV4cCI6MjA4NDg0OTgyNn0.O1bPUNHw7kzpWecAyT4Pizh2ITRSal3PJsrUIkZY04o";
|
|
30315
|
-
var CALLBACK_PORT = 54321;
|
|
30316
|
-
var DEFAULT_API_URL = "https://preflightlaunch.com";
|
|
30317
|
-
|
|
30318
30325
|
// src/lib/api-client.ts
|
|
30319
30326
|
var API_TIMEOUT_MS = 3e4;
|
|
30320
30327
|
async function refreshSession() {
|
|
@@ -30379,10 +30386,14 @@ function decodeJwtPayload(token) {
|
|
|
30379
30386
|
const decoded = Buffer.from(payload, "base64url").toString("utf-8");
|
|
30380
30387
|
return JSON.parse(decoded);
|
|
30381
30388
|
}
|
|
30382
|
-
async function loginWithBrowser() {
|
|
30389
|
+
async function loginWithBrowser(mode = "login") {
|
|
30383
30390
|
const { apiUrl } = getConfig();
|
|
30384
30391
|
const baseUrl = apiUrl || DEFAULT_API_URL;
|
|
30385
|
-
|
|
30392
|
+
if (mode === "signup") {
|
|
30393
|
+
await open_default(`${baseUrl}/auth/signup`);
|
|
30394
|
+
return null;
|
|
30395
|
+
}
|
|
30396
|
+
return new Promise((resolve4) => {
|
|
30386
30397
|
const server = http.createServer(async (req, res) => {
|
|
30387
30398
|
const url = new URL(req.url, `http://localhost:${CALLBACK_PORT}`);
|
|
30388
30399
|
if (url.pathname === "/callback") {
|
|
@@ -30393,7 +30404,7 @@ async function loginWithBrowser() {
|
|
|
30393
30404
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
30394
30405
|
res.end(htmlPage("Login failed", errorMsg));
|
|
30395
30406
|
server.close();
|
|
30396
|
-
|
|
30407
|
+
resolve4(null);
|
|
30397
30408
|
return;
|
|
30398
30409
|
}
|
|
30399
30410
|
try {
|
|
@@ -30405,12 +30416,12 @@ async function loginWithBrowser() {
|
|
|
30405
30416
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
30406
30417
|
res.end(htmlPage("Logged in to Preflight!", "You can close this tab and return to your terminal."));
|
|
30407
30418
|
server.close();
|
|
30408
|
-
|
|
30419
|
+
resolve4({ email });
|
|
30409
30420
|
} catch (err) {
|
|
30410
30421
|
res.writeHead(500, { "Content-Type": "text/html" });
|
|
30411
30422
|
res.end(htmlPage("Login failed", "Could not process authentication tokens."));
|
|
30412
30423
|
server.close();
|
|
30413
|
-
|
|
30424
|
+
resolve4(null);
|
|
30414
30425
|
}
|
|
30415
30426
|
} else {
|
|
30416
30427
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
@@ -30423,7 +30434,7 @@ async function loginWithBrowser() {
|
|
|
30423
30434
|
} else {
|
|
30424
30435
|
console.error(`Server error: ${err.message}`);
|
|
30425
30436
|
}
|
|
30426
|
-
|
|
30437
|
+
resolve4(null);
|
|
30427
30438
|
});
|
|
30428
30439
|
server.listen(CALLBACK_PORT, () => {
|
|
30429
30440
|
const redirectTo = encodeURIComponent(`http://localhost:${CALLBACK_PORT}/callback`);
|
|
@@ -30432,7 +30443,7 @@ async function loginWithBrowser() {
|
|
|
30432
30443
|
});
|
|
30433
30444
|
setTimeout(() => {
|
|
30434
30445
|
server.close();
|
|
30435
|
-
|
|
30446
|
+
resolve4(null);
|
|
30436
30447
|
}, 5 * 60 * 1e3);
|
|
30437
30448
|
});
|
|
30438
30449
|
}
|
|
@@ -32673,6 +32684,76 @@ function D(t2, e, s) {
|
|
|
32673
32684
|
const i = t2 + e, r = Math.max(s.length - 1, 0), n = i < 0 ? r : i > r ? 0 : i;
|
|
32674
32685
|
return s[n].disabled ? D(n, e < 0 ? -1 : 1, s) : n;
|
|
32675
32686
|
}
|
|
32687
|
+
var Mt = class extends x {
|
|
32688
|
+
options;
|
|
32689
|
+
cursor = 0;
|
|
32690
|
+
get _value() {
|
|
32691
|
+
return this.options[this.cursor].value;
|
|
32692
|
+
}
|
|
32693
|
+
get _enabledOptions() {
|
|
32694
|
+
return this.options.filter((e) => e.disabled !== true);
|
|
32695
|
+
}
|
|
32696
|
+
toggleAll() {
|
|
32697
|
+
const e = this._enabledOptions, s = this.value !== void 0 && this.value.length === e.length;
|
|
32698
|
+
this.value = s ? [] : e.map((i) => i.value);
|
|
32699
|
+
}
|
|
32700
|
+
toggleInvert() {
|
|
32701
|
+
const e = this.value;
|
|
32702
|
+
if (!e) return;
|
|
32703
|
+
const s = this._enabledOptions.filter((i) => !e.includes(i.value));
|
|
32704
|
+
this.value = s.map((i) => i.value);
|
|
32705
|
+
}
|
|
32706
|
+
toggleValue() {
|
|
32707
|
+
this.value === void 0 && (this.value = []);
|
|
32708
|
+
const e = this.value.includes(this._value);
|
|
32709
|
+
this.value = e ? this.value.filter((s) => s !== this._value) : [...this.value, this._value];
|
|
32710
|
+
}
|
|
32711
|
+
constructor(e) {
|
|
32712
|
+
super(e, false), this.options = e.options, this.value = [...e.initialValues ?? []];
|
|
32713
|
+
const s = Math.max(this.options.findIndex(({ value: i }) => i === e.cursorAt), 0);
|
|
32714
|
+
this.cursor = this.options[s].disabled ? D(s, 1, this.options) : s, this.on("key", (i) => {
|
|
32715
|
+
i === "a" && this.toggleAll(), i === "i" && this.toggleInvert();
|
|
32716
|
+
}), this.on("cursor", (i) => {
|
|
32717
|
+
switch (i) {
|
|
32718
|
+
case "left":
|
|
32719
|
+
case "up":
|
|
32720
|
+
this.cursor = D(this.cursor, -1, this.options);
|
|
32721
|
+
break;
|
|
32722
|
+
case "down":
|
|
32723
|
+
case "right":
|
|
32724
|
+
this.cursor = D(this.cursor, 1, this.options);
|
|
32725
|
+
break;
|
|
32726
|
+
case "space":
|
|
32727
|
+
this.toggleValue();
|
|
32728
|
+
break;
|
|
32729
|
+
}
|
|
32730
|
+
});
|
|
32731
|
+
}
|
|
32732
|
+
};
|
|
32733
|
+
var Lt = class extends x {
|
|
32734
|
+
_mask = "\u2022";
|
|
32735
|
+
get cursor() {
|
|
32736
|
+
return this._cursor;
|
|
32737
|
+
}
|
|
32738
|
+
get masked() {
|
|
32739
|
+
return this.userInput.replaceAll(/./g, this._mask);
|
|
32740
|
+
}
|
|
32741
|
+
get userInputWithCursor() {
|
|
32742
|
+
if (this.state === "submit" || this.state === "cancel") return this.masked;
|
|
32743
|
+
const e = this.userInput;
|
|
32744
|
+
if (this.cursor >= e.length) return `${this.masked}${import_picocolors.default.inverse(import_picocolors.default.hidden("_"))}`;
|
|
32745
|
+
const s = this.masked, i = s.slice(0, this.cursor), r = s.slice(this.cursor);
|
|
32746
|
+
return `${i}${import_picocolors.default.inverse(r[0])}${r.slice(1)}`;
|
|
32747
|
+
}
|
|
32748
|
+
clear() {
|
|
32749
|
+
this._clearUserInput();
|
|
32750
|
+
}
|
|
32751
|
+
constructor({ mask: e, ...s }) {
|
|
32752
|
+
super(s), this._mask = e ?? "\u2022", this.on("userInput", (i) => {
|
|
32753
|
+
this._setValue(i);
|
|
32754
|
+
});
|
|
32755
|
+
}
|
|
32756
|
+
};
|
|
32676
32757
|
var Wt = class extends x {
|
|
32677
32758
|
options;
|
|
32678
32759
|
cursor = 0;
|
|
@@ -33042,6 +33123,105 @@ ${import_picocolors2.default.gray(x2)} ${e}
|
|
|
33042
33123
|
|
|
33043
33124
|
`);
|
|
33044
33125
|
};
|
|
33126
|
+
var Q2 = (e, r) => e.split(`
|
|
33127
|
+
`).map((s) => r(s)).join(`
|
|
33128
|
+
`);
|
|
33129
|
+
var Lt2 = (e) => {
|
|
33130
|
+
const r = (i, n) => {
|
|
33131
|
+
const o = i.label ?? String(i.value);
|
|
33132
|
+
return n === "disabled" ? `${import_picocolors2.default.gray(z2)} ${Q2(o, (u) => import_picocolors2.default.strikethrough(import_picocolors2.default.gray(u)))}${i.hint ? ` ${import_picocolors2.default.dim(`(${i.hint ?? "disabled"})`)}` : ""}` : n === "active" ? `${import_picocolors2.default.cyan(te)} ${o}${i.hint ? ` ${import_picocolors2.default.dim(`(${i.hint})`)}` : ""}` : n === "selected" ? `${import_picocolors2.default.green(G2)} ${Q2(o, import_picocolors2.default.dim)}${i.hint ? ` ${import_picocolors2.default.dim(`(${i.hint})`)}` : ""}` : n === "cancelled" ? `${Q2(o, (u) => import_picocolors2.default.strikethrough(import_picocolors2.default.dim(u)))}` : n === "active-selected" ? `${import_picocolors2.default.green(G2)} ${o}${i.hint ? ` ${import_picocolors2.default.dim(`(${i.hint})`)}` : ""}` : n === "submitted" ? `${Q2(o, import_picocolors2.default.dim)}` : `${import_picocolors2.default.dim(z2)} ${Q2(o, import_picocolors2.default.dim)}`;
|
|
33133
|
+
}, s = e.required ?? true;
|
|
33134
|
+
return new Mt({ options: e.options, signal: e.signal, input: e.input, output: e.output, initialValues: e.initialValues, required: s, cursorAt: e.cursorAt, validate(i) {
|
|
33135
|
+
if (s && (i === void 0 || i.length === 0)) return `Please select at least one option.
|
|
33136
|
+
${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
|
|
33137
|
+
}, render() {
|
|
33138
|
+
const i = Bt(e.output, e.message, `${Ee(this.state)} `, `${N2(this.state)} `), n = `${import_picocolors2.default.gray(h)}
|
|
33139
|
+
${i}
|
|
33140
|
+
`, o = this.value ?? [], u = (l, a) => {
|
|
33141
|
+
if (l.disabled) return r(l, "disabled");
|
|
33142
|
+
const d = o.includes(l.value);
|
|
33143
|
+
return a && d ? r(l, "active-selected") : d ? r(l, "selected") : r(l, a ? "active" : "inactive");
|
|
33144
|
+
};
|
|
33145
|
+
switch (this.state) {
|
|
33146
|
+
case "submit": {
|
|
33147
|
+
const l = this.options.filter(({ value: d }) => o.includes(d)).map((d) => r(d, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none"), a = Bt(e.output, l, `${import_picocolors2.default.gray(h)} `);
|
|
33148
|
+
return `${n}${a}`;
|
|
33149
|
+
}
|
|
33150
|
+
case "cancel": {
|
|
33151
|
+
const l = this.options.filter(({ value: d }) => o.includes(d)).map((d) => r(d, "cancelled")).join(import_picocolors2.default.dim(", "));
|
|
33152
|
+
if (l.trim() === "") return `${n}${import_picocolors2.default.gray(h)}`;
|
|
33153
|
+
const a = Bt(e.output, l, `${import_picocolors2.default.gray(h)} `);
|
|
33154
|
+
return `${n}${a}
|
|
33155
|
+
${import_picocolors2.default.gray(h)}`;
|
|
33156
|
+
}
|
|
33157
|
+
case "error": {
|
|
33158
|
+
const l = `${import_picocolors2.default.yellow(h)} `, a = this.error.split(`
|
|
33159
|
+
`).map((E, p) => p === 0 ? `${import_picocolors2.default.yellow(x2)} ${import_picocolors2.default.yellow(E)}` : ` ${E}`).join(`
|
|
33160
|
+
`), d = n.split(`
|
|
33161
|
+
`).length, g = a.split(`
|
|
33162
|
+
`).length + 1;
|
|
33163
|
+
return `${n}${l}${J2({ output: e.output, options: this.options, cursor: this.cursor, maxItems: e.maxItems, columnPadding: l.length, rowPadding: d + g, style: u }).join(`
|
|
33164
|
+
${l}`)}
|
|
33165
|
+
${a}
|
|
33166
|
+
`;
|
|
33167
|
+
}
|
|
33168
|
+
default: {
|
|
33169
|
+
const l = `${import_picocolors2.default.cyan(h)} `, a = n.split(`
|
|
33170
|
+
`).length;
|
|
33171
|
+
return `${n}${l}${J2({ output: e.output, options: this.options, cursor: this.cursor, maxItems: e.maxItems, columnPadding: l.length, rowPadding: a + 2, style: u }).join(`
|
|
33172
|
+
${l}`)}
|
|
33173
|
+
${import_picocolors2.default.cyan(x2)}
|
|
33174
|
+
`;
|
|
33175
|
+
}
|
|
33176
|
+
}
|
|
33177
|
+
} }).prompt();
|
|
33178
|
+
};
|
|
33179
|
+
var jt = (e) => import_picocolors2.default.dim(e);
|
|
33180
|
+
var Vt2 = (e, r, s) => {
|
|
33181
|
+
const i = { hard: true, trim: false }, n = q2(e, r, i).split(`
|
|
33182
|
+
`), o = n.reduce((a, d) => Math.max(M2(d), a), 0), u = n.map(s).reduce((a, d) => Math.max(M2(d), a), 0), l = r - (u - o);
|
|
33183
|
+
return q2(e, l, i);
|
|
33184
|
+
};
|
|
33185
|
+
var kt2 = (e = "", r = "", s) => {
|
|
33186
|
+
const i = s?.output ?? P2.stdout, n = (s?.withGuide ?? _.withGuide) !== false, o = s?.format ?? jt, u = ["", ...Vt2(e, rt(i) - 6, o).split(`
|
|
33187
|
+
`).map(o), ""], l = M2(r), a = Math.max(u.reduce((p, y2) => {
|
|
33188
|
+
const $ = M2(y2);
|
|
33189
|
+
return $ > p ? $ : p;
|
|
33190
|
+
}, 0), l) + 2, d = u.map((p) => `${import_picocolors2.default.gray(h)} ${p}${" ".repeat(a - M2(p))}${import_picocolors2.default.gray(h)}`).join(`
|
|
33191
|
+
`), g = n ? `${import_picocolors2.default.gray(h)}
|
|
33192
|
+
` : "", E = n ? Ne : pe;
|
|
33193
|
+
i.write(`${g}${import_picocolors2.default.green(k2)} ${import_picocolors2.default.reset(r)} ${import_picocolors2.default.gray(se.repeat(Math.max(a - l - 1, 1)) + he)}
|
|
33194
|
+
${d}
|
|
33195
|
+
${import_picocolors2.default.gray(E + se.repeat(a + 2) + me)}
|
|
33196
|
+
`);
|
|
33197
|
+
};
|
|
33198
|
+
var Gt = (e) => new Lt({ validate: e.validate, mask: e.mask ?? Pe, signal: e.signal, input: e.input, output: e.output, render() {
|
|
33199
|
+
const r = `${import_picocolors2.default.gray(h)}
|
|
33200
|
+
${N2(this.state)} ${e.message}
|
|
33201
|
+
`, s = this.userInputWithCursor, i = this.masked;
|
|
33202
|
+
switch (this.state) {
|
|
33203
|
+
case "error": {
|
|
33204
|
+
const n = i ? ` ${i}` : "";
|
|
33205
|
+
return e.clearOnError && this.clear(), `${r.trim()}
|
|
33206
|
+
${import_picocolors2.default.yellow(h)}${n}
|
|
33207
|
+
${import_picocolors2.default.yellow(x2)} ${import_picocolors2.default.yellow(this.error)}
|
|
33208
|
+
`;
|
|
33209
|
+
}
|
|
33210
|
+
case "submit": {
|
|
33211
|
+
const n = i ? ` ${import_picocolors2.default.dim(i)}` : "";
|
|
33212
|
+
return `${r}${import_picocolors2.default.gray(h)}${n}`;
|
|
33213
|
+
}
|
|
33214
|
+
case "cancel": {
|
|
33215
|
+
const n = i ? ` ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(i))}` : "";
|
|
33216
|
+
return `${r}${import_picocolors2.default.gray(h)}${n}${i ? `
|
|
33217
|
+
${import_picocolors2.default.gray(h)}` : ""}`;
|
|
33218
|
+
}
|
|
33219
|
+
default:
|
|
33220
|
+
return `${r}${import_picocolors2.default.cyan(h)} ${s}
|
|
33221
|
+
${import_picocolors2.default.cyan(x2)}
|
|
33222
|
+
`;
|
|
33223
|
+
}
|
|
33224
|
+
} }).prompt();
|
|
33045
33225
|
var Ut = import_picocolors2.default.magenta;
|
|
33046
33226
|
var Ie = ({ indicator: e = "dots", onCancel: r, output: s = process.stdout, cancelMessage: i, errorMessage: n, frames: o = ee ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], delay: u = ee ? 80 : 120, signal: l, ...a } = {}) => {
|
|
33047
33227
|
const d = ue();
|
|
@@ -33312,9 +33492,10 @@ function renderReportJson(report, items) {
|
|
|
33312
33492
|
|
|
33313
33493
|
// src/lib/project-finder.ts
|
|
33314
33494
|
init_esm_shims();
|
|
33315
|
-
import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
|
|
33316
|
-
import {
|
|
33317
|
-
import {
|
|
33495
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
33496
|
+
import { execFileSync } from "child_process";
|
|
33497
|
+
import { join as join2, basename as basename2, dirname, resolve as resolve2 } from "path";
|
|
33498
|
+
import { homedir as homedir2, platform } from "os";
|
|
33318
33499
|
|
|
33319
33500
|
// src/ui/interactive.ts
|
|
33320
33501
|
init_esm_shims();
|
|
@@ -33324,24 +33505,24 @@ function intro(title) {
|
|
|
33324
33505
|
R2.info(title);
|
|
33325
33506
|
}
|
|
33326
33507
|
}
|
|
33327
|
-
function showTagline() {
|
|
33328
|
-
R2.message(`${APP_TAGLINE}
|
|
33329
|
-
Catch rejection reasons before Apple does.`);
|
|
33330
|
-
}
|
|
33331
|
-
function brandSplash() {
|
|
33332
|
-
console.log();
|
|
33333
|
-
console.log(brand(` ${APP_NAME.split("").join(" ")}`));
|
|
33334
|
-
console.log();
|
|
33335
|
-
console.log(subtext(` ${APP_TAGLINE}`));
|
|
33336
|
-
console.log(subtext(` v${APP_VERSION}`));
|
|
33337
|
-
console.log();
|
|
33338
|
-
}
|
|
33339
33508
|
function outro(message) {
|
|
33340
33509
|
Wt2(message || "Done!");
|
|
33341
33510
|
}
|
|
33342
33511
|
function tip(message) {
|
|
33343
33512
|
console.log();
|
|
33344
|
-
console.log(subtext(`
|
|
33513
|
+
console.log(subtext(` Tip: ${message}`));
|
|
33514
|
+
console.log();
|
|
33515
|
+
}
|
|
33516
|
+
function renderHeader(email, credits) {
|
|
33517
|
+
clearScreen();
|
|
33518
|
+
console.log();
|
|
33519
|
+
console.log(brand(` ${APP_NAME.split("").map((c) => c.toUpperCase()).join(" ")}`));
|
|
33520
|
+
if (email) {
|
|
33521
|
+
const creditDisplay = credits !== void 0 ? credits < 100 ? source_default.yellow(`${credits} credits`) : `${credits} credits` : "";
|
|
33522
|
+
console.log(subtext(` ${email}${creditDisplay ? ` \xB7 ${creditDisplay}` : ""}`));
|
|
33523
|
+
} else {
|
|
33524
|
+
console.log(subtext(` ${APP_TAGLINE}`));
|
|
33525
|
+
}
|
|
33345
33526
|
console.log();
|
|
33346
33527
|
}
|
|
33347
33528
|
async function select(opts) {
|
|
@@ -33350,7 +33531,17 @@ async function select(opts) {
|
|
|
33350
33531
|
options: opts.options
|
|
33351
33532
|
});
|
|
33352
33533
|
if (Ct(result)) {
|
|
33353
|
-
|
|
33534
|
+
return null;
|
|
33535
|
+
}
|
|
33536
|
+
return result;
|
|
33537
|
+
}
|
|
33538
|
+
async function multiselect(opts) {
|
|
33539
|
+
const result = await Lt2({
|
|
33540
|
+
message: opts.message,
|
|
33541
|
+
options: opts.options,
|
|
33542
|
+
required: opts.required ?? false
|
|
33543
|
+
});
|
|
33544
|
+
if (Ct(result)) {
|
|
33354
33545
|
return null;
|
|
33355
33546
|
}
|
|
33356
33547
|
return result;
|
|
@@ -33358,7 +33549,6 @@ async function select(opts) {
|
|
|
33358
33549
|
async function confirm(message, initialValue = true) {
|
|
33359
33550
|
const result = await Mt2({ message, initialValue });
|
|
33360
33551
|
if (Ct(result)) {
|
|
33361
|
-
Pt("Cancelled.");
|
|
33362
33552
|
return null;
|
|
33363
33553
|
}
|
|
33364
33554
|
return result;
|
|
@@ -33366,7 +33556,13 @@ async function confirm(message, initialValue = true) {
|
|
|
33366
33556
|
async function text(opts) {
|
|
33367
33557
|
const result = await Qt(opts);
|
|
33368
33558
|
if (Ct(result)) {
|
|
33369
|
-
|
|
33559
|
+
return null;
|
|
33560
|
+
}
|
|
33561
|
+
return result;
|
|
33562
|
+
}
|
|
33563
|
+
async function password(opts) {
|
|
33564
|
+
const result = await Gt({ message: opts.message, validate: opts.validate });
|
|
33565
|
+
if (Ct(result)) {
|
|
33370
33566
|
return null;
|
|
33371
33567
|
}
|
|
33372
33568
|
return result;
|
|
@@ -33375,6 +33571,14 @@ function spinner() {
|
|
|
33375
33571
|
return Ie();
|
|
33376
33572
|
}
|
|
33377
33573
|
var log = R2;
|
|
33574
|
+
function clearScreen() {
|
|
33575
|
+
if (process.stdout.isTTY) {
|
|
33576
|
+
process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
33577
|
+
}
|
|
33578
|
+
}
|
|
33579
|
+
function note(message, title) {
|
|
33580
|
+
kt2(message, title);
|
|
33581
|
+
}
|
|
33378
33582
|
|
|
33379
33583
|
// src/lib/project-finder.ts
|
|
33380
33584
|
var SEARCH_DIRS = [
|
|
@@ -33386,6 +33590,45 @@ var SEARCH_DIRS = [
|
|
|
33386
33590
|
"code",
|
|
33387
33591
|
"dev"
|
|
33388
33592
|
];
|
|
33593
|
+
var NOISE_PATTERNS = [
|
|
33594
|
+
"/Pods/",
|
|
33595
|
+
"/DerivedData/",
|
|
33596
|
+
"/Carthage/",
|
|
33597
|
+
"/build/",
|
|
33598
|
+
"/.build/",
|
|
33599
|
+
"/SourcePackages/",
|
|
33600
|
+
"/Library/Developer/",
|
|
33601
|
+
"/.Trash/"
|
|
33602
|
+
];
|
|
33603
|
+
function spotlightSearch() {
|
|
33604
|
+
if (platform() !== "darwin") return [];
|
|
33605
|
+
try {
|
|
33606
|
+
const output = execFileSync("mdfind", [
|
|
33607
|
+
'kMDItemFSName == "*.xcodeproj" || kMDItemFSName == "*.xcworkspace"'
|
|
33608
|
+
], { encoding: "utf-8", timeout: 5e3 });
|
|
33609
|
+
const lines = output.trim().split("\n").filter(Boolean);
|
|
33610
|
+
const seen = /* @__PURE__ */ new Set();
|
|
33611
|
+
const projects = [];
|
|
33612
|
+
for (const fullPath of lines) {
|
|
33613
|
+
if (NOISE_PATTERNS.some((pattern) => fullPath.includes(pattern))) continue;
|
|
33614
|
+
const projectDir = dirname(fullPath);
|
|
33615
|
+
if (seen.has(projectDir)) continue;
|
|
33616
|
+
seen.add(projectDir);
|
|
33617
|
+
const type = fullPath.endsWith(".xcworkspace") ? "xcworkspace" : "xcodeproj";
|
|
33618
|
+
const name = basename2(fullPath).replace(/\.(xcodeproj|xcworkspace)$/, "");
|
|
33619
|
+
let modifiedAt;
|
|
33620
|
+
try {
|
|
33621
|
+
modifiedAt = statSync2(fullPath).mtimeMs;
|
|
33622
|
+
} catch {
|
|
33623
|
+
}
|
|
33624
|
+
projects.push({ name, path: projectDir, type, fullPath, modifiedAt });
|
|
33625
|
+
}
|
|
33626
|
+
projects.sort((a, b) => (b.modifiedAt ?? 0) - (a.modifiedAt ?? 0));
|
|
33627
|
+
return projects;
|
|
33628
|
+
} catch {
|
|
33629
|
+
return [];
|
|
33630
|
+
}
|
|
33631
|
+
}
|
|
33389
33632
|
function findXcodeProjects(extraDirs = []) {
|
|
33390
33633
|
const home = homedir2();
|
|
33391
33634
|
const projects = [];
|
|
@@ -33447,9 +33690,23 @@ function findProjectInDir(dir) {
|
|
|
33447
33690
|
}
|
|
33448
33691
|
return null;
|
|
33449
33692
|
}
|
|
33693
|
+
function browseWithFinder() {
|
|
33694
|
+
if (platform() !== "darwin") return null;
|
|
33695
|
+
try {
|
|
33696
|
+
const result = execFileSync("osascript", [
|
|
33697
|
+
"-e",
|
|
33698
|
+
'POSIX path of (choose folder with prompt "Select your Xcode project folder")'
|
|
33699
|
+
], { encoding: "utf-8", timeout: 12e4 });
|
|
33700
|
+
const path5 = result.trim();
|
|
33701
|
+
return path5.endsWith("/") ? path5.slice(0, -1) : path5;
|
|
33702
|
+
} catch {
|
|
33703
|
+
return null;
|
|
33704
|
+
}
|
|
33705
|
+
}
|
|
33450
33706
|
function buildProjectChoices(lastScannedPath) {
|
|
33451
33707
|
const choices = [];
|
|
33452
33708
|
const cwd = process.cwd();
|
|
33709
|
+
const addedPaths = /* @__PURE__ */ new Set();
|
|
33453
33710
|
if (lastScannedPath && existsSync2(lastScannedPath)) {
|
|
33454
33711
|
const proj = findProjectInDir(lastScannedPath);
|
|
33455
33712
|
if (proj) {
|
|
@@ -33458,24 +33715,37 @@ function buildProjectChoices(lastScannedPath) {
|
|
|
33458
33715
|
label: `${proj.name} (last scanned)`,
|
|
33459
33716
|
hint: shortenPath(lastScannedPath)
|
|
33460
33717
|
});
|
|
33718
|
+
addedPaths.add(lastScannedPath);
|
|
33461
33719
|
}
|
|
33462
33720
|
}
|
|
33463
33721
|
const cwdProj = findProjectInDir(cwd);
|
|
33464
|
-
if (cwdProj && cwd
|
|
33722
|
+
if (cwdProj && !addedPaths.has(cwd)) {
|
|
33465
33723
|
choices.push({
|
|
33466
33724
|
value: cwd,
|
|
33467
33725
|
label: cwdProj.name,
|
|
33468
|
-
hint: `Current directory
|
|
33726
|
+
hint: `Current directory`
|
|
33469
33727
|
});
|
|
33728
|
+
addedPaths.add(cwd);
|
|
33729
|
+
}
|
|
33730
|
+
let found = spotlightSearch();
|
|
33731
|
+
if (found.length === 0) {
|
|
33732
|
+
found = findXcodeProjects();
|
|
33470
33733
|
}
|
|
33471
|
-
const
|
|
33472
|
-
|
|
33473
|
-
if (proj.path === lastScannedPath || proj.path === cwd) continue;
|
|
33734
|
+
for (const proj of found.slice(0, 8)) {
|
|
33735
|
+
if (addedPaths.has(proj.path)) continue;
|
|
33474
33736
|
choices.push({
|
|
33475
33737
|
value: proj.path,
|
|
33476
33738
|
label: proj.name,
|
|
33477
33739
|
hint: shortenPath(proj.path)
|
|
33478
33740
|
});
|
|
33741
|
+
addedPaths.add(proj.path);
|
|
33742
|
+
}
|
|
33743
|
+
if (platform() === "darwin") {
|
|
33744
|
+
choices.push({
|
|
33745
|
+
value: "__finder__",
|
|
33746
|
+
label: "Open Finder to pick a folder",
|
|
33747
|
+
hint: "Browse with macOS file picker"
|
|
33748
|
+
});
|
|
33479
33749
|
}
|
|
33480
33750
|
choices.push({
|
|
33481
33751
|
value: "__manual__",
|
|
@@ -33486,15 +33756,20 @@ function buildProjectChoices(lastScannedPath) {
|
|
|
33486
33756
|
}
|
|
33487
33757
|
async function interactiveProjectSelect() {
|
|
33488
33758
|
const choices = buildProjectChoices(getLastScannedPath());
|
|
33489
|
-
|
|
33490
|
-
|
|
33491
|
-
|
|
33759
|
+
const realProjects = choices.filter((c) => !c.value.startsWith("__"));
|
|
33760
|
+
if (realProjects.length === 0) {
|
|
33761
|
+
log.info("No Xcode projects found on your Mac.");
|
|
33492
33762
|
}
|
|
33493
33763
|
const selected = await select({
|
|
33494
33764
|
message: "Where's your Xcode project?",
|
|
33495
33765
|
options: choices
|
|
33496
33766
|
});
|
|
33497
33767
|
if (selected === null) return null;
|
|
33768
|
+
if (selected === "__finder__") {
|
|
33769
|
+
const finderPath = browseWithFinder();
|
|
33770
|
+
if (!finderPath) return null;
|
|
33771
|
+
return finderPath;
|
|
33772
|
+
}
|
|
33498
33773
|
if (selected === "__manual__") return promptForManualPath();
|
|
33499
33774
|
return selected;
|
|
33500
33775
|
}
|
|
@@ -33504,6 +33779,8 @@ async function promptForManualPath() {
|
|
|
33504
33779
|
placeholder: "./MyApp",
|
|
33505
33780
|
validate: (val) => {
|
|
33506
33781
|
if (!val?.trim()) return "Path is required";
|
|
33782
|
+
const resolved = resolve2(val.trim());
|
|
33783
|
+
if (!existsSync2(resolved)) return "Directory not found";
|
|
33507
33784
|
}
|
|
33508
33785
|
});
|
|
33509
33786
|
}
|
|
@@ -33590,14 +33867,411 @@ async function promptLogin() {
|
|
|
33590
33867
|
return result === "login";
|
|
33591
33868
|
}
|
|
33592
33869
|
|
|
33870
|
+
// src/lib/submission-questions.ts
|
|
33871
|
+
init_esm_shims();
|
|
33872
|
+
var CATEGORIES = [
|
|
33873
|
+
"Business",
|
|
33874
|
+
"Developer Tools",
|
|
33875
|
+
"Education",
|
|
33876
|
+
"Finance",
|
|
33877
|
+
"Health & Fitness",
|
|
33878
|
+
"Lifestyle",
|
|
33879
|
+
"Productivity",
|
|
33880
|
+
"Social Networking",
|
|
33881
|
+
"Utilities"
|
|
33882
|
+
];
|
|
33883
|
+
var AGE_RATING_CONTENT_TYPES = [
|
|
33884
|
+
{ value: "cartoonViolence", label: "Cartoon violence", hint: "e.g., Tom & Jerry style" },
|
|
33885
|
+
{ value: "realisticViolence", label: "Realistic violence", hint: "e.g., combat games" },
|
|
33886
|
+
{ value: "prolongedViolence", label: "Graphic/intense violence", hint: "e.g., gore, torture" },
|
|
33887
|
+
{ value: "sexualContent", label: "Sexual content or nudity", hint: "e.g., explicit images" },
|
|
33888
|
+
{ value: "matureSuggestive", label: "Mature or suggestive themes", hint: "e.g., dating, romance" },
|
|
33889
|
+
{ value: "profanity", label: "Swearing or crude humor", hint: "e.g., curse words" },
|
|
33890
|
+
{ value: "alcoholDrugs", label: "Alcohol, tobacco, or drugs", hint: "e.g., drinking scenes" },
|
|
33891
|
+
{ value: "gamblingSimulated", label: "Gambling (no real money)", hint: "e.g., casino games with fake chips" },
|
|
33892
|
+
{ value: "horrorFear", label: "Horror or scary content", hint: "e.g., jump scares" },
|
|
33893
|
+
{ value: "medicalTreatment", label: "Medical or health advice", hint: "e.g., treatment suggestions" },
|
|
33894
|
+
{ value: "gamblingContests", label: "Real money gambling or paid contests", hint: "e.g., betting, fantasy sports" }
|
|
33895
|
+
];
|
|
33896
|
+
var PRIVACY_DATA_TYPES = [
|
|
33897
|
+
{ value: "contact", label: "Contact Info", hint: "Name, email, phone, address" },
|
|
33898
|
+
{ value: "health", label: "Health & Fitness", hint: "Workouts, steps, medical info" },
|
|
33899
|
+
{ value: "financial", label: "Financial Info", hint: "Credit cards, bank details" },
|
|
33900
|
+
{ value: "location", label: "Location", hint: "GPS, location data" },
|
|
33901
|
+
{ value: "sensitive", label: "Sensitive Info", hint: "Race, religion, politics" },
|
|
33902
|
+
{ value: "contacts", label: "Contacts", hint: "Phone contacts, address book" },
|
|
33903
|
+
{ value: "content", label: "User Content", hint: "Photos, videos, posts" },
|
|
33904
|
+
{ value: "browsing", label: "Browsing History", hint: "Websites visited" },
|
|
33905
|
+
{ value: "search", label: "Search History", hint: "In-app searches" },
|
|
33906
|
+
{ value: "identifiers", label: "Identifiers", hint: "User ID, device ID" },
|
|
33907
|
+
{ value: "purchases", label: "Purchases", hint: "Purchase history" },
|
|
33908
|
+
{ value: "usage", label: "Usage Data", hint: "Button taps, feature usage" },
|
|
33909
|
+
{ value: "diagnostics", label: "Diagnostics", hint: "Crash reports (Firebase, Sentry)" },
|
|
33910
|
+
{ value: "other", label: "Other Data", hint: "Anything else not listed" }
|
|
33911
|
+
];
|
|
33912
|
+
var FEATURE_ITEMS = [
|
|
33913
|
+
{ value: "ugc", label: "User Posts & Uploads", hint: "Comments, photos, sharing" },
|
|
33914
|
+
{ value: "login", label: "Account / Login", hint: "Sign up or log in required" },
|
|
33915
|
+
{ value: "iap", label: "Pay to Unlock Features", hint: "One-time purchases" },
|
|
33916
|
+
{ value: "subscriptions", label: "Subscription / Recurring Payment", hint: "Weekly, monthly, yearly" },
|
|
33917
|
+
{ value: "ads", label: "Ads in Your App", hint: "Banner, video, or sponsored" },
|
|
33918
|
+
{ value: "thirdPartyLogin", label: "Sign in with Apple / Google", hint: "Social login" },
|
|
33919
|
+
{ value: "aiContent", label: "AI-Generated Content", hint: "ChatGPT, DALL-E, etc." },
|
|
33920
|
+
{ value: "healthClaims", label: "Health / Medical Advice", hint: "Diagnosis, treatment" },
|
|
33921
|
+
{ value: "crypto", label: "Crypto / NFTs", hint: "Buy, sell, trade" }
|
|
33922
|
+
];
|
|
33923
|
+
function calculateAgeRating(answers) {
|
|
33924
|
+
if (answers.prolongedViolence === 2 || answers.sexualContent === 2 || answers.gamblingSimulated === 2 || answers.gamblingContests > 0) {
|
|
33925
|
+
return "17+";
|
|
33926
|
+
}
|
|
33927
|
+
if (answers.realisticViolence > 0 || answers.sexualContent > 0 || answers.matureSuggestive === 2 || answers.alcoholDrugs === 2 || answers.gamblingSimulated > 0) {
|
|
33928
|
+
return "12+";
|
|
33929
|
+
}
|
|
33930
|
+
if (answers.cartoonViolence === 2 || answers.matureSuggestive > 0 || answers.profanity === 2 || answers.horrorFear === 2) {
|
|
33931
|
+
return "9+";
|
|
33932
|
+
}
|
|
33933
|
+
return "4+";
|
|
33934
|
+
}
|
|
33935
|
+
async function collectAppDetails(projectName) {
|
|
33936
|
+
const skipGate = await select({
|
|
33937
|
+
message: "App Details (you can always add these later on the web)",
|
|
33938
|
+
options: [
|
|
33939
|
+
{ value: "fill", label: "Fill in now", hint: "Name, description, keywords, category" },
|
|
33940
|
+
{ value: "skip", label: "Skip for now", hint: "Just use the project name" }
|
|
33941
|
+
]
|
|
33942
|
+
});
|
|
33943
|
+
if (skipGate === null) return null;
|
|
33944
|
+
if (skipGate === "skip") {
|
|
33945
|
+
return {
|
|
33946
|
+
appName: projectName,
|
|
33947
|
+
signInRequired: false
|
|
33948
|
+
};
|
|
33949
|
+
}
|
|
33950
|
+
const appName = await text({
|
|
33951
|
+
message: "App Name",
|
|
33952
|
+
placeholder: projectName,
|
|
33953
|
+
defaultValue: projectName,
|
|
33954
|
+
validate: (val) => {
|
|
33955
|
+
if (!val?.trim()) return "App name is required";
|
|
33956
|
+
}
|
|
33957
|
+
});
|
|
33958
|
+
if (appName === null) return null;
|
|
33959
|
+
const description = await text({
|
|
33960
|
+
message: "Description (press Enter to skip)",
|
|
33961
|
+
placeholder: "Describe your app as it appears in the App Store"
|
|
33962
|
+
});
|
|
33963
|
+
if (description === null) return null;
|
|
33964
|
+
const keywords = await text({
|
|
33965
|
+
message: "Keywords (press Enter to skip)",
|
|
33966
|
+
placeholder: "Comma-separated, 100 chars max",
|
|
33967
|
+
validate: (val) => {
|
|
33968
|
+
if (val && val.length > 100) return "Keywords must be 100 characters or less";
|
|
33969
|
+
}
|
|
33970
|
+
});
|
|
33971
|
+
if (keywords === null) return null;
|
|
33972
|
+
const promotionalText = await text({
|
|
33973
|
+
message: "Promotional Text (press Enter to skip)",
|
|
33974
|
+
placeholder: "Short promotional text, 170 chars max",
|
|
33975
|
+
validate: (val) => {
|
|
33976
|
+
if (val && val.length > 170) return "Promotional text must be 170 characters or less";
|
|
33977
|
+
}
|
|
33978
|
+
});
|
|
33979
|
+
if (promotionalText === null) return null;
|
|
33980
|
+
const categoryOptions = [
|
|
33981
|
+
{ value: "__skip__", label: "Skip", hint: "Choose later" },
|
|
33982
|
+
...CATEGORIES.map((c) => ({ value: c, label: c }))
|
|
33983
|
+
];
|
|
33984
|
+
const category = await select({
|
|
33985
|
+
message: "Primary Category",
|
|
33986
|
+
options: categoryOptions
|
|
33987
|
+
});
|
|
33988
|
+
if (category === null) return null;
|
|
33989
|
+
const supportUrl = await text({
|
|
33990
|
+
message: "Support URL (press Enter to skip)",
|
|
33991
|
+
placeholder: "https://example.com/support"
|
|
33992
|
+
});
|
|
33993
|
+
if (supportUrl === null) return null;
|
|
33994
|
+
const marketingUrl = await text({
|
|
33995
|
+
message: "Marketing URL (press Enter to skip)",
|
|
33996
|
+
placeholder: "https://example.com"
|
|
33997
|
+
});
|
|
33998
|
+
if (marketingUrl === null) return null;
|
|
33999
|
+
const signInRequired = await confirm("Does your app require sign-in for review?", false);
|
|
34000
|
+
if (signInRequired === null) return null;
|
|
34001
|
+
let demoUsername;
|
|
34002
|
+
let demoPassword;
|
|
34003
|
+
if (signInRequired) {
|
|
34004
|
+
const email = await text({
|
|
34005
|
+
message: "Demo Email",
|
|
34006
|
+
placeholder: "test@example.com",
|
|
34007
|
+
validate: (val) => {
|
|
34008
|
+
if (!val?.trim()) return "Demo email is required when sign-in is required";
|
|
34009
|
+
}
|
|
34010
|
+
});
|
|
34011
|
+
if (email === null) return null;
|
|
34012
|
+
demoUsername = email;
|
|
34013
|
+
const pass = await password({
|
|
34014
|
+
message: "Demo Password",
|
|
34015
|
+
validate: (val) => {
|
|
34016
|
+
if (!val?.trim()) return "Demo password is required when sign-in is required";
|
|
34017
|
+
}
|
|
34018
|
+
});
|
|
34019
|
+
if (pass === null) return null;
|
|
34020
|
+
demoPassword = pass;
|
|
34021
|
+
}
|
|
34022
|
+
return {
|
|
34023
|
+
appName: appName.trim(),
|
|
34024
|
+
description: description?.trim() || void 0,
|
|
34025
|
+
keywords: keywords?.trim() || void 0,
|
|
34026
|
+
category: category === "__skip__" ? void 0 : category,
|
|
34027
|
+
supportUrl: supportUrl?.trim() || void 0,
|
|
34028
|
+
promotionalText: promotionalText?.trim() || void 0,
|
|
34029
|
+
marketingUrl: marketingUrl?.trim() || void 0,
|
|
34030
|
+
signInRequired,
|
|
34031
|
+
demoUsername,
|
|
34032
|
+
demoPassword
|
|
34033
|
+
};
|
|
34034
|
+
}
|
|
34035
|
+
async function collectAgeRating() {
|
|
34036
|
+
log.step(subtext("Step 1 of 3: Age Rating"));
|
|
34037
|
+
const defaultAnswers = {
|
|
34038
|
+
cartoonViolence: 0,
|
|
34039
|
+
realisticViolence: 0,
|
|
34040
|
+
prolongedViolence: 0,
|
|
34041
|
+
sexualContent: 0,
|
|
34042
|
+
matureSuggestive: 0,
|
|
34043
|
+
profanity: 0,
|
|
34044
|
+
alcoholDrugs: 0,
|
|
34045
|
+
gamblingSimulated: 0,
|
|
34046
|
+
horrorFear: 0,
|
|
34047
|
+
medicalTreatment: 0,
|
|
34048
|
+
gamblingContests: 0,
|
|
34049
|
+
unrestrictedWebAccess: false,
|
|
34050
|
+
madeForKids: false
|
|
34051
|
+
};
|
|
34052
|
+
const hasMatureContent = await confirm(
|
|
34053
|
+
"Does your app contain any mature content? (violence, sexual content, drugs, gambling, horror)",
|
|
34054
|
+
false
|
|
34055
|
+
);
|
|
34056
|
+
if (hasMatureContent === null) return null;
|
|
34057
|
+
if (!hasMatureContent) {
|
|
34058
|
+
const rating = calculateAgeRating(defaultAnswers);
|
|
34059
|
+
log.success(`Age Rating: ${rating} (no mature content)`);
|
|
34060
|
+
const looksRight = await confirm("Does that look right?", true);
|
|
34061
|
+
if (looksRight === null) return null;
|
|
34062
|
+
if (!looksRight) {
|
|
34063
|
+
return collectAgeRatingDetailed(defaultAnswers);
|
|
34064
|
+
}
|
|
34065
|
+
return { answers: defaultAnswers, rating };
|
|
34066
|
+
}
|
|
34067
|
+
return collectAgeRatingDetailed(defaultAnswers);
|
|
34068
|
+
}
|
|
34069
|
+
async function collectAgeRatingDetailed(answers) {
|
|
34070
|
+
const selectedTypes = await multiselect({
|
|
34071
|
+
message: "Which types of content does your app contain? (Space to select, Enter to confirm)",
|
|
34072
|
+
options: AGE_RATING_CONTENT_TYPES
|
|
34073
|
+
});
|
|
34074
|
+
if (selectedTypes === null) return null;
|
|
34075
|
+
const updatedAnswers = { ...answers };
|
|
34076
|
+
for (const typeKey of selectedTypes) {
|
|
34077
|
+
const typeInfo = AGE_RATING_CONTENT_TYPES.find((t2) => t2.value === typeKey);
|
|
34078
|
+
if (!typeInfo) continue;
|
|
34079
|
+
const severity = await select({
|
|
34080
|
+
message: `${typeInfo.label}: how much?`,
|
|
34081
|
+
options: [
|
|
34082
|
+
{ value: "1", label: "A little", hint: "Minor/occasional" },
|
|
34083
|
+
{ value: "2", label: "A lot", hint: "Frequent/prominent" }
|
|
34084
|
+
]
|
|
34085
|
+
});
|
|
34086
|
+
if (severity === null) return null;
|
|
34087
|
+
updatedAnswers[typeKey] = parseInt(severity);
|
|
34088
|
+
}
|
|
34089
|
+
const webAccess = await confirm("Can users browse any website in your app? (e.g., in-app browser)", false);
|
|
34090
|
+
if (webAccess === null) return null;
|
|
34091
|
+
updatedAnswers.unrestrictedWebAccess = webAccess;
|
|
34092
|
+
const madeForKids = await confirm("Is this app designed specifically for kids under 13?", false);
|
|
34093
|
+
if (madeForKids === null) return null;
|
|
34094
|
+
updatedAnswers.madeForKids = madeForKids;
|
|
34095
|
+
const rating = calculateAgeRating(updatedAnswers);
|
|
34096
|
+
log.success(`Age Rating: ${rating}`);
|
|
34097
|
+
return { answers: updatedAnswers, rating };
|
|
34098
|
+
}
|
|
34099
|
+
async function collectPrivacyData() {
|
|
34100
|
+
log.step(subtext("Step 2 of 3: Privacy & Data"));
|
|
34101
|
+
const collectsData = await confirm("Does your app collect any user data?", false);
|
|
34102
|
+
if (collectsData === null) return null;
|
|
34103
|
+
const emptyData = Object.fromEntries(
|
|
34104
|
+
PRIVACY_DATA_TYPES.map((t2) => [t2.value, { collected: false, linked: false }])
|
|
34105
|
+
);
|
|
34106
|
+
if (!collectsData) {
|
|
34107
|
+
return { data: emptyData, tracking: false };
|
|
34108
|
+
}
|
|
34109
|
+
const collectedTypes = await multiselect({
|
|
34110
|
+
message: "What data does your app collect? (Space to select, Enter to confirm)",
|
|
34111
|
+
options: PRIVACY_DATA_TYPES
|
|
34112
|
+
});
|
|
34113
|
+
if (collectedTypes === null) return null;
|
|
34114
|
+
const data = { ...emptyData };
|
|
34115
|
+
for (const typeKey of collectedTypes) {
|
|
34116
|
+
data[typeKey] = { collected: true, linked: false };
|
|
34117
|
+
const linked = await confirm(
|
|
34118
|
+
`Can you tie ${PRIVACY_DATA_TYPES.find((t2) => t2.value === typeKey)?.label || typeKey} to a specific person? (e.g., through their account)`,
|
|
34119
|
+
false
|
|
34120
|
+
);
|
|
34121
|
+
if (linked === null) return null;
|
|
34122
|
+
data[typeKey].linked = linked;
|
|
34123
|
+
}
|
|
34124
|
+
const tracking = await confirm(
|
|
34125
|
+
"Does your app use data to track users across other companies' apps and websites?",
|
|
34126
|
+
false
|
|
34127
|
+
);
|
|
34128
|
+
if (tracking === null) return null;
|
|
34129
|
+
return { data, tracking };
|
|
34130
|
+
}
|
|
34131
|
+
async function collectFeatureChecklist() {
|
|
34132
|
+
log.step(subtext("Step 3 of 3: Features"));
|
|
34133
|
+
const selectedFeatures = await multiselect({
|
|
34134
|
+
message: "Which features does your app include? (Space to select, Enter to confirm)",
|
|
34135
|
+
options: FEATURE_ITEMS
|
|
34136
|
+
});
|
|
34137
|
+
if (selectedFeatures === null) return null;
|
|
34138
|
+
const checklist = {
|
|
34139
|
+
ugc: selectedFeatures.includes("ugc"),
|
|
34140
|
+
login: selectedFeatures.includes("login"),
|
|
34141
|
+
iap: selectedFeatures.includes("iap"),
|
|
34142
|
+
subscriptions: selectedFeatures.includes("subscriptions"),
|
|
34143
|
+
ads: selectedFeatures.includes("ads"),
|
|
34144
|
+
thirdPartyLogin: selectedFeatures.includes("thirdPartyLogin"),
|
|
34145
|
+
aiContent: selectedFeatures.includes("aiContent"),
|
|
34146
|
+
healthClaims: selectedFeatures.includes("healthClaims"),
|
|
34147
|
+
crypto: selectedFeatures.includes("crypto")
|
|
34148
|
+
};
|
|
34149
|
+
if (checklist.login) {
|
|
34150
|
+
const hasAccountDeletion = await confirm(
|
|
34151
|
+
"Does your app have an account deletion button? (Apple requires this!)",
|
|
34152
|
+
false
|
|
34153
|
+
);
|
|
34154
|
+
if (hasAccountDeletion === null) return null;
|
|
34155
|
+
checklist.accountDeletion = hasAccountDeletion;
|
|
34156
|
+
}
|
|
34157
|
+
if (checklist.iap || checklist.subscriptions) {
|
|
34158
|
+
const hasRestorePurchases = await confirm(
|
|
34159
|
+
'Does your app have a "Restore Purchases" button? (Apple requires this!)',
|
|
34160
|
+
false
|
|
34161
|
+
);
|
|
34162
|
+
if (hasRestorePurchases === null) return null;
|
|
34163
|
+
checklist.restorePurchases = hasRestorePurchases;
|
|
34164
|
+
}
|
|
34165
|
+
return checklist;
|
|
34166
|
+
}
|
|
34167
|
+
async function collectCompliance() {
|
|
34168
|
+
const ageResult = await collectAgeRating();
|
|
34169
|
+
if (ageResult === null) return null;
|
|
34170
|
+
const privacyResult = await collectPrivacyData();
|
|
34171
|
+
if (privacyResult === null) return null;
|
|
34172
|
+
const checklistResult = await collectFeatureChecklist();
|
|
34173
|
+
if (checklistResult === null) return null;
|
|
34174
|
+
return {
|
|
34175
|
+
ageRatingAnswers: ageResult.answers,
|
|
34176
|
+
ageRating: ageResult.rating,
|
|
34177
|
+
privacyDeclarations: privacyResult,
|
|
34178
|
+
checklist: checklistResult
|
|
34179
|
+
};
|
|
34180
|
+
}
|
|
34181
|
+
function formatComplianceForApi(compliance) {
|
|
34182
|
+
return {
|
|
34183
|
+
age_rating: compliance.ageRatingAnswers,
|
|
34184
|
+
age_rating_result: compliance.ageRating,
|
|
34185
|
+
privacy_declarations: {
|
|
34186
|
+
data: compliance.privacyDeclarations.data,
|
|
34187
|
+
tracking: compliance.privacyDeclarations.tracking
|
|
34188
|
+
},
|
|
34189
|
+
checklist: compliance.checklist
|
|
34190
|
+
};
|
|
34191
|
+
}
|
|
34192
|
+
function formatComplianceSummary(compliance) {
|
|
34193
|
+
const lines = [];
|
|
34194
|
+
lines.push(` Age Rating: ${compliance.ageRating}`);
|
|
34195
|
+
const collectedTypes = Object.entries(compliance.privacyDeclarations.data).filter(([_2, v]) => v.collected).map(([k3, _2]) => {
|
|
34196
|
+
const typeInfo = PRIVACY_DATA_TYPES.find((t2) => t2.value === k3);
|
|
34197
|
+
return typeInfo?.label || k3;
|
|
34198
|
+
});
|
|
34199
|
+
if (collectedTypes.length > 0) {
|
|
34200
|
+
lines.push(` Privacy: ${collectedTypes.join(", ")}`);
|
|
34201
|
+
} else {
|
|
34202
|
+
lines.push(` Privacy: No data collected`);
|
|
34203
|
+
}
|
|
34204
|
+
const enabledFeatures = Object.entries(compliance.checklist).filter(([_2, v]) => v === true).map(([k3, _2]) => {
|
|
34205
|
+
const featureInfo = FEATURE_ITEMS.find((f) => f.value === k3);
|
|
34206
|
+
return featureInfo?.label || k3;
|
|
34207
|
+
});
|
|
34208
|
+
if (enabledFeatures.length > 0) {
|
|
34209
|
+
lines.push(` Features: ${enabledFeatures.join(", ")}`);
|
|
34210
|
+
} else {
|
|
34211
|
+
lines.push(` Features: None selected`);
|
|
34212
|
+
}
|
|
34213
|
+
return lines;
|
|
34214
|
+
}
|
|
34215
|
+
|
|
33593
34216
|
// src/commands/submit.ts
|
|
33594
|
-
async function
|
|
34217
|
+
async function openUrl(url) {
|
|
34218
|
+
try {
|
|
34219
|
+
const open = (await import("./open-A77P4RC4.js")).default;
|
|
34220
|
+
await open(url);
|
|
34221
|
+
} catch {
|
|
34222
|
+
console.log(subtext(` Visit: ${url}`));
|
|
34223
|
+
}
|
|
34224
|
+
}
|
|
34225
|
+
async function fetchCredits() {
|
|
34226
|
+
try {
|
|
34227
|
+
const res = await apiRequest("/api/credits");
|
|
34228
|
+
if (!res.ok) return null;
|
|
34229
|
+
const data = await res.json();
|
|
34230
|
+
return data.credits ?? null;
|
|
34231
|
+
} catch {
|
|
34232
|
+
return null;
|
|
34233
|
+
}
|
|
34234
|
+
}
|
|
34235
|
+
async function creditPreCheck() {
|
|
34236
|
+
const credits = await fetchCredits();
|
|
34237
|
+
if (credits === null) {
|
|
34238
|
+
log.warning("Could not verify credit balance. Proceeding anyway.");
|
|
34239
|
+
return true;
|
|
34240
|
+
}
|
|
34241
|
+
if (credits >= 100) return true;
|
|
34242
|
+
log.warning(`You need 100 credits for a review. You currently have ${credits}.`);
|
|
34243
|
+
console.log();
|
|
34244
|
+
const wantsBuy = await confirm("Would you like to buy more credits?");
|
|
34245
|
+
if (wantsBuy === null || !wantsBuy) return false;
|
|
34246
|
+
await openUrl("https://preflightlaunch.com/pricing");
|
|
34247
|
+
log.info("Opened pricing page in browser.");
|
|
34248
|
+
console.log();
|
|
34249
|
+
log.info(subtext("Waiting for credits... Press Enter to check now, or Esc to cancel."));
|
|
34250
|
+
let attempts = 0;
|
|
34251
|
+
const maxAttempts = 60;
|
|
34252
|
+
while (attempts < maxAttempts) {
|
|
34253
|
+
await new Promise((r) => setTimeout(r, 1e4));
|
|
34254
|
+
attempts++;
|
|
34255
|
+
const newCredits = await fetchCredits();
|
|
34256
|
+
if (newCredits !== null && newCredits >= 100) {
|
|
34257
|
+
log.success(`Credits updated! You now have ${newCredits} credits.`);
|
|
34258
|
+
return true;
|
|
34259
|
+
}
|
|
34260
|
+
}
|
|
34261
|
+
log.warning("Still waiting for credits. You can try again later.");
|
|
34262
|
+
return false;
|
|
34263
|
+
}
|
|
34264
|
+
async function submitCommand(path5, options = {}, fromMenu = false) {
|
|
33595
34265
|
if (!isLoggedIn()) {
|
|
34266
|
+
if (fromMenu) {
|
|
34267
|
+
log.error("Not logged in.");
|
|
34268
|
+
return;
|
|
34269
|
+
}
|
|
33596
34270
|
const wantsLogin = await promptLogin();
|
|
33597
34271
|
if (wantsLogin) {
|
|
33598
34272
|
const s = spinner();
|
|
33599
34273
|
s.start("Opening browser...");
|
|
33600
|
-
const result = await loginWithBrowser();
|
|
34274
|
+
const result = await loginWithBrowser("login");
|
|
33601
34275
|
if (result) {
|
|
33602
34276
|
s.stop(`Logged in as ${result.email}`);
|
|
33603
34277
|
} else {
|
|
@@ -33610,18 +34284,23 @@ async function submitCommand(path5, options = {}) {
|
|
|
33610
34284
|
return;
|
|
33611
34285
|
}
|
|
33612
34286
|
}
|
|
34287
|
+
if (fromMenu) {
|
|
34288
|
+
const hasCredits = await creditPreCheck();
|
|
34289
|
+
if (!hasCredits) return;
|
|
34290
|
+
}
|
|
33613
34291
|
if (!path5) {
|
|
33614
34292
|
const resolvedPath = await interactiveProjectSelect();
|
|
33615
34293
|
if (!resolvedPath) return;
|
|
33616
34294
|
path5 = resolvedPath;
|
|
33617
34295
|
}
|
|
33618
|
-
const dir =
|
|
34296
|
+
const dir = resolve3(path5);
|
|
33619
34297
|
setLastScannedPath(dir);
|
|
33620
34298
|
const detected = scanProject(dir);
|
|
33621
|
-
const
|
|
33622
|
-
|
|
33623
|
-
if (options.
|
|
33624
|
-
if (options.
|
|
34299
|
+
const projectName = detected.projectName || "Unknown App";
|
|
34300
|
+
let appName = options.appName || projectName;
|
|
34301
|
+
if (options.plist) detected.infoPlist = resolve3(options.plist);
|
|
34302
|
+
if (options.manifest) detected.privacyManifest = resolve3(options.manifest);
|
|
34303
|
+
if (options.ipa) detected.ipa = resolve3(options.ipa);
|
|
33625
34304
|
const filesToUpload = [];
|
|
33626
34305
|
if (detected.infoPlist) {
|
|
33627
34306
|
filesToUpload.push({ type: "plist", filename: "Info.plist", path: detected.infoPlist });
|
|
@@ -33641,39 +34320,94 @@ async function submitCommand(path5, options = {}) {
|
|
|
33641
34320
|
});
|
|
33642
34321
|
}
|
|
33643
34322
|
if (filesToUpload.length === 0) {
|
|
33644
|
-
log.warning("No files to upload.
|
|
34323
|
+
log.warning("No files to upload. Make sure you're pointing to an Xcode project directory.");
|
|
34324
|
+
if (fromMenu) return;
|
|
34325
|
+
log.info(subtext("Use --plist, --manifest, --ipa, or --screenshots flags to specify files manually."));
|
|
33645
34326
|
return;
|
|
33646
34327
|
}
|
|
33647
|
-
|
|
33648
|
-
|
|
33649
|
-
|
|
33650
|
-
const
|
|
33651
|
-
|
|
33652
|
-
|
|
33653
|
-
|
|
33654
|
-
|
|
33655
|
-
|
|
33656
|
-
|
|
33657
|
-
|
|
33658
|
-
|
|
34328
|
+
let appDetails = null;
|
|
34329
|
+
let compliance = null;
|
|
34330
|
+
if (fromMenu) {
|
|
34331
|
+
const reviewType = await select({
|
|
34332
|
+
message: "What would you like to include in your review?",
|
|
34333
|
+
options: [
|
|
34334
|
+
{ value: "quick", label: "Quick review (just analyze my project files)", hint: "Fastest option" },
|
|
34335
|
+
{ value: "full", label: "Full review (add app details + compliance info)", hint: "More thorough" }
|
|
34336
|
+
]
|
|
34337
|
+
});
|
|
34338
|
+
if (reviewType === null) return;
|
|
34339
|
+
if (reviewType === "full") {
|
|
34340
|
+
appDetails = await collectAppDetails(projectName);
|
|
34341
|
+
if (appDetails === null) return;
|
|
34342
|
+
appName = appDetails.appName;
|
|
34343
|
+
compliance = await collectCompliance();
|
|
34344
|
+
if (compliance === null) return;
|
|
34345
|
+
}
|
|
34346
|
+
}
|
|
34347
|
+
if (fromMenu) {
|
|
34348
|
+
console.log();
|
|
34349
|
+
note(buildSummary(appName, dir, filesToUpload, compliance), "Review Summary");
|
|
34350
|
+
const action = await select({
|
|
34351
|
+
message: `Submit review? (100 credits)`,
|
|
34352
|
+
options: [
|
|
34353
|
+
{ value: "submit", label: "Submit review", hint: "100 credits will be deducted" },
|
|
34354
|
+
{ value: "cancel", label: "Cancel", hint: "Back to menu" }
|
|
34355
|
+
]
|
|
34356
|
+
});
|
|
34357
|
+
if (action === null || action === "cancel") return;
|
|
34358
|
+
} else {
|
|
34359
|
+
if (!fromMenu) {
|
|
34360
|
+
intro(`Submit ${appName} for analysis`);
|
|
34361
|
+
const fileLines = filesToUpload.map((f) => {
|
|
34362
|
+
const size = getFileSize(f.path);
|
|
34363
|
+
const icon = f.type === "screenshot" ? icons.image : icons.file;
|
|
34364
|
+
return ` ${icon} ${f.filename} ${subtext(`(${formatBytes(size)})`)}`;
|
|
34365
|
+
});
|
|
34366
|
+
log.message(source_default.bold("Files to upload:") + "\n" + fileLines.join("\n"));
|
|
34367
|
+
const shouldContinue = await confirm("This will use 100 credits. Continue?");
|
|
34368
|
+
if (shouldContinue === null || !shouldContinue) {
|
|
34369
|
+
outro("Submission cancelled.");
|
|
34370
|
+
return;
|
|
34371
|
+
}
|
|
34372
|
+
}
|
|
33659
34373
|
}
|
|
34374
|
+
log.info(subtext("Reviews usually take 1-3 minutes."));
|
|
34375
|
+
console.log();
|
|
33660
34376
|
const spinner2 = createSpinner("Creating submission...");
|
|
33661
34377
|
spinner2.start();
|
|
34378
|
+
let activeSpinner = spinner2;
|
|
33662
34379
|
try {
|
|
34380
|
+
const submissionBody = { app_name: appName };
|
|
34381
|
+
if (appDetails) {
|
|
34382
|
+
if (appDetails.description) submissionBody.description = appDetails.description;
|
|
34383
|
+
if (appDetails.keywords) submissionBody.keywords = appDetails.keywords;
|
|
34384
|
+
if (appDetails.category) submissionBody.category = appDetails.category;
|
|
34385
|
+
if (appDetails.supportUrl) submissionBody.support_url = appDetails.supportUrl;
|
|
34386
|
+
if (appDetails.promotionalText) submissionBody.promotional_text = appDetails.promotionalText;
|
|
34387
|
+
if (appDetails.marketingUrl) submissionBody.marketing_url = appDetails.marketingUrl;
|
|
34388
|
+
submissionBody.sign_in_required = appDetails.signInRequired;
|
|
34389
|
+
if (appDetails.demoUsername) submissionBody.demo_username = appDetails.demoUsername;
|
|
34390
|
+
if (appDetails.demoPassword) submissionBody.demo_password = appDetails.demoPassword;
|
|
34391
|
+
}
|
|
34392
|
+
if (compliance) {
|
|
34393
|
+
Object.assign(submissionBody, formatComplianceForApi(compliance));
|
|
34394
|
+
}
|
|
33663
34395
|
const createRes = await apiRequest("/api/submissions", {
|
|
33664
34396
|
method: "POST",
|
|
33665
|
-
body: JSON.stringify(
|
|
34397
|
+
body: JSON.stringify(submissionBody)
|
|
33666
34398
|
});
|
|
33667
34399
|
const createData = await createRes.json();
|
|
33668
34400
|
if (!createRes.ok) {
|
|
33669
34401
|
spinner2.stop();
|
|
33670
34402
|
log.error(createData.message || "Failed to create submission");
|
|
33671
|
-
process.
|
|
34403
|
+
if (!fromMenu) process.exitCode = 1;
|
|
34404
|
+
return;
|
|
33672
34405
|
}
|
|
33673
34406
|
const submissionId = createData.submissionId;
|
|
33674
34407
|
spinner2.succeed("Submission created");
|
|
33675
34408
|
const uploadSpinner = createSpinner("Getting upload URLs...");
|
|
33676
34409
|
uploadSpinner.start();
|
|
34410
|
+
activeSpinner = uploadSpinner;
|
|
33677
34411
|
const urlsRes = await apiRequest(`/api/submissions/${submissionId}/upload-urls`, {
|
|
33678
34412
|
method: "POST",
|
|
33679
34413
|
body: JSON.stringify({
|
|
@@ -33688,7 +34422,8 @@ async function submitCommand(path5, options = {}) {
|
|
|
33688
34422
|
if (!urlsRes.ok) {
|
|
33689
34423
|
uploadSpinner.stop();
|
|
33690
34424
|
log.error(urlsData.message || "Failed to get upload URLs");
|
|
33691
|
-
process.
|
|
34425
|
+
if (!fromMenu) process.exitCode = 1;
|
|
34426
|
+
return;
|
|
33692
34427
|
}
|
|
33693
34428
|
for (let i = 0; i < urlsData.urls.length; i++) {
|
|
33694
34429
|
const urlInfo = urlsData.urls[i];
|
|
@@ -33704,35 +34439,60 @@ async function submitCommand(path5, options = {}) {
|
|
|
33704
34439
|
if (!uploadRes.ok) {
|
|
33705
34440
|
uploadSpinner.stop();
|
|
33706
34441
|
log.error(`Failed to upload ${fileInfo.filename}: HTTP ${uploadRes.status} ${uploadRes.statusText}`);
|
|
33707
|
-
process.
|
|
34442
|
+
if (!fromMenu) process.exitCode = 1;
|
|
34443
|
+
return;
|
|
33708
34444
|
}
|
|
33709
34445
|
}
|
|
33710
34446
|
uploadSpinner.succeed("Files uploaded");
|
|
33711
34447
|
const analyzeSpinner = createSpinner("Starting analysis...");
|
|
33712
34448
|
analyzeSpinner.start();
|
|
33713
|
-
|
|
33714
|
-
|
|
33715
|
-
|
|
33716
|
-
|
|
33717
|
-
|
|
33718
|
-
|
|
33719
|
-
|
|
33720
|
-
|
|
33721
|
-
|
|
33722
|
-
|
|
33723
|
-
|
|
33724
|
-
|
|
33725
|
-
|
|
33726
|
-
|
|
33727
|
-
|
|
34449
|
+
activeSpinner = analyzeSpinner;
|
|
34450
|
+
const finalizePayload = {
|
|
34451
|
+
files: filesToUpload.map((f) => ({
|
|
34452
|
+
type: f.type,
|
|
34453
|
+
index: f.index
|
|
34454
|
+
}))
|
|
34455
|
+
};
|
|
34456
|
+
let finalizeSuccess = false;
|
|
34457
|
+
let maxFinalizeRetries = 3;
|
|
34458
|
+
while (!finalizeSuccess && maxFinalizeRetries > 0) {
|
|
34459
|
+
const finalizeRes = await apiRequest(`/api/submissions/${submissionId}/finalize`, {
|
|
34460
|
+
method: "POST",
|
|
34461
|
+
body: JSON.stringify(finalizePayload)
|
|
34462
|
+
});
|
|
34463
|
+
const finalizeData = await finalizeRes.json();
|
|
34464
|
+
if (finalizeRes.ok) {
|
|
34465
|
+
finalizeSuccess = true;
|
|
34466
|
+
} else if (finalizeRes.status === 402) {
|
|
34467
|
+
analyzeSpinner.stop();
|
|
34468
|
+
log.warning(`Not enough credits. Need ${finalizeData.required ?? 100}, have ${finalizeData.credits ?? 0}.`);
|
|
34469
|
+
console.log();
|
|
34470
|
+
const wantsBuy = await confirm("Would you like to buy more credits?");
|
|
34471
|
+
if (wantsBuy === null || !wantsBuy) return;
|
|
34472
|
+
await openUrl("https://preflightlaunch.com/pricing");
|
|
34473
|
+
log.info("Opened pricing page. Press Enter when you've purchased credits.");
|
|
34474
|
+
const ready = await confirm("Ready to continue?");
|
|
34475
|
+
if (ready === null || !ready) return;
|
|
34476
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
34477
|
+
analyzeSpinner.start();
|
|
34478
|
+
activeSpinner = analyzeSpinner;
|
|
34479
|
+
analyzeSpinner.text = "Retrying analysis...";
|
|
34480
|
+
maxFinalizeRetries--;
|
|
33728
34481
|
} else {
|
|
34482
|
+
analyzeSpinner.stop();
|
|
33729
34483
|
log.error(finalizeData.message || "Failed to finalize submission");
|
|
34484
|
+
if (!fromMenu) process.exitCode = 1;
|
|
34485
|
+
return;
|
|
33730
34486
|
}
|
|
33731
|
-
|
|
34487
|
+
}
|
|
34488
|
+
if (!finalizeSuccess) {
|
|
34489
|
+
analyzeSpinner.stop();
|
|
34490
|
+
log.error("Could not finalize after multiple attempts. Your files are saved -- try again later.");
|
|
34491
|
+
return;
|
|
33732
34492
|
}
|
|
33733
34493
|
analyzeSpinner.text = "AI review in progress...";
|
|
33734
34494
|
const reportData = await pollForReport(submissionId, analyzeSpinner);
|
|
33735
|
-
analyzeSpinner.
|
|
34495
|
+
analyzeSpinner.succeed("Analysis complete!");
|
|
33736
34496
|
if (reportData.status === "complete" && reportData.data) {
|
|
33737
34497
|
if (options.json) {
|
|
33738
34498
|
console.log(JSON.stringify(reportData.data, null, 2));
|
|
@@ -33740,43 +34500,59 @@ async function submitCommand(path5, options = {}) {
|
|
|
33740
34500
|
renderReport(reportData.data.report, reportData.data.items);
|
|
33741
34501
|
console.log(subtext(` Full report: https://preflightlaunch.com/report/${reportData.data.report.id}`));
|
|
33742
34502
|
console.log();
|
|
33743
|
-
|
|
33744
|
-
|
|
33745
|
-
|
|
33746
|
-
|
|
33747
|
-
|
|
33748
|
-
|
|
33749
|
-
|
|
33750
|
-
|
|
33751
|
-
|
|
33752
|
-
|
|
33753
|
-
|
|
33754
|
-
} else if (next === "another") {
|
|
33755
|
-
await submitCommand();
|
|
34503
|
+
if (!fromMenu) {
|
|
34504
|
+
const next = await select({
|
|
34505
|
+
message: "What next?",
|
|
34506
|
+
options: [
|
|
34507
|
+
{ value: "open", label: "Open full report in browser" },
|
|
34508
|
+
{ value: "done", label: "Done" }
|
|
34509
|
+
]
|
|
34510
|
+
});
|
|
34511
|
+
if (next === "open") {
|
|
34512
|
+
await openUrl(`https://preflightlaunch.com/report/${reportData.data.report.id}`);
|
|
34513
|
+
}
|
|
33756
34514
|
}
|
|
33757
34515
|
}
|
|
33758
34516
|
} else if (reportData.status === "failed") {
|
|
33759
34517
|
log.error("Analysis failed. Please try submitting again or contact support.");
|
|
33760
|
-
process.
|
|
34518
|
+
if (!fromMenu) process.exitCode = 1;
|
|
33761
34519
|
} else {
|
|
33762
34520
|
log.warning("Analysis is still running. Check status with:");
|
|
33763
34521
|
console.log(subtext(` preflight status ${submissionId}`));
|
|
33764
34522
|
}
|
|
33765
34523
|
} catch (err) {
|
|
33766
|
-
|
|
34524
|
+
activeSpinner.stop();
|
|
33767
34525
|
log.error(`Submit failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
33768
|
-
process.
|
|
34526
|
+
if (!fromMenu) process.exitCode = 1;
|
|
34527
|
+
}
|
|
34528
|
+
}
|
|
34529
|
+
function buildSummary(appName, dir, files, compliance) {
|
|
34530
|
+
const home = __require("os").homedir();
|
|
34531
|
+
const shortDir = dir.startsWith(home) ? "~" + dir.slice(home.length) : dir;
|
|
34532
|
+
const fileTypes = files.map((f) => f.filename).join(", ");
|
|
34533
|
+
const screenshotCount = files.filter((f) => f.type === "screenshot").length;
|
|
34534
|
+
let summary = `App: ${appName}
|
|
34535
|
+
`;
|
|
34536
|
+
summary += `Project: ${shortDir}
|
|
34537
|
+
`;
|
|
34538
|
+
summary += `Files: ${fileTypes}${screenshotCount > 0 ? ` (${screenshotCount} screenshots)` : ""}
|
|
34539
|
+
`;
|
|
34540
|
+
if (compliance) {
|
|
34541
|
+
const complianceLines = formatComplianceSummary(compliance);
|
|
34542
|
+
summary += complianceLines.map((l) => l.trim()).join("\n");
|
|
33769
34543
|
}
|
|
34544
|
+
return summary;
|
|
33770
34545
|
}
|
|
33771
34546
|
function getFileSize(filePath) {
|
|
33772
34547
|
try {
|
|
33773
|
-
return
|
|
34548
|
+
return statSync3(filePath).size;
|
|
33774
34549
|
} catch {
|
|
33775
34550
|
return 0;
|
|
33776
34551
|
}
|
|
33777
34552
|
}
|
|
33778
34553
|
async function pollForReport(submissionId, spinner2, maxAttempts = 60, interval = 5e3) {
|
|
33779
34554
|
let consecutiveFailures = 0;
|
|
34555
|
+
const startTime = Date.now();
|
|
33780
34556
|
for (let i = 0; i < maxAttempts; i++) {
|
|
33781
34557
|
await new Promise((r) => setTimeout(r, interval));
|
|
33782
34558
|
const res = await apiRequest(`/api/submissions/${submissionId}`);
|
|
@@ -33793,9 +34569,9 @@ async function pollForReport(submissionId, spinner2, maxAttempts = 60, interval
|
|
|
33793
34569
|
consecutiveFailures = 0;
|
|
33794
34570
|
const data = await res.json();
|
|
33795
34571
|
const submission = data.data;
|
|
33796
|
-
const
|
|
33797
|
-
const
|
|
33798
|
-
spinner2.text =
|
|
34572
|
+
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
34573
|
+
const status = submission.status || "analyzing";
|
|
34574
|
+
spinner2.text = `AI review in progress... (${elapsed}s elapsed)`;
|
|
33799
34575
|
if (submission.status === "complete") {
|
|
33800
34576
|
if (submission.report_id) {
|
|
33801
34577
|
const reportRes = await apiRequest(`/api/reports/${submission.report_id}`);
|
|
@@ -33816,7 +34592,9 @@ export {
|
|
|
33816
34592
|
createSpinner,
|
|
33817
34593
|
success,
|
|
33818
34594
|
error,
|
|
34595
|
+
DEFAULT_API_URL,
|
|
33819
34596
|
getConfig,
|
|
34597
|
+
clearAuth,
|
|
33820
34598
|
isLoggedIn,
|
|
33821
34599
|
hasRunBefore,
|
|
33822
34600
|
markAsRun,
|
|
@@ -33832,19 +34610,16 @@ export {
|
|
|
33832
34610
|
critical,
|
|
33833
34611
|
icons,
|
|
33834
34612
|
intro,
|
|
33835
|
-
showTagline,
|
|
33836
|
-
brandSplash,
|
|
33837
|
-
outro,
|
|
33838
34613
|
tip,
|
|
34614
|
+
renderHeader,
|
|
33839
34615
|
select,
|
|
34616
|
+
confirm,
|
|
33840
34617
|
spinner,
|
|
33841
34618
|
log,
|
|
33842
|
-
findXcodeProjects,
|
|
33843
|
-
findProjectInDir,
|
|
33844
34619
|
interactiveProjectSelect,
|
|
33845
34620
|
renderReport,
|
|
33846
34621
|
renderReportJson,
|
|
33847
34622
|
handleUnknownCommand,
|
|
33848
34623
|
submitCommand
|
|
33849
34624
|
};
|
|
33850
|
-
//# sourceMappingURL=chunk-
|
|
34625
|
+
//# sourceMappingURL=chunk-PMKDGQCB.js.map
|