@sitepong/fastnode 0.1.0 → 0.1.2
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/actions/index.cjs +227 -27
- package/dist/actions/index.cjs.map +1 -1
- package/dist/actions/index.mjs +227 -27
- package/dist/actions/index.mjs.map +1 -1
- package/dist/cli/index.cjs +227 -27
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +227 -27
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index-D6zjGlPL.d.cts +158 -0
- package/dist/index-DHw08dUc.d.ts +158 -0
- package/dist/index.cjs +228 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +228 -28
- package/dist/index.mjs.map +1 -1
- package/dist/lane/index.cjs +227 -27
- package/dist/lane/index.cjs.map +1 -1
- package/dist/lane/index.mjs +227 -27
- package/dist/lane/index.mjs.map +1 -1
- package/dist/pilot/index.cjs +190 -12
- package/dist/pilot/index.cjs.map +1 -1
- package/dist/pilot/index.d.cts +1 -1
- package/dist/pilot/index.d.ts +1 -1
- package/dist/pilot/index.mjs +186 -14
- package/dist/pilot/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/index-DkvinY7_.d.ts +0 -54
- package/dist/index-HRiaaX-Q.d.cts +0 -54
package/dist/cli/index.mjs
CHANGED
|
@@ -184,8 +184,8 @@ async function revokeExpiredCertificates(options) {
|
|
|
184
184
|
return count;
|
|
185
185
|
}
|
|
186
186
|
async function importToKeychain(certData, keychainPath, keychainPassword) {
|
|
187
|
-
const { tmpdir:
|
|
188
|
-
const tempCertPath = join(
|
|
187
|
+
const { tmpdir: tmpdir8 } = await import('os');
|
|
188
|
+
const tempCertPath = join(tmpdir8(), `fastnode-cert-${Date.now()}.cer`);
|
|
189
189
|
await writeFile(tempCertPath, certData);
|
|
190
190
|
try {
|
|
191
191
|
const args = [
|
|
@@ -1617,14 +1617,14 @@ var init_building = __esm({
|
|
|
1617
1617
|
name: "clean_build_artifacts",
|
|
1618
1618
|
description: "Remove build artifacts (IPA, dSYM, etc.)",
|
|
1619
1619
|
async run(params, ctx) {
|
|
1620
|
-
const { rm:
|
|
1620
|
+
const { rm: rm4 } = await import('fs/promises');
|
|
1621
1621
|
const paths = [
|
|
1622
1622
|
ctx.get("IPA_OUTPUT_PATH"),
|
|
1623
1623
|
ctx.get("PKG_OUTPUT_PATH"),
|
|
1624
1624
|
ctx.get("DSYM_OUTPUT_PATH")
|
|
1625
1625
|
].filter(Boolean);
|
|
1626
1626
|
for (const p of paths) {
|
|
1627
|
-
await
|
|
1627
|
+
await rm4(p, { force: true }).catch(() => {
|
|
1628
1628
|
});
|
|
1629
1629
|
}
|
|
1630
1630
|
return { cleaned: paths };
|
|
@@ -2271,23 +2271,13 @@ var init_request = __esm({
|
|
|
2271
2271
|
};
|
|
2272
2272
|
}
|
|
2273
2273
|
});
|
|
2274
|
-
|
|
2275
|
-
// src/pilot/index.ts
|
|
2276
|
-
var pilot_exports = {};
|
|
2277
|
-
__export(pilot_exports, {
|
|
2278
|
-
distributeToGroups: () => distributeToGroups,
|
|
2279
|
-
expireBuild: () => expireBuild,
|
|
2280
|
-
setChangelog: () => setChangelog,
|
|
2281
|
-
uploadToTestFlight: () => uploadToTestFlight,
|
|
2282
|
-
waitForProcessing: () => waitForProcessing
|
|
2283
|
-
});
|
|
2284
|
-
async function uploadToTestFlight(options) {
|
|
2274
|
+
async function uploadWithAltool(options) {
|
|
2285
2275
|
if (!existsSync(options.ipaPath)) {
|
|
2286
2276
|
throw new Error(`File not found: ${options.ipaPath}`);
|
|
2287
2277
|
}
|
|
2288
2278
|
const platform = options.platform ?? "ios";
|
|
2289
2279
|
const timeout = options.timeout ?? 18e5;
|
|
2290
|
-
const keyDir = await mkdtemp(join(tmpdir(), "fastnode-
|
|
2280
|
+
const keyDir = await mkdtemp(join(tmpdir(), "fastnode-altool-"));
|
|
2291
2281
|
const keyPath = join(keyDir, `AuthKey_${options.apiKeyId}.p8`);
|
|
2292
2282
|
await writeFile(keyPath, options.apiPrivateKey);
|
|
2293
2283
|
return new Promise((resolve4) => {
|
|
@@ -2311,24 +2301,228 @@ async function uploadToTestFlight(options) {
|
|
|
2311
2301
|
const timer = setTimeout(() => {
|
|
2312
2302
|
child.kill("SIGTERM");
|
|
2313
2303
|
}, timeout);
|
|
2314
|
-
|
|
2304
|
+
const onData = (data) => {
|
|
2315
2305
|
const chunk = data.toString();
|
|
2316
2306
|
output += chunk;
|
|
2317
2307
|
options.onOutput?.(chunk);
|
|
2308
|
+
};
|
|
2309
|
+
child.stdout.on("data", onData);
|
|
2310
|
+
child.stderr.on("data", onData);
|
|
2311
|
+
child.on("close", async (code) => {
|
|
2312
|
+
clearTimeout(timer);
|
|
2313
|
+
await unlink(keyPath).catch(() => {
|
|
2314
|
+
});
|
|
2315
|
+
await rm(keyDir, { recursive: true, force: true }).catch(() => {
|
|
2316
|
+
});
|
|
2317
|
+
resolve4({ success: code === 0, output, backend: "altool" });
|
|
2318
2318
|
});
|
|
2319
|
-
|
|
2319
|
+
});
|
|
2320
|
+
}
|
|
2321
|
+
var init_upload_altool = __esm({
|
|
2322
|
+
"src/pilot/upload-altool.ts"() {
|
|
2323
|
+
}
|
|
2324
|
+
});
|
|
2325
|
+
async function resolveTransporter() {
|
|
2326
|
+
const override = process.env.ITMSTRANSPORTER_BIN;
|
|
2327
|
+
if (override) {
|
|
2328
|
+
if (!existsSync(override)) {
|
|
2329
|
+
throw new Error(
|
|
2330
|
+
`ITMSTRANSPORTER_BIN is set to "${override}" but that path does not exist.`
|
|
2331
|
+
);
|
|
2332
|
+
}
|
|
2333
|
+
return override;
|
|
2334
|
+
}
|
|
2335
|
+
const candidates = process.platform === "darwin" ? [
|
|
2336
|
+
// Xcode 15+: Transporter.app bundled with Xcode
|
|
2337
|
+
"/Applications/Xcode.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Versions/A/itms/bin/iTMSTransporter",
|
|
2338
|
+
// Standalone Transporter.app from the Mac App Store
|
|
2339
|
+
"/Applications/Transporter.app/Contents/itms/bin/iTMSTransporter"
|
|
2340
|
+
] : [
|
|
2341
|
+
"/usr/local/itms/bin/iTMSTransporter",
|
|
2342
|
+
"/opt/itms/bin/iTMSTransporter",
|
|
2343
|
+
"/usr/local/bin/iTMSTransporter"
|
|
2344
|
+
];
|
|
2345
|
+
for (const path of candidates) {
|
|
2346
|
+
if (existsSync(path)) return path;
|
|
2347
|
+
}
|
|
2348
|
+
throw new Error(
|
|
2349
|
+
[
|
|
2350
|
+
"iTMSTransporter not found.",
|
|
2351
|
+
"",
|
|
2352
|
+
"Install options:",
|
|
2353
|
+
process.platform === "darwin" ? " - Install Xcode (includes Transporter)" : " - Download Apple's standalone iTMSTransporter package for Linux",
|
|
2354
|
+
" - Or set ITMSTRANSPORTER_BIN to the absolute path of the binary",
|
|
2355
|
+
"",
|
|
2356
|
+
`Searched: ${candidates.join(", ")}`
|
|
2357
|
+
].join("\n")
|
|
2358
|
+
);
|
|
2359
|
+
}
|
|
2360
|
+
async function verifyJava() {
|
|
2361
|
+
return new Promise((resolve4, reject) => {
|
|
2362
|
+
const child = spawn("java", ["-version"], { stdio: ["ignore", "pipe", "pipe"] });
|
|
2363
|
+
let stderr = "";
|
|
2364
|
+
child.stderr.on("data", (d) => {
|
|
2365
|
+
stderr += d.toString();
|
|
2366
|
+
});
|
|
2367
|
+
child.on("error", (err) => {
|
|
2368
|
+
reject(
|
|
2369
|
+
new Error(
|
|
2370
|
+
`java not found on PATH (${err.message}). Install Java 17 LTS and ensure it is on PATH.`
|
|
2371
|
+
)
|
|
2372
|
+
);
|
|
2373
|
+
});
|
|
2374
|
+
child.on("close", (code) => {
|
|
2375
|
+
if (code !== 0) {
|
|
2376
|
+
reject(new Error(`java -version exited ${code}: ${stderr}`));
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
const match = stderr.match(/version "([^"]+)"/);
|
|
2380
|
+
resolve4({ version: match?.[1] ?? "unknown" });
|
|
2381
|
+
});
|
|
2382
|
+
});
|
|
2383
|
+
}
|
|
2384
|
+
var init_transporter_install = __esm({
|
|
2385
|
+
"src/pilot/transporter-install.ts"() {
|
|
2386
|
+
}
|
|
2387
|
+
});
|
|
2388
|
+
async function uploadWithTransporter(options) {
|
|
2389
|
+
if (!existsSync(options.ipaPath)) {
|
|
2390
|
+
throw new Error(`File not found: ${options.ipaPath}`);
|
|
2391
|
+
}
|
|
2392
|
+
await verifyJava();
|
|
2393
|
+
const transporterBin = await resolveTransporter();
|
|
2394
|
+
const platform = options.platform ?? "ios";
|
|
2395
|
+
const timeout = options.timeout ?? 18e5;
|
|
2396
|
+
const keyDir = await mkdtemp(join(tmpdir(), "fastnode-itms-"));
|
|
2397
|
+
const keyPath = join(keyDir, `AuthKey_${options.apiKeyId}.p8`);
|
|
2398
|
+
await writeFile(keyPath, options.apiPrivateKey);
|
|
2399
|
+
return new Promise((resolve4) => {
|
|
2400
|
+
const args = [
|
|
2401
|
+
"-m",
|
|
2402
|
+
"upload",
|
|
2403
|
+
"-assetFile",
|
|
2404
|
+
options.ipaPath,
|
|
2405
|
+
"-apiKey",
|
|
2406
|
+
options.apiKeyId,
|
|
2407
|
+
"-apiIssuer",
|
|
2408
|
+
options.apiIssuerId,
|
|
2409
|
+
// WONoPause prevents the JVM from waiting on stdin in non-TTY
|
|
2410
|
+
// environments (CI, LaunchAgent) where it would hang forever.
|
|
2411
|
+
"-WONoPause",
|
|
2412
|
+
"true"
|
|
2413
|
+
];
|
|
2414
|
+
if (platform !== "ios") {
|
|
2415
|
+
args.push("-bundleType", platform);
|
|
2416
|
+
}
|
|
2417
|
+
const child = spawn(transporterBin, args, {
|
|
2418
|
+
env: {
|
|
2419
|
+
...process.env,
|
|
2420
|
+
API_PRIVATE_KEYS_DIR: keyDir
|
|
2421
|
+
},
|
|
2422
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
2423
|
+
});
|
|
2424
|
+
let output = "";
|
|
2425
|
+
const timer = setTimeout(() => {
|
|
2426
|
+
child.kill("SIGTERM");
|
|
2427
|
+
}, timeout);
|
|
2428
|
+
const onData = (data) => {
|
|
2320
2429
|
const chunk = data.toString();
|
|
2321
2430
|
output += chunk;
|
|
2322
2431
|
options.onOutput?.(chunk);
|
|
2323
|
-
}
|
|
2432
|
+
};
|
|
2433
|
+
child.stdout.on("data", onData);
|
|
2434
|
+
child.stderr.on("data", onData);
|
|
2324
2435
|
child.on("close", async (code) => {
|
|
2325
2436
|
clearTimeout(timer);
|
|
2326
|
-
await
|
|
2437
|
+
await rm(keyDir, { recursive: true, force: true }).catch(() => {
|
|
2438
|
+
});
|
|
2439
|
+
resolve4({ success: code === 0, output, backend: "transporter" });
|
|
2440
|
+
});
|
|
2441
|
+
child.on("error", async (err) => {
|
|
2442
|
+
clearTimeout(timer);
|
|
2443
|
+
await rm(keyDir, { recursive: true, force: true }).catch(() => {
|
|
2444
|
+
});
|
|
2445
|
+
resolve4({
|
|
2446
|
+
success: false,
|
|
2447
|
+
output: output + `
|
|
2448
|
+
Process error: ${err.message}`,
|
|
2449
|
+
backend: "transporter"
|
|
2327
2450
|
});
|
|
2328
|
-
resolve4({ success: code === 0, output });
|
|
2329
2451
|
});
|
|
2330
2452
|
});
|
|
2331
2453
|
}
|
|
2454
|
+
var init_upload_transporter = __esm({
|
|
2455
|
+
"src/pilot/upload-transporter.ts"() {
|
|
2456
|
+
init_transporter_install();
|
|
2457
|
+
}
|
|
2458
|
+
});
|
|
2459
|
+
|
|
2460
|
+
// src/pilot/classify.ts
|
|
2461
|
+
function classifyUploadError(output) {
|
|
2462
|
+
for (const { pattern, kind } of RULES) {
|
|
2463
|
+
if (pattern.test(output)) return kind;
|
|
2464
|
+
}
|
|
2465
|
+
return null;
|
|
2466
|
+
}
|
|
2467
|
+
function isTransientUploadError(output) {
|
|
2468
|
+
return classifyUploadError(output) !== null;
|
|
2469
|
+
}
|
|
2470
|
+
var RULES;
|
|
2471
|
+
var init_classify = __esm({
|
|
2472
|
+
"src/pilot/classify.ts"() {
|
|
2473
|
+
RULES = [
|
|
2474
|
+
// Apple's finalize-upload call returning 5xx — the most common transient
|
|
2475
|
+
// failure we see in practice. Example:
|
|
2476
|
+
// "CHANGE UPLOAD STATE TO COMPLETE (UPLOADING ASSET DESCRIPTION):
|
|
2477
|
+
// received status code 500; internal server error."
|
|
2478
|
+
{ pattern: /CHANGE UPLOAD STATE TO COMPLETE/i, kind: "finalize_failed" },
|
|
2479
|
+
// Generic 5xx from ASC backend services
|
|
2480
|
+
{ pattern: /status code 5\d\d/i, kind: "apple_5xx" },
|
|
2481
|
+
{ pattern: /internal server error/i, kind: "apple_5xx" },
|
|
2482
|
+
{ pattern: /Service Unavailable/i, kind: "apple_5xx" },
|
|
2483
|
+
{ pattern: /Bad Gateway/i, kind: "apple_5xx" },
|
|
2484
|
+
// Network-level interruptions during the upload body transfer
|
|
2485
|
+
{ pattern: /Connection reset/i, kind: "connection_reset" },
|
|
2486
|
+
{ pattern: /SocketException/i, kind: "connection_reset" },
|
|
2487
|
+
{ pattern: /Broken pipe/i, kind: "connection_reset" },
|
|
2488
|
+
// Timeouts — distinct from resets because the other side may have
|
|
2489
|
+
// actually processed the request, so dedupe logic may matter.
|
|
2490
|
+
{ pattern: /Read timed out/i, kind: "network_timeout" },
|
|
2491
|
+
{ pattern: /SocketTimeoutException/i, kind: "network_timeout" },
|
|
2492
|
+
{ pattern: /Operation timed out/i, kind: "network_timeout" },
|
|
2493
|
+
// JVM-internal errors from iTMSTransporter (OOM, thread interruption, etc.)
|
|
2494
|
+
{ pattern: /java\.lang\.OutOfMemoryError/i, kind: "transporter_jvm_error" },
|
|
2495
|
+
{ pattern: /EOFException/i, kind: "transporter_jvm_error" }
|
|
2496
|
+
];
|
|
2497
|
+
}
|
|
2498
|
+
});
|
|
2499
|
+
|
|
2500
|
+
// src/pilot/index.ts
|
|
2501
|
+
var pilot_exports = {};
|
|
2502
|
+
__export(pilot_exports, {
|
|
2503
|
+
classifyUploadError: () => classifyUploadError,
|
|
2504
|
+
distributeToGroups: () => distributeToGroups,
|
|
2505
|
+
expireBuild: () => expireBuild,
|
|
2506
|
+
isTransientUploadError: () => isTransientUploadError,
|
|
2507
|
+
resolveTransporter: () => resolveTransporter,
|
|
2508
|
+
setChangelog: () => setChangelog,
|
|
2509
|
+
uploadToTestFlight: () => uploadToTestFlight,
|
|
2510
|
+
uploadWithAltool: () => uploadWithAltool,
|
|
2511
|
+
uploadWithTransporter: () => uploadWithTransporter,
|
|
2512
|
+
verifyJava: () => verifyJava,
|
|
2513
|
+
waitForProcessing: () => waitForProcessing
|
|
2514
|
+
});
|
|
2515
|
+
async function uploadToTestFlight(options) {
|
|
2516
|
+
const backend = selectBackend(options.backend ?? "auto");
|
|
2517
|
+
if (backend === "altool") {
|
|
2518
|
+
return uploadWithAltool(options);
|
|
2519
|
+
}
|
|
2520
|
+
return uploadWithTransporter(options);
|
|
2521
|
+
}
|
|
2522
|
+
function selectBackend(pref) {
|
|
2523
|
+
if (pref !== "auto") return pref;
|
|
2524
|
+
return process.platform === "darwin" ? "altool" : "transporter";
|
|
2525
|
+
}
|
|
2332
2526
|
async function waitForProcessing(client, params) {
|
|
2333
2527
|
const timeout = params.timeout ?? 18e5;
|
|
2334
2528
|
const pollInterval = params.pollInterval ?? 3e4;
|
|
@@ -2449,6 +2643,12 @@ function sleep2(ms) {
|
|
|
2449
2643
|
var init_pilot = __esm({
|
|
2450
2644
|
"src/pilot/index.ts"() {
|
|
2451
2645
|
init_request();
|
|
2646
|
+
init_upload_altool();
|
|
2647
|
+
init_upload_transporter();
|
|
2648
|
+
init_upload_altool();
|
|
2649
|
+
init_upload_transporter();
|
|
2650
|
+
init_classify();
|
|
2651
|
+
init_transporter_install();
|
|
2452
2652
|
}
|
|
2453
2653
|
});
|
|
2454
2654
|
async function loadMetadata(metadataPath) {
|
|
@@ -2536,9 +2736,9 @@ var init_metadata = __esm({
|
|
|
2536
2736
|
// src/xcode/upload.ts
|
|
2537
2737
|
var upload_exports = {};
|
|
2538
2738
|
__export(upload_exports, {
|
|
2539
|
-
uploadWithAltool: () =>
|
|
2739
|
+
uploadWithAltool: () => uploadWithAltool2
|
|
2540
2740
|
});
|
|
2541
|
-
async function
|
|
2741
|
+
async function uploadWithAltool2(options) {
|
|
2542
2742
|
requireMacOS("altool upload");
|
|
2543
2743
|
let keyDir;
|
|
2544
2744
|
if (options.apiPrivateKey && !options.apiKeyPath) {
|
|
@@ -2647,8 +2847,8 @@ async function uploadToAppStore(options) {
|
|
|
2647
2847
|
if (!options.skipBinaryUpload) {
|
|
2648
2848
|
const binaryPath = options.ipaPath ?? options.pkgPath;
|
|
2649
2849
|
if (binaryPath && options.apiKeyId && options.apiIssuerId) {
|
|
2650
|
-
const { uploadWithAltool:
|
|
2651
|
-
await
|
|
2850
|
+
const { uploadWithAltool: uploadWithAltool3 } = await Promise.resolve().then(() => (init_upload(), upload_exports));
|
|
2851
|
+
await uploadWithAltool3({
|
|
2652
2852
|
filePath: binaryPath,
|
|
2653
2853
|
apiKeyId: options.apiKeyId,
|
|
2654
2854
|
apiIssuerId: options.apiIssuerId,
|
|
@@ -3434,8 +3634,8 @@ async function captureScreenshots(options) {
|
|
|
3434
3634
|
const outputDir = options.outputDirectory ?? join(process.cwd(), "screenshots");
|
|
3435
3635
|
const retries = options.numberOfRetries ?? 1;
|
|
3436
3636
|
if (options.clearPreviousScreenshots && existsSync(outputDir)) {
|
|
3437
|
-
const { rm:
|
|
3438
|
-
await
|
|
3637
|
+
const { rm: rm4 } = await import('fs/promises');
|
|
3638
|
+
await rm4(outputDir, { recursive: true, force: true });
|
|
3439
3639
|
}
|
|
3440
3640
|
mkdirSync(outputDir, { recursive: true });
|
|
3441
3641
|
const screenshots = {};
|