@absolutejs/absolute 0.20.0-beta.80 → 0.20.0-beta.81
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/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build.js +1170 -222
- package/dist/build.js.map +7 -5
- package/dist/cli/{compile-x4hfth3p.js → compile-t73ac1zb.js} +2 -2
- package/dist/cli/{config-z8wwxatc.js → config-naw5fer4.js} +1 -1
- package/dist/cli/{dev-8vv459ty.js → dev-skb8dz33.js} +1 -1
- package/dist/cli/{index-w5y7wxn9.js → index-8gksmws3.js} +1 -1
- package/dist/cli/{index-6fb7k6dg.js → index-czw3jd8f.js} +47 -1
- package/dist/cli/{index-d4ar3mwd.js → index-q78x1k9q.js} +2 -2
- package/dist/cli/index.js +5 -5
- package/dist/cli/{mobile-mfp26v2d.js → mobile-rdwdcks1.js} +359 -136
- package/dist/cli/{start-dtrp1pry.js → start-jbgfw27x.js} +3 -3
- package/dist/index.js +2043 -1095
- package/dist/index.js.map +7 -5
- package/dist/mobile/index.js +946 -4
- package/dist/mobile/index.js.map +7 -5
- package/dist/mobile/remoteMacAgentEntry.js +205 -205
- package/dist/src/mobile/config.d.ts +8 -0
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/updateServer.d.ts +33 -0
- package/dist/types/build.d.ts +16 -0
- package/package.json +3 -2
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
} from "./index-zh6hhrwy.js";
|
|
5
5
|
import {
|
|
6
6
|
start
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-q78x1k9q.js";
|
|
8
8
|
import {
|
|
9
9
|
ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
|
|
10
10
|
ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
|
|
11
11
|
resolveAbsoluteMobileRoute
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-8gksmws3.js";
|
|
13
13
|
import"./index-bzs19w3r.js";
|
|
14
14
|
import"./index-s2tazax7.js";
|
|
15
15
|
import {
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
import"./index-w5vswatm.js";
|
|
50
50
|
import {
|
|
51
51
|
normalizeAbsoluteMobileConfig
|
|
52
|
-
} from "./index-
|
|
52
|
+
} from "./index-czw3jd8f.js";
|
|
53
53
|
import {
|
|
54
54
|
ABSOLUTE_MOBILE_UPDATE_FORMAT,
|
|
55
55
|
absoluteDeviceNativeRequirements,
|
|
@@ -16768,15 +16768,15 @@ var require_main = __commonJS(function(exports) {
|
|
|
16768
16768
|
|
|
16769
16769
|
// src/cli/scripts/mobile.ts
|
|
16770
16770
|
import {
|
|
16771
|
-
access as
|
|
16772
|
-
mkdir as
|
|
16771
|
+
access as access12,
|
|
16772
|
+
mkdir as mkdir12,
|
|
16773
16773
|
mkdtemp as mkdtemp3,
|
|
16774
16774
|
readFile as readFile16,
|
|
16775
16775
|
rm as rm6,
|
|
16776
16776
|
writeFile as writeFile14
|
|
16777
16777
|
} from "fs/promises";
|
|
16778
|
-
import { createPublicKey } from "crypto";
|
|
16779
|
-
import { join as join13, relative as
|
|
16778
|
+
import { createPublicKey as createPublicKey2 } from "crypto";
|
|
16779
|
+
import { join as join13, relative as relative11, resolve as resolve12 } from "path";
|
|
16780
16780
|
import { createInterface } from "readline/promises";
|
|
16781
16781
|
|
|
16782
16782
|
// src/mobile/nativeDeepLinks.ts
|
|
@@ -19083,8 +19083,8 @@ var waitForAbsoluteAndroidHmrApply = async (session, options) => {
|
|
|
19083
19083
|
};
|
|
19084
19084
|
|
|
19085
19085
|
// src/mobile/releaseDoctor.ts
|
|
19086
|
-
import { access as
|
|
19087
|
-
import { dirname as
|
|
19086
|
+
import { access as access4, readFile as readFile8, readdir as readdir3 } from "fs/promises";
|
|
19087
|
+
import { dirname as dirname5, extname, join as join7, relative as relative3 } from "path";
|
|
19088
19088
|
|
|
19089
19089
|
// src/mobile/mobileBundleInspection.ts
|
|
19090
19090
|
import { createHash } from "crypto";
|
|
@@ -19240,6 +19240,171 @@ var inspectAbsoluteMobileBundle = async (config, projectRoot) => {
|
|
|
19240
19240
|
}
|
|
19241
19241
|
};
|
|
19242
19242
|
|
|
19243
|
+
// src/mobile/updateServer.ts
|
|
19244
|
+
import {
|
|
19245
|
+
createPrivateKey,
|
|
19246
|
+
createPublicKey,
|
|
19247
|
+
X509Certificate
|
|
19248
|
+
} from "crypto";
|
|
19249
|
+
import { access as access3, mkdir as mkdir5 } from "fs/promises";
|
|
19250
|
+
import { dirname as dirname4, isAbsolute, relative as relative2, resolve as resolve4, sep } from "path";
|
|
19251
|
+
import { pathToFileURL } from "url";
|
|
19252
|
+
import { Elysia as Elysia2 } from "elysia";
|
|
19253
|
+
var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1;
|
|
19254
|
+
var DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE = "mobile.update.ts";
|
|
19255
|
+
var object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19256
|
+
var projectPath = (projectRoot, requested) => {
|
|
19257
|
+
const root = resolve4(projectRoot);
|
|
19258
|
+
const path = resolve4(root, requested);
|
|
19259
|
+
const projectRelative = relative2(root, path);
|
|
19260
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep}`) || isAbsolute(projectRelative))
|
|
19261
|
+
throw new TypeError("mobile.updates.server.registry must remain inside the project.");
|
|
19262
|
+
return path;
|
|
19263
|
+
};
|
|
19264
|
+
var isRegistry = (value) => object(value) && [
|
|
19265
|
+
"publishUpdate",
|
|
19266
|
+
"promoteUpdate",
|
|
19267
|
+
"rollbackUpdate",
|
|
19268
|
+
"resolveUpdate",
|
|
19269
|
+
"readUpdateFile"
|
|
19270
|
+
].every((method) => typeof value[method] === "function");
|
|
19271
|
+
var serverMetadata = (value) => {
|
|
19272
|
+
if (!object(value))
|
|
19273
|
+
throw new TypeError("Mobile update registry must export valid absoluteMobileUpdateServer metadata. Run `absolute mobile update provision`.");
|
|
19274
|
+
const { format, provider, storage } = value;
|
|
19275
|
+
if (format !== ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT || storage !== "local" && storage !== "durable" || typeof provider !== "string" || !provider)
|
|
19276
|
+
throw new TypeError("Mobile update registry must export valid absoluteMobileUpdateServer metadata. Run `absolute mobile update provision`.");
|
|
19277
|
+
const metadata = {
|
|
19278
|
+
format: ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT,
|
|
19279
|
+
provider,
|
|
19280
|
+
storage
|
|
19281
|
+
};
|
|
19282
|
+
return metadata;
|
|
19283
|
+
};
|
|
19284
|
+
var loadAbsoluteMobileUpdateServerModule = async (projectRoot, requestedModulePath = DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE) => {
|
|
19285
|
+
const modulePath = projectPath(projectRoot, requestedModulePath);
|
|
19286
|
+
await access3(modulePath).catch(() => {
|
|
19287
|
+
throw new TypeError(`Mobile update server registry does not exist: ${modulePath}. Run \`absolute mobile update provision\`.`);
|
|
19288
|
+
});
|
|
19289
|
+
const loaded = await import(pathToFileURL(modulePath).href);
|
|
19290
|
+
if (!object(loaded))
|
|
19291
|
+
throw new TypeError("Mobile update registry module has no exports.");
|
|
19292
|
+
const registry = loaded.default ?? loaded.registry;
|
|
19293
|
+
if (!isRegistry(registry))
|
|
19294
|
+
throw new TypeError("Mobile update registry must implement publication, promotion, rollback, resolution, and file reads.");
|
|
19295
|
+
return {
|
|
19296
|
+
metadata: serverMetadata(loaded.absoluteMobileUpdateServer),
|
|
19297
|
+
registry
|
|
19298
|
+
};
|
|
19299
|
+
};
|
|
19300
|
+
var expoSigningOptions = (config) => {
|
|
19301
|
+
if (!config.updates?.expoCodeSigning)
|
|
19302
|
+
return;
|
|
19303
|
+
const entries = Object.entries(config.updateServer?.expoCodeSigningKeys ?? {});
|
|
19304
|
+
const keys = Object.fromEntries(entries.map(([keyId, key]) => {
|
|
19305
|
+
const privateKey = process.env[key.privateKeyEnv];
|
|
19306
|
+
if (!privateKey)
|
|
19307
|
+
throw new TypeError(`Expo update serving requires ${key.privateKeyEnv} on the trusted server.`);
|
|
19308
|
+
try {
|
|
19309
|
+
const certificate = new X509Certificate(key.certificatePem);
|
|
19310
|
+
const expected = certificate.publicKey.export({
|
|
19311
|
+
format: "der",
|
|
19312
|
+
type: "spki"
|
|
19313
|
+
});
|
|
19314
|
+
const actual = createPublicKey(createPrivateKey(privateKey)).export({
|
|
19315
|
+
format: "der",
|
|
19316
|
+
type: "spki"
|
|
19317
|
+
});
|
|
19318
|
+
if (!expected.equals(actual))
|
|
19319
|
+
throw new Error("key mismatch");
|
|
19320
|
+
} catch (error) {
|
|
19321
|
+
throw new TypeError(`${key.privateKeyEnv} must contain the RSA private key matching Expo update key ${keyId}.`, { cause: error });
|
|
19322
|
+
}
|
|
19323
|
+
return [keyId, { certificate: key.certificatePem, privateKey }];
|
|
19324
|
+
}));
|
|
19325
|
+
return { keys };
|
|
19326
|
+
};
|
|
19327
|
+
var inspectAbsoluteMobileUpdateServer = async (config, projectRoot) => {
|
|
19328
|
+
if (!config.updates)
|
|
19329
|
+
return;
|
|
19330
|
+
const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, config.updateServer?.registryModule);
|
|
19331
|
+
if (module.metadata.storage !== "durable")
|
|
19332
|
+
throw new TypeError("Mobile production updates require durable object storage; the configured registry is local-only.");
|
|
19333
|
+
if (config.engine === "expo")
|
|
19334
|
+
expoSigningOptions(config);
|
|
19335
|
+
return module.metadata;
|
|
19336
|
+
};
|
|
19337
|
+
var publicKeysSource = (publicKeys) => JSON.stringify(publicKeys, null, "\t");
|
|
19338
|
+
var renderAbsoluteMobileUpdateRegistry = (options) => {
|
|
19339
|
+
const metadata = `export const absoluteMobileUpdateServer = {
|
|
19340
|
+
format: 1,
|
|
19341
|
+
provider: '${options.storage}',
|
|
19342
|
+
storage: '${options.storage === "local" ? "local" : "durable"}'
|
|
19343
|
+
} as const;`;
|
|
19344
|
+
if (options.storage === "local")
|
|
19345
|
+
return `import { fileURLToPath } from 'node:url';
|
|
19346
|
+
import { localBlobStore } from '@absolutejs/blob/local';
|
|
19347
|
+
import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
|
|
19348
|
+
|
|
19349
|
+
${metadata}
|
|
19350
|
+
|
|
19351
|
+
const store = localBlobStore({
|
|
19352
|
+
root: process.env.ABSOLUTE_MOBILE_UPDATE_LOCAL_ROOT ??
|
|
19353
|
+
fileURLToPath(new URL('./.absolutejs/mobile/update-registry/', import.meta.url))
|
|
19354
|
+
});
|
|
19355
|
+
|
|
19356
|
+
export default createMobileUpdateRegistry({
|
|
19357
|
+
publicKeys: ${publicKeysSource(options.publicKeys)},
|
|
19358
|
+
store
|
|
19359
|
+
});
|
|
19360
|
+
`;
|
|
19361
|
+
return `import { S3Client } from '@aws-sdk/client-s3';
|
|
19362
|
+
import { awsS3BlobStore } from '@absolutejs/blob/aws-s3';
|
|
19363
|
+
import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
|
|
19364
|
+
|
|
19365
|
+
${metadata}
|
|
19366
|
+
|
|
19367
|
+
const required = (name: string) => {
|
|
19368
|
+
const value = process.env[name];
|
|
19369
|
+
if (!value) throw new Error(\`Missing \${name}\`);
|
|
19370
|
+
return value;
|
|
19371
|
+
};
|
|
19372
|
+
|
|
19373
|
+
const client = new S3Client({
|
|
19374
|
+
region: process.env.ABSOLUTE_MOBILE_UPDATE_S3_REGION ?? 'auto',
|
|
19375
|
+
forcePathStyle: process.env.ABSOLUTE_MOBILE_UPDATE_S3_FORCE_PATH_STYLE === '1',
|
|
19376
|
+
...(process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT
|
|
19377
|
+
? { endpoint: process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT }
|
|
19378
|
+
: {})
|
|
19379
|
+
});
|
|
19380
|
+
const store = awsS3BlobStore({
|
|
19381
|
+
bucket: required('ABSOLUTE_MOBILE_UPDATE_S3_BUCKET'),
|
|
19382
|
+
client
|
|
19383
|
+
});
|
|
19384
|
+
|
|
19385
|
+
export default createMobileUpdateRegistry({
|
|
19386
|
+
publicKeys: ${publicKeysSource(options.publicKeys)},
|
|
19387
|
+
store
|
|
19388
|
+
});
|
|
19389
|
+
`;
|
|
19390
|
+
};
|
|
19391
|
+
var writeAbsoluteMobileUpdateRegistry = async (options) => {
|
|
19392
|
+
const path = projectPath(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
|
|
19393
|
+
if (!options.force) {
|
|
19394
|
+
await access3(path).then(() => {
|
|
19395
|
+
throw new TypeError(`Mobile update registry already exists: ${path}. Pass --force to replace it.`);
|
|
19396
|
+
}, () => {
|
|
19397
|
+
return;
|
|
19398
|
+
});
|
|
19399
|
+
}
|
|
19400
|
+
await mkdir5(dirname4(path), { recursive: true });
|
|
19401
|
+
await Bun.write(path, renderAbsoluteMobileUpdateRegistry({
|
|
19402
|
+
publicKeys: options.publicKeys,
|
|
19403
|
+
storage: options.storage
|
|
19404
|
+
}));
|
|
19405
|
+
return path;
|
|
19406
|
+
};
|
|
19407
|
+
|
|
19243
19408
|
// src/mobile/releaseDoctor.ts
|
|
19244
19409
|
var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1;
|
|
19245
19410
|
var HMR_ASSET_PATTERN = /(?:__HMR_WS__|hmr-timing|__absolute_target|absolutejs-error-overlay)/u;
|
|
@@ -19262,7 +19427,7 @@ var MANUAL_REVIEW = [
|
|
|
19262
19427
|
];
|
|
19263
19428
|
var pathExists2 = async (path) => {
|
|
19264
19429
|
try {
|
|
19265
|
-
await
|
|
19430
|
+
await access4(path);
|
|
19266
19431
|
return true;
|
|
19267
19432
|
} catch {
|
|
19268
19433
|
return false;
|
|
@@ -19298,6 +19463,16 @@ var warn = (id, detail, path, remediation) => ({
|
|
|
19298
19463
|
remediation,
|
|
19299
19464
|
status: "warn"
|
|
19300
19465
|
});
|
|
19466
|
+
var mobileUpdateServerCheck = async (config, projectRoot) => {
|
|
19467
|
+
if (!config.updates)
|
|
19468
|
+
return;
|
|
19469
|
+
try {
|
|
19470
|
+
const metadata = await inspectAbsoluteMobileUpdateServer(config, projectRoot);
|
|
19471
|
+
return pass("updates.trusted-server", `The trusted update server uses durable ${metadata?.provider ?? "object"} storage, supports publish/promote/rollback, and has valid server-only signing material.`, config.updateServer?.registryModule);
|
|
19472
|
+
} catch (error) {
|
|
19473
|
+
return fail("updates.trusted-server", error instanceof Error ? error.message : "The trusted mobile update server is not release-ready.", config.updateServer?.registryModule ?? "mobile.update.ts", "Run `absolute mobile update provision --storage s3 --force`, provision its environment variables on the trusted server, and rerun the release doctor.");
|
|
19474
|
+
}
|
|
19475
|
+
};
|
|
19301
19476
|
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19302
19477
|
var readJsonObject = async (path) => {
|
|
19303
19478
|
const value = JSON.parse(await readFile8(path, "utf8"));
|
|
@@ -19445,7 +19620,7 @@ var manifestReleaseCheck = async (manifestPath) => {
|
|
|
19445
19620
|
const source = await readFile8(manifestPath, "utf8");
|
|
19446
19621
|
const cleartext = /android:usesCleartextTraffic=["']true["']/u.test(source);
|
|
19447
19622
|
const networkConfigName = source.match(/android:networkSecurityConfig=["']@xml\/([a-z0-9_]+)["']/u)?.[1];
|
|
19448
|
-
const networkConfigPath = networkConfigName ? join7(
|
|
19623
|
+
const networkConfigPath = networkConfigName ? join7(dirname5(manifestPath), "res", "xml", `${networkConfigName}.xml`) : undefined;
|
|
19449
19624
|
const developmentTrustReference = /android:networkSecurityConfig=["']@xml\/absolutejs_dev_network_security["']/u.test(source);
|
|
19450
19625
|
const developmentTrustContents = networkConfigPath ? await readFile8(networkConfigPath, "utf8").then((value) => value.includes("@raw/absolutejs_dev_ca")).catch(() => false) : false;
|
|
19451
19626
|
const developmentTrust = developmentTrustReference || developmentTrustContents;
|
|
@@ -19657,7 +19832,7 @@ var nativeObservabilityProjectionCheck = async (config, platform) => {
|
|
|
19657
19832
|
return registration && plugin ? pass("android.native-observability", "The Android process-exit collector is projected and registered.", plugin) : fail("android.native-observability", "The Android process-exit collector is missing or unregistered.", plugin ?? sourceRoot, "Run `absolute mobile sync android` before building the release.");
|
|
19658
19833
|
};
|
|
19659
19834
|
var iosNativeSecurityCheck = async (iosRoot) => {
|
|
19660
|
-
const applicationFiles = async (extensions) => (await sourceFiles(iosRoot, extensions)).filter((path) => !
|
|
19835
|
+
const applicationFiles = async (extensions) => (await sourceFiles(iosRoot, extensions)).filter((path) => !relative3(iosRoot, path).split(/[\\/]/u).some((part) => ["Pods", "DerivedData", "build"].includes(part)));
|
|
19661
19836
|
const entitlementPaths = await applicationFiles(new Set([".entitlements"]));
|
|
19662
19837
|
const unsafeEntitlements = await containsPattern(entitlementPaths, /<key>(?:com\.apple\.security\.)?get-task-allow<\/key>\s*<true\s*\/>/u);
|
|
19663
19838
|
if (unsafeEntitlements)
|
|
@@ -19671,12 +19846,12 @@ var iosNativeSecurityCheck = async (iosRoot) => {
|
|
|
19671
19846
|
var iosDeepLinkProjectionCheck = async (config, iosRoot) => {
|
|
19672
19847
|
const infoPath = join7(iosRoot, "App/App/Info.plist");
|
|
19673
19848
|
const entitlementsPath = join7(iosRoot, "App/AbsoluteJS.entitlements");
|
|
19674
|
-
const
|
|
19849
|
+
const projectPath2 = join7(iosRoot, "App/App.xcodeproj/project.pbxproj");
|
|
19675
19850
|
try {
|
|
19676
19851
|
const [info, entitlements, project] = await Promise.all([
|
|
19677
19852
|
readFile8(infoPath, "utf8"),
|
|
19678
19853
|
readFile8(entitlementsPath, "utf8"),
|
|
19679
|
-
readFile8(
|
|
19854
|
+
readFile8(projectPath2, "utf8")
|
|
19680
19855
|
]);
|
|
19681
19856
|
if (config.deepLinkScheme && (!info.includes("<key>CFBundleURLTypes</key>") || !info.includes(`<string>${config.deepLinkScheme}</string>`)))
|
|
19682
19857
|
throw new TypeError("iOS custom URL scheme does not match mobile config.");
|
|
@@ -19761,8 +19936,8 @@ var expoIosPushCapabilityCheck = async (iosRoot, requirements) => {
|
|
|
19761
19936
|
};
|
|
19762
19937
|
var expoIosCapabilityProjectionCheck = async (config, requirements) => {
|
|
19763
19938
|
const iosRoot = join7(config.nativeProjectDirectory, "ios");
|
|
19764
|
-
const
|
|
19765
|
-
const project = await readFile8(
|
|
19939
|
+
const projectPath2 = await uniqueExpoIosFile(iosRoot, "**/*.xcodeproj/project.pbxproj", "Xcode project");
|
|
19940
|
+
const project = await readFile8(projectPath2, "utf8");
|
|
19766
19941
|
const privacy = await expoIosPrivacyCapabilityCheck(iosRoot, project, requirements);
|
|
19767
19942
|
if (privacy)
|
|
19768
19943
|
return privacy;
|
|
@@ -19780,10 +19955,10 @@ var iosCapabilityProjectionCheck = async (config, requirements) => {
|
|
|
19780
19955
|
return fail("mobile.device-capabilities", "iOS system-bar capability is missing its required view-controller setting.", infoPath, "Run `absolute mobile sync ios` to regenerate native capability settings.");
|
|
19781
19956
|
if (requirements.iosPrivacyAccessedApis.length > 0) {
|
|
19782
19957
|
const privacyPath = join7(appRoot, "PrivacyInfo.xcprivacy");
|
|
19783
|
-
const
|
|
19958
|
+
const projectPath2 = join7(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
19784
19959
|
const [privacy, project] = await Promise.all([
|
|
19785
19960
|
readFile8(privacyPath, "utf8").catch(() => ""),
|
|
19786
|
-
readFile8(
|
|
19961
|
+
readFile8(projectPath2, "utf8").catch(() => "")
|
|
19787
19962
|
]);
|
|
19788
19963
|
const missing = requirements.iosPrivacyAccessedApis.some(({ api, reasons }) => !privacy.includes(`<string>${api}</string>`) || reasons.some((reason) => !privacy.includes(`<string>${reason}</string>`)));
|
|
19789
19964
|
if (missing || !project.includes("PrivacyInfo.xcprivacy in Resources"))
|
|
@@ -19856,7 +20031,7 @@ var inspectAndroidRelease = async (config, projectRoot) => {
|
|
|
19856
20031
|
]);
|
|
19857
20032
|
return checks.filter((check) => check !== undefined).map((check) => ({
|
|
19858
20033
|
...check,
|
|
19859
|
-
path: check.path ?
|
|
20034
|
+
path: check.path ? relative3(projectRoot, check.path).replaceAll("\\", "/") || "." : undefined
|
|
19860
20035
|
}));
|
|
19861
20036
|
};
|
|
19862
20037
|
var inspectExpoAndroidRelease = async (config, projectRoot) => {
|
|
@@ -19878,7 +20053,7 @@ var inspectExpoAndroidRelease = async (config, projectRoot) => {
|
|
|
19878
20053
|
]);
|
|
19879
20054
|
return checks.filter((check) => check !== undefined).map((check) => ({
|
|
19880
20055
|
...check,
|
|
19881
|
-
path: check.path ?
|
|
20056
|
+
path: check.path ? relative3(projectRoot, check.path).replaceAll("\\", "/") || "." : undefined
|
|
19882
20057
|
}));
|
|
19883
20058
|
};
|
|
19884
20059
|
var uniqueExpoIosFile = async (iosRoot, pattern, label) => {
|
|
@@ -19892,7 +20067,7 @@ var uniqueExpoIosFile = async (iosRoot, pattern, label) => {
|
|
|
19892
20067
|
};
|
|
19893
20068
|
var expoIosNativeProjectionCheck = async (config, iosRoot) => {
|
|
19894
20069
|
try {
|
|
19895
|
-
const [infoPath, entitlementsPath,
|
|
20070
|
+
const [infoPath, entitlementsPath, projectPath2] = await Promise.all([
|
|
19896
20071
|
uniqueExpoIosFile(iosRoot, "**/Info.plist", "Info.plist"),
|
|
19897
20072
|
uniqueExpoIosFile(iosRoot, "**/*.entitlements", "entitlements"),
|
|
19898
20073
|
uniqueExpoIosFile(iosRoot, "**/*.xcodeproj/project.pbxproj", "Xcode project")
|
|
@@ -19900,7 +20075,7 @@ var expoIosNativeProjectionCheck = async (config, iosRoot) => {
|
|
|
19900
20075
|
const [info, entitlements, project] = await Promise.all([
|
|
19901
20076
|
readFile8(infoPath, "utf8"),
|
|
19902
20077
|
readFile8(entitlementsPath, "utf8"),
|
|
19903
|
-
readFile8(
|
|
20078
|
+
readFile8(projectPath2, "utf8")
|
|
19904
20079
|
]);
|
|
19905
20080
|
if (/<key>NSAllowsArbitraryLoads<\/key>\s*<true\s*\/>/u.test(info))
|
|
19906
20081
|
throw new TypeError("Expo iOS App Transport Security permits arbitrary network loads.");
|
|
@@ -19936,7 +20111,7 @@ var inspectExpoIosRelease = async (config, projectRoot) => {
|
|
|
19936
20111
|
checks.push(nativeObservability);
|
|
19937
20112
|
return checks.map((check) => ({
|
|
19938
20113
|
...check,
|
|
19939
|
-
path: check.path ?
|
|
20114
|
+
path: check.path ? relative3(projectRoot, check.path).replaceAll("\\", "/") || "." : undefined
|
|
19940
20115
|
}));
|
|
19941
20116
|
};
|
|
19942
20117
|
var inspectIosRelease = async (config, projectRoot) => {
|
|
@@ -19978,7 +20153,7 @@ var inspectIosRelease = async (config, projectRoot) => {
|
|
|
19978
20153
|
checks.push(updateWatchdog);
|
|
19979
20154
|
return checks.map((check) => ({
|
|
19980
20155
|
...check,
|
|
19981
|
-
path: check.path ?
|
|
20156
|
+
path: check.path ? relative3(projectRoot, check.path).replaceAll("\\", "/") || "." : undefined
|
|
19982
20157
|
}));
|
|
19983
20158
|
};
|
|
19984
20159
|
var createAbsoluteMobileComplianceReport = (config, result) => {
|
|
@@ -20006,11 +20181,12 @@ var inspectAbsoluteMobileRelease = async (config, projectRoot) => {
|
|
|
20006
20181
|
Promise.resolve(productionOriginCheck(config, projectRoot)),
|
|
20007
20182
|
Promise.resolve(associationIdentityCheck(config, projectRoot)),
|
|
20008
20183
|
dependencyLockCheck(projectRoot),
|
|
20009
|
-
config.engine === "expo" ? expoVersionCheck(config) : capacitorVersionCheck(config, projectRoot)
|
|
20184
|
+
config.engine === "expo" ? expoVersionCheck(config) : capacitorVersionCheck(config, projectRoot),
|
|
20185
|
+
mobileUpdateServerCheck(config, projectRoot)
|
|
20010
20186
|
]);
|
|
20011
|
-
const checks = globalChecks.map((check) => ({
|
|
20187
|
+
const checks = globalChecks.filter((check) => check !== undefined).map((check) => ({
|
|
20012
20188
|
...check,
|
|
20013
|
-
path: check.path ?
|
|
20189
|
+
path: check.path ? relative3(projectRoot, check.path).replaceAll("\\", "/") || "." : undefined
|
|
20014
20190
|
}));
|
|
20015
20191
|
if (config.platforms.includes("android"))
|
|
20016
20192
|
checks.push(...config.engine === "expo" ? await inspectExpoAndroidRelease(config, projectRoot) : await inspectAndroidRelease(config, projectRoot));
|
|
@@ -20020,13 +20196,13 @@ var inspectAbsoluteMobileRelease = async (config, projectRoot) => {
|
|
|
20020
20196
|
if (syncSchema) {
|
|
20021
20197
|
checks.push({
|
|
20022
20198
|
...syncSchema,
|
|
20023
|
-
path: syncSchema.path ?
|
|
20199
|
+
path: syncSchema.path ? relative3(projectRoot, syncSchema.path).replaceAll("\\", "/") || "." : undefined
|
|
20024
20200
|
});
|
|
20025
20201
|
}
|
|
20026
20202
|
const deviceCapabilities = await deviceCapabilityReleaseCheck(config, projectRoot);
|
|
20027
20203
|
checks.push({
|
|
20028
20204
|
...deviceCapabilities,
|
|
20029
|
-
path: deviceCapabilities.path ?
|
|
20205
|
+
path: deviceCapabilities.path ? relative3(projectRoot, deviceCapabilities.path).replaceAll("\\", "/") || "." : undefined
|
|
20030
20206
|
});
|
|
20031
20207
|
return {
|
|
20032
20208
|
checks,
|
|
@@ -20037,9 +20213,9 @@ var inspectAbsoluteMobileRelease = async (config, projectRoot) => {
|
|
|
20037
20213
|
// src/mobile/androidRelease.ts
|
|
20038
20214
|
import { createHash as createHash2 } from "crypto";
|
|
20039
20215
|
import {
|
|
20040
|
-
access as
|
|
20216
|
+
access as access5,
|
|
20041
20217
|
copyFile,
|
|
20042
|
-
mkdir as
|
|
20218
|
+
mkdir as mkdir6,
|
|
20043
20219
|
mkdtemp,
|
|
20044
20220
|
readFile as readFile9,
|
|
20045
20221
|
realpath,
|
|
@@ -20048,7 +20224,7 @@ import {
|
|
|
20048
20224
|
stat as stat2,
|
|
20049
20225
|
writeFile as writeFile8
|
|
20050
20226
|
} from "fs/promises";
|
|
20051
|
-
import { dirname as
|
|
20227
|
+
import { dirname as dirname6, isAbsolute as isAbsolute2, join as join8, relative as relative4, resolve as resolve5, sep as sep2 } from "path";
|
|
20052
20228
|
var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1;
|
|
20053
20229
|
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20054
20230
|
var requireManifest = (value) => {
|
|
@@ -20063,7 +20239,7 @@ var requireManifest = (value) => {
|
|
|
20063
20239
|
};
|
|
20064
20240
|
var pathExists3 = async (path) => {
|
|
20065
20241
|
try {
|
|
20066
|
-
await
|
|
20242
|
+
await access5(path);
|
|
20067
20243
|
return true;
|
|
20068
20244
|
} catch {
|
|
20069
20245
|
return false;
|
|
@@ -20133,10 +20309,10 @@ var fingerprintExpoAndroidProject = async (nativeDirectory) => {
|
|
|
20133
20309
|
return createHash2("sha256").update(records.join("")).digest("hex");
|
|
20134
20310
|
};
|
|
20135
20311
|
var safeOutputDirectory = (projectRoot, requested) => {
|
|
20136
|
-
const root =
|
|
20137
|
-
const output =
|
|
20138
|
-
const projectRelative =
|
|
20139
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
20312
|
+
const root = resolve5(projectRoot);
|
|
20313
|
+
const output = resolve5(root, requested ?? ".absolutejs/mobile/releases/android");
|
|
20314
|
+
const projectRelative = relative4(root, output);
|
|
20315
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep2}`) || isAbsolute2(projectRelative)) {
|
|
20140
20316
|
throw new TypeError("mobile build --outdir must remain inside the project.");
|
|
20141
20317
|
}
|
|
20142
20318
|
return output;
|
|
@@ -20156,8 +20332,8 @@ var installRelease = async (artifactPath, metadata, outputRoot) => {
|
|
|
20156
20332
|
}
|
|
20157
20333
|
return { artifactPath: destination, metadata: existing, releaseRoot };
|
|
20158
20334
|
}
|
|
20159
|
-
await
|
|
20160
|
-
const staging = await mkdtemp(join8(
|
|
20335
|
+
await mkdir6(dirname6(releaseRoot), { recursive: true });
|
|
20336
|
+
const staging = await mkdtemp(join8(dirname6(releaseRoot), ".android-stage-"));
|
|
20161
20337
|
try {
|
|
20162
20338
|
await copyFile(artifactPath, join8(staging, artifactName));
|
|
20163
20339
|
const complete = {
|
|
@@ -20191,7 +20367,7 @@ var buildAbsoluteAndroidRelease = async (options) => {
|
|
|
20191
20367
|
if (options.versionCode !== undefined && (!Number.isSafeInteger(options.versionCode) || options.versionCode < 1 || options.versionCode > 2100000000)) {
|
|
20192
20368
|
throw new TypeError("Android versionCode must be an integer from 1 through 2100000000.");
|
|
20193
20369
|
}
|
|
20194
|
-
const projectRoot =
|
|
20370
|
+
const projectRoot = resolve5(options.projectRoot);
|
|
20195
20371
|
const host = options.host ?? detectAbsoluteMobileHost();
|
|
20196
20372
|
if (options.config.engine === "expo" && host === "wsl") {
|
|
20197
20373
|
throw new TypeError("Expo Android production builds from WSL are not available yet. Run the generated CI workflow on Linux or build from native Windows while the WSL projection is completed.");
|
|
@@ -20369,7 +20545,7 @@ var waitForAbsoluteIosHmrLog = async (options) => {
|
|
|
20369
20545
|
};
|
|
20370
20546
|
|
|
20371
20547
|
// src/mobile/nativeTestReport.ts
|
|
20372
|
-
import { mkdir as
|
|
20548
|
+
import { mkdir as mkdir7, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
|
|
20373
20549
|
import { join as join9 } from "path";
|
|
20374
20550
|
var secretPattern = /(authorization|access[_ -]?token|refresh[_ -]?token|socket[_ -]?ticket|password|cookie)(\s*[=:]\s*)([^\s,;]+)/giu;
|
|
20375
20551
|
var bearerPattern = /bearer\s+[^\s,;]+/giu;
|
|
@@ -20518,7 +20694,7 @@ ${table(report.manualChecks)}
|
|
|
20518
20694
|
`;
|
|
20519
20695
|
};
|
|
20520
20696
|
var writeAbsoluteNativeTestReport = async (directory, report) => {
|
|
20521
|
-
await
|
|
20697
|
+
await mkdir7(directory, { recursive: true });
|
|
20522
20698
|
const jsonPath = join9(directory, "report.json");
|
|
20523
20699
|
const markdownPath = join9(directory, "report.md");
|
|
20524
20700
|
await Promise.all([
|
|
@@ -20774,9 +20950,9 @@ var createAbsoluteAndroidTestReport = (options) => {
|
|
|
20774
20950
|
};
|
|
20775
20951
|
|
|
20776
20952
|
// src/mobile/releasePublisher.ts
|
|
20777
|
-
import { access as
|
|
20778
|
-
import { isAbsolute as
|
|
20779
|
-
import { pathToFileURL } from "url";
|
|
20953
|
+
import { access as access6 } from "fs/promises";
|
|
20954
|
+
import { isAbsolute as isAbsolute3, relative as relative5, resolve as resolve6, sep as sep3 } from "path";
|
|
20955
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
20780
20956
|
var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
20781
20957
|
if (typeof publisher.prepareIosRelease !== "function") {
|
|
20782
20958
|
throw new TypeError("App Store Connect publishing requires a registry module created with @absolutejs/deploy/app-store-connect.");
|
|
@@ -20801,20 +20977,20 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
|
|
|
20801
20977
|
var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20802
20978
|
var isPublisher = (value) => isRecord5(value) && typeof value.publish === "function";
|
|
20803
20979
|
var publisherModulePath = (projectRoot, requested) => {
|
|
20804
|
-
const root =
|
|
20805
|
-
const path =
|
|
20806
|
-
const projectRelative =
|
|
20807
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
20980
|
+
const root = resolve6(projectRoot);
|
|
20981
|
+
const path = resolve6(root, requested);
|
|
20982
|
+
const projectRelative = relative5(root, path);
|
|
20983
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep3}`) || isAbsolute3(projectRelative)) {
|
|
20808
20984
|
throw new TypeError("mobile publish --registry must remain inside the project.");
|
|
20809
20985
|
}
|
|
20810
20986
|
return path;
|
|
20811
20987
|
};
|
|
20812
20988
|
var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
|
|
20813
20989
|
const modulePath = publisherModulePath(projectRoot, requestedModulePath);
|
|
20814
|
-
await
|
|
20990
|
+
await access6(modulePath).catch(() => {
|
|
20815
20991
|
throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
|
|
20816
20992
|
});
|
|
20817
|
-
const loaded = await import(
|
|
20993
|
+
const loaded = await import(pathToFileURL2(modulePath).href);
|
|
20818
20994
|
const publisher = isRecord5(loaded) ? loaded.default ?? loaded.registry : undefined;
|
|
20819
20995
|
if (!isPublisher(publisher)) {
|
|
20820
20996
|
throw new TypeError("Native release registry module must default-export a registry with publish(options).");
|
|
@@ -20873,8 +21049,8 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
20873
21049
|
};
|
|
20874
21050
|
|
|
20875
21051
|
// src/mobile/mobileInspect.ts
|
|
20876
|
-
import { access as
|
|
20877
|
-
import { join as join10, relative as
|
|
21052
|
+
import { access as access7, readFile as readFile12 } from "fs/promises";
|
|
21053
|
+
import { join as join10, relative as relative6, resolve as resolve7 } from "path";
|
|
20878
21054
|
var ABSOLUTE_MOBILE_INSPECTION_FORMAT = 1;
|
|
20879
21055
|
var MOBILE_PACKAGE_NAMES = new Set([
|
|
20880
21056
|
"@absolutejs/absolute",
|
|
@@ -20889,12 +21065,12 @@ var MOBILE_PACKAGE_NAMES = new Set([
|
|
|
20889
21065
|
]);
|
|
20890
21066
|
var isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20891
21067
|
var portablePath2 = (projectRoot, path) => {
|
|
20892
|
-
const value =
|
|
21068
|
+
const value = relative6(resolve7(projectRoot), resolve7(path)).replaceAll("\\", "/");
|
|
20893
21069
|
return value || ".";
|
|
20894
21070
|
};
|
|
20895
21071
|
var pathExists4 = async (path) => {
|
|
20896
21072
|
try {
|
|
20897
|
-
await
|
|
21073
|
+
await access7(path);
|
|
20898
21074
|
return true;
|
|
20899
21075
|
} catch {
|
|
20900
21076
|
return false;
|
|
@@ -21035,8 +21211,8 @@ var renderAbsoluteMobileProjectInspection = (report) => {
|
|
|
21035
21211
|
|
|
21036
21212
|
// src/mobile/ciWorkflow.ts
|
|
21037
21213
|
import { existsSync } from "fs";
|
|
21038
|
-
import { access as
|
|
21039
|
-
import { dirname as
|
|
21214
|
+
import { access as access8, mkdir as mkdir8, readFile as readFile13, writeFile as writeFile10 } from "fs/promises";
|
|
21215
|
+
import { dirname as dirname7, extname as extname2, relative as relative7, resolve as resolve8, sep as sep4 } from "path";
|
|
21040
21216
|
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1;
|
|
21041
21217
|
var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
|
|
21042
21218
|
var CI_ENV_INDENTATION = 6;
|
|
@@ -21057,18 +21233,18 @@ var RESERVED_SECRET_NAMES = new Set([
|
|
|
21057
21233
|
]);
|
|
21058
21234
|
var exists2 = async (path) => {
|
|
21059
21235
|
try {
|
|
21060
|
-
await
|
|
21236
|
+
await access8(path);
|
|
21061
21237
|
return true;
|
|
21062
21238
|
} catch {
|
|
21063
21239
|
return false;
|
|
21064
21240
|
}
|
|
21065
21241
|
};
|
|
21066
21242
|
var yamlString = (value) => `'${value.replaceAll("'", "''")}'`;
|
|
21067
|
-
var
|
|
21068
|
-
const root =
|
|
21069
|
-
const path =
|
|
21070
|
-
const portable =
|
|
21071
|
-
if (portable === ".." || portable.startsWith(`..${
|
|
21243
|
+
var projectPath2 = (projectRoot, value, field, options = {}) => {
|
|
21244
|
+
const root = resolve8(projectRoot);
|
|
21245
|
+
const path = resolve8(root, value);
|
|
21246
|
+
const portable = relative7(root, path).replaceAll("\\", "/");
|
|
21247
|
+
if (portable === ".." || portable.startsWith(`..${sep4}`) || portable.startsWith("../") || portable === "") {
|
|
21072
21248
|
throw new TypeError(`${field} must remain inside the project root.`);
|
|
21073
21249
|
}
|
|
21074
21250
|
if (/\r|\n/u.test(portable) || portable.startsWith("-"))
|
|
@@ -21078,11 +21254,11 @@ var projectPath = (projectRoot, value, field, options = {}) => {
|
|
|
21078
21254
|
return portable;
|
|
21079
21255
|
};
|
|
21080
21256
|
var workflowOutputPath = (projectRoot, value) => {
|
|
21081
|
-
const root =
|
|
21082
|
-
const workflows =
|
|
21083
|
-
const path =
|
|
21084
|
-
const portable =
|
|
21085
|
-
if (portable === ".." || portable.startsWith(`..${
|
|
21257
|
+
const root = resolve8(projectRoot);
|
|
21258
|
+
const workflows = resolve8(root, ".github/workflows");
|
|
21259
|
+
const path = resolve8(root, value ?? ".github/workflows/absolute-mobile.yml");
|
|
21260
|
+
const portable = relative7(workflows, path);
|
|
21261
|
+
if (portable === ".." || portable.startsWith(`..${sep4}`) || extname2(path) !== ".yml" && extname2(path) !== ".yaml") {
|
|
21086
21262
|
throw new TypeError("mobile ci github --output must be a .yml or .yaml file inside .github/workflows.");
|
|
21087
21263
|
}
|
|
21088
21264
|
return path;
|
|
@@ -21449,9 +21625,9 @@ var createAbsoluteMobileGithubWorkflow = (options) => {
|
|
|
21449
21625
|
].sort();
|
|
21450
21626
|
const includePublishing = options.includePublishing === true;
|
|
21451
21627
|
const customSecrets = normalizeSecretEnvironment(options.secretEnvironment);
|
|
21452
|
-
const serverEntry =
|
|
21453
|
-
const configPath = options.configPath ?
|
|
21454
|
-
const registryModule =
|
|
21628
|
+
const serverEntry = projectPath2(options.projectRoot, options.serverEntry ?? "server.ts", "mobile ci github server entry");
|
|
21629
|
+
const configPath = options.configPath ? projectPath2(options.projectRoot, options.configPath, "mobile ci github --config") : undefined;
|
|
21630
|
+
const registryModule = projectPath2(options.projectRoot, options.registryModule ?? "mobile.release.ts", "mobile ci github --registry", { allowMissing: !includePublishing });
|
|
21455
21631
|
const environment = commandEnvironment({
|
|
21456
21632
|
configPath,
|
|
21457
21633
|
registryModule,
|
|
@@ -21513,9 +21689,9 @@ var writeAbsoluteMobileGithubWorkflow = async (options) => {
|
|
|
21513
21689
|
const generated = createAbsoluteMobileGithubWorkflow(options);
|
|
21514
21690
|
const previous = await exists2(path) ? await readFile13(path, "utf8") : undefined;
|
|
21515
21691
|
if (previous !== undefined && previous !== generated.workflow && !options.force)
|
|
21516
|
-
throw new TypeError(`${
|
|
21692
|
+
throw new TypeError(`${relative7(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
|
|
21517
21693
|
if (previous !== generated.workflow) {
|
|
21518
|
-
await
|
|
21694
|
+
await mkdir8(dirname7(path), { recursive: true });
|
|
21519
21695
|
await writeFile10(path, generated.workflow);
|
|
21520
21696
|
}
|
|
21521
21697
|
return {
|
|
@@ -21532,7 +21708,7 @@ var writeAbsoluteMobileGithubWorkflow = async (options) => {
|
|
|
21532
21708
|
import { createHash as createHash3, sign, verify } from "crypto";
|
|
21533
21709
|
import {
|
|
21534
21710
|
cp,
|
|
21535
|
-
mkdir as
|
|
21711
|
+
mkdir as mkdir9,
|
|
21536
21712
|
mkdtemp as mkdtemp2,
|
|
21537
21713
|
readdir as readdir4,
|
|
21538
21714
|
readFile as readFile14,
|
|
@@ -21541,7 +21717,7 @@ import {
|
|
|
21541
21717
|
stat as stat4,
|
|
21542
21718
|
writeFile as writeFile11
|
|
21543
21719
|
} from "fs/promises";
|
|
21544
|
-
import { dirname as
|
|
21720
|
+
import { dirname as dirname8, join as join11, relative as relative8, resolve as resolve9 } from "path";
|
|
21545
21721
|
var UPDATE_MANIFEST_FILE = "update.json";
|
|
21546
21722
|
var UPDATE_FILES_DIRECTORY = "files";
|
|
21547
21723
|
var sha256 = (value) => createHash3("sha256").update(value).digest("hex");
|
|
@@ -21553,7 +21729,7 @@ var listFiles = async (root, directory = root) => {
|
|
|
21553
21729
|
return listFiles(root, path);
|
|
21554
21730
|
if (!entry.isFile())
|
|
21555
21731
|
throw new TypeError("Mobile updates cannot contain links or special files.");
|
|
21556
|
-
return [
|
|
21732
|
+
return [relative8(root, path).replaceAll("\\", "/")];
|
|
21557
21733
|
}));
|
|
21558
21734
|
return paths.flat().sort((left, right) => left.localeCompare(right));
|
|
21559
21735
|
};
|
|
@@ -21567,8 +21743,8 @@ var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) =>
|
|
|
21567
21743
|
}));
|
|
21568
21744
|
var releaseIdFor = (value) => `amu_${sha256(canonicalizeAbsoluteMobileUpdate(value))}`;
|
|
21569
21745
|
var buildAbsoluteMobileUpdate = async (options) => {
|
|
21570
|
-
const bundleDirectory =
|
|
21571
|
-
const outputRoot =
|
|
21746
|
+
const bundleDirectory = resolve9(options.bundleDirectory);
|
|
21747
|
+
const outputRoot = resolve9(options.outputDirectory);
|
|
21572
21748
|
if (outputRoot === bundleDirectory || outputRoot.startsWith(`${bundleDirectory}/`))
|
|
21573
21749
|
throw new TypeError("Mobile update output must be outside the embedded bundle.");
|
|
21574
21750
|
const paths = await listFiles(bundleDirectory);
|
|
@@ -21596,7 +21772,7 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
21596
21772
|
value: signature.toString("base64")
|
|
21597
21773
|
}
|
|
21598
21774
|
});
|
|
21599
|
-
await
|
|
21775
|
+
await mkdir9(outputRoot, { recursive: true });
|
|
21600
21776
|
const outputDirectory = join11(outputRoot, manifest.releaseId);
|
|
21601
21777
|
const staging = await mkdtemp2(join11(outputRoot, ".stage-"));
|
|
21602
21778
|
try {
|
|
@@ -21619,7 +21795,7 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
21619
21795
|
outputDirectory
|
|
21620
21796
|
};
|
|
21621
21797
|
};
|
|
21622
|
-
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile14(join11(
|
|
21798
|
+
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile14(join11(resolve9(directory), UPDATE_MANIFEST_FILE), "utf8")));
|
|
21623
21799
|
var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
|
|
21624
21800
|
const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
|
|
21625
21801
|
const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
|
|
@@ -21629,11 +21805,11 @@ var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
|
|
|
21629
21805
|
};
|
|
21630
21806
|
|
|
21631
21807
|
// src/mobile/expoUpdate.ts
|
|
21632
|
-
import { access as
|
|
21633
|
-
import { dirname as
|
|
21808
|
+
import { access as access9, mkdir as mkdir10, readFile as readFile15, writeFile as writeFile12 } from "fs/promises";
|
|
21809
|
+
import { dirname as dirname9, extname as extname3, join as join12 } from "path";
|
|
21634
21810
|
var ABSOLUTE_EXPO_UPDATE_DESCRIPTOR = "_absolute/expo-update.json";
|
|
21635
21811
|
var ABSOLUTE_EXPO_UPDATE_FORMAT = 1;
|
|
21636
|
-
var
|
|
21812
|
+
var object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21637
21813
|
var safePath = (value, field) => {
|
|
21638
21814
|
if (typeof value !== "string" || value.length === 0)
|
|
21639
21815
|
throw new TypeError(`Expo update ${field} is invalid.`);
|
|
@@ -21652,7 +21828,7 @@ var extension = (value, path) => {
|
|
|
21652
21828
|
return value;
|
|
21653
21829
|
};
|
|
21654
21830
|
var asset = (value) => {
|
|
21655
|
-
if (!
|
|
21831
|
+
if (!object2(value))
|
|
21656
21832
|
throw new TypeError("Expo update asset is invalid.");
|
|
21657
21833
|
const path = safePath(value.path, "asset path");
|
|
21658
21834
|
const normalizedExtension = extension(value.extension ?? value.ext, path);
|
|
@@ -21662,9 +21838,9 @@ var asset = (value) => {
|
|
|
21662
21838
|
};
|
|
21663
21839
|
};
|
|
21664
21840
|
var platform = (value) => {
|
|
21665
|
-
if (!
|
|
21841
|
+
if (!object2(value) || !Array.isArray(value.assets))
|
|
21666
21842
|
throw new TypeError("Expo update platform metadata is invalid.");
|
|
21667
|
-
const launchValue =
|
|
21843
|
+
const launchValue = object2(value.launchAsset) ? value.launchAsset : { path: value.bundle };
|
|
21668
21844
|
const launchPath = safePath(launchValue.path, "launch bundle");
|
|
21669
21845
|
const launchExtension = extension(launchValue.extension ?? null, launchPath);
|
|
21670
21846
|
const assets = value.assets.map(asset);
|
|
@@ -21677,7 +21853,7 @@ var platform = (value) => {
|
|
|
21677
21853
|
};
|
|
21678
21854
|
};
|
|
21679
21855
|
var parseAbsoluteExpoUpdateDescriptor = (value) => {
|
|
21680
|
-
if (!
|
|
21856
|
+
if (!object2(value) || value.engine !== "expo" || value.format !== ABSOLUTE_EXPO_UPDATE_FORMAT || !object2(value.expoConfig) || !object2(value.platforms) || typeof value.runtimeVersion !== "string" || !/^[a-f0-9]{64}$/u.test(value.runtimeVersion))
|
|
21681
21857
|
throw new TypeError("AbsoluteJS Expo update descriptor is invalid.");
|
|
21682
21858
|
const platforms = {};
|
|
21683
21859
|
for (const name of ["android", "ios"]) {
|
|
@@ -21697,7 +21873,7 @@ var parseAbsoluteExpoUpdateDescriptor = (value) => {
|
|
|
21697
21873
|
};
|
|
21698
21874
|
var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
21699
21875
|
const metadata = JSON.parse(await readFile15(join12(options.exportDirectory, "metadata.json"), "utf8"));
|
|
21700
|
-
if (!
|
|
21876
|
+
if (!object2(metadata) || !object2(metadata.fileMetadata))
|
|
21701
21877
|
throw new TypeError("Expo export metadata.json is invalid.");
|
|
21702
21878
|
const descriptor = parseAbsoluteExpoUpdateDescriptor({
|
|
21703
21879
|
engine: "expo",
|
|
@@ -21707,11 +21883,11 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
|
21707
21883
|
runtimeVersion: options.runtimeVersion
|
|
21708
21884
|
});
|
|
21709
21885
|
const referenced = Object.values(descriptor.platforms).flatMap((entry) => entry ? [entry.launchAsset, ...entry.assets] : []);
|
|
21710
|
-
await Promise.all(referenced.map(({ path }) =>
|
|
21886
|
+
await Promise.all(referenced.map(({ path }) => access9(join12(options.exportDirectory, path)).catch(() => {
|
|
21711
21887
|
throw new TypeError(`Expo export metadata references missing asset ${path}.`);
|
|
21712
21888
|
})));
|
|
21713
21889
|
const destination = join12(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
|
|
21714
|
-
await
|
|
21890
|
+
await mkdir10(dirname9(destination), { recursive: true });
|
|
21715
21891
|
await writeFile12(destination, `${JSON.stringify(descriptor, null, "\t")}
|
|
21716
21892
|
`);
|
|
21717
21893
|
return { descriptor, path: destination };
|
|
@@ -21719,18 +21895,18 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
|
21719
21895
|
|
|
21720
21896
|
// src/mobile/expoCodeSigning.ts
|
|
21721
21897
|
var import_code_signing_certificates = __toESM(require_main(), 1);
|
|
21722
|
-
import { access as
|
|
21723
|
-
import { dirname as
|
|
21724
|
-
var exists3 = async (path) =>
|
|
21898
|
+
import { access as access10, mkdir as mkdir11, writeFile as writeFile13 } from "fs/promises";
|
|
21899
|
+
import { dirname as dirname10, isAbsolute as isAbsolute4, relative as relative9, resolve as resolve10, sep as sep5 } from "path";
|
|
21900
|
+
var exists3 = async (path) => access10(path).then(() => true).catch(() => false);
|
|
21725
21901
|
var inside = (root, path) => {
|
|
21726
|
-
const location =
|
|
21727
|
-
return location === "" || location !== ".." && !location.startsWith(`..${
|
|
21902
|
+
const location = relative9(root, path);
|
|
21903
|
+
return location === "" || location !== ".." && !location.startsWith(`..${sep5}`) && !isAbsolute4(location);
|
|
21728
21904
|
};
|
|
21729
21905
|
var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
21730
|
-
const root =
|
|
21731
|
-
const certificatePath =
|
|
21732
|
-
const privateKeyPath =
|
|
21733
|
-
const publicKeyPath =
|
|
21906
|
+
const root = resolve10(options.projectRoot);
|
|
21907
|
+
const certificatePath = resolve10(root, options.certificatePath);
|
|
21908
|
+
const privateKeyPath = resolve10(root, options.privateKeyPath);
|
|
21909
|
+
const publicKeyPath = resolve10(root, options.publicKeyPath ?? resolve10(dirname10(privateKeyPath), "public-key.pem"));
|
|
21734
21910
|
if (!inside(root, certificatePath))
|
|
21735
21911
|
throw new TypeError("Expo code-signing certificate must be written inside the project so store builds can embed it.");
|
|
21736
21912
|
if (inside(root, privateKeyPath) || inside(root, publicKeyPath))
|
|
@@ -21760,7 +21936,7 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
|
21760
21936
|
import_code_signing_certificates.validateSelfSignedCertificate(certificate, keyPair);
|
|
21761
21937
|
const { privateKeyPEM, publicKeyPEM } = import_code_signing_certificates.convertKeyPairToPEM(keyPair);
|
|
21762
21938
|
const certificatePem = import_code_signing_certificates.convertCertificateToCertificatePEM(certificate);
|
|
21763
|
-
await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) =>
|
|
21939
|
+
await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) => mkdir11(dirname10(path), { recursive: true })));
|
|
21764
21940
|
await Promise.all([
|
|
21765
21941
|
writeFile13(certificatePath, certificatePem, { flag: "wx", mode: 420 }),
|
|
21766
21942
|
writeFile13(privateKeyPath, privateKeyPEM, { flag: "wx", mode: 384 }),
|
|
@@ -21775,26 +21951,26 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
|
21775
21951
|
};
|
|
21776
21952
|
|
|
21777
21953
|
// src/mobile/updatePublisher.ts
|
|
21778
|
-
import { access as
|
|
21779
|
-
import { isAbsolute as
|
|
21780
|
-
import { pathToFileURL as
|
|
21781
|
-
var
|
|
21782
|
-
var isPublisher2 = (value) =>
|
|
21783
|
-
var
|
|
21784
|
-
const root =
|
|
21785
|
-
const path =
|
|
21786
|
-
const projectRelative =
|
|
21787
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
21954
|
+
import { access as access11 } from "fs/promises";
|
|
21955
|
+
import { isAbsolute as isAbsolute5, relative as relative10, resolve as resolve11, sep as sep6 } from "path";
|
|
21956
|
+
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
21957
|
+
var object3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21958
|
+
var isPublisher2 = (value) => object3(value) && typeof value.publishUpdate === "function" && typeof value.promoteUpdate === "function" && typeof value.rollbackUpdate === "function";
|
|
21959
|
+
var projectPath3 = (projectRoot, requested, label) => {
|
|
21960
|
+
const root = resolve11(projectRoot);
|
|
21961
|
+
const path = resolve11(root, requested);
|
|
21962
|
+
const projectRelative = relative10(root, path);
|
|
21963
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep6}`) || isAbsolute5(projectRelative))
|
|
21788
21964
|
throw new TypeError(`${label} must remain inside the project.`);
|
|
21789
21965
|
return path;
|
|
21790
21966
|
};
|
|
21791
21967
|
var loadAbsoluteMobileUpdatePublisher = async (projectRoot, requestedModulePath) => {
|
|
21792
|
-
const modulePath =
|
|
21793
|
-
await
|
|
21968
|
+
const modulePath = projectPath3(projectRoot, requestedModulePath, "mobile update registry");
|
|
21969
|
+
await access11(modulePath).catch(() => {
|
|
21794
21970
|
throw new TypeError(`Mobile update registry does not exist: ${modulePath}`);
|
|
21795
21971
|
});
|
|
21796
|
-
const loaded = await import(
|
|
21797
|
-
const publisher =
|
|
21972
|
+
const loaded = await import(pathToFileURL3(modulePath).href);
|
|
21973
|
+
const publisher = object3(loaded) ? loaded.default ?? loaded.registry : undefined;
|
|
21798
21974
|
if (!isPublisher2(publisher))
|
|
21799
21975
|
throw new TypeError("Mobile update registry must implement publishUpdate, promoteUpdate, and rollbackUpdate.");
|
|
21800
21976
|
return publisher;
|
|
@@ -21812,7 +21988,7 @@ var promoteAbsoluteMobileUpdate = async (options) => {
|
|
|
21812
21988
|
return result;
|
|
21813
21989
|
};
|
|
21814
21990
|
var publishAbsoluteMobileUpdate = async (options) => {
|
|
21815
|
-
const releaseDirectory =
|
|
21991
|
+
const releaseDirectory = projectPath3(options.projectRoot, options.releaseDirectory, "mobile update release directory");
|
|
21816
21992
|
const manifest = await readAbsoluteMobileUpdate(releaseDirectory);
|
|
21817
21993
|
const result = await options.publisher.publishUpdate({
|
|
21818
21994
|
manifest,
|
|
@@ -21948,7 +22124,7 @@ var requireMobileConfig = (value) => {
|
|
|
21948
22124
|
var capacitorExecutable = async (projectRoot) => {
|
|
21949
22125
|
const executable = join13(projectRoot, "node_modules", ".bin", "cap");
|
|
21950
22126
|
try {
|
|
21951
|
-
await
|
|
22127
|
+
await access12(executable);
|
|
21952
22128
|
return executable;
|
|
21953
22129
|
} catch {
|
|
21954
22130
|
throw new TypeError(`Capacitor is not installed in this app. Run: bun add ${CAPACITOR_PACKAGES.join(" ")}`);
|
|
@@ -21971,7 +22147,7 @@ var runCapacitorForPlatforms = (projectRoot, command, platforms) => platforms.re
|
|
|
21971
22147
|
var expoExecutable = async (project) => {
|
|
21972
22148
|
const executable = join13(project, "node_modules", ".bin", "expo");
|
|
21973
22149
|
try {
|
|
21974
|
-
await
|
|
22150
|
+
await access12(executable);
|
|
21975
22151
|
return executable;
|
|
21976
22152
|
} catch {
|
|
21977
22153
|
throw new TypeError("Expo dependencies are not installed in the generated shell. Run `absolute mobile init --yes`.");
|
|
@@ -22206,7 +22382,7 @@ var sync = async (args) => {
|
|
|
22206
22382
|
};
|
|
22207
22383
|
var associations = async (args) => {
|
|
22208
22384
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
22209
|
-
const outputDirectory =
|
|
22385
|
+
const outputDirectory = resolve12(projectRoot, valueAfter(args, "--outdir") ?? ".absolutejs/mobile/associations");
|
|
22210
22386
|
if (args.includes("--verify")) {
|
|
22211
22387
|
const result2 = await verifyAbsoluteMobileAssociationFiles(mobile);
|
|
22212
22388
|
console.log(`Verified ${result2.results.length} hosted association files`);
|
|
@@ -22258,7 +22434,7 @@ var generateGithubCi = async (args) => {
|
|
|
22258
22434
|
const publicResult = {
|
|
22259
22435
|
changed: result.changed,
|
|
22260
22436
|
format: result.format,
|
|
22261
|
-
path:
|
|
22437
|
+
path: relative11(projectRoot, result.path).replaceAll("\\", "/"),
|
|
22262
22438
|
platforms: result.platforms,
|
|
22263
22439
|
publishing: result.publishing,
|
|
22264
22440
|
requiredSecrets: result.requiredSecrets
|
|
@@ -22370,7 +22546,7 @@ var prepareExpoMobileUpdateExport = async (options) => {
|
|
|
22370
22546
|
};
|
|
22371
22547
|
await ensureExpoPackages(mobile.nativeProjectDirectory, options.args);
|
|
22372
22548
|
const temporaryParent = join13(options.projectRoot, ".absolutejs", "mobile", "expo-update-exports");
|
|
22373
|
-
await
|
|
22549
|
+
await mkdir12(temporaryParent, { recursive: true });
|
|
22374
22550
|
const temporaryDirectory = await mkdtemp3(join13(temporaryParent, ".stage-"));
|
|
22375
22551
|
try {
|
|
22376
22552
|
await runExpo(mobile.nativeProjectDirectory, [
|
|
@@ -22430,9 +22606,9 @@ var buildMobileUpdate = async (args) => {
|
|
|
22430
22606
|
const runtimeFingerprint = isRecord6(embedded) ? embedded.nativeRuntime : undefined;
|
|
22431
22607
|
if (typeof runtimeFingerprint !== "string" || !/^[a-f0-9]{64}$/u.test(runtimeFingerprint))
|
|
22432
22608
|
throw new TypeError("Prepared mobile bundle is missing its native runtime fingerprint.");
|
|
22433
|
-
const privateKey = await readFile16(
|
|
22609
|
+
const privateKey = await readFile16(resolve12(projectRoot, signingKeyPath));
|
|
22434
22610
|
const configuredPublicKey = Buffer.from(mobile.updates.publicKeys[keyId], "base64");
|
|
22435
|
-
const derivedPublicKey =
|
|
22611
|
+
const derivedPublicKey = createPublicKey2(privateKey).export({
|
|
22436
22612
|
format: "der",
|
|
22437
22613
|
type: "spki"
|
|
22438
22614
|
});
|
|
@@ -22493,7 +22669,7 @@ var generateExpoUpdateSigning = async (args) => {
|
|
|
22493
22669
|
...valueAfter(args, "--public-key") ? { publicKeyPath: valueAfter(args, "--public-key") } : {},
|
|
22494
22670
|
...validityYears === undefined ? {} : { validityYears }
|
|
22495
22671
|
});
|
|
22496
|
-
const certificatePath =
|
|
22672
|
+
const certificatePath = relative11(projectRoot, result.certificatePath).replaceAll("\\", "/");
|
|
22497
22673
|
sendTelemetryEvent("mobile:update-code-signing-generated", {
|
|
22498
22674
|
engine: "expo",
|
|
22499
22675
|
validityYears: validityYears ?? 10
|
|
@@ -22516,13 +22692,56 @@ var updateRollout = (args, fallback) => {
|
|
|
22516
22692
|
return rollout;
|
|
22517
22693
|
};
|
|
22518
22694
|
var mobileUpdatePublisher = async (args) => {
|
|
22519
|
-
const { projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
22520
|
-
|
|
22695
|
+
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
22696
|
+
if (!mobile.updates || !mobile.updateServer)
|
|
22697
|
+
throw new TypeError("Mobile updates are not configured.");
|
|
22698
|
+
const modulePath = valueAfter(args, "--registry") ?? mobile.updateServer.registryModule;
|
|
22521
22699
|
return {
|
|
22522
22700
|
projectRoot,
|
|
22523
22701
|
publisher: await loadAbsoluteMobileUpdatePublisher(projectRoot, modulePath)
|
|
22524
22702
|
};
|
|
22525
22703
|
};
|
|
22704
|
+
var provisionMobileUpdate = async (args) => {
|
|
22705
|
+
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
22706
|
+
if (!mobile.updates || !mobile.updateServer)
|
|
22707
|
+
throw new TypeError("mobile update provision requires mobile.updates.publicKeys in absolute.config.ts.");
|
|
22708
|
+
const requestedStorage = valueAfter(args, "--storage") ?? "local";
|
|
22709
|
+
if (requestedStorage !== "local" && requestedStorage !== "s3")
|
|
22710
|
+
throw new TypeError("--storage must be local or s3.");
|
|
22711
|
+
const modulePath = valueAfter(args, "--registry") ?? mobile.updateServer.registryModule;
|
|
22712
|
+
const packages = [
|
|
22713
|
+
"@absolutejs/deploy@0.25.5",
|
|
22714
|
+
"@absolutejs/blob@0.5.2",
|
|
22715
|
+
...requestedStorage === "s3" ? [
|
|
22716
|
+
"@aws-sdk/client-s3@3.1095.0",
|
|
22717
|
+
"@aws-sdk/lib-storage@3.1095.0",
|
|
22718
|
+
"@aws-sdk/s3-request-presigner@3.1095.0"
|
|
22719
|
+
] : []
|
|
22720
|
+
];
|
|
22721
|
+
const installed = await directProjectPackages(projectRoot);
|
|
22722
|
+
const missing = packages.filter((spec) => !installed.has(packageNameFromSpec(spec)));
|
|
22723
|
+
await installApprovedPackages(projectRoot, args, `Mobile update serving needs ${missing.map(packageNameFromSpec).join(", ")}. Install them now?`, missing);
|
|
22724
|
+
const path = await writeAbsoluteMobileUpdateRegistry({
|
|
22725
|
+
force: args.includes("--force"),
|
|
22726
|
+
modulePath,
|
|
22727
|
+
projectRoot,
|
|
22728
|
+
publicKeys: mobile.updates.publicKeys,
|
|
22729
|
+
storage: requestedStorage
|
|
22730
|
+
});
|
|
22731
|
+
console.log(`Provisioned ${requestedStorage === "local" ? "local development" : "durable S3-compatible"} mobile update storage in ${relative11(projectRoot, path).replaceAll("\\", "/")}.`);
|
|
22732
|
+
if (requestedStorage === "local")
|
|
22733
|
+
console.log("Production release checks will require durable storage. Re-run with --storage s3 --force before deploying.");
|
|
22734
|
+
else
|
|
22735
|
+
console.log("Set ABSOLUTE_MOBILE_UPDATE_S3_BUCKET and standard AWS credentials on the trusted server; endpoint and region overrides are optional.");
|
|
22736
|
+
const expoSigning = mobile.updates.expoCodeSigning;
|
|
22737
|
+
if (expoSigning) {
|
|
22738
|
+
const signingKey = mobile.updateServer.expoCodeSigningKeys[expoSigning.keyId];
|
|
22739
|
+
if (!signingKey)
|
|
22740
|
+
throw new TypeError("The active Expo server signing key is missing.");
|
|
22741
|
+
console.log(`Set ${signingKey.privateKeyEnv} only on the trusted server.`);
|
|
22742
|
+
}
|
|
22743
|
+
return path;
|
|
22744
|
+
};
|
|
22526
22745
|
var publishMobileUpdate = async (args) => {
|
|
22527
22746
|
const releaseDirectory = args.find((value, index) => {
|
|
22528
22747
|
if (value.startsWith("-"))
|
|
@@ -23144,7 +23363,7 @@ var requireAndroidTestPort = (args, projectRoot) => {
|
|
|
23144
23363
|
}
|
|
23145
23364
|
return { https: args.includes("--https"), port };
|
|
23146
23365
|
}
|
|
23147
|
-
const instances = listLiveInstances().filter((instance2) =>
|
|
23366
|
+
const instances = listLiveInstances().filter((instance2) => resolve12(instance2.cwd) === resolve12(projectRoot) && instance2.source === "dev" && instance2.port !== null);
|
|
23148
23367
|
if (instances.length !== 1) {
|
|
23149
23368
|
throw new TypeError(instances.length === 0 ? "No running AbsoluteJS dev server was found for this project. Start `bun dev`, wait for Android to report ready, then run `absolute mobile test android`." : "Multiple dev servers are running for this project. Select one with mobile test android --port <port>.");
|
|
23150
23369
|
}
|
|
@@ -23191,8 +23410,8 @@ var selectAndroidSerial = (adb, explicitSerial) => {
|
|
|
23191
23410
|
return selected;
|
|
23192
23411
|
};
|
|
23193
23412
|
var safeArtifactRoot = (projectRoot, value) => {
|
|
23194
|
-
const root =
|
|
23195
|
-
if (root !== projectRoot && !root.startsWith(`${
|
|
23413
|
+
const root = resolve12(projectRoot, value ?? ".absolutejs/mobile/test-artifacts");
|
|
23414
|
+
if (root !== projectRoot && !root.startsWith(`${resolve12(projectRoot)}/`)) {
|
|
23196
23415
|
throw new TypeError("mobile test --artifacts must remain inside the project.");
|
|
23197
23416
|
}
|
|
23198
23417
|
return root;
|
|
@@ -23220,7 +23439,7 @@ var waitForRequestedAndroidHmr = async (args, session, checks, timeoutMs) => {
|
|
|
23220
23439
|
});
|
|
23221
23440
|
};
|
|
23222
23441
|
var writeAndroidFailureArtifacts = async (options) => {
|
|
23223
|
-
await
|
|
23442
|
+
await mkdir12(options.artifactRoot, { recursive: true });
|
|
23224
23443
|
const screenshot = options.session ? await options.session.screenshot(join13(options.artifactRoot, "android-failure.png")).catch(() => {
|
|
23225
23444
|
return;
|
|
23226
23445
|
}) : undefined;
|
|
@@ -23359,14 +23578,14 @@ var requireIosTestContext = (args, projectRoot) => {
|
|
|
23359
23578
|
const port = Number(explicit);
|
|
23360
23579
|
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
23361
23580
|
throw new TypeError("mobile test --port must be a valid TCP port.");
|
|
23362
|
-
const instance2 = listLiveInstances().find((candidate) =>
|
|
23581
|
+
const instance2 = listLiveInstances().find((candidate) => resolve12(candidate.cwd) === resolve12(projectRoot) && candidate.source === "dev" && candidate.port === port);
|
|
23363
23582
|
return {
|
|
23364
23583
|
https: instance2?.https ?? args.includes("--https"),
|
|
23365
23584
|
instance: instance2,
|
|
23366
23585
|
port
|
|
23367
23586
|
};
|
|
23368
23587
|
}
|
|
23369
|
-
const instances = listLiveInstances().filter((instance2) =>
|
|
23588
|
+
const instances = listLiveInstances().filter((instance2) => resolve12(instance2.cwd) === resolve12(projectRoot) && instance2.source === "dev" && instance2.port !== null);
|
|
23370
23589
|
if (instances.length !== 1)
|
|
23371
23590
|
throw new TypeError(instances.length === 0 ? "No running AbsoluteJS dev server was found for this project. Start `bun dev`, wait for iOS to report ready, then run `absolute mobile test ios`." : "Multiple dev servers are running for this project. Select one with mobile test ios --port <port>.");
|
|
23372
23591
|
const [instance] = instances;
|
|
@@ -23489,7 +23708,7 @@ var requireCapturedCommand = (command, label) => {
|
|
|
23489
23708
|
return result;
|
|
23490
23709
|
};
|
|
23491
23710
|
var writeIosFailureArtifacts = async (options) => {
|
|
23492
|
-
await
|
|
23711
|
+
await mkdir12(options.artifactRoot, { recursive: true });
|
|
23493
23712
|
const screenshot = join13(options.artifactRoot, "ios-failure.png");
|
|
23494
23713
|
const screenshotResult = captureCommand2([
|
|
23495
23714
|
options.xcrun,
|
|
@@ -23527,8 +23746,8 @@ var nativeReportRoot = (args, projectRoot, platform2) => {
|
|
|
23527
23746
|
var absolutejsVersionForReport = async () => {
|
|
23528
23747
|
let absolutejsVersion = process.env.ABSOLUTE_VERSION ?? "unknown";
|
|
23529
23748
|
const versions = await Promise.all([
|
|
23530
|
-
|
|
23531
|
-
|
|
23749
|
+
resolve12(import.meta.dir, "..", "..", "package.json"),
|
|
23750
|
+
resolve12(import.meta.dir, "..", "..", "..", "package.json")
|
|
23532
23751
|
].map((candidate) => readPackageVersionForIosReport(candidate).catch(() => "unknown")));
|
|
23533
23752
|
for (const version of versions) {
|
|
23534
23753
|
if (version === "unknown")
|
|
@@ -23752,7 +23971,7 @@ var testIos = async (args) => {
|
|
|
23752
23971
|
mobile.appId
|
|
23753
23972
|
], "iOS app launch");
|
|
23754
23973
|
await waitForIosHmrClient({ https, port, timeoutMs });
|
|
23755
|
-
await
|
|
23974
|
+
await mkdir12(artifactRoot, { recursive: true });
|
|
23756
23975
|
const screenshot = join13(artifactRoot, "ios-simulator.png");
|
|
23757
23976
|
requireCapturedCommand([xcrun, "simctl", "io", simulator.udid, "screenshot", screenshot], "iOS simulator screenshot");
|
|
23758
23977
|
const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
|
|
@@ -23895,6 +24114,10 @@ var runMobile = async (args) => {
|
|
|
23895
24114
|
await buildMobileUpdate(args.slice(2));
|
|
23896
24115
|
return;
|
|
23897
24116
|
}
|
|
24117
|
+
if (command === "update" && args[1] === "provision") {
|
|
24118
|
+
await provisionMobileUpdate(args.slice(2));
|
|
24119
|
+
return;
|
|
24120
|
+
}
|
|
23898
24121
|
if (command === "update" && args[1] === "signing" && args[2] === "generate") {
|
|
23899
24122
|
await generateExpoUpdateSigning(args.slice(3));
|
|
23900
24123
|
return;
|
|
@@ -23919,7 +24142,7 @@ var runMobile = async (args) => {
|
|
|
23919
24142
|
await publishIos(args.slice(2));
|
|
23920
24143
|
return;
|
|
23921
24144
|
}
|
|
23922
|
-
throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [inspect [name] [--json] | clean [name] --yes | --json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | inspect [--json] [--require-bundle] | associations [--outdir dir] [--verify] | ci github [server-entry] [--publish] [--registry module] [--secret-env NAME] [--output path] [--force] [--json] | doctor [ios|android|release [ios|android]] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--remote name] [--outdir dir] [--web-outdir dir] [--unsigned] | update signing generate --private-key path [--certificate path] [--public-key path] [--key-id id] [--common-name name] [--validity-years n] | update build [server-entry] --classification bug-fix|content|security --key-id id --signing-key path --within-submitted-purpose [--outdir dir] [--web-outdir dir] | update publish <release-directory> [--rollout fraction] [--registry module] | update promote --release id --rollout fraction [--registry module] | update rollback [--release id] [--registry module] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--remote name] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--device identifier [--remote name] | --udid id] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--artifacts dir] [--json]> [--config path]");
|
|
24145
|
+
throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [inspect [name] [--json] | clean [name] --yes | --json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | inspect [--json] [--require-bundle] | associations [--outdir dir] [--verify] | ci github [server-entry] [--publish] [--registry module] [--secret-env NAME] [--output path] [--force] [--json] | doctor [ios|android|release [ios|android]] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--remote name] [--outdir dir] [--web-outdir dir] [--unsigned] | update provision [--storage local|s3] [--registry module] [--force] [--yes] | update signing generate --private-key path [--certificate path] [--public-key path] [--key-id id] [--common-name name] [--validity-years n] | update build [server-entry] --classification bug-fix|content|security --key-id id --signing-key path --within-submitted-purpose [--outdir dir] [--web-outdir dir] | update publish <release-directory> [--rollout fraction] [--registry module] | update promote --release id --rollout fraction [--registry module] | update rollback [--release id] [--registry module] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--remote name] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--device identifier [--remote name] | --udid id] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--artifacts dir] [--json]> [--config path]");
|
|
23923
24146
|
};
|
|
23924
24147
|
export {
|
|
23925
24148
|
runMobile
|