@absolutejs/absolute 0.20.0-beta.37 → 0.20.0-beta.39
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/README.md +20 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +1193 -282
- package/dist/mobile/index.js +594 -49
- package/dist/mobile/index.js.map +8 -7
- package/dist/mobile/remoteMacAgentEntry.js +6 -6
- package/dist/src/mobile/androidRelease.d.ts +6 -0
- package/dist/src/mobile/ciWorkflow.d.ts +26 -0
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/iosRelease.d.ts +1 -0
- package/dist/src/mobile/mobileBundleInspection.d.ts +55 -0
- package/dist/src/mobile/mobileInspect.d.ts +42 -16
- package/dist/src/mobile/releaseDoctor.d.ts +23 -1
- package/package.json +1 -1
package/dist/mobile/index.js
CHANGED
|
@@ -860,12 +860,12 @@ var init_deviceCapabilities = __esm(() => {
|
|
|
860
860
|
});
|
|
861
861
|
|
|
862
862
|
// src/cli/scripts/telemetry.ts
|
|
863
|
-
import { existsSync as
|
|
863
|
+
import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync5, writeFileSync } from "fs";
|
|
864
864
|
import { homedir as homedir3 } from "os";
|
|
865
865
|
import { join as join15 } from "path";
|
|
866
866
|
var configDir, configPath, getTelemetryConfig = () => {
|
|
867
867
|
try {
|
|
868
|
-
if (!
|
|
868
|
+
if (!existsSync4(configPath))
|
|
869
869
|
return null;
|
|
870
870
|
const raw = readFileSync5(configPath, "utf-8");
|
|
871
871
|
const config = JSON.parse(raw);
|
|
@@ -880,11 +880,11 @@ var init_telemetry = __esm(() => {
|
|
|
880
880
|
});
|
|
881
881
|
|
|
882
882
|
// src/cli/telemetryEvent.ts
|
|
883
|
-
import { existsSync as
|
|
883
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6 } from "fs";
|
|
884
884
|
import { arch, platform } from "os";
|
|
885
|
-
import { dirname as
|
|
885
|
+
import { dirname as dirname11, join as join16, parse } from "path";
|
|
886
886
|
var checkCandidate = (candidate) => {
|
|
887
|
-
if (!
|
|
887
|
+
if (!existsSync5(candidate)) {
|
|
888
888
|
return null;
|
|
889
889
|
}
|
|
890
890
|
const pkg = JSON.parse(readFileSync6(candidate, "utf-8"));
|
|
@@ -907,7 +907,7 @@ var checkCandidate = (candidate) => {
|
|
|
907
907
|
if (version) {
|
|
908
908
|
return version;
|
|
909
909
|
}
|
|
910
|
-
dir =
|
|
910
|
+
dir = dirname11(dir);
|
|
911
911
|
}
|
|
912
912
|
return "unknown";
|
|
913
913
|
}, sendTelemetryEvent = (event, payload) => {
|
|
@@ -2032,6 +2032,21 @@ var verifyAabSignature = (artifactPath, capture, jarsigner) => {
|
|
|
2032
2032
|
]);
|
|
2033
2033
|
return result.exitCode === 0 && /jar verified/iu.test(result.stdout);
|
|
2034
2034
|
};
|
|
2035
|
+
var signAab = (artifactPath, capture, jarsigner, signing) => {
|
|
2036
|
+
const result = capture([
|
|
2037
|
+
jarsigner,
|
|
2038
|
+
"-keystore",
|
|
2039
|
+
signing.keystorePath,
|
|
2040
|
+
"-storepass:env",
|
|
2041
|
+
signing.storePasswordEnvironment,
|
|
2042
|
+
"-keypass:env",
|
|
2043
|
+
signing.keyPasswordEnvironment,
|
|
2044
|
+
artifactPath,
|
|
2045
|
+
signing.keyAlias
|
|
2046
|
+
]);
|
|
2047
|
+
if (result.exitCode !== 0)
|
|
2048
|
+
throw new TypeError("jarsigner could not sign the Android App Bundle with the configured CI identity.");
|
|
2049
|
+
};
|
|
2035
2050
|
var sha256File = async (path) => createHash4("sha256").update(await readFile4(path)).digest("hex");
|
|
2036
2051
|
var safeOutputDirectory = (projectRoot, requested) => {
|
|
2037
2052
|
const root = resolve3(projectRoot);
|
|
@@ -2126,7 +2141,16 @@ var buildAbsoluteAndroidRelease = async (options) => {
|
|
|
2126
2141
|
throw new TypeError(`Android Gradle did not produce the expected App Bundle: ${artifactPath}`);
|
|
2127
2142
|
}
|
|
2128
2143
|
const capture = options.capture ?? defaultCapture;
|
|
2129
|
-
const
|
|
2144
|
+
const jarsigner = options.jarsigner === undefined ? Bun.which("jarsigner") : options.jarsigner;
|
|
2145
|
+
let signed = verifyAabSignature(artifactPath, capture, jarsigner);
|
|
2146
|
+
if (signed === false && options.signing) {
|
|
2147
|
+
if (!jarsigner)
|
|
2148
|
+
throw new TypeError("Could not sign the Android App Bundle because jarsigner is unavailable.");
|
|
2149
|
+
signAab(artifactPath, capture, jarsigner, options.signing);
|
|
2150
|
+
signed = verifyAabSignature(artifactPath, capture, jarsigner);
|
|
2151
|
+
if (!signed)
|
|
2152
|
+
throw new TypeError("Android App Bundle signature verification failed after CI signing.");
|
|
2153
|
+
}
|
|
2130
2154
|
if (signed === null && !options.allowUnsigned) {
|
|
2131
2155
|
throw new TypeError("Could not verify the Android App Bundle signature because jarsigner is unavailable. Install a JDK, or use --unsigned only for a non-publishable build.");
|
|
2132
2156
|
}
|
|
@@ -2256,6 +2280,14 @@ import {
|
|
|
2256
2280
|
} from "fs/promises";
|
|
2257
2281
|
import { dirname as dirname3, isAbsolute as isAbsolute3, join as join5, relative as relative4, resolve as resolve4, sep as sep3 } from "path";
|
|
2258
2282
|
var ABSOLUTE_IOS_RELEASE_FORMAT = 1;
|
|
2283
|
+
var developmentTeamArgument = (value) => {
|
|
2284
|
+
if (value === undefined)
|
|
2285
|
+
return;
|
|
2286
|
+
const team = value.trim().toUpperCase();
|
|
2287
|
+
if (!/^[A-Z0-9]{10}$/u.test(team))
|
|
2288
|
+
throw new TypeError("iOS development team must contain ten letters or digits.");
|
|
2289
|
+
return `DEVELOPMENT_TEAM=${team}`;
|
|
2290
|
+
};
|
|
2259
2291
|
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2260
2292
|
var requireManifest2 = (value) => {
|
|
2261
2293
|
if (!isRecord2(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
|
|
@@ -2448,8 +2480,10 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
2448
2480
|
await writeFile5(exportPlist, exportOptions());
|
|
2449
2481
|
const run = options.run ?? defaultRun;
|
|
2450
2482
|
try {
|
|
2483
|
+
const developmentTeam = developmentTeamArgument(options.developmentTeam);
|
|
2451
2484
|
const versionArguments = [
|
|
2452
2485
|
`MARKETING_VERSION=${marketingVersion}`,
|
|
2486
|
+
...developmentTeam ? [developmentTeam] : [],
|
|
2453
2487
|
...buildNumber === undefined ? [] : [`CURRENT_PROJECT_VERSION=${buildNumber}`]
|
|
2454
2488
|
];
|
|
2455
2489
|
const archiveExit = await run([
|
|
@@ -5427,12 +5461,26 @@ var shellPushModule = () => {
|
|
|
5427
5461
|
throw new TypeError("AbsoluteJS mobile push shell module is missing.");
|
|
5428
5462
|
};
|
|
5429
5463
|
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
5430
|
-
var
|
|
5464
|
+
var contentSecurityPolicy = (productionOrigin) => {
|
|
5465
|
+
const backend = new URL(productionOrigin);
|
|
5466
|
+
const socketOrigin = `${backend.protocol === "https:" ? "wss:" : "ws:"}//${backend.host}`;
|
|
5467
|
+
return [
|
|
5468
|
+
"default-src 'self' data: blob: https:",
|
|
5469
|
+
"base-uri 'none'",
|
|
5470
|
+
"object-src 'none'",
|
|
5471
|
+
"script-src 'self'",
|
|
5472
|
+
"style-src 'self' 'unsafe-inline'",
|
|
5473
|
+
`connect-src 'self' ${backend.origin} ${socketOrigin}`,
|
|
5474
|
+
"form-action 'none'"
|
|
5475
|
+
].join("; ");
|
|
5476
|
+
};
|
|
5477
|
+
var indexHtml = (appName, productionOrigin) => `<!doctype html>
|
|
5431
5478
|
<html>
|
|
5432
5479
|
<head>
|
|
5433
5480
|
<meta charset="utf-8">
|
|
5434
5481
|
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
|
5435
5482
|
<meta name="color-scheme" content="light dark">
|
|
5483
|
+
<meta http-equiv="Content-Security-Policy" content="${escapeHtml(contentSecurityPolicy(productionOrigin))}">
|
|
5436
5484
|
<title>${escapeHtml(appName)}</title>
|
|
5437
5485
|
</head>
|
|
5438
5486
|
<body>
|
|
@@ -5663,7 +5711,7 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
5663
5711
|
await Promise.all([
|
|
5664
5712
|
writeFile10(join9(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
5665
5713
|
`),
|
|
5666
|
-
writeFile10(join9(staging, INDEX_FILE), indexHtml(options.config.appName)),
|
|
5714
|
+
writeFile10(join9(staging, INDEX_FILE), indexHtml(options.config.appName, options.config.productionOrigin)),
|
|
5667
5715
|
buildShellBootstrap(staging, options.auth !== undefined, options.auth !== undefined && options.sync === true, `absolutejs.${options.auth?.clientId ?? options.config.appId}.`, options.deviceCapabilities, options.projectRoot)
|
|
5668
5716
|
]);
|
|
5669
5717
|
await installBundle(staging, destination);
|
|
@@ -6126,6 +6174,500 @@ var installAbsoluteMobileSyncRemediation = (bridge = {
|
|
|
6126
6174
|
// src/mobile/index.ts
|
|
6127
6175
|
init_deviceCapabilities();
|
|
6128
6176
|
|
|
6177
|
+
// src/mobile/ciWorkflow.ts
|
|
6178
|
+
import { existsSync as existsSync3 } from "fs";
|
|
6179
|
+
import { access as access9, mkdir as mkdir11, readFile as readFile15, writeFile as writeFile12 } from "fs/promises";
|
|
6180
|
+
import { dirname as dirname10, extname as extname4, relative as relative10, resolve as resolve13, sep as sep6 } from "path";
|
|
6181
|
+
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1;
|
|
6182
|
+
var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
|
|
6183
|
+
var CI_ENV_INDENTATION = 6;
|
|
6184
|
+
var RESERVED_SECRET_NAMES = new Set([
|
|
6185
|
+
"ABSOLUTE_ANDROID_KEYSTORE_BASE64",
|
|
6186
|
+
"ABSOLUTE_ANDROID_KEYSTORE_PASSWORD",
|
|
6187
|
+
"ABSOLUTE_ANDROID_KEY_ALIAS",
|
|
6188
|
+
"ABSOLUTE_ANDROID_KEY_PASSWORD",
|
|
6189
|
+
"ABSOLUTE_GOOGLE_CREDENTIALS_BASE64",
|
|
6190
|
+
"ABSOLUTE_IOS_CERTIFICATE_BASE64",
|
|
6191
|
+
"ABSOLUTE_IOS_CERTIFICATE_PASSWORD",
|
|
6192
|
+
"ABSOLUTE_IOS_PROVISIONING_PROFILE_BASE64",
|
|
6193
|
+
"ABSOLUTE_IOS_KEYCHAIN_PASSWORD",
|
|
6194
|
+
"ABSOLUTE_IOS_DEVELOPMENT_TEAM",
|
|
6195
|
+
"APP_STORE_CONNECT_ISSUER_ID",
|
|
6196
|
+
"APP_STORE_CONNECT_KEY_ID",
|
|
6197
|
+
"APP_STORE_CONNECT_PRIVATE_KEY_BASE64"
|
|
6198
|
+
]);
|
|
6199
|
+
var exists3 = async (path) => {
|
|
6200
|
+
try {
|
|
6201
|
+
await access9(path);
|
|
6202
|
+
return true;
|
|
6203
|
+
} catch {
|
|
6204
|
+
return false;
|
|
6205
|
+
}
|
|
6206
|
+
};
|
|
6207
|
+
var yamlString = (value) => `'${value.replaceAll("'", "''")}'`;
|
|
6208
|
+
var projectPath = (projectRoot, value, field2, options = {}) => {
|
|
6209
|
+
const root = resolve13(projectRoot);
|
|
6210
|
+
const path = resolve13(root, value);
|
|
6211
|
+
const portable = relative10(root, path).replaceAll("\\", "/");
|
|
6212
|
+
if (portable === ".." || portable.startsWith(`..${sep6}`) || portable.startsWith("../") || portable === "") {
|
|
6213
|
+
throw new TypeError(`${field2} must remain inside the project root.`);
|
|
6214
|
+
}
|
|
6215
|
+
if (/\r|\n/u.test(portable) || portable.startsWith("-"))
|
|
6216
|
+
throw new TypeError(`${field2} contains an unsafe path.`);
|
|
6217
|
+
if (!options.allowMissing && !existsSync3(path))
|
|
6218
|
+
throw new TypeError(`${field2} does not exist inside the project.`);
|
|
6219
|
+
return portable;
|
|
6220
|
+
};
|
|
6221
|
+
var workflowOutputPath = (projectRoot, value) => {
|
|
6222
|
+
const root = resolve13(projectRoot);
|
|
6223
|
+
const workflows = resolve13(root, ".github/workflows");
|
|
6224
|
+
const path = resolve13(root, value ?? ".github/workflows/absolute-mobile.yml");
|
|
6225
|
+
const portable = relative10(workflows, path);
|
|
6226
|
+
if (portable === ".." || portable.startsWith(`..${sep6}`) || extname4(path) !== ".yml" && extname4(path) !== ".yaml") {
|
|
6227
|
+
throw new TypeError("mobile ci github --output must be a .yml or .yaml file inside .github/workflows.");
|
|
6228
|
+
}
|
|
6229
|
+
return path;
|
|
6230
|
+
};
|
|
6231
|
+
var normalizeSecretEnvironment = (values = []) => {
|
|
6232
|
+
const names = [...new Set(values)].sort();
|
|
6233
|
+
for (const name of names) {
|
|
6234
|
+
if (!SECRET_NAME_PATTERN.test(name))
|
|
6235
|
+
throw new TypeError("mobile ci github --secret-env values must be uppercase environment variable names.");
|
|
6236
|
+
if (name.startsWith("GITHUB_") || name.startsWith("RUNNER_") || name.startsWith("ACTIONS_") || RESERVED_SECRET_NAMES.has(name)) {
|
|
6237
|
+
throw new TypeError(`mobile ci github --secret-env cannot replace reserved variable ${name}.`);
|
|
6238
|
+
}
|
|
6239
|
+
}
|
|
6240
|
+
return names;
|
|
6241
|
+
};
|
|
6242
|
+
var customSecretEnvironment = (names, indentation = CI_ENV_INDENTATION) => names.map((name) => `${" ".repeat(indentation)}${name}: \${{ secrets.${name} }}`).join(`
|
|
6243
|
+
`);
|
|
6244
|
+
var commandEnvironment = (options) => ` ABSOLUTE_CONFIG_PATH: ${yamlString(options.configPath ?? "")}
|
|
6245
|
+
ABSOLUTE_REGISTRY_MODULE: ${yamlString(options.registryModule)}
|
|
6246
|
+
ABSOLUTE_SERVER_ENTRY: ${yamlString(options.serverEntry)}`;
|
|
6247
|
+
var appendConfigArgument = `if [[ -n "$ABSOLUTE_CONFIG_PATH" ]]; then
|
|
6248
|
+
args+=(--config "$ABSOLUTE_CONFIG_PATH")
|
|
6249
|
+
fi`;
|
|
6250
|
+
var installSteps = ` - name: Check out source
|
|
6251
|
+
uses: actions/checkout@v6
|
|
6252
|
+
- name: Install Bun
|
|
6253
|
+
uses: oven-sh/setup-bun@v2
|
|
6254
|
+
- name: Install exact dependencies
|
|
6255
|
+
run: bun ci`;
|
|
6256
|
+
var bundleAuditSteps = ` - name: Prepare production mobile bundle
|
|
6257
|
+
shell: bash
|
|
6258
|
+
run: |
|
|
6259
|
+
args=(bunx absolute prepare "$ABSOLUTE_SERVER_ENTRY" --outdir .absolutejs/mobile-ci/server)
|
|
6260
|
+
${appendConfigArgument}
|
|
6261
|
+
"\${args[@]}"
|
|
6262
|
+
- name: Run cryptographic mobile bundle audit
|
|
6263
|
+
id: mobile-bundle-audit
|
|
6264
|
+
continue-on-error: true
|
|
6265
|
+
shell: bash
|
|
6266
|
+
run: |
|
|
6267
|
+
mkdir -p .absolutejs/mobile-ci
|
|
6268
|
+
args=(bunx absolute mobile inspect --json --require-bundle)
|
|
6269
|
+
${appendConfigArgument}
|
|
6270
|
+
"\${args[@]}" > .absolutejs/mobile-ci/inspection.json
|
|
6271
|
+
- name: Upload mobile inspection report
|
|
6272
|
+
if: always()
|
|
6273
|
+
uses: actions/upload-artifact@v7
|
|
6274
|
+
with:
|
|
6275
|
+
name: absolute-mobile-inspection
|
|
6276
|
+
path: .absolutejs/mobile-ci/inspection.json
|
|
6277
|
+
if-no-files-found: error
|
|
6278
|
+
retention-days: 30
|
|
6279
|
+
include-hidden-files: true
|
|
6280
|
+
- name: Enforce mobile bundle audit
|
|
6281
|
+
if: steps.mobile-bundle-audit.outcome != 'success'
|
|
6282
|
+
run: exit 1`;
|
|
6283
|
+
var releaseAuditSteps = (platform) => ` - name: Run redacted mobile release audit
|
|
6284
|
+
id: mobile-release-audit
|
|
6285
|
+
continue-on-error: true
|
|
6286
|
+
shell: bash
|
|
6287
|
+
run: |
|
|
6288
|
+
mkdir -p .absolutejs/mobile-ci
|
|
6289
|
+
args=(bunx absolute mobile doctor release ${platform} --json)
|
|
6290
|
+
${appendConfigArgument}
|
|
6291
|
+
"\${args[@]}" > .absolutejs/mobile-ci/compliance.json
|
|
6292
|
+
- name: Upload mobile compliance report
|
|
6293
|
+
if: always()
|
|
6294
|
+
uses: actions/upload-artifact@v7
|
|
6295
|
+
with:
|
|
6296
|
+
name: absolute-mobile-compliance-\${{ github.job }}
|
|
6297
|
+
path: .absolutejs/mobile-ci/compliance.json
|
|
6298
|
+
if-no-files-found: error
|
|
6299
|
+
retention-days: 30
|
|
6300
|
+
include-hidden-files: true
|
|
6301
|
+
- name: Enforce mobile release audit
|
|
6302
|
+
if: steps.mobile-release-audit.outcome != 'success'
|
|
6303
|
+
run: exit 1`;
|
|
6304
|
+
var platformInput = (platforms) => {
|
|
6305
|
+
const choices = platforms.length === 2 ? ["all", ...platforms] : platforms;
|
|
6306
|
+
return ` platform:
|
|
6307
|
+
description: Native platform to build
|
|
6308
|
+
required: true
|
|
6309
|
+
type: choice
|
|
6310
|
+
default: ${choices[0]}
|
|
6311
|
+
options:
|
|
6312
|
+
${choices.map((value) => ` - ${value}`).join(`
|
|
6313
|
+
`)}`;
|
|
6314
|
+
};
|
|
6315
|
+
var publishingInputs = (platforms, includePublishing) => {
|
|
6316
|
+
if (!includePublishing)
|
|
6317
|
+
return "";
|
|
6318
|
+
const fields = [
|
|
6319
|
+
` publish:
|
|
6320
|
+
description: Publish through mobile.release.ts after the signed build
|
|
6321
|
+
required: true
|
|
6322
|
+
type: boolean
|
|
6323
|
+
default: false`,
|
|
6324
|
+
` channel:
|
|
6325
|
+
description: Optional AbsoluteJS immutable release channel
|
|
6326
|
+
required: false
|
|
6327
|
+
type: string`
|
|
6328
|
+
];
|
|
6329
|
+
if (platforms.includes("android"))
|
|
6330
|
+
fields.push(` play_track:
|
|
6331
|
+
description: Optional Google Play track
|
|
6332
|
+
required: true
|
|
6333
|
+
type: choice
|
|
6334
|
+
default: registry-only
|
|
6335
|
+
options:
|
|
6336
|
+
- registry-only
|
|
6337
|
+
- internal
|
|
6338
|
+
- alpha
|
|
6339
|
+
- beta
|
|
6340
|
+
- production`);
|
|
6341
|
+
if (platforms.includes("ios")) {
|
|
6342
|
+
fields.push(` testflight_group:
|
|
6343
|
+
description: Optional internal or external TestFlight group
|
|
6344
|
+
required: false
|
|
6345
|
+
type: string`);
|
|
6346
|
+
fields.push(` submit_testflight_review:
|
|
6347
|
+
description: Explicitly submit an external TestFlight build for review
|
|
6348
|
+
required: true
|
|
6349
|
+
type: boolean
|
|
6350
|
+
default: false`);
|
|
6351
|
+
}
|
|
6352
|
+
return `
|
|
6353
|
+
${fields.join(`
|
|
6354
|
+
`)}`;
|
|
6355
|
+
};
|
|
6356
|
+
var jobCondition = (platform) => `github.event_name == 'workflow_dispatch' && (inputs.platform == 'all' || inputs.platform == '${platform}')`;
|
|
6357
|
+
var androidJob = (options) => {
|
|
6358
|
+
const custom = customSecretEnvironment(options.customSecrets);
|
|
6359
|
+
const publishEnvironment = options.includePublishing ? `
|
|
6360
|
+
ABSOLUTE_PUBLISH: \${{ inputs.publish }}
|
|
6361
|
+
ABSOLUTE_RELEASE_CHANNEL: \${{ inputs.channel }}
|
|
6362
|
+
ABSOLUTE_PLAY_TRACK: \${{ inputs.play_track }}
|
|
6363
|
+
ABSOLUTE_GOOGLE_CREDENTIALS_BASE64: \${{ secrets.ABSOLUTE_GOOGLE_CREDENTIALS_BASE64 }}
|
|
6364
|
+
GOOGLE_APPLICATION_CREDENTIALS: \${{ runner.temp }}/absolute-google-credentials.json` : "";
|
|
6365
|
+
const publishCommand = options.includePublishing ? `if [[ "$ABSOLUTE_PUBLISH" == "true" ]]; then
|
|
6366
|
+
args=(bunx absolute mobile publish android "$ABSOLUTE_SERVER_ENTRY" --registry "$ABSOLUTE_REGISTRY_MODULE")
|
|
6367
|
+
if [[ -n "$ABSOLUTE_RELEASE_CHANNEL" ]]; then
|
|
6368
|
+
args+=(--channel "$ABSOLUTE_RELEASE_CHANNEL")
|
|
6369
|
+
fi
|
|
6370
|
+
if [[ "$ABSOLUTE_PLAY_TRACK" != "registry-only" ]]; then
|
|
6371
|
+
args+=(--play-track "$ABSOLUTE_PLAY_TRACK")
|
|
6372
|
+
fi
|
|
6373
|
+
else
|
|
6374
|
+
args=(bunx absolute mobile build android "$ABSOLUTE_SERVER_ENTRY")
|
|
6375
|
+
fi` : `args=(bunx absolute mobile build android "$ABSOLUTE_SERVER_ENTRY")`;
|
|
6376
|
+
const googleSetup = options.includePublishing ? `
|
|
6377
|
+
if [[ "$ABSOLUTE_PUBLISH" == "true" && "$ABSOLUTE_PLAY_TRACK" != "registry-only" ]]; then
|
|
6378
|
+
if [[ -z "$ABSOLUTE_GOOGLE_CREDENTIALS_BASE64" ]]; then
|
|
6379
|
+
echo "ABSOLUTE_GOOGLE_CREDENTIALS_BASE64 is required for Google Play publication." >&2
|
|
6380
|
+
exit 1
|
|
6381
|
+
fi
|
|
6382
|
+
printf '%s' "$ABSOLUTE_GOOGLE_CREDENTIALS_BASE64" | base64 --decode > "$GOOGLE_APPLICATION_CREDENTIALS"
|
|
6383
|
+
chmod 600 "$GOOGLE_APPLICATION_CREDENTIALS"
|
|
6384
|
+
fi` : "";
|
|
6385
|
+
return `
|
|
6386
|
+
android:
|
|
6387
|
+
name: Signed Android release
|
|
6388
|
+
needs: validate
|
|
6389
|
+
if: \${{ ${jobCondition("android")} }}
|
|
6390
|
+
runs-on: ubuntu-latest
|
|
6391
|
+
environment: absolute-mobile-release
|
|
6392
|
+
permissions:
|
|
6393
|
+
contents: read
|
|
6394
|
+
id-token: write
|
|
6395
|
+
attestations: write
|
|
6396
|
+
env:
|
|
6397
|
+
ABSOLUTE_ANDROID_KEYSTORE_BASE64: \${{ secrets.ABSOLUTE_ANDROID_KEYSTORE_BASE64 }}
|
|
6398
|
+
ABSOLUTE_ANDROID_KEYSTORE_PASSWORD: \${{ secrets.ABSOLUTE_ANDROID_KEYSTORE_PASSWORD }}
|
|
6399
|
+
ABSOLUTE_ANDROID_KEY_ALIAS: \${{ secrets.ABSOLUTE_ANDROID_KEY_ALIAS }}
|
|
6400
|
+
ABSOLUTE_ANDROID_KEY_PASSWORD: \${{ secrets.ABSOLUTE_ANDROID_KEY_PASSWORD }}
|
|
6401
|
+
ABSOLUTE_ANDROID_KEYSTORE_PATH: \${{ runner.temp }}/absolute-release.jks${publishEnvironment}${custom ? `
|
|
6402
|
+
${custom}` : ""}
|
|
6403
|
+
${commandEnvironment({ configPath: undefined, registryModule: "", serverEntry: "" })}
|
|
6404
|
+
steps:
|
|
6405
|
+
${installSteps}
|
|
6406
|
+
- name: Provision Android signing
|
|
6407
|
+
shell: bash
|
|
6408
|
+
run: |
|
|
6409
|
+
required=(
|
|
6410
|
+
ABSOLUTE_ANDROID_KEYSTORE_BASE64
|
|
6411
|
+
ABSOLUTE_ANDROID_KEYSTORE_PASSWORD
|
|
6412
|
+
ABSOLUTE_ANDROID_KEY_ALIAS
|
|
6413
|
+
ABSOLUTE_ANDROID_KEY_PASSWORD
|
|
6414
|
+
)
|
|
6415
|
+
for name in "\${required[@]}"; do
|
|
6416
|
+
if [[ -z "\${!name}" ]]; then
|
|
6417
|
+
echo "$name is required in the absolute-mobile-release environment." >&2
|
|
6418
|
+
exit 1
|
|
6419
|
+
fi
|
|
6420
|
+
done
|
|
6421
|
+
printf '%s' "$ABSOLUTE_ANDROID_KEYSTORE_BASE64" | base64 --decode > "\${{ runner.temp }}/absolute-release.jks"
|
|
6422
|
+
chmod 600 "\${{ runner.temp }}/absolute-release.jks"${googleSetup}
|
|
6423
|
+
- name: Build or publish Android
|
|
6424
|
+
shell: bash
|
|
6425
|
+
run: |
|
|
6426
|
+
${publishCommand}
|
|
6427
|
+
${appendConfigArgument}
|
|
6428
|
+
"\${args[@]}"
|
|
6429
|
+
${releaseAuditSteps("android")}
|
|
6430
|
+
- name: Attest Android App Bundle
|
|
6431
|
+
if: inputs.attest
|
|
6432
|
+
uses: actions/attest@v4
|
|
6433
|
+
with:
|
|
6434
|
+
subject-path: .absolutejs/mobile/releases/android/**/app-release.aab
|
|
6435
|
+
- name: Upload Android release
|
|
6436
|
+
uses: actions/upload-artifact@v7
|
|
6437
|
+
with:
|
|
6438
|
+
name: absolute-mobile-android
|
|
6439
|
+
path: .absolutejs/mobile/releases/android/
|
|
6440
|
+
if-no-files-found: error
|
|
6441
|
+
retention-days: 14
|
|
6442
|
+
include-hidden-files: true
|
|
6443
|
+
- name: Remove Android credentials
|
|
6444
|
+
if: always()
|
|
6445
|
+
shell: bash
|
|
6446
|
+
run: |
|
|
6447
|
+
rm -f "\${{ runner.temp }}/absolute-release.jks"
|
|
6448
|
+
rm -f "\${{ runner.temp }}/absolute-google-credentials.json"`;
|
|
6449
|
+
};
|
|
6450
|
+
var iosJob = (options) => {
|
|
6451
|
+
const custom = customSecretEnvironment(options.customSecrets);
|
|
6452
|
+
const publishEnvironment = options.includePublishing ? `
|
|
6453
|
+
ABSOLUTE_PUBLISH: \${{ inputs.publish }}
|
|
6454
|
+
ABSOLUTE_RELEASE_CHANNEL: \${{ inputs.channel }}
|
|
6455
|
+
ABSOLUTE_TESTFLIGHT_GROUP: \${{ inputs.testflight_group }}
|
|
6456
|
+
ABSOLUTE_TESTFLIGHT_SUBMIT_REVIEW: \${{ inputs.submit_testflight_review }}
|
|
6457
|
+
APP_STORE_CONNECT_ISSUER_ID: \${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
|
|
6458
|
+
APP_STORE_CONNECT_KEY_ID: \${{ secrets.APP_STORE_CONNECT_KEY_ID }}
|
|
6459
|
+
APP_STORE_CONNECT_PRIVATE_KEY_BASE64: \${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY_BASE64 }}
|
|
6460
|
+
APP_STORE_CONNECT_PRIVATE_KEY_PATH: \${{ runner.temp }}/AuthKey_AbsoluteJS.p8` : "";
|
|
6461
|
+
const publishCommand = options.includePublishing ? `if [[ "$ABSOLUTE_PUBLISH" == "true" ]]; then
|
|
6462
|
+
args=(bunx absolute mobile publish ios "$ABSOLUTE_SERVER_ENTRY" --registry "$ABSOLUTE_REGISTRY_MODULE")
|
|
6463
|
+
if [[ -n "$ABSOLUTE_RELEASE_CHANNEL" ]]; then
|
|
6464
|
+
args+=(--channel "$ABSOLUTE_RELEASE_CHANNEL")
|
|
6465
|
+
fi
|
|
6466
|
+
if [[ -n "$ABSOLUTE_TESTFLIGHT_GROUP" ]]; then
|
|
6467
|
+
args+=(--testflight-group "$ABSOLUTE_TESTFLIGHT_GROUP")
|
|
6468
|
+
fi
|
|
6469
|
+
if [[ "$ABSOLUTE_TESTFLIGHT_SUBMIT_REVIEW" == "true" ]]; then
|
|
6470
|
+
args+=(--testflight-submit-review)
|
|
6471
|
+
fi
|
|
6472
|
+
else
|
|
6473
|
+
args=(bunx absolute mobile build ios "$ABSOLUTE_SERVER_ENTRY")
|
|
6474
|
+
fi` : `args=(bunx absolute mobile build ios "$ABSOLUTE_SERVER_ENTRY")`;
|
|
6475
|
+
const appStoreSetup = options.includePublishing ? `
|
|
6476
|
+
if [[ "$ABSOLUTE_PUBLISH" == "true" && -n "$ABSOLUTE_TESTFLIGHT_GROUP" ]]; then
|
|
6477
|
+
required+=(APP_STORE_CONNECT_ISSUER_ID APP_STORE_CONNECT_KEY_ID APP_STORE_CONNECT_PRIVATE_KEY_BASE64)
|
|
6478
|
+
fi` : "";
|
|
6479
|
+
const appStoreDecode = options.includePublishing ? `
|
|
6480
|
+
if [[ "$ABSOLUTE_PUBLISH" == "true" && -n "$ABSOLUTE_TESTFLIGHT_GROUP" ]]; then
|
|
6481
|
+
printf '%s' "$APP_STORE_CONNECT_PRIVATE_KEY_BASE64" | base64 --decode > "$APP_STORE_CONNECT_PRIVATE_KEY_PATH"
|
|
6482
|
+
chmod 600 "$APP_STORE_CONNECT_PRIVATE_KEY_PATH"
|
|
6483
|
+
fi` : "";
|
|
6484
|
+
return `
|
|
6485
|
+
ios:
|
|
6486
|
+
name: Signed iOS release
|
|
6487
|
+
needs: validate
|
|
6488
|
+
if: \${{ ${jobCondition("ios")} }}
|
|
6489
|
+
runs-on: macos-latest
|
|
6490
|
+
environment: absolute-mobile-release
|
|
6491
|
+
permissions:
|
|
6492
|
+
contents: read
|
|
6493
|
+
id-token: write
|
|
6494
|
+
attestations: write
|
|
6495
|
+
env:
|
|
6496
|
+
ABSOLUTE_IOS_CERTIFICATE_BASE64: \${{ secrets.ABSOLUTE_IOS_CERTIFICATE_BASE64 }}
|
|
6497
|
+
ABSOLUTE_IOS_CERTIFICATE_PASSWORD: \${{ secrets.ABSOLUTE_IOS_CERTIFICATE_PASSWORD }}
|
|
6498
|
+
ABSOLUTE_IOS_PROVISIONING_PROFILE_BASE64: \${{ secrets.ABSOLUTE_IOS_PROVISIONING_PROFILE_BASE64 }}
|
|
6499
|
+
ABSOLUTE_IOS_KEYCHAIN_PASSWORD: \${{ secrets.ABSOLUTE_IOS_KEYCHAIN_PASSWORD }}${publishEnvironment}${custom ? `
|
|
6500
|
+
${custom}` : ""}
|
|
6501
|
+
ABSOLUTE_IOS_DEVELOPMENT_TEAM: \${{ secrets.ABSOLUTE_IOS_DEVELOPMENT_TEAM }}
|
|
6502
|
+
${commandEnvironment({ configPath: undefined, registryModule: "", serverEntry: "" })}
|
|
6503
|
+
steps:
|
|
6504
|
+
${installSteps}
|
|
6505
|
+
- name: Provision iOS signing
|
|
6506
|
+
shell: bash
|
|
6507
|
+
run: |
|
|
6508
|
+
required=(
|
|
6509
|
+
ABSOLUTE_IOS_CERTIFICATE_BASE64
|
|
6510
|
+
ABSOLUTE_IOS_CERTIFICATE_PASSWORD
|
|
6511
|
+
ABSOLUTE_IOS_PROVISIONING_PROFILE_BASE64
|
|
6512
|
+
ABSOLUTE_IOS_KEYCHAIN_PASSWORD
|
|
6513
|
+
ABSOLUTE_IOS_DEVELOPMENT_TEAM
|
|
6514
|
+
)${appStoreSetup}
|
|
6515
|
+
for name in "\${required[@]}"; do
|
|
6516
|
+
if [[ -z "\${!name}" ]]; then
|
|
6517
|
+
echo "$name is required in the absolute-mobile-release environment." >&2
|
|
6518
|
+
exit 1
|
|
6519
|
+
fi
|
|
6520
|
+
done
|
|
6521
|
+
CERTIFICATE_PATH="\${{ runner.temp }}/absolute-signing.p12"
|
|
6522
|
+
PROFILE_PATH="\${{ runner.temp }}/absolute.mobileprovision"
|
|
6523
|
+
KEYCHAIN_PATH="\${{ runner.temp }}/absolute-signing.keychain-db"
|
|
6524
|
+
PROFILE_DESTINATION="$HOME/Library/MobileDevice/Provisioning Profiles/absolute.mobileprovision"
|
|
6525
|
+
printf '%s' "$ABSOLUTE_IOS_CERTIFICATE_BASE64" | base64 --decode > "$CERTIFICATE_PATH"
|
|
6526
|
+
printf '%s' "$ABSOLUTE_IOS_PROVISIONING_PROFILE_BASE64" | base64 --decode > "$PROFILE_PATH"
|
|
6527
|
+
security create-keychain -p "$ABSOLUTE_IOS_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
6528
|
+
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
|
|
6529
|
+
security unlock-keychain -p "$ABSOLUTE_IOS_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
6530
|
+
security import "$CERTIFICATE_PATH" -P "$ABSOLUTE_IOS_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
|
|
6531
|
+
security set-key-partition-list -S apple-tool:,apple: -k "$ABSOLUTE_IOS_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
6532
|
+
security list-keychain -d user -s "$KEYCHAIN_PATH"
|
|
6533
|
+
mkdir -p "$(dirname "$PROFILE_DESTINATION")"
|
|
6534
|
+
cp "$PROFILE_PATH" "$PROFILE_DESTINATION"${appStoreDecode}
|
|
6535
|
+
- name: Build or publish iOS
|
|
6536
|
+
shell: bash
|
|
6537
|
+
run: |
|
|
6538
|
+
${publishCommand}
|
|
6539
|
+
${appendConfigArgument}
|
|
6540
|
+
"\${args[@]}"
|
|
6541
|
+
${releaseAuditSteps("ios")}
|
|
6542
|
+
- name: Attest iOS IPA
|
|
6543
|
+
if: inputs.attest
|
|
6544
|
+
uses: actions/attest@v4
|
|
6545
|
+
with:
|
|
6546
|
+
subject-path: .absolutejs/mobile/releases/ios/**/App.ipa
|
|
6547
|
+
- name: Upload iOS release
|
|
6548
|
+
uses: actions/upload-artifact@v7
|
|
6549
|
+
with:
|
|
6550
|
+
name: absolute-mobile-ios
|
|
6551
|
+
path: .absolutejs/mobile/releases/ios/
|
|
6552
|
+
if-no-files-found: error
|
|
6553
|
+
retention-days: 14
|
|
6554
|
+
include-hidden-files: true
|
|
6555
|
+
- name: Remove iOS credentials
|
|
6556
|
+
if: always()
|
|
6557
|
+
shell: bash
|
|
6558
|
+
run: |
|
|
6559
|
+
security delete-keychain "\${{ runner.temp }}/absolute-signing.keychain-db" 2>/dev/null || true
|
|
6560
|
+
rm -f "$HOME/Library/MobileDevice/Provisioning Profiles/absolute.mobileprovision"
|
|
6561
|
+
rm -f "\${{ runner.temp }}/absolute-signing.p12"
|
|
6562
|
+
rm -f "\${{ runner.temp }}/absolute.mobileprovision"
|
|
6563
|
+
rm -f "\${{ runner.temp }}/AuthKey_AbsoluteJS.p8"`;
|
|
6564
|
+
};
|
|
6565
|
+
var requiredSecrets = (platforms, includePublishing, custom) => [
|
|
6566
|
+
...platforms.includes("android") ? [
|
|
6567
|
+
"ABSOLUTE_ANDROID_KEYSTORE_BASE64",
|
|
6568
|
+
"ABSOLUTE_ANDROID_KEYSTORE_PASSWORD",
|
|
6569
|
+
"ABSOLUTE_ANDROID_KEY_ALIAS",
|
|
6570
|
+
"ABSOLUTE_ANDROID_KEY_PASSWORD",
|
|
6571
|
+
...includePublishing ? ["ABSOLUTE_GOOGLE_CREDENTIALS_BASE64"] : []
|
|
6572
|
+
] : [],
|
|
6573
|
+
...platforms.includes("ios") ? [
|
|
6574
|
+
"ABSOLUTE_IOS_CERTIFICATE_BASE64",
|
|
6575
|
+
"ABSOLUTE_IOS_CERTIFICATE_PASSWORD",
|
|
6576
|
+
"ABSOLUTE_IOS_PROVISIONING_PROFILE_BASE64",
|
|
6577
|
+
"ABSOLUTE_IOS_KEYCHAIN_PASSWORD",
|
|
6578
|
+
"ABSOLUTE_IOS_DEVELOPMENT_TEAM",
|
|
6579
|
+
...includePublishing ? [
|
|
6580
|
+
"APP_STORE_CONNECT_ISSUER_ID",
|
|
6581
|
+
"APP_STORE_CONNECT_KEY_ID",
|
|
6582
|
+
"APP_STORE_CONNECT_PRIVATE_KEY_BASE64"
|
|
6583
|
+
] : []
|
|
6584
|
+
] : [],
|
|
6585
|
+
...custom
|
|
6586
|
+
];
|
|
6587
|
+
var createAbsoluteMobileGithubWorkflow = (options) => {
|
|
6588
|
+
const platforms = [
|
|
6589
|
+
...options.config.platforms
|
|
6590
|
+
].sort();
|
|
6591
|
+
const includePublishing = options.includePublishing === true;
|
|
6592
|
+
const customSecrets = normalizeSecretEnvironment(options.secretEnvironment);
|
|
6593
|
+
const serverEntry = projectPath(options.projectRoot, options.serverEntry ?? "server.ts", "mobile ci github server entry");
|
|
6594
|
+
const configPath = options.configPath ? projectPath(options.projectRoot, options.configPath, "mobile ci github --config") : undefined;
|
|
6595
|
+
const registryModule = projectPath(options.projectRoot, options.registryModule ?? "mobile.release.ts", "mobile ci github --registry", { allowMissing: !includePublishing });
|
|
6596
|
+
const environment = commandEnvironment({
|
|
6597
|
+
configPath,
|
|
6598
|
+
registryModule,
|
|
6599
|
+
serverEntry
|
|
6600
|
+
});
|
|
6601
|
+
let workflow = `# Generated by AbsoluteJS. Regenerate with: absolute mobile ci github${includePublishing ? " --publish" : ""}
|
|
6602
|
+
name: AbsoluteJS Mobile
|
|
6603
|
+
|
|
6604
|
+
on:
|
|
6605
|
+
pull_request:
|
|
6606
|
+
workflow_dispatch:
|
|
6607
|
+
inputs:
|
|
6608
|
+
${platformInput(platforms)}
|
|
6609
|
+
attest:
|
|
6610
|
+
description: Generate GitHub artifact provenance attestations
|
|
6611
|
+
required: true
|
|
6612
|
+
type: boolean
|
|
6613
|
+
default: false${publishingInputs(platforms, includePublishing)}
|
|
6614
|
+
|
|
6615
|
+
concurrency:
|
|
6616
|
+
group: absolute-mobile-\${{ github.repository }}
|
|
6617
|
+
cancel-in-progress: false
|
|
6618
|
+
|
|
6619
|
+
jobs:
|
|
6620
|
+
validate:
|
|
6621
|
+
name: Validate mobile release inputs
|
|
6622
|
+
runs-on: ubuntu-latest
|
|
6623
|
+
permissions:
|
|
6624
|
+
contents: read
|
|
6625
|
+
env:
|
|
6626
|
+
${environment}
|
|
6627
|
+
steps:
|
|
6628
|
+
${installSteps}
|
|
6629
|
+
${bundleAuditSteps}${platforms.includes("android") ? androidJob({ customSecrets, includePublishing }) : ""}${platforms.includes("ios") ? iosJob({ customSecrets, includePublishing }) : ""}
|
|
6630
|
+
`;
|
|
6631
|
+
const replacements = new Map([
|
|
6632
|
+
[
|
|
6633
|
+
"ABSOLUTE_CONFIG_PATH: ''",
|
|
6634
|
+
`ABSOLUTE_CONFIG_PATH: ${yamlString(configPath ?? "")}`
|
|
6635
|
+
],
|
|
6636
|
+
[
|
|
6637
|
+
"ABSOLUTE_REGISTRY_MODULE: ''",
|
|
6638
|
+
`ABSOLUTE_REGISTRY_MODULE: ${yamlString(registryModule)}`
|
|
6639
|
+
],
|
|
6640
|
+
[
|
|
6641
|
+
"ABSOLUTE_SERVER_ENTRY: ''",
|
|
6642
|
+
`ABSOLUTE_SERVER_ENTRY: ${yamlString(serverEntry)}`
|
|
6643
|
+
]
|
|
6644
|
+
]);
|
|
6645
|
+
for (const [placeholder, replacement] of replacements)
|
|
6646
|
+
workflow = workflow.replaceAll(placeholder, replacement);
|
|
6647
|
+
return {
|
|
6648
|
+
requiredSecrets: requiredSecrets(platforms, includePublishing, customSecrets),
|
|
6649
|
+
workflow
|
|
6650
|
+
};
|
|
6651
|
+
};
|
|
6652
|
+
var writeAbsoluteMobileGithubWorkflow = async (options) => {
|
|
6653
|
+
const path = workflowOutputPath(options.projectRoot, options.outputPath);
|
|
6654
|
+
const generated = createAbsoluteMobileGithubWorkflow(options);
|
|
6655
|
+
const previous = await exists3(path) ? await readFile15(path, "utf8") : undefined;
|
|
6656
|
+
if (previous !== undefined && previous !== generated.workflow && !options.force)
|
|
6657
|
+
throw new TypeError(`${relative10(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
|
|
6658
|
+
if (previous !== generated.workflow) {
|
|
6659
|
+
await mkdir11(dirname10(path), { recursive: true });
|
|
6660
|
+
await writeFile12(path, generated.workflow);
|
|
6661
|
+
}
|
|
6662
|
+
return {
|
|
6663
|
+
changed: previous !== generated.workflow,
|
|
6664
|
+
format: ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT,
|
|
6665
|
+
path,
|
|
6666
|
+
platforms: [...options.config.platforms].sort(),
|
|
6667
|
+
publishing: options.includePublishing === true,
|
|
6668
|
+
requiredSecrets: generated.requiredSecrets
|
|
6669
|
+
};
|
|
6670
|
+
};
|
|
6129
6671
|
// src/mobile/compatibilityDispatcher.ts
|
|
6130
6672
|
import { Elysia as Elysia2 } from "elysia";
|
|
6131
6673
|
|
|
@@ -6342,7 +6884,7 @@ var createAbsoluteMobilePreviewPlugin = (mobile) => {
|
|
|
6342
6884
|
});
|
|
6343
6885
|
};
|
|
6344
6886
|
// src/mobile/nativeDeepLinks.ts
|
|
6345
|
-
import { readFile as
|
|
6887
|
+
import { readFile as readFile16, rename as rename11, writeFile as writeFile13 } from "fs/promises";
|
|
6346
6888
|
import { join as join17 } from "path";
|
|
6347
6889
|
var START_MARKER = "<!-- absolutejs:deep-links:start -->";
|
|
6348
6890
|
var END_MARKER = "<!-- absolutejs:deep-links:end -->";
|
|
@@ -6350,11 +6892,11 @@ var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
|
|
|
6350
6892
|
var NOT_FOUND = -1;
|
|
6351
6893
|
var escapeXml = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
6352
6894
|
var writeChangedFile = async (path, source) => {
|
|
6353
|
-
const current = await
|
|
6895
|
+
const current = await readFile16(path, "utf8");
|
|
6354
6896
|
if (current === source)
|
|
6355
6897
|
return false;
|
|
6356
6898
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
6357
|
-
await
|
|
6899
|
+
await writeFile13(temporary, source, { flag: "wx" });
|
|
6358
6900
|
await rename11(temporary, path);
|
|
6359
6901
|
return true;
|
|
6360
6902
|
};
|
|
@@ -6401,7 +6943,7 @@ ${hosts}
|
|
|
6401
6943
|
};
|
|
6402
6944
|
var configureAndroid = async (config) => {
|
|
6403
6945
|
const path = join17(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
6404
|
-
const source = await
|
|
6946
|
+
const source = await readFile16(path, "utf8");
|
|
6405
6947
|
const mainActivity = source.indexOf('android:name=".MainActivity"');
|
|
6406
6948
|
if (mainActivity === NOT_FOUND) {
|
|
6407
6949
|
throw new TypeError("Android MainActivity was not found.");
|
|
@@ -6427,7 +6969,7 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
|
|
|
6427
6969
|
`;
|
|
6428
6970
|
var configureIosInfo = async (config) => {
|
|
6429
6971
|
const path = join17(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
6430
|
-
const source = await
|
|
6972
|
+
const source = await readFile16(path, "utf8");
|
|
6431
6973
|
const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
|
|
6432
6974
|
${END_MARKER}
|
|
6433
6975
|
`;
|
|
@@ -6453,7 +6995,7 @@ var configureIosEntitlements = async (config) => {
|
|
|
6453
6995
|
const path = join17(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
6454
6996
|
let current = "";
|
|
6455
6997
|
try {
|
|
6456
|
-
current = await
|
|
6998
|
+
current = await readFile16(path, "utf8");
|
|
6457
6999
|
} catch (error) {
|
|
6458
7000
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
6459
7001
|
throw error;
|
|
@@ -6463,13 +7005,13 @@ var configureIosEntitlements = async (config) => {
|
|
|
6463
7005
|
if (current === source)
|
|
6464
7006
|
return false;
|
|
6465
7007
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
6466
|
-
await
|
|
7008
|
+
await writeFile13(temporary, source, { flag: "wx" });
|
|
6467
7009
|
await rename11(temporary, path);
|
|
6468
7010
|
return true;
|
|
6469
7011
|
};
|
|
6470
7012
|
var configureIosProject = async (config) => {
|
|
6471
7013
|
const path = join17(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
6472
|
-
const source = await
|
|
7014
|
+
const source = await readFile16(path, "utf8");
|
|
6473
7015
|
const declarations = [
|
|
6474
7016
|
...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
|
|
6475
7017
|
].map((match) => match[1]);
|
|
@@ -6508,7 +7050,7 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
|
|
|
6508
7050
|
};
|
|
6509
7051
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
6510
7052
|
init_deviceCapabilities();
|
|
6511
|
-
import { readFile as
|
|
7053
|
+
import { readFile as readFile17, rename as rename12, writeFile as writeFile14 } from "fs/promises";
|
|
6512
7054
|
import { join as join18 } from "path";
|
|
6513
7055
|
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
|
|
6514
7056
|
var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
|
|
@@ -6519,11 +7061,11 @@ var PUSH_START_MARKER = "absolutejs:push-notifications:start";
|
|
|
6519
7061
|
var PUSH_END_MARKER = "absolutejs:push-notifications:end";
|
|
6520
7062
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
6521
7063
|
var writeChangedFile2 = async (path, source) => {
|
|
6522
|
-
const current = await
|
|
7064
|
+
const current = await readFile17(path, "utf8");
|
|
6523
7065
|
if (current === source)
|
|
6524
7066
|
return false;
|
|
6525
7067
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
6526
|
-
await
|
|
7068
|
+
await writeFile14(temporary, source, { flag: "wx" });
|
|
6527
7069
|
await rename12(temporary, path);
|
|
6528
7070
|
return true;
|
|
6529
7071
|
};
|
|
@@ -6532,14 +7074,14 @@ var writeOptionalChangedFile = async (path, source) => {
|
|
|
6532
7074
|
if (current === source)
|
|
6533
7075
|
return false;
|
|
6534
7076
|
if (current === null) {
|
|
6535
|
-
await
|
|
7077
|
+
await writeFile14(path, source, { flag: "wx" });
|
|
6536
7078
|
return true;
|
|
6537
7079
|
}
|
|
6538
7080
|
return writeChangedFile2(path, source);
|
|
6539
7081
|
};
|
|
6540
7082
|
var optionalSource = async (path) => {
|
|
6541
7083
|
try {
|
|
6542
|
-
return await
|
|
7084
|
+
return await readFile17(path, "utf8");
|
|
6543
7085
|
} catch (error) {
|
|
6544
7086
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
6545
7087
|
return null;
|
|
@@ -6653,15 +7195,15 @@ var writeIosPrivacyManifest = async (path, current, source) => {
|
|
|
6653
7195
|
return false;
|
|
6654
7196
|
if (current !== null)
|
|
6655
7197
|
return writeChangedFile2(path, source);
|
|
6656
|
-
await
|
|
7198
|
+
await writeFile14(path, source, { flag: "wx" });
|
|
6657
7199
|
return true;
|
|
6658
7200
|
};
|
|
6659
7201
|
var configureIosPrivacyProject = async (config, requirements) => {
|
|
6660
7202
|
if (requirements.iosPrivacyAccessedApis.length === 0)
|
|
6661
7203
|
return false;
|
|
6662
|
-
const
|
|
6663
|
-
const project = await
|
|
6664
|
-
return writeChangedFile2(
|
|
7204
|
+
const projectPath2 = join18(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
7205
|
+
const project = await readFile17(projectPath2, "utf8");
|
|
7206
|
+
return writeChangedFile2(projectPath2, addIosPrivacyProjectReference(project));
|
|
6665
7207
|
};
|
|
6666
7208
|
var addIosPrivacyProjectReference = (source) => {
|
|
6667
7209
|
const fileMatch = source.match(/([A-F0-9]{24}) \/\* PrivacyInfo\.xcprivacy \*\/ = \{isa = PBXFileReference;/u);
|
|
@@ -6713,7 +7255,7 @@ ${next.slice(index)}`;
|
|
|
6713
7255
|
};
|
|
6714
7256
|
var configureIos2 = async (config, plan) => {
|
|
6715
7257
|
const path = join18(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
6716
|
-
const source = await
|
|
7258
|
+
const source = await readFile17(path, "utf8");
|
|
6717
7259
|
const requirements = absoluteDeviceNativeRequirements(plan);
|
|
6718
7260
|
const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
|
|
6719
7261
|
const ownedStart = source.indexOf(START_MARKER2);
|
|
@@ -6806,7 +7348,7 @@ var replacePushRegion = (source, region, insertion) => {
|
|
|
6806
7348
|
};
|
|
6807
7349
|
var configureAndroid2 = async (config, plan) => {
|
|
6808
7350
|
const path = join18(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
6809
|
-
const source = await
|
|
7351
|
+
const source = await readFile17(path, "utf8");
|
|
6810
7352
|
const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
|
|
6811
7353
|
const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
|
|
6812
7354
|
`);
|
|
@@ -6855,8 +7397,8 @@ var applyAbsoluteNativeDeviceCapabilities = async (projectRoot, config, platform
|
|
|
6855
7397
|
};
|
|
6856
7398
|
};
|
|
6857
7399
|
// src/mobile/releasePublisher.ts
|
|
6858
|
-
import { access as
|
|
6859
|
-
import { isAbsolute as isAbsolute6, relative as
|
|
7400
|
+
import { access as access10 } from "fs/promises";
|
|
7401
|
+
import { isAbsolute as isAbsolute6, relative as relative11, resolve as resolve14, sep as sep7 } from "path";
|
|
6860
7402
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6861
7403
|
var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
6862
7404
|
if (typeof publisher.prepareIosRelease !== "function") {
|
|
@@ -6882,17 +7424,17 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
|
|
|
6882
7424
|
var isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6883
7425
|
var isPublisher = (value) => isRecord9(value) && typeof value.publish === "function";
|
|
6884
7426
|
var publisherModulePath = (projectRoot, requested) => {
|
|
6885
|
-
const root =
|
|
6886
|
-
const path =
|
|
6887
|
-
const projectRelative =
|
|
6888
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
7427
|
+
const root = resolve14(projectRoot);
|
|
7428
|
+
const path = resolve14(root, requested);
|
|
7429
|
+
const projectRelative = relative11(root, path);
|
|
7430
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep7}`) || isAbsolute6(projectRelative)) {
|
|
6889
7431
|
throw new TypeError("mobile publish --registry must remain inside the project.");
|
|
6890
7432
|
}
|
|
6891
7433
|
return path;
|
|
6892
7434
|
};
|
|
6893
7435
|
var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
|
|
6894
7436
|
const modulePath = publisherModulePath(projectRoot, requestedModulePath);
|
|
6895
|
-
await
|
|
7437
|
+
await access10(modulePath).catch(() => {
|
|
6896
7438
|
throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
|
|
6897
7439
|
});
|
|
6898
7440
|
const loaded = await import(pathToFileURL3(modulePath).href);
|
|
@@ -6953,8 +7495,8 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
6953
7495
|
return publication;
|
|
6954
7496
|
};
|
|
6955
7497
|
// src/mobile/routeMetadataTransform.ts
|
|
6956
|
-
import { existsSync as
|
|
6957
|
-
import { dirname as
|
|
7498
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
|
|
7499
|
+
import { dirname as dirname12, extname as extname5, relative as relative12, resolve as resolve15 } from "path";
|
|
6958
7500
|
import ts2 from "typescript";
|
|
6959
7501
|
var ROUTE_METHODS = new Set(["get", "head"]);
|
|
6960
7502
|
var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
|
|
@@ -7005,7 +7547,7 @@ var PAGE_HANDLERS = new Map([
|
|
|
7005
7547
|
]
|
|
7006
7548
|
]);
|
|
7007
7549
|
var posixPath = (value) => value.replace(/\\/g, "/");
|
|
7008
|
-
var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(
|
|
7550
|
+
var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname12(entry), existsSync6, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync6, "tsconfig.json");
|
|
7009
7551
|
var createProgram = (entry, projectRoot) => {
|
|
7010
7552
|
const configPath2 = findTsconfig(entry, projectRoot);
|
|
7011
7553
|
if (!configPath2) {
|
|
@@ -7017,7 +7559,7 @@ var createProgram = (entry, projectRoot) => {
|
|
|
7017
7559
|
target: ts2.ScriptTarget.ESNext
|
|
7018
7560
|
});
|
|
7019
7561
|
}
|
|
7020
|
-
const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync7(path, "utf8")).config, ts2.sys,
|
|
7562
|
+
const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync7(path, "utf8")).config, ts2.sys, dirname12(configPath2));
|
|
7021
7563
|
if (!parsed.fileNames.includes(entry))
|
|
7022
7564
|
parsed.fileNames.push(entry);
|
|
7023
7565
|
return ts2.createProgram(parsed.fileNames, parsed.options);
|
|
@@ -7123,7 +7665,7 @@ var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
|
|
|
7123
7665
|
const declaration = symbol?.declarations?.[0];
|
|
7124
7666
|
const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
|
|
7125
7667
|
const exportedName = symbol?.name ?? expression.getText(sourceFile);
|
|
7126
|
-
const source = posixPath(
|
|
7668
|
+
const source = posixPath(relative12(projectRoot, file));
|
|
7127
7669
|
return `${source}#${exportedName}`;
|
|
7128
7670
|
};
|
|
7129
7671
|
var resolveAlias = (symbol, checker) => {
|
|
@@ -7362,7 +7904,7 @@ var analyzeProgram = (program, projectRoot) => {
|
|
|
7362
7904
|
const checker = program.getTypeChecker();
|
|
7363
7905
|
const analyzed = new Map;
|
|
7364
7906
|
for (const sourceFile of program.getSourceFiles()) {
|
|
7365
|
-
const resolvedFile =
|
|
7907
|
+
const resolvedFile = resolve15(sourceFile.fileName);
|
|
7366
7908
|
if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
|
|
7367
7909
|
continue;
|
|
7368
7910
|
const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
|
|
@@ -7455,31 +7997,31 @@ var transformFile = (source, fileName, analysis) => {
|
|
|
7455
7997
|
};
|
|
7456
7998
|
var ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL = ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION;
|
|
7457
7999
|
var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
7458
|
-
const projectRoot =
|
|
7459
|
-
const entry =
|
|
8000
|
+
const projectRoot = resolve15(options.projectRoot ?? process.cwd());
|
|
8001
|
+
const entry = resolve15(options.entry);
|
|
7460
8002
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
7461
8003
|
return {
|
|
7462
8004
|
name: "absolute-mobile-route-metadata",
|
|
7463
8005
|
setup(build) {
|
|
7464
8006
|
build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
|
|
7465
|
-
const analysis = analyzed.get(
|
|
8007
|
+
const analysis = analyzed.get(resolve15(path));
|
|
7466
8008
|
if (!analysis)
|
|
7467
8009
|
return;
|
|
7468
8010
|
const source = await Bun.file(path).text();
|
|
7469
8011
|
return {
|
|
7470
8012
|
contents: transformFile(source, path, analysis),
|
|
7471
|
-
loader:
|
|
8013
|
+
loader: extname5(path).endsWith("x") ? "tsx" : "ts"
|
|
7472
8014
|
};
|
|
7473
8015
|
});
|
|
7474
8016
|
}
|
|
7475
8017
|
};
|
|
7476
8018
|
};
|
|
7477
8019
|
var inspectAbsoluteMobileRouteMetadata = (options) => {
|
|
7478
|
-
const projectRoot =
|
|
7479
|
-
const entry =
|
|
8020
|
+
const projectRoot = resolve15(options.projectRoot ?? process.cwd());
|
|
8021
|
+
const entry = resolve15(options.entry);
|
|
7480
8022
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
7481
8023
|
return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
|
|
7482
|
-
file: posixPath(
|
|
8024
|
+
file: posixPath(relative12(projectRoot, file)),
|
|
7483
8025
|
metadata
|
|
7484
8026
|
})));
|
|
7485
8027
|
};
|
|
@@ -7687,6 +8229,7 @@ var http = createAbsoluteHttpClient();
|
|
|
7687
8229
|
// src/mobile/shellHttp.ts
|
|
7688
8230
|
var installAbsoluteMobileShellHttp = (origin, fetch2 = globalThis.fetch) => installAbsoluteHttpTransport(createAbsoluteHttpTransport({ fetch: fetch2, origin, runtime: "native" }));
|
|
7689
8231
|
export {
|
|
8232
|
+
writeAbsoluteMobileGithubWorkflow,
|
|
7690
8233
|
writeAbsoluteCapacitorConfig,
|
|
7691
8234
|
waitForAbsoluteIosHmrLog,
|
|
7692
8235
|
verifyAbsoluteMobileCompatibilityProducer,
|
|
@@ -7775,6 +8318,7 @@ export {
|
|
|
7775
8318
|
createAbsoluteMobilePageRequest,
|
|
7776
8319
|
createAbsoluteMobilePageErrorResponse,
|
|
7777
8320
|
createAbsoluteMobileInvalidRequestResponse,
|
|
8321
|
+
createAbsoluteMobileGithubWorkflow,
|
|
7778
8322
|
createAbsoluteMobileFileArtifactStore,
|
|
7779
8323
|
createAbsoluteMobileCompatibilityDispatcher,
|
|
7780
8324
|
createAbsoluteMobileCompatibilityArtifact,
|
|
@@ -7817,11 +8361,12 @@ export {
|
|
|
7817
8361
|
ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT,
|
|
7818
8362
|
ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT,
|
|
7819
8363
|
ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
|
|
8364
|
+
ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT,
|
|
7820
8365
|
ABSOLUTE_IOS_SIMULATOR_NAME,
|
|
7821
8366
|
ABSOLUTE_IOS_RELEASE_FORMAT,
|
|
7822
8367
|
ABSOLUTE_AUTH_PACKAGE,
|
|
7823
8368
|
ABSOLUTE_ANDROID_RELEASE_FORMAT
|
|
7824
8369
|
};
|
|
7825
8370
|
|
|
7826
|
-
//# debugId=
|
|
8371
|
+
//# debugId=1C9BEF9E4B461BFB64756E2164756E21
|
|
7827
8372
|
//# sourceMappingURL=index.js.map
|