@absolutejs/absolute 0.20.0-beta.80 → 0.20.0-beta.82
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 +1200 -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-hkxh2ab5.js} +390 -136
- package/dist/cli/{start-dtrp1pry.js → start-jbgfw27x.js} +3 -3
- package/dist/index.js +2073 -1095
- package/dist/index.js.map +7 -5
- package/dist/mobile/index.js +976 -4
- package/dist/mobile/index.js.map +7 -5
- package/dist/mobile/remoteMacAgentEntry.js +222 -222
- 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 +34 -0
- package/dist/types/build.d.ts +16 -0
- package/package.json +7 -2
package/dist/build.js
CHANGED
|
@@ -27618,10 +27618,14 @@ var DEFAULT_BATCH_SIZE = 12, DEFAULT_POLL_MS = 25, DEFAULT_MAX_PAUSE_MS = 2000,
|
|
|
27618
27618
|
};
|
|
27619
27619
|
|
|
27620
27620
|
// src/mobile/config.ts
|
|
27621
|
+
var exports_config = {};
|
|
27622
|
+
__export(exports_config, {
|
|
27623
|
+
normalizeAbsoluteMobileConfig: () => normalizeAbsoluteMobileConfig
|
|
27624
|
+
});
|
|
27621
27625
|
import { readFileSync as readFileSync35 } from "fs";
|
|
27622
27626
|
import { resolve as resolve44 } from "path";
|
|
27623
27627
|
import { createHash as createHash5, createPublicKey, X509Certificate } from "crypto";
|
|
27624
|
-
var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FINGERPRINT_PATTERN, UPDATE_NAME_PATTERN, UPDATE_PUBLIC_KEY_PATTERN, DEFAULT_UPDATE_BOOT_TIMEOUT_MS = 20000, MINIMUM_UPDATE_BOOT_TIMEOUT_MS = 5000, MAXIMUM_UPDATE_BOOT_TIMEOUT_MS = 120000, HOSTNAME_PATTERN, EXPO_RESERVED_ROUTE_PREFIXES, resolveProjectPath = (projectRoot, value, field) => {
|
|
27628
|
+
var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FINGERPRINT_PATTERN, UPDATE_NAME_PATTERN, UPDATE_PUBLIC_KEY_PATTERN, ENVIRONMENT_NAME_PATTERN, DEFAULT_UPDATE_BOOT_TIMEOUT_MS = 20000, MINIMUM_UPDATE_BOOT_TIMEOUT_MS = 5000, MAXIMUM_UPDATE_BOOT_TIMEOUT_MS = 120000, HOSTNAME_PATTERN, EXPO_RESERVED_ROUTE_PREFIXES, resolveProjectPath = (projectRoot, value, field) => {
|
|
27625
27629
|
const root = resolve44(projectRoot);
|
|
27626
27630
|
const path = resolve44(root, value);
|
|
27627
27631
|
if (path !== root && !path.startsWith(`${root}/`)) {
|
|
@@ -27806,6 +27810,48 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
|
|
|
27806
27810
|
publicKeys,
|
|
27807
27811
|
...expoCodeSigning ? { expoCodeSigning } : {}
|
|
27808
27812
|
};
|
|
27813
|
+
}, normalizeUpdateServer = (config, productionOrigin, projectRoot, updates) => {
|
|
27814
|
+
if (!updates || !config.updates)
|
|
27815
|
+
return;
|
|
27816
|
+
const registryModule = requireText(config.updates.server?.registry ?? "mobile.update.ts", "mobile.updates.server.registry");
|
|
27817
|
+
resolveProjectPath(projectRoot, registryModule, "mobile.updates.server.registry");
|
|
27818
|
+
const expoPrivateKeyEnv = requireText(config.updates.server?.expoPrivateKeyEnv ?? "ABSOLUTE_EXPO_UPDATE_PRIVATE_KEY", "mobile.updates.server.expoPrivateKeyEnv");
|
|
27819
|
+
if (!ENVIRONMENT_NAME_PATTERN.test(expoPrivateKeyEnv))
|
|
27820
|
+
throw new TypeError("mobile.updates.server.expoPrivateKeyEnv must be a valid environment variable name.");
|
|
27821
|
+
const autoMount = config.updates.server?.autoMount ?? true;
|
|
27822
|
+
if (autoMount) {
|
|
27823
|
+
const manifest = new URL(updates.manifestUrl);
|
|
27824
|
+
if (manifest.origin !== productionOrigin)
|
|
27825
|
+
throw new TypeError("mobile.updates.manifestUrl must use mobile.server.productionOrigin while mobile.updates.server.autoMount is enabled.");
|
|
27826
|
+
if (!manifest.pathname.endsWith("/update.json"))
|
|
27827
|
+
throw new TypeError("mobile.updates.manifestUrl must end in /update.json while mobile.updates.server.autoMount is enabled.");
|
|
27828
|
+
}
|
|
27829
|
+
const expoCodeSigningKeys = {};
|
|
27830
|
+
if (updates.expoCodeSigning)
|
|
27831
|
+
expoCodeSigningKeys[updates.expoCodeSigning.keyId] = {
|
|
27832
|
+
certificatePem: updates.expoCodeSigning.certificatePem,
|
|
27833
|
+
privateKeyEnv: expoPrivateKeyEnv
|
|
27834
|
+
};
|
|
27835
|
+
for (const [keyId, key] of Object.entries(config.updates.server?.expoCodeSigningKeys ?? {}).sort(([left], [right]) => left.localeCompare(right))) {
|
|
27836
|
+
if (!updates.expoCodeSigning)
|
|
27837
|
+
throw new TypeError("mobile.updates.server.expoCodeSigningKeys requires the Expo engine and expoCodeSigning.");
|
|
27838
|
+
if (!UPDATE_NAME_PATTERN.test(keyId))
|
|
27839
|
+
throw new TypeError("mobile.updates.server.expoCodeSigningKeys contains an invalid key ID.");
|
|
27840
|
+
if (expoCodeSigningKeys[keyId])
|
|
27841
|
+
throw new TypeError(`mobile.updates.server.expoCodeSigningKeys.${keyId} duplicates the active Expo key.`);
|
|
27842
|
+
const privateKeyEnv = requireText(key.privateKeyEnv, `mobile.updates.server.expoCodeSigningKeys.${keyId}.privateKeyEnv`);
|
|
27843
|
+
if (!ENVIRONMENT_NAME_PATTERN.test(privateKeyEnv))
|
|
27844
|
+
throw new TypeError(`mobile.updates.server.expoCodeSigningKeys.${keyId}.privateKeyEnv must be a valid environment variable name.`);
|
|
27845
|
+
const certificatePath = resolveProjectPath(projectRoot, requireText(key.certificatePath, `mobile.updates.server.expoCodeSigningKeys.${keyId}.certificatePath`), `mobile.updates.server.expoCodeSigningKeys.${keyId}.certificatePath`);
|
|
27846
|
+
const { certificate, certificatePem } = readExpoCodeSigningCertificate(certificatePath);
|
|
27847
|
+
if (certificate.publicKey.asymmetricKeyType !== "rsa" || certificate.issuer !== certificate.subject || !certificate.verify(certificate.publicKey))
|
|
27848
|
+
throw new TypeError(`mobile.updates.server.expoCodeSigningKeys.${keyId} certificate must be a self-signed RSA root.`);
|
|
27849
|
+
const now = Date.now();
|
|
27850
|
+
if (now < Date.parse(certificate.validFrom) || now > Date.parse(certificate.validTo))
|
|
27851
|
+
throw new TypeError(`mobile.updates.server.expoCodeSigningKeys.${keyId} certificate is not currently valid.`);
|
|
27852
|
+
expoCodeSigningKeys[keyId] = { certificatePem, privateKeyEnv };
|
|
27853
|
+
}
|
|
27854
|
+
return { autoMount, expoCodeSigningKeys, registryModule };
|
|
27809
27855
|
}, validateExpoNativeRouteSegment = (path, segment, index, count, parameters) => {
|
|
27810
27856
|
if (segment === "*" && (index !== count - 1 || count === 1)) {
|
|
27811
27857
|
throw new TypeError(`mobile.routes.native route ${path} must use * once, as the final segment after a static or parameterized prefix.`);
|
|
@@ -27865,6 +27911,7 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
|
|
|
27865
27911
|
throw new TypeError("mobile.deepLinks.scheme is not a valid URL scheme.");
|
|
27866
27912
|
}
|
|
27867
27913
|
const updates = normalizeUpdates(config, productionOrigin, projectRoot);
|
|
27914
|
+
const updateServer = normalizeUpdateServer(config, productionOrigin, projectRoot, updates);
|
|
27868
27915
|
const observability = normalizeObservability(config, productionOrigin);
|
|
27869
27916
|
return {
|
|
27870
27917
|
androidCertificateFingerprints: normalizeCertificateFingerprints(config.deepLinks?.android?.sha256CertificateFingerprints),
|
|
@@ -27884,7 +27931,8 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
|
|
|
27884
27931
|
platforms: normalizePlatforms(config.platforms),
|
|
27885
27932
|
productionOrigin,
|
|
27886
27933
|
pushAndroidGoogleServicesFile: resolveProjectPath(projectRoot, config.pushNotifications?.android?.googleServicesFile ?? "google-services.json", "mobile.pushNotifications.android.googleServicesFile"),
|
|
27887
|
-
...updates ? { updates } : {}
|
|
27934
|
+
...updates ? { updates } : {},
|
|
27935
|
+
...updateServer ? { updateServer } : {}
|
|
27888
27936
|
};
|
|
27889
27937
|
};
|
|
27890
27938
|
var init_config = __esm(() => {
|
|
@@ -27894,6 +27942,7 @@ var init_config = __esm(() => {
|
|
|
27894
27942
|
CERTIFICATE_FINGERPRINT_PATTERN = /^[0-9A-F]{64}$/;
|
|
27895
27943
|
UPDATE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
|
|
27896
27944
|
UPDATE_PUBLIC_KEY_PATTERN = /^[A-Za-z0-9+/]+={0,2}$/u;
|
|
27945
|
+
ENVIRONMENT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
27897
27946
|
HOSTNAME_PATTERN = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:\.(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?))*$/;
|
|
27898
27947
|
EXPO_RESERVED_ROUTE_PREFIXES = new Set([
|
|
27899
27948
|
"_expo",
|
|
@@ -28412,6 +28461,919 @@ var init_mobilePreviewClientBundle = __esm(() => {
|
|
|
28412
28461
|
init_rewriteImportsPlugin();
|
|
28413
28462
|
});
|
|
28414
28463
|
|
|
28464
|
+
// node_modules/@absolutejs/deploy/dist/mobileUpdate.js
|
|
28465
|
+
var exports_mobileUpdate = {};
|
|
28466
|
+
__export(exports_mobileUpdate, {
|
|
28467
|
+
MOBILE_UPDATE_REGISTRY_FORMAT: () => MOBILE_UPDATE_REGISTRY_FORMAT,
|
|
28468
|
+
MobileUpdateRegistryError: () => MobileUpdateRegistryError,
|
|
28469
|
+
createMobileUpdateHandler: () => createMobileUpdateHandler,
|
|
28470
|
+
createMobileUpdateRegistry: () => createMobileUpdateRegistry,
|
|
28471
|
+
parseMobileUpdateManifest: () => parseMobileUpdateManifest
|
|
28472
|
+
});
|
|
28473
|
+
import {
|
|
28474
|
+
createHash as createHash6,
|
|
28475
|
+
createPrivateKey,
|
|
28476
|
+
createPublicKey as createPublicKey2,
|
|
28477
|
+
sign,
|
|
28478
|
+
verify,
|
|
28479
|
+
X509Certificate as X509Certificate2
|
|
28480
|
+
} from "crypto";
|
|
28481
|
+
import { readFile as readFile9, stat as stat3 } from "fs/promises";
|
|
28482
|
+
import path from "path";
|
|
28483
|
+
var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updates", MAX_FILE_BYTES, MAX_TOTAL_BYTES, HASH, RELEASE, APP_ID, NAME, EXPO_DESCRIPTOR = "_absolute/expo-update.json", EXPO_CODE_SIGNING_ALGORITHM = "rsa-v1_5-sha256", MobileUpdateRegistryError, object3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), text2 = (value, field) => {
|
|
28484
|
+
if (typeof value !== "string" || value.length === 0)
|
|
28485
|
+
throw new MobileUpdateRegistryError(`Mobile update ${field} is invalid`);
|
|
28486
|
+
return value;
|
|
28487
|
+
}, iso = (value) => typeof value === "string" && Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value, safePath = (value) => {
|
|
28488
|
+
const file5 = text2(value, "file path").replaceAll("\\", "/");
|
|
28489
|
+
if (file5.startsWith("/") || file5.split("/").some((segment) => !segment || segment === "." || segment === ".."))
|
|
28490
|
+
throw new MobileUpdateRegistryError("Mobile update file path is invalid");
|
|
28491
|
+
return file5;
|
|
28492
|
+
}, expoAsset = (value) => {
|
|
28493
|
+
if (!object3(value))
|
|
28494
|
+
throw new MobileUpdateRegistryError("Expo update asset is invalid");
|
|
28495
|
+
const assetPath = safePath(value.path);
|
|
28496
|
+
if (value.extension !== undefined && (typeof value.extension !== "string" || !/^[A-Za-z0-9]+$/.test(value.extension)))
|
|
28497
|
+
throw new MobileUpdateRegistryError("Expo update asset extension is invalid");
|
|
28498
|
+
return {
|
|
28499
|
+
...typeof value.extension === "string" ? { extension: value.extension } : {},
|
|
28500
|
+
path: assetPath
|
|
28501
|
+
};
|
|
28502
|
+
}, parseExpoUpdateDescriptor = (bytes) => {
|
|
28503
|
+
let value;
|
|
28504
|
+
try {
|
|
28505
|
+
value = JSON.parse(new TextDecoder().decode(bytes));
|
|
28506
|
+
} catch {
|
|
28507
|
+
throw new MobileUpdateRegistryError("Expo update descriptor is invalid");
|
|
28508
|
+
}
|
|
28509
|
+
if (!object3(value) || value.engine !== "expo" || value.format !== 1 || !object3(value.expoConfig) || !object3(value.platforms) || typeof value.runtimeVersion !== "string" || !HASH.test(value.runtimeVersion))
|
|
28510
|
+
throw new MobileUpdateRegistryError("Expo update descriptor is invalid");
|
|
28511
|
+
const platforms = {};
|
|
28512
|
+
for (const name of ["android", "ios"]) {
|
|
28513
|
+
const candidate = value.platforms[name];
|
|
28514
|
+
if (candidate === undefined)
|
|
28515
|
+
continue;
|
|
28516
|
+
if (!object3(candidate) || !Array.isArray(candidate.assets) || !object3(candidate.launchAsset))
|
|
28517
|
+
throw new MobileUpdateRegistryError("Expo update platform descriptor is invalid");
|
|
28518
|
+
platforms[name] = {
|
|
28519
|
+
assets: candidate.assets.map(expoAsset),
|
|
28520
|
+
launchAsset: expoAsset(candidate.launchAsset)
|
|
28521
|
+
};
|
|
28522
|
+
}
|
|
28523
|
+
if (Object.keys(platforms).length === 0)
|
|
28524
|
+
throw new MobileUpdateRegistryError("Expo update descriptor has no native platforms");
|
|
28525
|
+
return {
|
|
28526
|
+
engine: "expo",
|
|
28527
|
+
expoConfig: value.expoConfig,
|
|
28528
|
+
format: 1,
|
|
28529
|
+
platforms,
|
|
28530
|
+
runtimeVersion: value.runtimeVersion
|
|
28531
|
+
};
|
|
28532
|
+
}, parseMobileUpdateManifest = (value) => {
|
|
28533
|
+
if (!object3(value) || value.format !== 1)
|
|
28534
|
+
throw new MobileUpdateRegistryError("Mobile update manifest is invalid");
|
|
28535
|
+
const appId = text2(value.appId, "appId");
|
|
28536
|
+
const channel = text2(value.channel, "channel");
|
|
28537
|
+
const releaseId = text2(value.releaseId, "releaseId");
|
|
28538
|
+
const runtimeFingerprint = text2(value.runtimeFingerprint, "runtime");
|
|
28539
|
+
if (!APP_ID.test(appId) || !NAME.test(channel) || !RELEASE.test(releaseId))
|
|
28540
|
+
throw new MobileUpdateRegistryError("Mobile update identity is invalid");
|
|
28541
|
+
if (!HASH.test(runtimeFingerprint) || !iso(value.createdAt))
|
|
28542
|
+
throw new MobileUpdateRegistryError("Mobile update runtime or timestamp is invalid");
|
|
28543
|
+
if (value.classification !== "bug-fix" && value.classification !== "content" && value.classification !== "security")
|
|
28544
|
+
throw new MobileUpdateRegistryError("Mobile update classification is invalid");
|
|
28545
|
+
if (value.withinSubmittedPurpose !== true)
|
|
28546
|
+
throw new MobileUpdateRegistryError("Mobile update policy attestation is missing");
|
|
28547
|
+
if (!Array.isArray(value.files) || value.files.length === 0)
|
|
28548
|
+
throw new MobileUpdateRegistryError("Mobile update file inventory is invalid");
|
|
28549
|
+
const files = value.files.map((candidate) => {
|
|
28550
|
+
if (!object3(candidate))
|
|
28551
|
+
throw new MobileUpdateRegistryError("Mobile update file is invalid");
|
|
28552
|
+
const filePath = safePath(candidate.path);
|
|
28553
|
+
if (!Number.isSafeInteger(candidate.bytes) || Number(candidate.bytes) < 0 || Number(candidate.bytes) > MAX_FILE_BYTES || typeof candidate.sha256 !== "string" || !HASH.test(candidate.sha256))
|
|
28554
|
+
throw new MobileUpdateRegistryError(`Mobile update file ${filePath} is invalid`);
|
|
28555
|
+
return {
|
|
28556
|
+
bytes: Number(candidate.bytes),
|
|
28557
|
+
path: filePath,
|
|
28558
|
+
sha256: candidate.sha256
|
|
28559
|
+
};
|
|
28560
|
+
});
|
|
28561
|
+
if (files.reduce((total, file5) => total + file5.bytes, 0) > MAX_TOTAL_BYTES || new Set(files.map((file5) => file5.path)).size !== files.length || files.some((file5, index) => index > 0 ? file5.path.localeCompare(files[index - 1]?.path ?? "") <= 0 : false))
|
|
28562
|
+
throw new MobileUpdateRegistryError("Mobile update file inventory is invalid");
|
|
28563
|
+
const signatureKeyId = object3(value.signature) ? text2(value.signature.keyId, "signature key") : "";
|
|
28564
|
+
const signatureValue = object3(value.signature) ? text2(value.signature.value, "signature") : "";
|
|
28565
|
+
if (!object3(value.signature) || value.signature.algorithm !== "ecdsa-p256-sha256" || !NAME.test(signatureKeyId) || !/^[A-Za-z0-9+/]+={0,2}$/.test(signatureValue) || Buffer.from(signatureValue, "base64").byteLength !== 64 || Buffer.from(signatureValue, "base64").toString("base64") !== signatureValue)
|
|
28566
|
+
throw new MobileUpdateRegistryError("Mobile update signature is invalid");
|
|
28567
|
+
return {
|
|
28568
|
+
appId,
|
|
28569
|
+
channel,
|
|
28570
|
+
classification: value.classification,
|
|
28571
|
+
createdAt: value.createdAt,
|
|
28572
|
+
files,
|
|
28573
|
+
format: 1,
|
|
28574
|
+
releaseId,
|
|
28575
|
+
runtimeFingerprint,
|
|
28576
|
+
signature: {
|
|
28577
|
+
algorithm: "ecdsa-p256-sha256",
|
|
28578
|
+
keyId: signatureKeyId,
|
|
28579
|
+
value: signatureValue
|
|
28580
|
+
},
|
|
28581
|
+
withinSubmittedPurpose: true
|
|
28582
|
+
};
|
|
28583
|
+
}, canonicalValue = (value) => {
|
|
28584
|
+
if (Array.isArray(value))
|
|
28585
|
+
return value.map(canonicalValue);
|
|
28586
|
+
if (!object3(value))
|
|
28587
|
+
return value;
|
|
28588
|
+
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalValue(value[key])]));
|
|
28589
|
+
}, verifyManifestSignature = (manifest, publicKeys) => {
|
|
28590
|
+
const encoded = publicKeys[manifest.signature.keyId];
|
|
28591
|
+
if (!encoded)
|
|
28592
|
+
throw new MobileUpdateRegistryError("Mobile update signing key is not trusted");
|
|
28593
|
+
let publicKey;
|
|
28594
|
+
try {
|
|
28595
|
+
const der = Buffer.from(encoded, "base64");
|
|
28596
|
+
if (der.toString("base64") !== encoded)
|
|
28597
|
+
throw new Error("invalid base64");
|
|
28598
|
+
publicKey = createPublicKey2({ format: "der", key: der, type: "spki" });
|
|
28599
|
+
} catch {
|
|
28600
|
+
throw new MobileUpdateRegistryError("Mobile update trusted public key is invalid");
|
|
28601
|
+
}
|
|
28602
|
+
if (publicKey.asymmetricKeyType !== "ec" || publicKey.asymmetricKeyDetails?.namedCurve !== "prime256v1")
|
|
28603
|
+
throw new MobileUpdateRegistryError("Mobile update trusted public key must use ECDSA P-256");
|
|
28604
|
+
const { signature: _signature, ...unsigned } = manifest;
|
|
28605
|
+
if (!verify("sha256", new TextEncoder().encode(JSON.stringify(canonicalValue(unsigned))), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64")))
|
|
28606
|
+
throw new MobileUpdateRegistryError("Mobile update signature verification failed");
|
|
28607
|
+
}, parseChannel = (value) => {
|
|
28608
|
+
if (!object3(value) || value.format !== MOBILE_UPDATE_REGISTRY_FORMAT)
|
|
28609
|
+
throw new MobileUpdateRegistryError("Mobile update channel is invalid");
|
|
28610
|
+
const appId = text2(value.appId, "channel appId");
|
|
28611
|
+
const channel = text2(value.channel, "channel");
|
|
28612
|
+
if (!APP_ID.test(appId) || !NAME.test(channel) || !iso(value.promotedAt) || typeof value.rollout !== "number" || value.rollout < 0 || value.rollout > 1 || value.releaseId !== undefined && (typeof value.releaseId !== "string" || !RELEASE.test(value.releaseId)) || value.fallbackReleaseId !== undefined && (typeof value.fallbackReleaseId !== "string" || !RELEASE.test(value.fallbackReleaseId)) || value.activationId !== undefined && (typeof value.activationId !== "string" || !HASH.test(value.activationId)) || value.activatedAt !== undefined && !iso(value.activatedAt) || value.activationId === undefined !== (value.activatedAt === undefined))
|
|
28613
|
+
throw new MobileUpdateRegistryError("Mobile update channel is invalid");
|
|
28614
|
+
return {
|
|
28615
|
+
...value.activationId ? { activationId: value.activationId } : {},
|
|
28616
|
+
...value.activatedAt ? { activatedAt: value.activatedAt } : {},
|
|
28617
|
+
appId,
|
|
28618
|
+
channel,
|
|
28619
|
+
...value.fallbackReleaseId ? { fallbackReleaseId: value.fallbackReleaseId } : {},
|
|
28620
|
+
format: MOBILE_UPDATE_REGISTRY_FORMAT,
|
|
28621
|
+
promotedAt: value.promotedAt,
|
|
28622
|
+
...value.releaseId ? { releaseId: value.releaseId } : {},
|
|
28623
|
+
rollout: value.rollout
|
|
28624
|
+
};
|
|
28625
|
+
}, normalizedPrefix = (value) => {
|
|
28626
|
+
const prefix = value.replace(/^\/+|\/+$/g, "");
|
|
28627
|
+
if (!prefix || prefix.split("/").some((segment) => segment === "." || segment === ".."))
|
|
28628
|
+
throw new MobileUpdateRegistryError("Mobile update prefix is invalid");
|
|
28629
|
+
return prefix;
|
|
28630
|
+
}, appHash = (appId) => createHash6("sha256").update(appId).digest("hex"), digest = (bytes) => createHash6("sha256").update(bytes).digest("hex"), json = (value) => new TextEncoder().encode(`${JSON.stringify(value, null, 2)}
|
|
28631
|
+
`), decode = (value) => JSON.parse(new TextDecoder().decode(value)), fileDigest = async (file5) => {
|
|
28632
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
28633
|
+
for await (const chunk of file5.stream())
|
|
28634
|
+
hasher.update(chunk);
|
|
28635
|
+
return hasher.digest("hex");
|
|
28636
|
+
}, rolloutMember = (input) => {
|
|
28637
|
+
if (input.rollout === 0)
|
|
28638
|
+
return false;
|
|
28639
|
+
if (input.rollout === 1)
|
|
28640
|
+
return true;
|
|
28641
|
+
const value = createHash6("sha256").update(`${input.appId}\x00${input.channel}\x00${input.releaseId}\x00${input.installationId}`).digest().readUInt32BE(0);
|
|
28642
|
+
return value / 4294967296 < input.rollout;
|
|
28643
|
+
}, createMobileUpdateRegistry = (options) => {
|
|
28644
|
+
const prefix = normalizedPrefix(options.prefix ?? DEFAULT_PREFIX);
|
|
28645
|
+
const clock = options.clock ?? (() => new Date);
|
|
28646
|
+
const root = (appId) => `${prefix}/${appHash(appId)}`;
|
|
28647
|
+
const releaseRoot = (manifest) => `${root(manifest.appId)}/releases/${manifest.releaseId}`;
|
|
28648
|
+
const manifestKey = (manifest) => `${releaseRoot(manifest)}/update.json`;
|
|
28649
|
+
const fileKey = (manifest, file5) => `${releaseRoot(manifest)}/files/${file5.path}`;
|
|
28650
|
+
const channelKey = (appId, channel) => {
|
|
28651
|
+
if (!APP_ID.test(appId) || !NAME.test(channel))
|
|
28652
|
+
throw new MobileUpdateRegistryError("Mobile update channel identity is invalid");
|
|
28653
|
+
return `${root(appId)}/channels/${channel}.json`;
|
|
28654
|
+
};
|
|
28655
|
+
const readManifest2 = async (appId, releaseId) => {
|
|
28656
|
+
const key = manifestKey({ appId, releaseId });
|
|
28657
|
+
const bytes = await options.store.get(key);
|
|
28658
|
+
if (!bytes)
|
|
28659
|
+
return null;
|
|
28660
|
+
const head = await options.store.head(key);
|
|
28661
|
+
if (!head || head.size !== bytes.byteLength || head.metadata?.sha256 !== digest(bytes))
|
|
28662
|
+
throw new MobileUpdateRegistryError("Stored mobile update manifest integrity failed");
|
|
28663
|
+
const manifest = parseMobileUpdateManifest(decode(bytes));
|
|
28664
|
+
verifyManifestSignature(manifest, options.publicKeys);
|
|
28665
|
+
if (manifest.appId !== appId || manifest.releaseId !== releaseId)
|
|
28666
|
+
throw new MobileUpdateRegistryError("Stored mobile update identity changed");
|
|
28667
|
+
return { key, manifest };
|
|
28668
|
+
};
|
|
28669
|
+
const readChannel = async (appId, channel) => {
|
|
28670
|
+
const bytes = await options.store.get(channelKey(appId, channel));
|
|
28671
|
+
if (!bytes)
|
|
28672
|
+
return null;
|
|
28673
|
+
const value = parseChannel(decode(bytes));
|
|
28674
|
+
if (value.appId !== appId || value.channel !== channel)
|
|
28675
|
+
throw new MobileUpdateRegistryError("Stored mobile update channel identity changed");
|
|
28676
|
+
return value;
|
|
28677
|
+
};
|
|
28678
|
+
const writeChannel = async (input, signal) => {
|
|
28679
|
+
const value = {
|
|
28680
|
+
...input,
|
|
28681
|
+
format: MOBILE_UPDATE_REGISTRY_FORMAT,
|
|
28682
|
+
promotedAt: clock().toISOString()
|
|
28683
|
+
};
|
|
28684
|
+
const bytes = json(value);
|
|
28685
|
+
await options.store.put(channelKey(value.appId, value.channel), bytes, {
|
|
28686
|
+
cacheControl: "no-cache",
|
|
28687
|
+
contentType: "application/json",
|
|
28688
|
+
maxBytes: bytes.byteLength,
|
|
28689
|
+
metadata: {
|
|
28690
|
+
channel: value.channel,
|
|
28691
|
+
...value.releaseId ? { releaseId: value.releaseId } : {},
|
|
28692
|
+
sha256: digest(bytes)
|
|
28693
|
+
},
|
|
28694
|
+
signal
|
|
28695
|
+
});
|
|
28696
|
+
return value;
|
|
28697
|
+
};
|
|
28698
|
+
const promoteUpdate = async (input) => {
|
|
28699
|
+
input.signal?.throwIfAborted();
|
|
28700
|
+
if (input.rollout <= 0 || input.rollout > 1)
|
|
28701
|
+
throw new MobileUpdateRegistryError("Mobile update rollout is invalid");
|
|
28702
|
+
const release = await readManifest2(input.appId, input.releaseId);
|
|
28703
|
+
if (!release || release.manifest.channel !== input.channel)
|
|
28704
|
+
throw new MobileUpdateRegistryError("Mobile update was not published to this channel");
|
|
28705
|
+
const existing = await readChannel(input.appId, input.channel);
|
|
28706
|
+
await writeChannel({
|
|
28707
|
+
appId: input.appId,
|
|
28708
|
+
channel: input.channel,
|
|
28709
|
+
...existing?.releaseId && existing.releaseId !== input.releaseId ? { fallbackReleaseId: existing.releaseId } : existing?.fallbackReleaseId ? { fallbackReleaseId: existing.fallbackReleaseId } : {},
|
|
28710
|
+
releaseId: input.releaseId,
|
|
28711
|
+
rollout: input.rollout
|
|
28712
|
+
}, input.signal);
|
|
28713
|
+
return {
|
|
28714
|
+
appId: input.appId,
|
|
28715
|
+
channel: input.channel,
|
|
28716
|
+
releaseId: input.releaseId,
|
|
28717
|
+
rollout: input.rollout,
|
|
28718
|
+
stage: "promoted"
|
|
28719
|
+
};
|
|
28720
|
+
};
|
|
28721
|
+
const resolveUpdateState = async (input) => {
|
|
28722
|
+
const channel = await readChannel(input.appId, input.channel);
|
|
28723
|
+
if (!channel?.releaseId)
|
|
28724
|
+
return { status: "empty" };
|
|
28725
|
+
const selected = rolloutMember({
|
|
28726
|
+
appId: input.appId,
|
|
28727
|
+
channel: input.channel,
|
|
28728
|
+
installationId: input.installationId,
|
|
28729
|
+
releaseId: channel.releaseId,
|
|
28730
|
+
rollout: channel.rollout
|
|
28731
|
+
}) ? channel.releaseId : channel.fallbackReleaseId;
|
|
28732
|
+
if (!selected)
|
|
28733
|
+
return { status: "empty" };
|
|
28734
|
+
const release = await readManifest2(input.appId, selected);
|
|
28735
|
+
if (!release || release.manifest.runtimeFingerprint !== input.runtimeFingerprint)
|
|
28736
|
+
return { status: "incompatible" };
|
|
28737
|
+
return {
|
|
28738
|
+
...selected === channel.releaseId && channel.activationId && channel.activatedAt ? {
|
|
28739
|
+
activationId: channel.activationId,
|
|
28740
|
+
activatedAt: channel.activatedAt
|
|
28741
|
+
} : {},
|
|
28742
|
+
manifest: release.manifest,
|
|
28743
|
+
manifestKey: release.key,
|
|
28744
|
+
status: "selected"
|
|
28745
|
+
};
|
|
28746
|
+
};
|
|
28747
|
+
return {
|
|
28748
|
+
publishUpdate: async (input) => {
|
|
28749
|
+
input.signal?.throwIfAborted();
|
|
28750
|
+
const manifest = parseMobileUpdateManifest(input.manifest);
|
|
28751
|
+
verifyManifestSignature(manifest, options.publicKeys);
|
|
28752
|
+
const localRoot = path.resolve(input.releaseDirectory);
|
|
28753
|
+
const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile9(path.join(localRoot, "update.json"), "utf8")));
|
|
28754
|
+
if (JSON.stringify(localManifest) !== JSON.stringify(manifest))
|
|
28755
|
+
throw new MobileUpdateRegistryError("Local mobile update manifest changed");
|
|
28756
|
+
const existing = await readManifest2(manifest.appId, manifest.releaseId);
|
|
28757
|
+
let reused = existing !== null;
|
|
28758
|
+
if (existing && JSON.stringify(existing.manifest) !== JSON.stringify(manifest))
|
|
28759
|
+
throw new MobileUpdateRegistryError("Published mobile update is immutable");
|
|
28760
|
+
if (!existing) {
|
|
28761
|
+
for (const file5 of manifest.files) {
|
|
28762
|
+
const local = path.join(localRoot, "files", file5.path);
|
|
28763
|
+
const metadata = await stat3(local).catch(() => null);
|
|
28764
|
+
if (!metadata?.isFile() || metadata.size !== file5.bytes)
|
|
28765
|
+
throw new MobileUpdateRegistryError(`Mobile update file ${file5.path} size changed`);
|
|
28766
|
+
if (await fileDigest(Bun.file(local)) !== file5.sha256)
|
|
28767
|
+
throw new MobileUpdateRegistryError(`Mobile update file ${file5.path} integrity failed`);
|
|
28768
|
+
const key = fileKey(manifest, file5);
|
|
28769
|
+
const stored = await options.store.head(key);
|
|
28770
|
+
if (!stored) {
|
|
28771
|
+
await options.store.put(key, Bun.file(local).stream(), {
|
|
28772
|
+
cacheControl: "public, max-age=31536000, immutable",
|
|
28773
|
+
contentType: "application/octet-stream",
|
|
28774
|
+
maxBytes: file5.bytes,
|
|
28775
|
+
metadata: { releaseid: manifest.releaseId, sha256: file5.sha256 },
|
|
28776
|
+
signal: input.signal
|
|
28777
|
+
});
|
|
28778
|
+
} else if (stored.size !== file5.bytes || stored.metadata?.sha256 !== file5.sha256 || (stored.metadata?.releaseid ?? stored.metadata?.releaseId) !== manifest.releaseId)
|
|
28779
|
+
throw new MobileUpdateRegistryError("Stored mobile update file identity changed");
|
|
28780
|
+
}
|
|
28781
|
+
const bytes = json(manifest);
|
|
28782
|
+
await options.store.put(manifestKey(manifest), bytes, {
|
|
28783
|
+
cacheControl: "public, max-age=31536000, immutable",
|
|
28784
|
+
contentType: "application/json",
|
|
28785
|
+
maxBytes: bytes.byteLength,
|
|
28786
|
+
metadata: { releaseid: manifest.releaseId, sha256: digest(bytes) },
|
|
28787
|
+
signal: input.signal
|
|
28788
|
+
});
|
|
28789
|
+
if (!await readManifest2(manifest.appId, manifest.releaseId))
|
|
28790
|
+
throw new MobileUpdateRegistryError("Mobile update publication verification failed");
|
|
28791
|
+
reused = false;
|
|
28792
|
+
}
|
|
28793
|
+
await promoteUpdate({
|
|
28794
|
+
appId: manifest.appId,
|
|
28795
|
+
channel: manifest.channel,
|
|
28796
|
+
releaseId: manifest.releaseId,
|
|
28797
|
+
rollout: input.rollout,
|
|
28798
|
+
signal: input.signal
|
|
28799
|
+
});
|
|
28800
|
+
return {
|
|
28801
|
+
appId: manifest.appId,
|
|
28802
|
+
channel: manifest.channel,
|
|
28803
|
+
releaseId: manifest.releaseId,
|
|
28804
|
+
reused,
|
|
28805
|
+
rollout: input.rollout,
|
|
28806
|
+
stage: "published"
|
|
28807
|
+
};
|
|
28808
|
+
},
|
|
28809
|
+
promoteUpdate,
|
|
28810
|
+
rollbackUpdate: async (input) => {
|
|
28811
|
+
input.signal?.throwIfAborted();
|
|
28812
|
+
const existing = await readChannel(input.appId, input.channel);
|
|
28813
|
+
if (!existing)
|
|
28814
|
+
throw new MobileUpdateRegistryError("Mobile update channel does not exist");
|
|
28815
|
+
if (input.releaseId) {
|
|
28816
|
+
const release = await readManifest2(input.appId, input.releaseId);
|
|
28817
|
+
if (!release || release.manifest.channel !== input.channel)
|
|
28818
|
+
throw new MobileUpdateRegistryError("Mobile rollback release was not published");
|
|
28819
|
+
}
|
|
28820
|
+
const activatedAt = clock().toISOString();
|
|
28821
|
+
await writeChannel({
|
|
28822
|
+
...input.releaseId ? {
|
|
28823
|
+
activationId: digest(new TextEncoder().encode(`${input.appId}\x00${input.channel}\x00${input.releaseId}\x00${activatedAt}`)),
|
|
28824
|
+
activatedAt
|
|
28825
|
+
} : {},
|
|
28826
|
+
appId: input.appId,
|
|
28827
|
+
channel: input.channel,
|
|
28828
|
+
...existing.releaseId ? { fallbackReleaseId: existing.releaseId } : {},
|
|
28829
|
+
...input.releaseId ? { releaseId: input.releaseId } : {},
|
|
28830
|
+
rollout: input.releaseId ? 1 : 0
|
|
28831
|
+
}, input.signal);
|
|
28832
|
+
return {
|
|
28833
|
+
appId: input.appId,
|
|
28834
|
+
channel: input.channel,
|
|
28835
|
+
...input.releaseId ? { releaseId: input.releaseId } : {},
|
|
28836
|
+
stage: "rolled-back"
|
|
28837
|
+
};
|
|
28838
|
+
},
|
|
28839
|
+
resolveUpdate: async (input) => {
|
|
28840
|
+
const resolution = await resolveUpdateState(input);
|
|
28841
|
+
return resolution.status === "selected" ? { manifest: resolution.manifest, manifestKey: resolution.manifestKey } : null;
|
|
28842
|
+
},
|
|
28843
|
+
resolveUpdateState,
|
|
28844
|
+
readUpdateFile: async (input) => {
|
|
28845
|
+
const release = await readManifest2(input.appId, input.releaseId);
|
|
28846
|
+
if (!release)
|
|
28847
|
+
return null;
|
|
28848
|
+
const requested = safePath(input.path);
|
|
28849
|
+
const file5 = release.manifest.files.find((candidate) => candidate.path === requested);
|
|
28850
|
+
if (!file5)
|
|
28851
|
+
return null;
|
|
28852
|
+
const key = fileKey(release.manifest, file5);
|
|
28853
|
+
const [bytes, head] = await Promise.all([
|
|
28854
|
+
options.store.get(key),
|
|
28855
|
+
options.store.head(key)
|
|
28856
|
+
]);
|
|
28857
|
+
if (!bytes || !head)
|
|
28858
|
+
return null;
|
|
28859
|
+
if (bytes.byteLength !== file5.bytes || head.size !== file5.bytes || head.metadata?.sha256 !== file5.sha256 || (head.metadata?.releaseid ?? head.metadata?.releaseId) !== release.manifest.releaseId || digest(bytes) !== file5.sha256)
|
|
28860
|
+
throw new MobileUpdateRegistryError("Stored mobile update file integrity failed");
|
|
28861
|
+
return { bytes, file: file5 };
|
|
28862
|
+
}
|
|
28863
|
+
};
|
|
28864
|
+
}, expoUpdateId = (releaseId) => {
|
|
28865
|
+
const hash = RELEASE.test(releaseId) ? releaseId.slice("amu_".length, "amu_".length + 32) : createHash6("sha256").update(releaseId).digest("hex").slice(0, 32);
|
|
28866
|
+
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20)}`;
|
|
28867
|
+
}, expoContentType = (extension, launch) => {
|
|
28868
|
+
if (launch)
|
|
28869
|
+
return "application/javascript";
|
|
28870
|
+
const normalized = extension?.toLowerCase();
|
|
28871
|
+
if (normalized === "png")
|
|
28872
|
+
return "image/png";
|
|
28873
|
+
if (normalized === "jpg" || normalized === "jpeg")
|
|
28874
|
+
return "image/jpeg";
|
|
28875
|
+
if (normalized === "webp")
|
|
28876
|
+
return "image/webp";
|
|
28877
|
+
if (normalized === "gif")
|
|
28878
|
+
return "image/gif";
|
|
28879
|
+
if (normalized === "svg")
|
|
28880
|
+
return "image/svg+xml";
|
|
28881
|
+
if (normalized === "json")
|
|
28882
|
+
return "application/json";
|
|
28883
|
+
if (normalized === "ttf")
|
|
28884
|
+
return "font/ttf";
|
|
28885
|
+
if (normalized === "otf")
|
|
28886
|
+
return "font/otf";
|
|
28887
|
+
if (normalized === "woff")
|
|
28888
|
+
return "font/woff";
|
|
28889
|
+
if (normalized === "woff2")
|
|
28890
|
+
return "font/woff2";
|
|
28891
|
+
return "application/octet-stream";
|
|
28892
|
+
}, encodeUpdatePath = (value) => value.split("/").map(encodeURIComponent).join("/"), expoProtocolHeaders, resolveExpoCodeSigning = (value) => {
|
|
28893
|
+
if (!value)
|
|
28894
|
+
return;
|
|
28895
|
+
const entries = Object.entries(value.keys);
|
|
28896
|
+
if (entries.length === 0)
|
|
28897
|
+
throw new MobileUpdateRegistryError("Expo code signing requires at least one key");
|
|
28898
|
+
return new Map(entries.map(([keyId, material]) => {
|
|
28899
|
+
if (!NAME.test(keyId))
|
|
28900
|
+
throw new MobileUpdateRegistryError("Expo code-signing key ID is invalid");
|
|
28901
|
+
let certificate;
|
|
28902
|
+
let privateKey;
|
|
28903
|
+
try {
|
|
28904
|
+
certificate = new X509Certificate2(material.certificate);
|
|
28905
|
+
privateKey = createPrivateKey(material.privateKey);
|
|
28906
|
+
} catch (error) {
|
|
28907
|
+
throw new MobileUpdateRegistryError("Expo code-signing certificate or private key is invalid", { cause: error });
|
|
28908
|
+
}
|
|
28909
|
+
if (certificate.publicKey.asymmetricKeyType !== "rsa" || privateKey.asymmetricKeyType !== "rsa" || certificate.issuer !== certificate.subject || !certificate.verify(certificate.publicKey))
|
|
28910
|
+
throw new MobileUpdateRegistryError("Expo code signing requires a self-signed RSA root and private key");
|
|
28911
|
+
const certificatePublicKey = certificate.publicKey.export({
|
|
28912
|
+
format: "der",
|
|
28913
|
+
type: "spki"
|
|
28914
|
+
});
|
|
28915
|
+
const privatePublicKey = createPublicKey2(privateKey).export({
|
|
28916
|
+
format: "der",
|
|
28917
|
+
type: "spki"
|
|
28918
|
+
});
|
|
28919
|
+
if (!certificatePublicKey.equals(privatePublicKey))
|
|
28920
|
+
throw new MobileUpdateRegistryError("Expo code-signing private key does not match its certificate");
|
|
28921
|
+
const now = Date.now();
|
|
28922
|
+
if (now < Date.parse(certificate.validFrom) || now > Date.parse(certificate.validTo))
|
|
28923
|
+
throw new MobileUpdateRegistryError("Expo code-signing certificate is not currently valid");
|
|
28924
|
+
return [keyId, { keyId, privateKey }];
|
|
28925
|
+
}));
|
|
28926
|
+
}, expoSignatureExpectation = (value) => {
|
|
28927
|
+
const fields = new Map;
|
|
28928
|
+
for (const raw of value.split(",")) {
|
|
28929
|
+
const match = /^\s*([a-z][a-z0-9_-]*)(?:=(\?1|\?0|"[^"\\]*"|[a-z0-9._-]+))?\s*$/u.exec(raw);
|
|
28930
|
+
if (!match || fields.has(match[1]))
|
|
28931
|
+
throw new MobileUpdateRegistryError("Expo code-signing expectation is invalid");
|
|
28932
|
+
const encoded = match[2];
|
|
28933
|
+
fields.set(match[1], encoded === undefined || encoded === "?1" ? true : encoded.startsWith('"') ? encoded.slice(1, -1) : encoded);
|
|
28934
|
+
}
|
|
28935
|
+
return fields;
|
|
28936
|
+
}, expoExtraParam = (request, key) => {
|
|
28937
|
+
const value = request.headers.get("expo-extra-params");
|
|
28938
|
+
if (!value)
|
|
28939
|
+
return null;
|
|
28940
|
+
for (const raw of value.split(",")) {
|
|
28941
|
+
const match = /^\s*([a-z][a-z0-9_.*-]*)=(?:"((?:[^"\\]|\\["\\])*)"|([^\s,]+))\s*$/u.exec(raw);
|
|
28942
|
+
if (!match || match[1] !== key)
|
|
28943
|
+
continue;
|
|
28944
|
+
return match[2] !== undefined ? match[2].replace(/\\(["\\])/gu, "$1") : match[3] ?? null;
|
|
28945
|
+
}
|
|
28946
|
+
return null;
|
|
28947
|
+
}, requestedExpoSignature = (request, codeSigning) => {
|
|
28948
|
+
const expectation = request.headers.get("expo-expect-signature");
|
|
28949
|
+
if (!expectation)
|
|
28950
|
+
return;
|
|
28951
|
+
if (!codeSigning)
|
|
28952
|
+
throw new MobileUpdateRegistryError("Expo end-to-end code signing is not configured");
|
|
28953
|
+
const fields = expoSignatureExpectation(expectation);
|
|
28954
|
+
const keyId = fields.get("keyid");
|
|
28955
|
+
const algorithm = fields.get("alg");
|
|
28956
|
+
const signatureRequested = fields.get("sig") === true;
|
|
28957
|
+
if (!signatureRequested || keyId !== undefined && typeof keyId !== "string" || algorithm !== undefined && algorithm !== EXPO_CODE_SIGNING_ALGORITHM)
|
|
28958
|
+
throw new MobileUpdateRegistryError("Requested Expo code-signing parameters are unsupported");
|
|
28959
|
+
const selected = typeof keyId === "string" ? codeSigning.get(keyId) : codeSigning.size === 1 ? codeSigning.values().next().value : undefined;
|
|
28960
|
+
if (!selected)
|
|
28961
|
+
throw new MobileUpdateRegistryError("Requested Expo code-signing key is unavailable");
|
|
28962
|
+
return selected;
|
|
28963
|
+
}, expoSignatureHeader = (body, codeSigning) => {
|
|
28964
|
+
const signature = sign("RSA-SHA256", Buffer.from(body), codeSigning.privateKey);
|
|
28965
|
+
return `sig="${signature.toString("base64")}", keyid="${codeSigning.keyId}", alg="${EXPO_CODE_SIGNING_ALGORITHM}"`;
|
|
28966
|
+
}, expoRollbackResponse = (request, codeSigning) => {
|
|
28967
|
+
const current = request.headers.get("expo-current-update-id");
|
|
28968
|
+
const embedded = request.headers.get("expo-embedded-update-id");
|
|
28969
|
+
if (!current || current === embedded)
|
|
28970
|
+
return new Response(null, { status: 204 });
|
|
28971
|
+
const boundary = `absolutejs-${crypto.randomUUID()}`;
|
|
28972
|
+
const directive = JSON.stringify({
|
|
28973
|
+
parameters: { commitTime: new Date().toISOString() },
|
|
28974
|
+
type: "rollBackToEmbedded"
|
|
28975
|
+
});
|
|
28976
|
+
const body = [
|
|
28977
|
+
`--${boundary}`,
|
|
28978
|
+
'content-disposition: form-data; name="directive"',
|
|
28979
|
+
"content-type: application/json; charset=utf-8",
|
|
28980
|
+
...codeSigning ? [`expo-signature: ${expoSignatureHeader(directive, codeSigning)}`] : [],
|
|
28981
|
+
"",
|
|
28982
|
+
directive,
|
|
28983
|
+
`--${boundary}--`,
|
|
28984
|
+
""
|
|
28985
|
+
].join(`\r
|
|
28986
|
+
`);
|
|
28987
|
+
return new Response(body, {
|
|
28988
|
+
headers: {
|
|
28989
|
+
...expoProtocolHeaders,
|
|
28990
|
+
"content-type": `multipart/mixed; boundary=${boundary}`
|
|
28991
|
+
}
|
|
28992
|
+
});
|
|
28993
|
+
}, createMobileUpdateHandler = (options) => {
|
|
28994
|
+
const route = (options.route ?? `/__absolute/mobile/updates/${options.channel}`).replace(/^\/+|\/+$/g, "");
|
|
28995
|
+
const allowedOrigins = new Set(options.allowedOrigins ?? ["capacitor://localhost", "https://localhost"]);
|
|
28996
|
+
const expoCodeSigning = resolveExpoCodeSigning(options.expoCodeSigning);
|
|
28997
|
+
return async (request) => {
|
|
28998
|
+
const origin = request.headers.get("origin");
|
|
28999
|
+
const cors = origin && allowedOrigins.has(origin) ? { "access-control-allow-origin": origin, vary: "Origin" } : {};
|
|
29000
|
+
if (request.method === "OPTIONS") {
|
|
29001
|
+
if (!origin || !allowedOrigins.has(origin))
|
|
29002
|
+
return new Response(null, { status: 403 });
|
|
29003
|
+
return new Response(null, {
|
|
29004
|
+
headers: {
|
|
29005
|
+
...cors,
|
|
29006
|
+
"access-control-allow-headers": "x-absolute-mobile-app,x-absolute-mobile-channel,x-absolute-mobile-installation,x-absolute-mobile-release,x-absolute-mobile-runtime",
|
|
29007
|
+
"access-control-allow-methods": "GET,OPTIONS",
|
|
29008
|
+
"access-control-max-age": "600"
|
|
29009
|
+
},
|
|
29010
|
+
status: 204
|
|
29011
|
+
});
|
|
29012
|
+
}
|
|
29013
|
+
if (request.method !== "GET")
|
|
29014
|
+
return new Response(null, { status: 405 });
|
|
29015
|
+
const pathname = new URL(request.url).pathname.replace(/^\/+/, "");
|
|
29016
|
+
const relative19 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
|
|
29017
|
+
if (relative19 === "update.json") {
|
|
29018
|
+
const expoProtocolVersion = request.headers.get("expo-protocol-version");
|
|
29019
|
+
const expoProtocol = expoProtocolVersion !== null;
|
|
29020
|
+
if (expoProtocol && expoProtocolVersion !== "1")
|
|
29021
|
+
return Response.json({
|
|
29022
|
+
error: `Unsupported Expo Updates protocol version: ${expoProtocolVersion}`
|
|
29023
|
+
}, { status: 406 });
|
|
29024
|
+
const appId = request.headers.get("x-absolute-mobile-app");
|
|
29025
|
+
const channel = request.headers.get("x-absolute-mobile-channel");
|
|
29026
|
+
const installationId = expoProtocol ? expoExtraParam(request, "absolute-installation") ?? request.headers.get("x-absolute-mobile-installation") : request.headers.get("x-absolute-mobile-installation");
|
|
29027
|
+
const runtimeFingerprint = expoProtocol ? request.headers.get("expo-runtime-version") : request.headers.get("x-absolute-mobile-runtime");
|
|
29028
|
+
if (appId !== options.appId || channel !== options.channel || !installationId || !runtimeFingerprint)
|
|
29029
|
+
return new Response(null, { status: 400 });
|
|
29030
|
+
const resolution = options.registry.resolveUpdateState ? await options.registry.resolveUpdateState({
|
|
29031
|
+
appId,
|
|
29032
|
+
channel,
|
|
29033
|
+
installationId,
|
|
29034
|
+
runtimeFingerprint
|
|
29035
|
+
}) : undefined;
|
|
29036
|
+
const selected = resolution ? resolution.status === "selected" ? resolution : null : await options.registry.resolveUpdate({
|
|
29037
|
+
appId,
|
|
29038
|
+
channel,
|
|
29039
|
+
installationId,
|
|
29040
|
+
runtimeFingerprint
|
|
29041
|
+
});
|
|
29042
|
+
if (expoProtocol) {
|
|
29043
|
+
let requestedCodeSigning;
|
|
29044
|
+
try {
|
|
29045
|
+
requestedCodeSigning = requestedExpoSignature(request, expoCodeSigning);
|
|
29046
|
+
} catch (error) {
|
|
29047
|
+
return Response.json({
|
|
29048
|
+
error: error instanceof Error ? error.message : "Expo code-signing negotiation failed"
|
|
29049
|
+
}, { status: expoCodeSigning ? 406 : 400 });
|
|
29050
|
+
}
|
|
29051
|
+
if (!selected) {
|
|
29052
|
+
if (resolution?.status === "incompatible")
|
|
29053
|
+
return new Response(null, { status: 204 });
|
|
29054
|
+
return expoRollbackResponse(request, requestedCodeSigning);
|
|
29055
|
+
}
|
|
29056
|
+
const platform2 = request.headers.get("expo-platform");
|
|
29057
|
+
if (platform2 !== "android" && platform2 !== "ios")
|
|
29058
|
+
return new Response(null, { status: 400 });
|
|
29059
|
+
const updateId = expoUpdateId((resolution?.status === "selected" ? resolution.activationId : undefined) ?? selected.manifest.releaseId);
|
|
29060
|
+
if (request.headers.get("expo-current-update-id") === updateId)
|
|
29061
|
+
return new Response(null, { status: 204 });
|
|
29062
|
+
const descriptorFile = await options.registry.readUpdateFile({
|
|
29063
|
+
appId,
|
|
29064
|
+
path: EXPO_DESCRIPTOR,
|
|
29065
|
+
releaseId: selected.manifest.releaseId
|
|
29066
|
+
});
|
|
29067
|
+
if (!descriptorFile)
|
|
29068
|
+
return new Response(null, { status: 409 });
|
|
29069
|
+
const descriptor = parseExpoUpdateDescriptor(descriptorFile.bytes);
|
|
29070
|
+
const platformUpdate = descriptor.platforms[platform2];
|
|
29071
|
+
if (!platformUpdate || descriptor.runtimeVersion !== runtimeFingerprint)
|
|
29072
|
+
return new Response(null, { status: 204 });
|
|
29073
|
+
const origin2 = new URL(request.url).origin;
|
|
29074
|
+
const releaseRoute = `${origin2}/${route}/${selected.manifest.releaseId}/files`;
|
|
29075
|
+
const protocolAsset = (asset, launch = false) => {
|
|
29076
|
+
const file22 = selected.manifest.files.find((candidate) => candidate.path === asset.path);
|
|
29077
|
+
if (!file22)
|
|
29078
|
+
throw new MobileUpdateRegistryError(`Expo update references missing signed asset ${asset.path}`);
|
|
29079
|
+
return {
|
|
29080
|
+
contentType: expoContentType(asset.extension, launch),
|
|
29081
|
+
...asset.extension ? { fileExtension: `.${asset.extension}` } : {},
|
|
29082
|
+
key: file22.sha256,
|
|
29083
|
+
hash: Buffer.from(file22.sha256, "hex").toString("base64url"),
|
|
29084
|
+
url: `${releaseRoute}/${encodeUpdatePath(asset.path)}`
|
|
29085
|
+
};
|
|
29086
|
+
};
|
|
29087
|
+
const manifest = JSON.stringify({
|
|
29088
|
+
assets: platformUpdate.assets.map((asset) => protocolAsset(asset)),
|
|
29089
|
+
createdAt: (resolution?.status === "selected" ? resolution.activatedAt : undefined) ?? selected.manifest.createdAt,
|
|
29090
|
+
extra: {
|
|
29091
|
+
absolutejs: {
|
|
29092
|
+
channel: selected.manifest.channel,
|
|
29093
|
+
releaseId: selected.manifest.releaseId
|
|
29094
|
+
},
|
|
29095
|
+
expoClient: descriptor.expoConfig
|
|
29096
|
+
},
|
|
29097
|
+
id: updateId,
|
|
29098
|
+
launchAsset: protocolAsset(platformUpdate.launchAsset, true),
|
|
29099
|
+
metadata: {
|
|
29100
|
+
channel: selected.manifest.channel,
|
|
29101
|
+
releaseId: selected.manifest.releaseId
|
|
29102
|
+
},
|
|
29103
|
+
runtimeVersion: descriptor.runtimeVersion
|
|
29104
|
+
});
|
|
29105
|
+
return new Response(manifest, {
|
|
29106
|
+
headers: {
|
|
29107
|
+
...expoProtocolHeaders,
|
|
29108
|
+
...requestedCodeSigning ? {
|
|
29109
|
+
"expo-signature": expoSignatureHeader(manifest, requestedCodeSigning)
|
|
29110
|
+
} : {}
|
|
29111
|
+
}
|
|
29112
|
+
});
|
|
29113
|
+
}
|
|
29114
|
+
if (!selected)
|
|
29115
|
+
return new Response(null, { status: 204 });
|
|
29116
|
+
return Response.json(selected.manifest, {
|
|
29117
|
+
headers: {
|
|
29118
|
+
...cors,
|
|
29119
|
+
"cache-control": "no-store",
|
|
29120
|
+
etag: `"${selected.manifest.releaseId}"`
|
|
29121
|
+
}
|
|
29122
|
+
});
|
|
29123
|
+
}
|
|
29124
|
+
const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative19);
|
|
29125
|
+
if (!match?.[1] || !match[2])
|
|
29126
|
+
return new Response(null, { status: 404 });
|
|
29127
|
+
const file5 = await options.registry.readUpdateFile({
|
|
29128
|
+
appId: options.appId,
|
|
29129
|
+
path: decodeURIComponent(match[2]),
|
|
29130
|
+
releaseId: match[1]
|
|
29131
|
+
});
|
|
29132
|
+
if (!file5)
|
|
29133
|
+
return new Response(null, { status: 404 });
|
|
29134
|
+
return new Response(new Blob([new Uint8Array(file5.bytes).buffer]), {
|
|
29135
|
+
headers: {
|
|
29136
|
+
...cors,
|
|
29137
|
+
"cache-control": "public, max-age=31536000, immutable",
|
|
29138
|
+
"content-length": String(file5.file.bytes),
|
|
29139
|
+
"content-type": expoContentType(file5.file.path.includes(".") ? file5.file.path.slice(file5.file.path.lastIndexOf(".") + 1) : undefined, false),
|
|
29140
|
+
etag: `"${file5.file.sha256}"`
|
|
29141
|
+
}
|
|
29142
|
+
});
|
|
29143
|
+
};
|
|
29144
|
+
};
|
|
29145
|
+
var init_mobileUpdate = __esm(() => {
|
|
29146
|
+
MAX_FILE_BYTES = 32 * 1024 * 1024;
|
|
29147
|
+
MAX_TOTAL_BYTES = 128 * 1024 * 1024;
|
|
29148
|
+
HASH = /^[a-f0-9]{64}$/;
|
|
29149
|
+
RELEASE = /^amu_[a-f0-9]{64}$/;
|
|
29150
|
+
APP_ID = /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)+$/;
|
|
29151
|
+
NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
29152
|
+
MobileUpdateRegistryError = class MobileUpdateRegistryError extends Error {
|
|
29153
|
+
};
|
|
29154
|
+
expoProtocolHeaders = {
|
|
29155
|
+
"cache-control": "private, max-age=0",
|
|
29156
|
+
"content-type": "application/expo+json",
|
|
29157
|
+
"expo-protocol-version": "1",
|
|
29158
|
+
"expo-sfv-version": "0"
|
|
29159
|
+
};
|
|
29160
|
+
});
|
|
29161
|
+
|
|
29162
|
+
// src/mobile/updateServer.ts
|
|
29163
|
+
var exports_updateServer = {};
|
|
29164
|
+
__export(exports_updateServer, {
|
|
29165
|
+
ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT: () => ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT,
|
|
29166
|
+
DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE: () => DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE,
|
|
29167
|
+
createAbsoluteMobileUpdateServerPlugin: () => createAbsoluteMobileUpdateServerPlugin,
|
|
29168
|
+
inspectAbsoluteMobileUpdateServer: () => inspectAbsoluteMobileUpdateServer,
|
|
29169
|
+
loadAbsoluteMobileUpdateServerModule: () => loadAbsoluteMobileUpdateServerModule,
|
|
29170
|
+
renderAbsoluteMobileUpdateRegistry: () => renderAbsoluteMobileUpdateRegistry,
|
|
29171
|
+
writeAbsoluteMobileUpdateRegistry: () => writeAbsoluteMobileUpdateRegistry
|
|
29172
|
+
});
|
|
29173
|
+
import {
|
|
29174
|
+
createPrivateKey as createPrivateKey2,
|
|
29175
|
+
createPublicKey as createPublicKey3,
|
|
29176
|
+
X509Certificate as X509Certificate3
|
|
29177
|
+
} from "crypto";
|
|
29178
|
+
import { access as access4, mkdir as mkdir13 } from "fs/promises";
|
|
29179
|
+
import { dirname as dirname31, isAbsolute as isAbsolute8, relative as relative19, resolve as resolve46, sep as sep4 } from "path";
|
|
29180
|
+
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
29181
|
+
import { Elysia as Elysia5 } from "elysia";
|
|
29182
|
+
var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1, DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE = "mobile.update.ts", object4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), projectPath = (projectRoot, requested) => {
|
|
29183
|
+
const root = resolve46(projectRoot);
|
|
29184
|
+
const path2 = resolve46(root, requested);
|
|
29185
|
+
const projectRelative = relative19(root, path2);
|
|
29186
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep4}`) || isAbsolute8(projectRelative))
|
|
29187
|
+
throw new TypeError("mobile.updates.server.registry must remain inside the project.");
|
|
29188
|
+
return path2;
|
|
29189
|
+
}, isRegistry2 = (value) => object4(value) && [
|
|
29190
|
+
"publishUpdate",
|
|
29191
|
+
"promoteUpdate",
|
|
29192
|
+
"rollbackUpdate",
|
|
29193
|
+
"resolveUpdate",
|
|
29194
|
+
"readUpdateFile"
|
|
29195
|
+
].every((method) => typeof value[method] === "function"), serverMetadata = (value) => {
|
|
29196
|
+
if (!object4(value))
|
|
29197
|
+
throw new TypeError("Mobile update registry must export valid absoluteMobileUpdateServer metadata. Run `absolute mobile update provision`.");
|
|
29198
|
+
const { format, provider, storage } = value;
|
|
29199
|
+
if (format !== ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT || storage !== "local" && storage !== "durable" || typeof provider !== "string" || !provider)
|
|
29200
|
+
throw new TypeError("Mobile update registry must export valid absoluteMobileUpdateServer metadata. Run `absolute mobile update provision`.");
|
|
29201
|
+
const metadata = {
|
|
29202
|
+
format: ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT,
|
|
29203
|
+
provider,
|
|
29204
|
+
storage
|
|
29205
|
+
};
|
|
29206
|
+
return metadata;
|
|
29207
|
+
}, loadAbsoluteMobileUpdateServerModule = async (projectRoot, requestedModulePath = DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE) => {
|
|
29208
|
+
const modulePath = projectPath(projectRoot, requestedModulePath);
|
|
29209
|
+
await access4(modulePath).catch(() => {
|
|
29210
|
+
throw new TypeError(`Mobile update server registry does not exist: ${modulePath}. Run \`absolute mobile update provision\`.`);
|
|
29211
|
+
});
|
|
29212
|
+
const loaded = await import(pathToFileURL3(modulePath).href);
|
|
29213
|
+
if (!object4(loaded))
|
|
29214
|
+
throw new TypeError("Mobile update registry module has no exports.");
|
|
29215
|
+
const registry2 = loaded.default ?? loaded.registry;
|
|
29216
|
+
if (!isRegistry2(registry2))
|
|
29217
|
+
throw new TypeError("Mobile update registry must implement publication, promotion, rollback, resolution, and file reads.");
|
|
29218
|
+
const metadata = serverMetadata(loaded.absoluteMobileUpdateServer);
|
|
29219
|
+
const verifier = loaded.verifyAbsoluteMobileUpdateServer;
|
|
29220
|
+
if (metadata.storage === "durable" && typeof verifier !== "function")
|
|
29221
|
+
throw new TypeError("Mobile update registries marked durable must export verifyAbsoluteMobileUpdateServer(). Re-run `absolute mobile update provision --storage s3 --force` or provide an active durability check.");
|
|
29222
|
+
return {
|
|
29223
|
+
metadata,
|
|
29224
|
+
registry: registry2,
|
|
29225
|
+
...typeof verifier === "function" ? {
|
|
29226
|
+
verifyDurability: async () => {
|
|
29227
|
+
await verifier();
|
|
29228
|
+
}
|
|
29229
|
+
} : {}
|
|
29230
|
+
};
|
|
29231
|
+
}, verifyDurableModule = async (module) => {
|
|
29232
|
+
if (module.metadata.storage !== "durable")
|
|
29233
|
+
throw new TypeError("Mobile production updates require durable object storage. Re-run `absolute mobile update provision --storage s3 --force` or configure a durable adapter.");
|
|
29234
|
+
try {
|
|
29235
|
+
await module.verifyDurability?.();
|
|
29236
|
+
} catch (error) {
|
|
29237
|
+
throw new TypeError(`Durable mobile update storage verification failed for ${module.metadata.provider}. Check the bucket, endpoint, credentials, and read/write/delete permissions.`, { cause: error });
|
|
29238
|
+
}
|
|
29239
|
+
}, expoSigningOptions = (config) => {
|
|
29240
|
+
if (!config.updates?.expoCodeSigning)
|
|
29241
|
+
return;
|
|
29242
|
+
const entries = Object.entries(config.updateServer?.expoCodeSigningKeys ?? {});
|
|
29243
|
+
const keys = Object.fromEntries(entries.map(([keyId, key]) => {
|
|
29244
|
+
const privateKey = process.env[key.privateKeyEnv];
|
|
29245
|
+
if (!privateKey)
|
|
29246
|
+
throw new TypeError(`Expo update serving requires ${key.privateKeyEnv} on the trusted server.`);
|
|
29247
|
+
try {
|
|
29248
|
+
const certificate = new X509Certificate3(key.certificatePem);
|
|
29249
|
+
const expected = certificate.publicKey.export({
|
|
29250
|
+
format: "der",
|
|
29251
|
+
type: "spki"
|
|
29252
|
+
});
|
|
29253
|
+
const actual = createPublicKey3(createPrivateKey2(privateKey)).export({
|
|
29254
|
+
format: "der",
|
|
29255
|
+
type: "spki"
|
|
29256
|
+
});
|
|
29257
|
+
if (!expected.equals(actual))
|
|
29258
|
+
throw new Error("key mismatch");
|
|
29259
|
+
} catch (error) {
|
|
29260
|
+
throw new TypeError(`${key.privateKeyEnv} must contain the RSA private key matching Expo update key ${keyId}.`, { cause: error });
|
|
29261
|
+
}
|
|
29262
|
+
return [keyId, { certificate: key.certificatePem, privateKey }];
|
|
29263
|
+
}));
|
|
29264
|
+
return { keys };
|
|
29265
|
+
}, createAbsoluteMobileUpdateServerPlugin = async (config, projectRoot, options = {}) => {
|
|
29266
|
+
const { updates, updateServer: server } = config;
|
|
29267
|
+
if (!updates || !server?.autoMount)
|
|
29268
|
+
return new Elysia5({ name: "absolutejs-mobile-updates-disabled" });
|
|
29269
|
+
const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, server.registryModule);
|
|
29270
|
+
if (options.production)
|
|
29271
|
+
await verifyDurableModule(module);
|
|
29272
|
+
const manifest = new URL(updates.manifestUrl);
|
|
29273
|
+
if (!manifest.pathname.endsWith("/update.json"))
|
|
29274
|
+
throw new TypeError("Auto-mounted mobile update manifests must end in /update.json.");
|
|
29275
|
+
const route = manifest.pathname.slice(0, -"/update.json".length);
|
|
29276
|
+
const { createMobileUpdateHandler: createMobileUpdateHandler2 } = await Promise.resolve().then(() => (init_mobileUpdate(), exports_mobileUpdate));
|
|
29277
|
+
const handler = createMobileUpdateHandler2({
|
|
29278
|
+
appId: config.appId,
|
|
29279
|
+
channel: updates.channel,
|
|
29280
|
+
...config.engine === "expo" ? { expoCodeSigning: expoSigningOptions(config) } : {},
|
|
29281
|
+
registry: module.registry,
|
|
29282
|
+
route
|
|
29283
|
+
});
|
|
29284
|
+
return new Elysia5({ name: "absolutejs-mobile-updates" }).all(`${route}/*`, ({ request }) => handler(request));
|
|
29285
|
+
}, inspectAbsoluteMobileUpdateServer = async (config, projectRoot) => {
|
|
29286
|
+
if (!config.updates)
|
|
29287
|
+
return;
|
|
29288
|
+
const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, config.updateServer?.registryModule);
|
|
29289
|
+
await verifyDurableModule(module);
|
|
29290
|
+
if (config.engine === "expo")
|
|
29291
|
+
expoSigningOptions(config);
|
|
29292
|
+
return module.metadata;
|
|
29293
|
+
}, publicKeysSource = (publicKeys) => JSON.stringify(publicKeys, null, "\t"), renderAbsoluteMobileUpdateRegistry = (options) => {
|
|
29294
|
+
const metadata = `export const absoluteMobileUpdateServer = {
|
|
29295
|
+
format: 1,
|
|
29296
|
+
provider: '${options.storage}',
|
|
29297
|
+
storage: '${options.storage === "local" ? "local" : "durable"}'
|
|
29298
|
+
} as const;`;
|
|
29299
|
+
if (options.storage === "local")
|
|
29300
|
+
return `import { fileURLToPath } from 'node:url';
|
|
29301
|
+
import { localBlobStore } from '@absolutejs/blob/local';
|
|
29302
|
+
import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
|
|
29303
|
+
|
|
29304
|
+
${metadata}
|
|
29305
|
+
|
|
29306
|
+
const store = localBlobStore({
|
|
29307
|
+
root: process.env.ABSOLUTE_MOBILE_UPDATE_LOCAL_ROOT ??
|
|
29308
|
+
fileURLToPath(new URL('./.absolutejs/mobile/update-registry/', import.meta.url))
|
|
29309
|
+
});
|
|
29310
|
+
|
|
29311
|
+
export default createMobileUpdateRegistry({
|
|
29312
|
+
publicKeys: ${publicKeysSource(options.publicKeys)},
|
|
29313
|
+
store
|
|
29314
|
+
});
|
|
29315
|
+
`;
|
|
29316
|
+
return `import { randomUUID } from 'node:crypto';
|
|
29317
|
+
import { DeleteObjectCommand, GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
|
29318
|
+
import { awsS3BlobStore } from '@absolutejs/blob/aws-s3';
|
|
29319
|
+
import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
|
|
29320
|
+
|
|
29321
|
+
${metadata}
|
|
29322
|
+
|
|
29323
|
+
const required = (name: string) => {
|
|
29324
|
+
const value = process.env[name];
|
|
29325
|
+
if (!value) throw new Error(\`Missing \${name}\`);
|
|
29326
|
+
return value;
|
|
29327
|
+
};
|
|
29328
|
+
|
|
29329
|
+
const bucket = required('ABSOLUTE_MOBILE_UPDATE_S3_BUCKET');
|
|
29330
|
+
const client = new S3Client({
|
|
29331
|
+
region: process.env.ABSOLUTE_MOBILE_UPDATE_S3_REGION ?? 'auto',
|
|
29332
|
+
forcePathStyle: process.env.ABSOLUTE_MOBILE_UPDATE_S3_FORCE_PATH_STYLE === '1',
|
|
29333
|
+
...(process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT
|
|
29334
|
+
? { endpoint: process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT }
|
|
29335
|
+
: {})
|
|
29336
|
+
});
|
|
29337
|
+
const store = awsS3BlobStore({ bucket, client });
|
|
29338
|
+
|
|
29339
|
+
export const verifyAbsoluteMobileUpdateServer = async () => {
|
|
29340
|
+
const key = \`absolutejs/mobile-updates/_health/\${randomUUID()}\`;
|
|
29341
|
+
const expected = randomUUID();
|
|
29342
|
+
let stored = false;
|
|
29343
|
+
try {
|
|
29344
|
+
await client.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: expected }));
|
|
29345
|
+
stored = true;
|
|
29346
|
+
const response = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
29347
|
+
if ((await response.Body?.transformToString()) !== expected)
|
|
29348
|
+
throw new Error('Durability probe read did not match its write.');
|
|
29349
|
+
} finally {
|
|
29350
|
+
if (stored) await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
|
|
29351
|
+
}
|
|
29352
|
+
};
|
|
29353
|
+
|
|
29354
|
+
export default createMobileUpdateRegistry({
|
|
29355
|
+
publicKeys: ${publicKeysSource(options.publicKeys)},
|
|
29356
|
+
store
|
|
29357
|
+
});
|
|
29358
|
+
`;
|
|
29359
|
+
}, writeAbsoluteMobileUpdateRegistry = async (options) => {
|
|
29360
|
+
const path2 = projectPath(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
|
|
29361
|
+
if (!options.force) {
|
|
29362
|
+
await access4(path2).then(() => {
|
|
29363
|
+
throw new TypeError(`Mobile update registry already exists: ${path2}. Pass --force to replace it.`);
|
|
29364
|
+
}, () => {
|
|
29365
|
+
return;
|
|
29366
|
+
});
|
|
29367
|
+
}
|
|
29368
|
+
await mkdir13(dirname31(path2), { recursive: true });
|
|
29369
|
+
await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
|
|
29370
|
+
publicKeys: options.publicKeys,
|
|
29371
|
+
storage: options.storage
|
|
29372
|
+
}));
|
|
29373
|
+
return path2;
|
|
29374
|
+
};
|
|
29375
|
+
var init_updateServer = () => {};
|
|
29376
|
+
|
|
28415
29377
|
// src/react/bridgeInternals.ts
|
|
28416
29378
|
var INTERNALS_KEYS, isRecord8 = (val) => typeof val === "object" && val !== null, findInternals = (mod) => {
|
|
28417
29379
|
for (const key of INTERNALS_KEYS) {
|
|
@@ -28457,10 +29419,10 @@ __export(exports_hmrCompiler, {
|
|
|
28457
29419
|
encodeHmrComponentId: () => encodeHmrComponentId,
|
|
28458
29420
|
getApplyMetadataModule: () => getApplyMetadataModule
|
|
28459
29421
|
});
|
|
28460
|
-
import { dirname as
|
|
29422
|
+
import { dirname as dirname32, relative as relative20, resolve as resolve47 } from "path";
|
|
28461
29423
|
import { performance as performance2 } from "perf_hooks";
|
|
28462
29424
|
var encodeHmrComponentId = (absoluteFilePath, className) => {
|
|
28463
|
-
const projectRel =
|
|
29425
|
+
const projectRel = relative20(process.cwd(), absoluteFilePath).replace(/\\/g, "/");
|
|
28464
29426
|
return `${projectRel}@${className}`;
|
|
28465
29427
|
}, getApplyMetadataModule = async (encodedId) => {
|
|
28466
29428
|
const decoded = decodeURIComponent(encodedId);
|
|
@@ -28469,8 +29431,8 @@ var encodeHmrComponentId = (absoluteFilePath, className) => {
|
|
|
28469
29431
|
return null;
|
|
28470
29432
|
const filePathRel = decoded.slice(0, separatorIndex);
|
|
28471
29433
|
const className = decoded.slice(separatorIndex + 1);
|
|
28472
|
-
const componentFilePath =
|
|
28473
|
-
const projectRelPath =
|
|
29434
|
+
const componentFilePath = resolve47(process.cwd(), filePathRel);
|
|
29435
|
+
const projectRelPath = relative20(process.cwd(), componentFilePath).replace(/\\/g, "/");
|
|
28474
29436
|
const cacheKey3 = encodeURIComponent(`${projectRelPath}@${className}`);
|
|
28475
29437
|
const { takePendingModule: takePendingModule2 } = await Promise.resolve().then(() => (init_fastHmrCompiler(), exports_fastHmrCompiler));
|
|
28476
29438
|
const cached = takePendingModule2(cacheKey3);
|
|
@@ -28480,7 +29442,7 @@ var encodeHmrComponentId = (absoluteFilePath, className) => {
|
|
|
28480
29442
|
const { resolveOwningComponents: resolveOwningComponents2 } = await Promise.resolve().then(() => (init_resolveOwningComponents(), exports_resolveOwningComponents));
|
|
28481
29443
|
const owners = resolveOwningComponents2({
|
|
28482
29444
|
changedFilePath: componentFilePath,
|
|
28483
|
-
userAngularRoot:
|
|
29445
|
+
userAngularRoot: dirname32(componentFilePath)
|
|
28484
29446
|
});
|
|
28485
29447
|
const owner = owners.find((o3) => o3.className === className);
|
|
28486
29448
|
const kind = owner?.kind ?? "component";
|
|
@@ -28502,7 +29464,7 @@ var exports_hmr = {};
|
|
|
28502
29464
|
__export(exports_hmr, {
|
|
28503
29465
|
hmr: () => hmr
|
|
28504
29466
|
});
|
|
28505
|
-
import
|
|
29467
|
+
import Elysia6 from "elysia";
|
|
28506
29468
|
import { websocket } from "elysia/websocket";
|
|
28507
29469
|
var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Reflect.get(globalThis, key), restoreStore = (store) => {
|
|
28508
29470
|
if (!store || typeof store !== "object")
|
|
@@ -28578,8 +29540,8 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
|
|
|
28578
29540
|
return null;
|
|
28579
29541
|
if (!pathname.startsWith("/"))
|
|
28580
29542
|
return null;
|
|
28581
|
-
const { resolve:
|
|
28582
|
-
const candidate =
|
|
29543
|
+
const { resolve: resolve48, normalize } = await import("path");
|
|
29544
|
+
const candidate = resolve48(buildDir, pathname.slice(1));
|
|
28583
29545
|
const normalizedBuild = normalize(buildDir);
|
|
28584
29546
|
if (!candidate.startsWith(normalizedBuild))
|
|
28585
29547
|
return null;
|
|
@@ -28598,7 +29560,7 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
|
|
|
28598
29560
|
return candidate;
|
|
28599
29561
|
}
|
|
28600
29562
|
return null;
|
|
28601
|
-
}, hmr = (hmrState, manifest, moduleServerHandler) => new
|
|
29563
|
+
}, hmr = (hmrState, manifest, moduleServerHandler) => new Elysia6({ name: "absolutejs-hmr" }).use(websocket({
|
|
28602
29564
|
idleTimeout: DEFAULT_WEBSOCKET_IDLE_TIMEOUT_SECONDS,
|
|
28603
29565
|
sendPings: true
|
|
28604
29566
|
})).request(async ({ request, store }) => {
|
|
@@ -28685,12 +29647,12 @@ __export(exports_devtoolsJson, {
|
|
|
28685
29647
|
resolveDevtoolsUuidCachePath: () => resolveDevtoolsUuidCachePath
|
|
28686
29648
|
});
|
|
28687
29649
|
import { existsSync as existsSync43, mkdirSync as mkdirSync14, readFileSync as readFileSync37, writeFileSync as writeFileSync10 } from "fs";
|
|
28688
|
-
import { dirname as
|
|
28689
|
-
import { Elysia as
|
|
29650
|
+
import { dirname as dirname33, join as join54, resolve as resolve48 } from "path";
|
|
29651
|
+
import { Elysia as Elysia7 } from "elysia";
|
|
28690
29652
|
var ENDPOINT = "/.well-known/appspecific/com.chrome.devtools.json", UUID_CACHE_KEY = "__absoluteDevtoolsWorkspaceUuid", getGlobalUuid = () => Reflect.get(globalThis, UUID_CACHE_KEY), setGlobalUuid = (uuid) => {
|
|
28691
29653
|
Reflect.set(globalThis, UUID_CACHE_KEY, uuid);
|
|
28692
29654
|
return uuid;
|
|
28693
|
-
}, isUuidV4 = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value), resolveDevtoolsUuidCachePath = (buildDir, uuidCachePath) =>
|
|
29655
|
+
}, isUuidV4 = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value), resolveDevtoolsUuidCachePath = (buildDir, uuidCachePath) => resolve48(uuidCachePath ?? join54(buildDir, ".absolute", "chrome-devtools-workspace-uuid")), readCachedUuid = (cachePath) => {
|
|
28694
29656
|
if (!existsSync43(cachePath))
|
|
28695
29657
|
return null;
|
|
28696
29658
|
try {
|
|
@@ -28712,14 +29674,14 @@ var ENDPOINT = "/.well-known/appspecific/com.chrome.devtools.json", UUID_CACHE_K
|
|
|
28712
29674
|
if (cachedUuid)
|
|
28713
29675
|
return setGlobalUuid(cachedUuid);
|
|
28714
29676
|
const uuid = crypto.randomUUID();
|
|
28715
|
-
mkdirSync14(
|
|
29677
|
+
mkdirSync14(dirname33(cachePath), { recursive: true });
|
|
28716
29678
|
writeFileSync10(cachePath, uuid, "utf-8");
|
|
28717
29679
|
return setGlobalUuid(uuid);
|
|
28718
29680
|
}, devtoolsJson = (buildDir, options = {}) => {
|
|
28719
|
-
const rootPath =
|
|
29681
|
+
const rootPath = resolve48(options.projectRoot ?? process.cwd());
|
|
28720
29682
|
const root = options.normalizeForWindowsContainer === false ? rootPath : normalizeDevtoolsWorkspaceRoot(rootPath);
|
|
28721
29683
|
const uuid = getOrCreateUuid(buildDir, options);
|
|
28722
|
-
return new
|
|
29684
|
+
return new Elysia7({ name: "absolute-devtools-json" }).get(ENDPOINT, () => ({
|
|
28723
29685
|
workspace: {
|
|
28724
29686
|
root,
|
|
28725
29687
|
uuid
|
|
@@ -28745,11 +29707,11 @@ __export(exports_imageOptimizer, {
|
|
|
28745
29707
|
imageOptimizer: () => imageOptimizer
|
|
28746
29708
|
});
|
|
28747
29709
|
import { existsSync as existsSync44 } from "fs";
|
|
28748
|
-
import { resolve as
|
|
28749
|
-
import { Elysia as
|
|
28750
|
-
var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avifInProgress, safeResolve = (
|
|
29710
|
+
import { resolve as resolve49 } from "path";
|
|
29711
|
+
import { Elysia as Elysia8 } from "elysia";
|
|
29712
|
+
var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avifInProgress, safeResolve = (path2, baseDir) => {
|
|
28751
29713
|
try {
|
|
28752
|
-
const resolved = validateSafePath(
|
|
29714
|
+
const resolved = validateSafePath(path2, baseDir);
|
|
28753
29715
|
if (existsSync44(resolved))
|
|
28754
29716
|
return resolved;
|
|
28755
29717
|
return null;
|
|
@@ -28758,7 +29720,7 @@ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avi
|
|
|
28758
29720
|
}
|
|
28759
29721
|
}, resolveLocalImage = (url, buildDir) => {
|
|
28760
29722
|
const cleanPath = url.startsWith("/") ? url.slice(1) : url;
|
|
28761
|
-
return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath,
|
|
29723
|
+
return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath, resolve49(process.cwd()));
|
|
28762
29724
|
}, parseQueryParams = (query, allowedSizes, defaultQuality) => {
|
|
28763
29725
|
const url = typeof query["url"] === "string" ? query["url"] : undefined;
|
|
28764
29726
|
const wParam = typeof query["w"] === "string" ? query["w"] : undefined;
|
|
@@ -28859,7 +29821,7 @@ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avi
|
|
|
28859
29821
|
}
|
|
28860
29822
|
});
|
|
28861
29823
|
}, imageOptimizer = (config, buildDir) => {
|
|
28862
|
-
const plugin = new
|
|
29824
|
+
const plugin = new Elysia8({ name: "image-optimizer" });
|
|
28863
29825
|
if (!config && config !== undefined)
|
|
28864
29826
|
return plugin;
|
|
28865
29827
|
if (config?.unoptimized)
|
|
@@ -28960,16 +29922,16 @@ var exports_requestInspector = {};
|
|
|
28960
29922
|
__export(exports_requestInspector, {
|
|
28961
29923
|
requestInspector: () => requestInspector
|
|
28962
29924
|
});
|
|
28963
|
-
import { Elysia as
|
|
29925
|
+
import { Elysia as Elysia9 } from "elysia";
|
|
28964
29926
|
var RING_MAX = 200, DEFAULT_STATUS = 200, ASSET_EXTENSION, requestLog = () => {
|
|
28965
29927
|
globalThis.__absoluteRequestLog ??= [];
|
|
28966
29928
|
return globalThis.__absoluteRequestLog;
|
|
28967
|
-
}, classify = (
|
|
28968
|
-
if (
|
|
29929
|
+
}, classify = (path2) => {
|
|
29930
|
+
if (path2.startsWith("/@") || path2.includes("/__hmr"))
|
|
28969
29931
|
return "hmr";
|
|
28970
|
-
if (
|
|
29932
|
+
if (path2.startsWith("/api"))
|
|
28971
29933
|
return "api";
|
|
28972
|
-
if (ASSET_EXTENSION.test(
|
|
29934
|
+
if (ASSET_EXTENSION.test(path2) || path2.startsWith("/assets/"))
|
|
28973
29935
|
return "asset";
|
|
28974
29936
|
return "page";
|
|
28975
29937
|
}, pathOf = (url) => {
|
|
@@ -28996,7 +29958,7 @@ var RING_MAX = 200, DEFAULT_STATUS = 200, ASSET_EXTENSION, requestLog = () => {
|
|
|
28996
29958
|
var init_requestInspector = __esm(() => {
|
|
28997
29959
|
ASSET_EXTENSION = /\.(?:avif|css|gif|ico|jpe?g|js|json|map|mjs|otf|png|svg|ttf|txt|wasm|webp|woff2?)$/i;
|
|
28998
29960
|
pending = new WeakMap;
|
|
28999
|
-
requestInspector = new
|
|
29961
|
+
requestInspector = new Elysia9({
|
|
29000
29962
|
name: "absolute-request-inspector"
|
|
29001
29963
|
}).get("/__absolute/requests", () => requestLog()).request(({ request }) => {
|
|
29002
29964
|
noteDevRequestStart();
|
|
@@ -29006,17 +29968,17 @@ var init_requestInspector = __esm(() => {
|
|
|
29006
29968
|
});
|
|
29007
29969
|
}).afterResponse(({ request, set, responseValue }) => {
|
|
29008
29970
|
noteDevRequestEnd();
|
|
29009
|
-
const
|
|
29010
|
-
if (
|
|
29971
|
+
const path2 = pathOf(request.url);
|
|
29972
|
+
if (path2.startsWith("/__absolute"))
|
|
29011
29973
|
return;
|
|
29012
29974
|
const entry = pending.get(request);
|
|
29013
29975
|
const log2 = requestLog();
|
|
29014
29976
|
log2.push({
|
|
29015
29977
|
at: Date.now(),
|
|
29016
29978
|
durationMs: entry === undefined ? 0 : performance.now() - entry.start,
|
|
29017
|
-
kind: classify(
|
|
29979
|
+
kind: classify(path2),
|
|
29018
29980
|
method: request.method,
|
|
29019
|
-
path,
|
|
29981
|
+
path: path2,
|
|
29020
29982
|
query: new URL(request.url).search,
|
|
29021
29983
|
requestHeaders: entry?.headers ?? {},
|
|
29022
29984
|
responseHeaders: toHeaderRecord(set.headers),
|
|
@@ -29029,7 +29991,7 @@ var init_requestInspector = __esm(() => {
|
|
|
29029
29991
|
});
|
|
29030
29992
|
|
|
29031
29993
|
// src/mobile/releaseArtifact.ts
|
|
29032
|
-
import { createHash as
|
|
29994
|
+
import { createHash as createHash7 } from "crypto";
|
|
29033
29995
|
var ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT = 1, ABSOLUTE_MOBILE_RETAINED_GENERATIONS = 3, SHA_256 = "sha256", RELEASE_ID_PREFIX = "amc_", MODULE_SEGMENT_PARENT = "..", EXPORT_NAME_PATTERN, frameworks2, isCanonicalRecord = (value) => {
|
|
29034
29996
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
29035
29997
|
return false;
|
|
@@ -29066,7 +30028,7 @@ var ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT = 1, ABSOLUTE_MOBILE_RETAINED_GENERATIO
|
|
|
29066
30028
|
return normalizeCanonicalRecord(value, ancestors);
|
|
29067
30029
|
}
|
|
29068
30030
|
throw new TypeError("Compatibility metadata must contain only finite JSON values.");
|
|
29069
|
-
}, canonicalJson = (value) => JSON.stringify(normalizeCanonicalValue(value, new Set)), hashCanonicalValue = (value) =>
|
|
30031
|
+
}, canonicalJson = (value) => JSON.stringify(normalizeCanonicalValue(value, new Set)), hashCanonicalValue = (value) => createHash7(SHA_256).update(canonicalJson(value)).digest("hex"), requireNonEmpty = (value, field) => {
|
|
29070
30032
|
if (!value.trim()) {
|
|
29071
30033
|
throw new TypeError(`${field} must not be empty.`);
|
|
29072
30034
|
}
|
|
@@ -29255,11 +30217,11 @@ var init_releaseArtifact = __esm(() => {
|
|
|
29255
30217
|
});
|
|
29256
30218
|
|
|
29257
30219
|
// src/mobile/artifactStore.ts
|
|
29258
|
-
import { createHash as
|
|
30220
|
+
import { createHash as createHash8 } from "crypto";
|
|
29259
30221
|
import {
|
|
29260
|
-
mkdir as
|
|
30222
|
+
mkdir as mkdir14,
|
|
29261
30223
|
mkdtemp as mkdtemp2,
|
|
29262
|
-
readFile as
|
|
30224
|
+
readFile as readFile10,
|
|
29263
30225
|
readdir as readdir5,
|
|
29264
30226
|
rename as rename5,
|
|
29265
30227
|
rm as rm13,
|
|
@@ -29268,18 +30230,18 @@ import {
|
|
|
29268
30230
|
import { join as join55, resolve as resolvePath } from "path";
|
|
29269
30231
|
var DEFAULT_MAX_PRODUCER_BYTES = 134217728, SHA_2562 = "sha256", ARTIFACT_FILE = "artifact.json", RELEASE_ID_PATTERN, DEFAULT_BLOB_PREFIX = "absolutejs/mobile-compatibility", hashBlob = async (blob) => {
|
|
29270
30232
|
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
29271
|
-
return
|
|
30233
|
+
return createHash8(SHA_2562).update(bytes).digest("hex");
|
|
29272
30234
|
}, blobFromBytes = (bytes) => {
|
|
29273
30235
|
const buffer = new ArrayBuffer(bytes.byteLength);
|
|
29274
30236
|
new Uint8Array(buffer).set(bytes);
|
|
29275
30237
|
return new Blob([buffer]);
|
|
29276
|
-
}, errorHasCode = (error, code2) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code2, appDirectoryName = (appId) =>
|
|
30238
|
+
}, errorHasCode = (error, code2) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code2, appDirectoryName = (appId) => createHash8(SHA_2562).update(appId).digest("hex"), requireReleaseId = (releaseId) => {
|
|
29277
30239
|
if (!RELEASE_ID_PATTERN.test(releaseId)) {
|
|
29278
30240
|
throw new TypeError("Invalid mobile compatibility release id.");
|
|
29279
30241
|
}
|
|
29280
30242
|
return releaseId;
|
|
29281
30243
|
}, readStoredArtifact = async (releaseDirectory) => {
|
|
29282
|
-
const serialized = await
|
|
30244
|
+
const serialized = await readFile10(join55(releaseDirectory, ARTIFACT_FILE), "utf8");
|
|
29283
30245
|
const parsed = JSON.parse(serialized);
|
|
29284
30246
|
return parseAbsoluteMobileCompatibilityArtifact(parsed);
|
|
29285
30247
|
}, validateStoredIdentity = (artifact, appId, releaseId) => {
|
|
@@ -29423,11 +30385,11 @@ var DEFAULT_MAX_PRODUCER_BYTES = 134217728, SHA_2562 = "sha256", ARTIFACT_FILE =
|
|
|
29423
30385
|
const validatedArtifact = parseAbsoluteMobileCompatibilityArtifact(release.artifact);
|
|
29424
30386
|
const validated = await verifyAbsoluteMobileCompatibilityProducer({ artifact: validatedArtifact, producer: release.producer }, maxProducerBytes);
|
|
29425
30387
|
const parent = appDirectory(validated.artifact.appId);
|
|
29426
|
-
await
|
|
30388
|
+
await mkdir14(parent, { recursive: true });
|
|
29427
30389
|
const staging = await mkdtemp2(join55(parent, ".stage-"));
|
|
29428
30390
|
const producerPath = join55(staging, validated.artifact.producer.module);
|
|
29429
30391
|
try {
|
|
29430
|
-
await
|
|
30392
|
+
await mkdir14(resolvePath(producerPath, ".."), {
|
|
29431
30393
|
recursive: true
|
|
29432
30394
|
});
|
|
29433
30395
|
await Promise.all([
|
|
@@ -29467,24 +30429,24 @@ __export(exports_materializedBundle, {
|
|
|
29467
30429
|
materializeAbsoluteMobileCompatibilityBundle: () => materializeAbsoluteMobileCompatibilityBundle,
|
|
29468
30430
|
readAbsoluteMobileMaterializedReleases: () => readAbsoluteMobileMaterializedReleases
|
|
29469
30431
|
});
|
|
29470
|
-
import { createHash as
|
|
30432
|
+
import { createHash as createHash9 } from "crypto";
|
|
29471
30433
|
import {
|
|
29472
|
-
access as
|
|
29473
|
-
mkdir as
|
|
30434
|
+
access as access5,
|
|
30435
|
+
mkdir as mkdir15,
|
|
29474
30436
|
mkdtemp as mkdtemp3,
|
|
29475
|
-
readFile as
|
|
30437
|
+
readFile as readFile11,
|
|
29476
30438
|
rename as rename6,
|
|
29477
30439
|
rm as rm14,
|
|
29478
30440
|
writeFile as writeFile12
|
|
29479
30441
|
} from "fs/promises";
|
|
29480
|
-
import { dirname as
|
|
29481
|
-
import { pathToFileURL as
|
|
30442
|
+
import { dirname as dirname34, join as join56, resolve as resolvePath2 } from "path";
|
|
30443
|
+
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
29482
30444
|
var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "current.json", BUNDLES_DIRECTORY = "bundles", ARTIFACT_FILE2 = "artifact.json", BUNDLE_ID_PATTERN, isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), errorHasCode2 = (error, code2) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code2, bundleIdFor = (currentReleaseId, releases) => {
|
|
29483
30445
|
const identity = JSON.stringify({
|
|
29484
30446
|
currentReleaseId,
|
|
29485
30447
|
releases: releases.map(({ releaseId }) => releaseId)
|
|
29486
30448
|
});
|
|
29487
|
-
return `amb_${
|
|
30449
|
+
return `amb_${createHash9("sha256").update(identity).digest("hex")}`;
|
|
29488
30450
|
}, parseBundleIndex = (value) => {
|
|
29489
30451
|
if (!isRecord9(value) || value.format !== ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT || typeof value.bundleId !== "string" || !BUNDLE_ID_PATTERN.test(value.bundleId) || typeof value.currentReleaseId !== "string" || !Array.isArray(value.releases)) {
|
|
29490
30452
|
throw new TypeError("Invalid materialized mobile compatibility bundle.");
|
|
@@ -29510,7 +30472,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29510
30472
|
}, writeRelease = async (root, release) => {
|
|
29511
30473
|
const directory = join56(root, release.artifact.releaseId);
|
|
29512
30474
|
const producerPath = join56(directory, release.artifact.producer.module);
|
|
29513
|
-
await
|
|
30475
|
+
await mkdir15(dirname34(producerPath), { recursive: true });
|
|
29514
30476
|
await Promise.all([
|
|
29515
30477
|
writeFile12(join56(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
|
|
29516
30478
|
`),
|
|
@@ -29519,7 +30481,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29519
30481
|
}, installImmutableBundle = async (bundlesRoot, bundleId, releases) => {
|
|
29520
30482
|
const destination = join56(bundlesRoot, bundleId);
|
|
29521
30483
|
try {
|
|
29522
|
-
await
|
|
30484
|
+
await access5(destination);
|
|
29523
30485
|
return destination;
|
|
29524
30486
|
} catch (error) {
|
|
29525
30487
|
if (!errorHasCode2(error, "ENOENT"))
|
|
@@ -29537,7 +30499,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29537
30499
|
throw error;
|
|
29538
30500
|
}
|
|
29539
30501
|
return destination;
|
|
29540
|
-
}, readCompatibilityModule = (modulePath) => import(
|
|
30502
|
+
}, readCompatibilityModule = (modulePath) => import(pathToFileURL4(modulePath).href), resolveProducerHandler = (loaded, exportName) => {
|
|
29541
30503
|
const value = loaded[exportName];
|
|
29542
30504
|
if (!isRecord9(value) || typeof value.handle !== "function") {
|
|
29543
30505
|
throw new TypeError(`Compatibility producer export ${exportName} must expose handle(request).`);
|
|
@@ -29556,7 +30518,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29556
30518
|
};
|
|
29557
30519
|
}, loadAbsoluteMobileMaterializedBundle = async (root) => {
|
|
29558
30520
|
const resolvedRoot = resolvePath2(root);
|
|
29559
|
-
const serialized = await
|
|
30521
|
+
const serialized = await readFile11(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
|
|
29560
30522
|
const parsed = JSON.parse(serialized);
|
|
29561
30523
|
const index = parseBundleIndex(parsed);
|
|
29562
30524
|
const bundleRoot = join56(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
|
|
@@ -29591,7 +30553,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29591
30553
|
});
|
|
29592
30554
|
const root = resolvePath2(input.root);
|
|
29593
30555
|
const bundlesRoot = join56(root, BUNDLES_DIRECTORY);
|
|
29594
|
-
await
|
|
30556
|
+
await mkdir15(bundlesRoot, { recursive: true });
|
|
29595
30557
|
const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
|
|
29596
30558
|
await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
|
|
29597
30559
|
const index = {
|
|
@@ -29609,7 +30571,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29609
30571
|
}, readAbsoluteMobileMaterializedReleases = async (root) => {
|
|
29610
30572
|
const resolvedRoot = resolvePath2(root);
|
|
29611
30573
|
try {
|
|
29612
|
-
const serialized = await
|
|
30574
|
+
const serialized = await readFile11(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
|
|
29613
30575
|
const parsed = JSON.parse(serialized);
|
|
29614
30576
|
const index = parseBundleIndex(parsed);
|
|
29615
30577
|
const bundleRoot = join56(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
|
|
@@ -30022,7 +30984,7 @@ var exports_compatibilityDispatcher = {};
|
|
|
30022
30984
|
__export(exports_compatibilityDispatcher, {
|
|
30023
30985
|
createAbsoluteMobileCompatibilityDispatcher: () => createAbsoluteMobileCompatibilityDispatcher
|
|
30024
30986
|
});
|
|
30025
|
-
import { Elysia as
|
|
30987
|
+
import { Elysia as Elysia10 } from "elysia";
|
|
30026
30988
|
var MOBILE_WEBVIEW_ORIGINS, MOBILE_REQUEST_HEADER_NAMES, MOBILE_CORS_ALLOW_HEADERS, MOBILE_CORS_METHODS, mobileWebViewOrigin = (request) => {
|
|
30027
30989
|
const origin = request.headers.get("origin");
|
|
30028
30990
|
return origin && MOBILE_WEBVIEW_ORIGINS.has(origin) ? origin : undefined;
|
|
@@ -30077,7 +31039,7 @@ var MOBILE_WEBVIEW_ORIGINS, MOBILE_REQUEST_HEADER_NAMES, MOBILE_CORS_ALLOW_HEADE
|
|
|
30077
31039
|
throw new TypeError("currentReleaseId must identify a retained compatibility artifact.");
|
|
30078
31040
|
}
|
|
30079
31041
|
const resolveProducer = createProducerResolver(options.loadProducer);
|
|
30080
|
-
return new
|
|
31042
|
+
return new Elysia10({ name: "absolutejs-mobile-compatibility-dispatcher" }).request(async ({ request }) => {
|
|
30081
31043
|
if (getCurrentAbsoluteMobileProducerContext())
|
|
30082
31044
|
return;
|
|
30083
31045
|
const preflight = mobilePreflightResponse(request);
|
|
@@ -30237,8 +31199,8 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
|
|
|
30237
31199
|
links.push(href);
|
|
30238
31200
|
}
|
|
30239
31201
|
return links;
|
|
30240
|
-
}, fetchRoute = async (baseUrl,
|
|
30241
|
-
const res = await fetchWithTimeout(`${baseUrl}${
|
|
31202
|
+
}, fetchRoute = async (baseUrl, path2) => {
|
|
31203
|
+
const res = await fetchWithTimeout(`${baseUrl}${path2}`, {
|
|
30242
31204
|
redirect: "manual"
|
|
30243
31205
|
});
|
|
30244
31206
|
if (!res.ok)
|
|
@@ -30252,21 +31214,21 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
|
|
|
30252
31214
|
const queue = ["/"];
|
|
30253
31215
|
const routes = [];
|
|
30254
31216
|
const crawlNextRoute = async () => {
|
|
30255
|
-
const
|
|
30256
|
-
if (!
|
|
31217
|
+
const path2 = queue.shift();
|
|
31218
|
+
if (!path2) {
|
|
30257
31219
|
return;
|
|
30258
31220
|
}
|
|
30259
|
-
if (visited.has(
|
|
31221
|
+
if (visited.has(path2)) {
|
|
30260
31222
|
await crawlNextRoute();
|
|
30261
31223
|
return;
|
|
30262
31224
|
}
|
|
30263
|
-
visited.add(
|
|
30264
|
-
const html = await fetchRoute(baseUrl,
|
|
31225
|
+
visited.add(path2);
|
|
31226
|
+
const html = await fetchRoute(baseUrl, path2).catch(() => null);
|
|
30265
31227
|
if (!html) {
|
|
30266
31228
|
await crawlNextRoute();
|
|
30267
31229
|
return;
|
|
30268
31230
|
}
|
|
30269
|
-
routes.push(
|
|
31231
|
+
routes.push(path2);
|
|
30270
31232
|
queue.push(...extractLinks(html, visited));
|
|
30271
31233
|
await crawlNextRoute();
|
|
30272
31234
|
};
|
|
@@ -30387,10 +31349,10 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
|
|
|
30387
31349
|
};
|
|
30388
31350
|
read();
|
|
30389
31351
|
}, formatServerOutput = (output) => {
|
|
30390
|
-
const
|
|
30391
|
-
if (!
|
|
31352
|
+
const text3 = output.join("").trim();
|
|
31353
|
+
if (!text3)
|
|
30392
31354
|
return "";
|
|
30393
|
-
return
|
|
31355
|
+
return text3.length > SERVER_OUTPUT_LIMIT ? text3.slice(-SERVER_OUTPUT_LIMIT) : text3;
|
|
30394
31356
|
}, createServerStartupError = (output) => {
|
|
30395
31357
|
const serverOutput = formatServerOutput(output);
|
|
30396
31358
|
const message = serverOutput ? `Server failed to start for pre-rendering.
|
|
@@ -30437,18 +31399,18 @@ __export(exports_prepare, {
|
|
|
30437
31399
|
prepare: () => prepare,
|
|
30438
31400
|
startDevPrebuild: () => startDevPrebuild
|
|
30439
31401
|
});
|
|
30440
|
-
import { createHash as
|
|
31402
|
+
import { createHash as createHash10 } from "crypto";
|
|
30441
31403
|
import { existsSync as existsSync45, readdirSync as readdirSync12, readFileSync as readFileSync39 } from "fs";
|
|
30442
|
-
import { basename as basename19, join as join58, relative as
|
|
30443
|
-
import { Elysia as
|
|
30444
|
-
var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_PLUGIN_RETRY_DELAY_MS = 50, waitForStaticPluginRetry = () => new Promise((
|
|
30445
|
-
setTimeout(
|
|
31404
|
+
import { basename as basename19, join as join58, relative as relative21, resolve as resolvePath3 } from "path";
|
|
31405
|
+
import { Elysia as Elysia11, NotFound } from "elysia";
|
|
31406
|
+
var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_PLUGIN_RETRY_DELAY_MS = 50, waitForStaticPluginRetry = () => new Promise((resolve50) => {
|
|
31407
|
+
setTimeout(resolve50, STATIC_PLUGIN_RETRY_DELAY_MS);
|
|
30446
31408
|
}), retryStaticPlugin = async (createStaticPlugin, options) => {
|
|
30447
31409
|
try {
|
|
30448
31410
|
return await createStaticPlugin(options);
|
|
30449
31411
|
} catch (error) {
|
|
30450
31412
|
logWarn(`Static asset routes were skipped this cycle \u2014 a build file was unavailable mid-rebuild: ${error instanceof Error ? error.message : String(error)}`);
|
|
30451
|
-
return new
|
|
31413
|
+
return new Elysia11({ name: "absolutejs-static-fallback" });
|
|
30452
31414
|
}
|
|
30453
31415
|
}, mountStaticPlugin = async (createStaticPlugin, options) => {
|
|
30454
31416
|
try {
|
|
@@ -30459,7 +31421,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30459
31421
|
}
|
|
30460
31422
|
}, MOBILE_DEV_MODULE_HEADERS, NATIVE_DEVICE_ADAPTER_PATH = "/__absolute/native-device-adapter.js", MOBILE_PREVIEW_CLIENT_PATH = "/__absolute/mobile-preview-client.js", loadMobileDevPlugin = async (mobile) => {
|
|
30461
31423
|
if (!mobile)
|
|
30462
|
-
return new
|
|
31424
|
+
return new Elysia11({ name: "absolutejs-mobile-disabled" });
|
|
30463
31425
|
const [
|
|
30464
31426
|
{ createAbsoluteMobileAssociationPlugin: createAbsoluteMobileAssociationPlugin2 },
|
|
30465
31427
|
{ createAbsoluteMobilePreviewPlugin: createAbsoluteMobilePreviewPlugin2 }
|
|
@@ -30470,19 +31432,33 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30470
31432
|
let nativeDevAdapterBundle;
|
|
30471
31433
|
const getNativeDevAdapterBundle = () => nativeDevAdapterBundle ??= Promise.resolve().then(() => (init_devDeviceAdapter(), exports_devDeviceAdapter)).then(({ buildAbsoluteNativeDevAdapter: buildAbsoluteNativeDevAdapter2 }) => buildAbsoluteNativeDevAdapter2(process.cwd(), mobile));
|
|
30472
31434
|
const getMobilePreviewClientBundle = () => Promise.resolve().then(() => (init_mobilePreviewClientBundle(), exports_mobilePreviewClientBundle)).then(({ getAbsoluteMobilePreviewClientBundle: getAbsoluteMobilePreviewClientBundle2 }) => getAbsoluteMobilePreviewClientBundle2());
|
|
30473
|
-
return new
|
|
31435
|
+
return new Elysia11({ name: "absolutejs-mobile-dev" }).use(createAbsoluteMobileAssociationPlugin2(mobile, process.cwd())).use(createAbsoluteMobilePreviewPlugin2(mobile)).get(NATIVE_DEVICE_ADAPTER_PATH, async () => new Response(await getNativeDevAdapterBundle(), {
|
|
30474
31436
|
headers: MOBILE_DEV_MODULE_HEADERS
|
|
30475
31437
|
})).get(MOBILE_PREVIEW_CLIENT_PATH, async () => new Response(await getMobilePreviewClientBundle(), {
|
|
30476
31438
|
headers: MOBILE_DEV_MODULE_HEADERS
|
|
30477
31439
|
}));
|
|
30478
31440
|
}, loadMobileAssociationPlugin = async (mobile) => {
|
|
30479
31441
|
if (!mobile) {
|
|
30480
|
-
return new
|
|
31442
|
+
return new Elysia11({ name: "absolutejs-mobile-associations-disabled" });
|
|
30481
31443
|
}
|
|
30482
31444
|
const { createAbsoluteMobileAssociationPlugin: createAbsoluteMobileAssociationPlugin2 } = await Promise.resolve().then(() => (init_associationFiles(), exports_associationFiles));
|
|
30483
31445
|
return createAbsoluteMobileAssociationPlugin2(mobile, process.cwd(), {
|
|
30484
31446
|
requireAll: true
|
|
30485
31447
|
});
|
|
31448
|
+
}, loadMobileUpdatePlugin = async (mobile, production) => {
|
|
31449
|
+
if (!mobile?.updates)
|
|
31450
|
+
return new Elysia11({ name: "absolutejs-mobile-updates-unconfigured" });
|
|
31451
|
+
const [
|
|
31452
|
+
{ normalizeAbsoluteMobileConfig: normalizeAbsoluteMobileConfig2 },
|
|
31453
|
+
{ createAbsoluteMobileUpdateServerPlugin: createAbsoluteMobileUpdateServerPlugin2 }
|
|
31454
|
+
] = await Promise.all([
|
|
31455
|
+
Promise.resolve().then(() => (init_config(), exports_config)),
|
|
31456
|
+
Promise.resolve().then(() => (init_updateServer(), exports_updateServer))
|
|
31457
|
+
]);
|
|
31458
|
+
const normalized = normalizeAbsoluteMobileConfig2(mobile, process.cwd());
|
|
31459
|
+
return createAbsoluteMobileUpdateServerPlugin2(normalized, process.cwd(), {
|
|
31460
|
+
production
|
|
31461
|
+
});
|
|
30486
31462
|
}, buildPrewarmDirs = (config) => {
|
|
30487
31463
|
const dirs = [];
|
|
30488
31464
|
if (config.svelteDirectory) {
|
|
@@ -30514,7 +31490,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30514
31490
|
return files;
|
|
30515
31491
|
}, PREWARM_MAX_PAUSE_MS = 60000, toWarmTasks = function* (files, warmCache, srcUrlPrefix) {
|
|
30516
31492
|
for (const file5 of files) {
|
|
30517
|
-
const rel =
|
|
31493
|
+
const rel = relative21(process.cwd(), file5).replace(/\\/g, "/");
|
|
30518
31494
|
yield () => warmCache(`${srcUrlPrefix}${rel}`);
|
|
30519
31495
|
}
|
|
30520
31496
|
}, builtPageSources = () => {
|
|
@@ -30555,7 +31531,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30555
31531
|
const srcPath = resolvePath3(devIndexDir, fileName);
|
|
30556
31532
|
if (!existsSync45(srcPath))
|
|
30557
31533
|
continue;
|
|
30558
|
-
const rel =
|
|
31534
|
+
const rel = relative21(process.cwd(), srcPath).replace(/\\/g, "/");
|
|
30559
31535
|
manifest[key] = `${SRC_URL_PREFIX2}${rel}`;
|
|
30560
31536
|
}
|
|
30561
31537
|
}, ICON_HASH_LENGTH = 8, registerIconVersioning = (buildDir) => {
|
|
@@ -30566,11 +31542,11 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30566
31542
|
const cached = cache2.get(href);
|
|
30567
31543
|
if (cached !== undefined)
|
|
30568
31544
|
return cached;
|
|
30569
|
-
const
|
|
30570
|
-
const filePath = join58(buildDir,
|
|
31545
|
+
const path2 = href.split("?")[0] ?? href;
|
|
31546
|
+
const filePath = join58(buildDir, path2);
|
|
30571
31547
|
let versioned = href;
|
|
30572
31548
|
if (existsSync45(filePath)) {
|
|
30573
|
-
const hash =
|
|
31549
|
+
const hash = createHash10("sha256").update(readFileSync39(filePath)).digest("hex").slice(0, ICON_HASH_LENGTH);
|
|
30574
31550
|
versioned = href.includes("?") ? `${href}&v=${hash}` : `${href}?v=${hash}`;
|
|
30575
31551
|
}
|
|
30576
31552
|
cache2.set(href, versioned);
|
|
@@ -30675,12 +31651,13 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30675
31651
|
const { requestInspector: requestInspector2 } = await Promise.resolve().then(() => (init_requestInspector(), exports_requestInspector));
|
|
30676
31652
|
const { serverTiming } = await import("@elysia/server-timing");
|
|
30677
31653
|
const mobileDevPlugin = await loadMobileDevPlugin(config.mobile);
|
|
30678
|
-
const
|
|
31654
|
+
const mobileUpdatePlugin = await loadMobileUpdatePlugin(config.mobile, false);
|
|
31655
|
+
const absolutejs = new Elysia11({ name: "absolutejs-runtime" }).use(requestInspector2).use(absoluteRequestContext).use(serverTiming()).use(devtoolsJson2(buildDir, {
|
|
30679
31656
|
normalizeForWindowsContainer: config.dev?.devtools?.normalizeForWindowsContainer,
|
|
30680
31657
|
projectRoot: config.dev?.devtools?.projectRoot,
|
|
30681
31658
|
uuid: config.dev?.devtools?.uuid,
|
|
30682
31659
|
uuidCachePath: config.dev?.devtools?.uuidCachePath
|
|
30683
|
-
})).use(imageOptimizer2(config.images, buildDir)).use(mobileDevPlugin).use(await mountStaticPlugin(staticPlugin, {
|
|
31660
|
+
})).use(imageOptimizer2(config.images, buildDir)).use(mobileDevPlugin).use(mobileUpdatePlugin).use(await mountStaticPlugin(staticPlugin, {
|
|
30684
31661
|
alwaysStatic: true,
|
|
30685
31662
|
assets: buildDir,
|
|
30686
31663
|
directive: "no-cache",
|
|
@@ -30719,7 +31696,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30719
31696
|
}, loadMobileCompatibilityPlugin = async (buildDir) => {
|
|
30720
31697
|
const root = join58(buildDir, ".absolutejs", "mobile-compatibility");
|
|
30721
31698
|
if (!existsSync45(join58(root, "current.json"))) {
|
|
30722
|
-
return new
|
|
31699
|
+
return new Elysia11({ name: "absolutejs-mobile-compatibility-empty" });
|
|
30723
31700
|
}
|
|
30724
31701
|
const [
|
|
30725
31702
|
{ loadAbsoluteMobileMaterializedBundle: loadAbsoluteMobileMaterializedBundle2 },
|
|
@@ -30730,12 +31707,12 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30730
31707
|
]);
|
|
30731
31708
|
const options = await loadAbsoluteMobileMaterializedBundle2(root);
|
|
30732
31709
|
return createAbsoluteMobileCompatibilityDispatcher2(options);
|
|
30733
|
-
}, createNotFoundPlugin = () => new
|
|
31710
|
+
}, createNotFoundPlugin = () => new Elysia11({ name: "absolutejs-not-found" }).error("global", NotFound, async () => {
|
|
30734
31711
|
const response = await renderFirstNotFound();
|
|
30735
31712
|
if (response)
|
|
30736
31713
|
return response;
|
|
30737
31714
|
return;
|
|
30738
|
-
}), createBuildErrorRecoveryPlugin = () => new
|
|
31715
|
+
}), createBuildErrorRecoveryPlugin = () => new Elysia11({ name: "absolutejs-build-error-recovery" }).error("global", async ({ error }) => {
|
|
30739
31716
|
const message = error instanceof Error ? error.message : String(error);
|
|
30740
31717
|
const assetMatch = /^Asset "(.+)" not found in manifest\.$/.exec(message);
|
|
30741
31718
|
if (!assetMatch)
|
|
@@ -30802,11 +31779,11 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30802
31779
|
staticLimit: MAX_STATIC_ROUTE_COUNT
|
|
30803
31780
|
});
|
|
30804
31781
|
const generatedAssetsRoot = join58(buildDir, ".absolutejs");
|
|
30805
|
-
const generatedAssetsPlugin = new
|
|
31782
|
+
const generatedAssetsPlugin = new Elysia11({
|
|
30806
31783
|
name: "absolutejs-generated-assets"
|
|
30807
31784
|
}).get("/.absolutejs/*", async ({ params, set }) => {
|
|
30808
31785
|
const requestedPath = resolvePath3(generatedAssetsRoot, params["*"]);
|
|
30809
|
-
if (
|
|
31786
|
+
if (relative21(generatedAssetsRoot, requestedPath).startsWith("..")) {
|
|
30810
31787
|
set.status = 404;
|
|
30811
31788
|
return "Not Found";
|
|
30812
31789
|
}
|
|
@@ -30826,7 +31803,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30826
31803
|
const hash = base.match(/[.-]([0-9a-z]{6,12})\.[0-9a-z]+$/i)?.[1];
|
|
30827
31804
|
return hash ? /[0-9]/.test(hash) && /[a-z]/i.test(hash) : false;
|
|
30828
31805
|
};
|
|
30829
|
-
const assetCachePlugin = new
|
|
31806
|
+
const assetCachePlugin = new Elysia11({
|
|
30830
31807
|
name: "absolutejs-asset-cache"
|
|
30831
31808
|
}).afterHandle("global", ({ request, responseValue }) => {
|
|
30832
31809
|
if (!(responseValue instanceof Response))
|
|
@@ -30843,13 +31820,14 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30843
31820
|
const prerenderMap = loadPrerenderMap(prerenderDir);
|
|
30844
31821
|
const mobileCompatibilityPlugin = await loadMobileCompatibilityPlugin(buildDir);
|
|
30845
31822
|
const mobileAssociationPlugin = await loadMobileAssociationPlugin(config.mobile);
|
|
31823
|
+
const mobileUpdatePlugin = await loadMobileUpdatePlugin(config.mobile, true);
|
|
30846
31824
|
recordStep("load prerender map", stepStartedAt);
|
|
30847
31825
|
if (prerenderMap.size > 0) {
|
|
30848
31826
|
const { PRERENDER_BYPASS_HEADER: PRERENDER_BYPASS_HEADER2, readTimestamp: readTimestamp2, rerenderRoute: rerenderRoute2 } = await Promise.resolve().then(() => (init_prerender(), exports_prerender));
|
|
30849
31827
|
const revalidateMs = config.static?.revalidate ? config.static.revalidate * MS_PER_SECOND2 : 0;
|
|
30850
31828
|
const port = Number(process.env.PORT) || DEFAULT_PORT2;
|
|
30851
31829
|
const rerendering = new Set;
|
|
30852
|
-
const prerenderPlugin = new
|
|
31830
|
+
const prerenderPlugin = new Elysia11({
|
|
30853
31831
|
name: "prerendered-pages"
|
|
30854
31832
|
}).request(({ request }) => {
|
|
30855
31833
|
const url = new URL(request.url);
|
|
@@ -30872,7 +31850,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30872
31850
|
});
|
|
30873
31851
|
stepStartedAt = performance.now();
|
|
30874
31852
|
const { imageOptimizer: imageOptimizer3 } = await Promise.resolve().then(() => (init_imageOptimizer(), exports_imageOptimizer));
|
|
30875
|
-
const absolutejs2 = new
|
|
31853
|
+
const absolutejs2 = new Elysia11({ name: "absolutejs-runtime" }).use(absoluteRequestContext).use(mobileAssociationPlugin).use(mobileCompatibilityPlugin).use(mobileUpdatePlugin).use(assetCachePlugin).use(imageOptimizer3(config.images, buildDir)).use(prerenderPlugin).use(staticFiles).use(generatedAssetsPlugin).use(createNotFoundPlugin());
|
|
30876
31854
|
await withOpenApi(absolutejs2, config, process.cwd(), false);
|
|
30877
31855
|
await withTelemetry(absolutejs2, config, process.cwd());
|
|
30878
31856
|
recordStep("assemble production runtime", stepStartedAt);
|
|
@@ -30881,7 +31859,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30881
31859
|
}
|
|
30882
31860
|
stepStartedAt = performance.now();
|
|
30883
31861
|
const { imageOptimizer: imageOptimizer2 } = await Promise.resolve().then(() => (init_imageOptimizer(), exports_imageOptimizer));
|
|
30884
|
-
const absolutejs = new
|
|
31862
|
+
const absolutejs = new Elysia11({ name: "absolutejs-runtime" }).use(absoluteRequestContext).use(mobileAssociationPlugin).use(mobileCompatibilityPlugin).use(mobileUpdatePlugin).use(assetCachePlugin).use(imageOptimizer2(config.images, buildDir)).use(staticFiles).use(generatedAssetsPlugin).use(createNotFoundPlugin());
|
|
30885
31863
|
await withOpenApi(absolutejs, config, process.cwd(), false);
|
|
30886
31864
|
await withTelemetry(absolutejs, config, process.cwd());
|
|
30887
31865
|
recordStep("assemble production runtime", stepStartedAt);
|
|
@@ -30961,7 +31939,7 @@ __export(exports_moduleServer, {
|
|
|
30961
31939
|
warnIfReactFastRefreshUnsupported: () => warnIfReactFastRefreshUnsupported
|
|
30962
31940
|
});
|
|
30963
31941
|
import { existsSync as existsSync46, readFileSync as readFileSync40, realpathSync as realpathSync3, statSync as statSync7 } from "fs";
|
|
30964
|
-
import { basename as basename20, dirname as
|
|
31942
|
+
import { basename as basename20, dirname as dirname35, extname as extname15, join as join59, resolve as resolve50, relative as relative22 } from "path";
|
|
30965
31943
|
var SRC_PREFIX = "/@src/", BROWSER_DEFINE, jsTranspiler2, legacyDecoratorTsconfig, tsTranspiler2, tsxTranspiler, TRANSPILABLE, ALL_EXPORTS_RE, STRING_CONTENTS_RE, preserveTypeExports = (originalSource, transpiled, valueExports) => {
|
|
30966
31944
|
const codeOnly = originalSource.replace(STRING_CONTENTS_RE, '""');
|
|
30967
31945
|
const allExports = [];
|
|
@@ -30981,10 +31959,10 @@ var SRC_PREFIX = "/@src/", BROWSER_DEFINE, jsTranspiler2, legacyDecoratorTsconfi
|
|
|
30981
31959
|
${stubs}
|
|
30982
31960
|
`;
|
|
30983
31961
|
}, resolveRelativeExtension = (srcPath, projectRoot, extensions) => {
|
|
30984
|
-
const directHit = extensions.find((ext) => existsSync46(
|
|
31962
|
+
const directHit = extensions.find((ext) => existsSync46(resolve50(projectRoot, srcPath + ext)));
|
|
30985
31963
|
if (directHit)
|
|
30986
31964
|
return srcPath + directHit;
|
|
30987
|
-
const indexHit = extensions.find((ext) => existsSync46(
|
|
31965
|
+
const indexHit = extensions.find((ext) => existsSync46(resolve50(projectRoot, srcPath, `index${ext}`)));
|
|
30988
31966
|
if (indexHit)
|
|
30989
31967
|
return `${srcPath}/index${indexHit}`;
|
|
30990
31968
|
return srcPath;
|
|
@@ -31013,7 +31991,7 @@ ${stubs}
|
|
|
31013
31991
|
return invalidationVersion > 0 ? `${mtime}.${invalidationVersion}` : `${mtime}`;
|
|
31014
31992
|
}, srcUrl = (relPath, projectRoot) => {
|
|
31015
31993
|
const base = `${SRC_PREFIX}${relPath.replace(/\\/g, "/")}`;
|
|
31016
|
-
const absPath =
|
|
31994
|
+
const absPath = resolve50(projectRoot, relPath);
|
|
31017
31995
|
const cached = mtimeCache.get(absPath);
|
|
31018
31996
|
if (cached !== undefined)
|
|
31019
31997
|
return `${base}?v=${buildVersion(cached, absPath)}`;
|
|
@@ -31025,12 +32003,12 @@ ${stubs}
|
|
|
31025
32003
|
return base;
|
|
31026
32004
|
}
|
|
31027
32005
|
}, resolveRelativeImport = (relPath, fileDir, projectRoot, extensions) => {
|
|
31028
|
-
const absPath =
|
|
31029
|
-
const rel =
|
|
32006
|
+
const absPath = resolve50(fileDir, relPath);
|
|
32007
|
+
const rel = relative22(projectRoot, absPath);
|
|
31030
32008
|
const extension = extname15(rel);
|
|
31031
32009
|
let srcPath = RESOLVED_MODULE_EXTENSIONS.has(extension) ? rel : resolveRelativeExtension(rel, projectRoot, extensions);
|
|
31032
32010
|
if (extname15(srcPath) === ".svelte") {
|
|
31033
|
-
srcPath =
|
|
32011
|
+
srcPath = relative22(projectRoot, resolveSvelteModulePath(resolve50(projectRoot, srcPath)));
|
|
31034
32012
|
}
|
|
31035
32013
|
return srcUrl(srcPath, projectRoot);
|
|
31036
32014
|
}, NODE_BUILTIN_RE, resolveAbsoluteSpecifier = (specifier, projectRoot) => {
|
|
@@ -31042,27 +32020,27 @@ ${stubs}
|
|
|
31042
32020
|
"import"
|
|
31043
32021
|
]);
|
|
31044
32022
|
if (fromExports)
|
|
31045
|
-
return
|
|
32023
|
+
return relative22(projectRoot, fromExports);
|
|
31046
32024
|
try {
|
|
31047
32025
|
const isScoped = specifier.startsWith("@");
|
|
31048
32026
|
const parts = specifier.split("/");
|
|
31049
32027
|
const packageName = isScoped ? `${parts[0]}/${parts[1]}` : parts[0];
|
|
31050
32028
|
const subpath = isScoped ? parts.slice(2).join("/") : parts.slice(1).join("/");
|
|
31051
32029
|
if (!subpath) {
|
|
31052
|
-
const pkgDir =
|
|
32030
|
+
const pkgDir = resolve50(projectRoot, "node_modules", packageName ?? "");
|
|
31053
32031
|
const pkgJsonPath = join59(pkgDir, "package.json");
|
|
31054
32032
|
if (existsSync46(pkgJsonPath)) {
|
|
31055
32033
|
const pkg = JSON.parse(readFileSync40(pkgJsonPath, "utf-8"));
|
|
31056
32034
|
const esmEntry = typeof pkg.module === "string" && pkg.module || typeof pkg.browser === "string" && pkg.browser;
|
|
31057
32035
|
if (esmEntry) {
|
|
31058
|
-
const resolved =
|
|
32036
|
+
const resolved = resolve50(pkgDir, esmEntry);
|
|
31059
32037
|
if (existsSync46(resolved))
|
|
31060
|
-
return
|
|
32038
|
+
return relative22(projectRoot, resolved);
|
|
31061
32039
|
}
|
|
31062
32040
|
}
|
|
31063
32041
|
}
|
|
31064
32042
|
} catch {}
|
|
31065
|
-
return
|
|
32043
|
+
return relative22(projectRoot, Bun.resolveSync(specifier, projectRoot));
|
|
31066
32044
|
} catch {
|
|
31067
32045
|
return;
|
|
31068
32046
|
}
|
|
@@ -31095,28 +32073,28 @@ ${stubs}
|
|
|
31095
32073
|
};
|
|
31096
32074
|
result = result.replace(/^((?:import\s+[^"'`;]+?\s+from|export\s+[^"'`;]+?\s+from|import)\s*["'])([^"'./][^"']*)(["'])/gm, stubReplace);
|
|
31097
32075
|
result = result.replace(/(import\s*\(\s*["'])([^"'./][^"']*)(["']\s*\))/g, stubReplace);
|
|
31098
|
-
const fileDir =
|
|
32076
|
+
const fileDir = dirname35(filePath);
|
|
31099
32077
|
result = result.replace(/(from\s*["'])(\.\.?\/[^"']+)(["'])/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, IMPORT_EXTENSIONS)}${suffix}` : _match);
|
|
31100
32078
|
result = result.replace(/(import\s*\(\s*["'])(\.\.?\/[^"']+)(["']\s*\))/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, IMPORT_EXTENSIONS)}${suffix}` : _match);
|
|
31101
32079
|
result = result.replace(/(import\s*["'])(\.\.?\/[^"']+)(["']\s*;?)/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, SIDE_EFFECT_EXTENSIONS)}${suffix}` : _match);
|
|
31102
32080
|
const rewriteAbsoluteToSrc = (_match, prefix, absPath, _ext, suffix) => {
|
|
31103
32081
|
if (absPath.startsWith(projectRoot)) {
|
|
31104
|
-
const rel2 =
|
|
32082
|
+
const rel2 = relative22(projectRoot, absPath).replace(/\\/g, "/");
|
|
31105
32083
|
return `${prefix}${srcUrl(rel2, projectRoot)}${suffix}`;
|
|
31106
32084
|
}
|
|
31107
|
-
const rel =
|
|
32085
|
+
const rel = relative22(projectRoot, absPath).replace(/\\/g, "/");
|
|
31108
32086
|
return `${prefix}${srcUrl(rel, projectRoot)}${suffix}`;
|
|
31109
32087
|
};
|
|
31110
32088
|
result = result.replace(/((?:from|import)\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["'])/g, rewriteAbsoluteToSrc);
|
|
31111
32089
|
result = result.replace(/(import\s*\(\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["']\s*\))/g, rewriteAbsoluteToSrc);
|
|
31112
32090
|
result = result.replace(/new\s+URL\(\s*["'](\.\.?\/[^"']+)["']\s*,\s*import\.meta\.url\s*\)/g, (_match, relPath) => {
|
|
31113
|
-
const absPath =
|
|
31114
|
-
const rel =
|
|
32091
|
+
const absPath = resolve50(fileDir, relPath);
|
|
32092
|
+
const rel = relative22(projectRoot, absPath);
|
|
31115
32093
|
return `new URL('${srcUrl(rel, projectRoot)}', import.meta.url)`;
|
|
31116
32094
|
});
|
|
31117
32095
|
result = result.replace(/import\.meta\.resolve\(\s*["'](\.\.?\/[^"']+)["']\s*\)/g, (_match, relPath) => {
|
|
31118
|
-
const absPath =
|
|
31119
|
-
const rel =
|
|
32096
|
+
const absPath = resolve50(fileDir, relPath);
|
|
32097
|
+
const rel = relative22(projectRoot, absPath);
|
|
31120
32098
|
return `'${srcUrl(rel, projectRoot)}'`;
|
|
31121
32099
|
});
|
|
31122
32100
|
return result;
|
|
@@ -31172,7 +32150,7 @@ ${code2}`;
|
|
|
31172
32150
|
transpiled = `var $RefreshReg$ = window.$RefreshReg$ || function(){};
|
|
31173
32151
|
` + `var $RefreshSig$ = window.$RefreshSig$ || function(){ return function(t){ return t; }; };
|
|
31174
32152
|
${transpiled}`;
|
|
31175
|
-
const relPath =
|
|
32153
|
+
const relPath = relative22(projectRoot, filePath).replace(/\\/g, "/");
|
|
31176
32154
|
transpiled = transpiled.replace(/\binput\.tsx:/g, `${relPath}:`);
|
|
31177
32155
|
transpiled += buildIslandMetadataExports(raw);
|
|
31178
32156
|
return rewriteImports(transpiled, filePath, projectRoot, rewriter);
|
|
@@ -31333,11 +32311,11 @@ ${code2}`;
|
|
|
31333
32311
|
if (compiled.css?.code) {
|
|
31334
32312
|
const cssPath = `${filePath}.css`;
|
|
31335
32313
|
svelteExternalCss.set(cssPath, compiled.css.code);
|
|
31336
|
-
const cssUrl = srcUrl(
|
|
32314
|
+
const cssUrl = srcUrl(relative22(projectRoot, cssPath), projectRoot);
|
|
31337
32315
|
code2 = `import "${cssUrl}";
|
|
31338
32316
|
${code2}`;
|
|
31339
32317
|
}
|
|
31340
|
-
const moduleUrl = `${SRC_PREFIX}${
|
|
32318
|
+
const moduleUrl = `${SRC_PREFIX}${relative22(projectRoot, filePath).replace(/\\/g, "/")}`;
|
|
31341
32319
|
code2 = code2.replace(/if\s*\(import\.meta\.hot\)\s*\{/, `if (typeof window !== "undefined") {
|
|
31342
32320
|
` + ` if (!window.__SVELTE_HMR_ACCEPT__) window.__SVELTE_HMR_ACCEPT__ = {};
|
|
31343
32321
|
` + ` var __hmr_accept = function(cb) { window.__SVELTE_HMR_ACCEPT__[${JSON.stringify(moduleUrl)}] = cb; };`);
|
|
@@ -31437,8 +32415,8 @@ ${code2}`;
|
|
|
31437
32415
|
code2 = injectVueHmr(code2, filePath, projectRoot, vueDir);
|
|
31438
32416
|
return rewriteImports(code2, filePath, projectRoot, rewriter);
|
|
31439
32417
|
}, injectVueHmr = (code2, filePath, projectRoot, vueDir) => {
|
|
31440
|
-
const hmrBase = vueDir ?
|
|
31441
|
-
const hmrId =
|
|
32418
|
+
const hmrBase = vueDir ? resolve50(vueDir) : projectRoot;
|
|
32419
|
+
const hmrId = relative22(hmrBase, filePath).replace(/\\/g, "/").replace(/\.vue$/, "");
|
|
31442
32420
|
let result = code2.replace(/export\s+default\s+/, "var __hmr_comp__ = ");
|
|
31443
32421
|
result += [
|
|
31444
32422
|
"",
|
|
@@ -31451,14 +32429,14 @@ ${code2}`;
|
|
|
31451
32429
|
].join(`
|
|
31452
32430
|
`);
|
|
31453
32431
|
return result;
|
|
31454
|
-
}, resolveSvelteModulePath = (
|
|
31455
|
-
if (existsSync46(
|
|
31456
|
-
return
|
|
31457
|
-
if (existsSync46(`${
|
|
31458
|
-
return `${
|
|
31459
|
-
if (existsSync46(`${
|
|
31460
|
-
return `${
|
|
31461
|
-
return
|
|
32432
|
+
}, resolveSvelteModulePath = (path2) => {
|
|
32433
|
+
if (existsSync46(path2))
|
|
32434
|
+
return path2;
|
|
32435
|
+
if (existsSync46(`${path2}.ts`))
|
|
32436
|
+
return `${path2}.ts`;
|
|
32437
|
+
if (existsSync46(`${path2}.js`))
|
|
32438
|
+
return `${path2}.js`;
|
|
32439
|
+
return path2;
|
|
31462
32440
|
}, jsResponse = (body) => {
|
|
31463
32441
|
const etag = `"${Bun.hash(body).toString(BASE_36_RADIX)}"`;
|
|
31464
32442
|
return new Response(body, {
|
|
@@ -31598,7 +32576,7 @@ export default {};
|
|
|
31598
32576
|
const escaped = virtualCss.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
|
|
31599
32577
|
return jsResponse(`var s=document.createElement('style');s.textContent=\`${escaped}\`;s.dataset.svelteHmr=${JSON.stringify(cssCheckPath)};var p=document.querySelector('style[data-svelte-hmr="${cssCheckPath}"]');if(p)p.remove();document.head.appendChild(s);`);
|
|
31600
32578
|
}, resolveSourcePath2 = (relPath, projectRoot) => {
|
|
31601
|
-
const filePath =
|
|
32579
|
+
const filePath = resolve50(projectRoot, relPath);
|
|
31602
32580
|
const ext = extname15(filePath);
|
|
31603
32581
|
if (ext === ".svelte")
|
|
31604
32582
|
return { ext, filePath: resolveSvelteModulePath(filePath) };
|
|
@@ -31616,10 +32594,10 @@ export default {};
|
|
|
31616
32594
|
return jsResponse(handleCssRequest(filePath));
|
|
31617
32595
|
if (ext === ".json") {
|
|
31618
32596
|
try {
|
|
31619
|
-
const { readFile:
|
|
32597
|
+
const { readFile: readFile12, stat: stat5 } = await import("fs/promises");
|
|
31620
32598
|
const fileExists2 = async (p2) => {
|
|
31621
32599
|
try {
|
|
31622
|
-
await
|
|
32600
|
+
await stat5(p2);
|
|
31623
32601
|
return true;
|
|
31624
32602
|
} catch {
|
|
31625
32603
|
return false;
|
|
@@ -31635,14 +32613,14 @@ export default {};
|
|
|
31635
32613
|
const absoluteCandidate = `/${tail.replace(/^\/+/, "")}`;
|
|
31636
32614
|
const candidates = [
|
|
31637
32615
|
absoluteCandidate,
|
|
31638
|
-
|
|
32616
|
+
resolve50(projectRoot, tail)
|
|
31639
32617
|
];
|
|
31640
32618
|
try {
|
|
31641
32619
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_loadConfig(), exports_loadConfig));
|
|
31642
32620
|
const cfg = await loadConfig2();
|
|
31643
|
-
const angularDir = cfg.angularDirectory &&
|
|
32621
|
+
const angularDir = cfg.angularDirectory && resolve50(projectRoot, cfg.angularDirectory);
|
|
31644
32622
|
if (angularDir)
|
|
31645
|
-
candidates.push(
|
|
32623
|
+
candidates.push(resolve50(angularDir, tail));
|
|
31646
32624
|
} catch {}
|
|
31647
32625
|
for (const candidate of candidates) {
|
|
31648
32626
|
if (await fileExists2(candidate)) {
|
|
@@ -31652,9 +32630,9 @@ export default {};
|
|
|
31652
32630
|
}
|
|
31653
32631
|
}
|
|
31654
32632
|
}
|
|
31655
|
-
const
|
|
31656
|
-
JSON.parse(
|
|
31657
|
-
return jsResponse(`export default ${
|
|
32633
|
+
const text3 = await readFile12(sourcePath, "utf-8");
|
|
32634
|
+
JSON.parse(text3);
|
|
32635
|
+
return jsResponse(`export default ${text3};`);
|
|
31658
32636
|
} catch (err) {
|
|
31659
32637
|
return new Response(`console.error('[ModuleServer] JSON load error in ${filePath}:', ${JSON.stringify(String(err))});`, {
|
|
31660
32638
|
headers: { "Content-Type": "application/javascript" },
|
|
@@ -31672,8 +32650,8 @@ export default {};
|
|
|
31672
32650
|
return transformAndCacheVue(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
|
|
31673
32651
|
if (!TRANSPILABLE.has(ext))
|
|
31674
32652
|
return;
|
|
31675
|
-
const
|
|
31676
|
-
const resolvedVueDir = vueDir ?
|
|
32653
|
+
const stat4 = statSync7(filePath);
|
|
32654
|
+
const resolvedVueDir = vueDir ? resolve50(vueDir) : undefined;
|
|
31677
32655
|
let content = REACT_EXTENSIONS.has(ext) ? transformReactFile(filePath, projectRoot, rewriter) : transformPlainFile(filePath, projectRoot, rewriter, resolvedVueDir);
|
|
31678
32656
|
const isAngularGeneratedJs = ext === ".js" && filePath.replace(/\\/g, "/").includes("/.absolutejs/generated/angular/");
|
|
31679
32657
|
if (isAngularGeneratedJs) {
|
|
@@ -31692,7 +32670,7 @@ export default {};
|
|
|
31692
32670
|
}
|
|
31693
32671
|
}
|
|
31694
32672
|
}
|
|
31695
|
-
setTransformed(filePath, content,
|
|
32673
|
+
setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
|
|
31696
32674
|
return jsResponse(content);
|
|
31697
32675
|
}, cachedAngularUserRoot, getAngularUserRoot = async (_projectRoot) => {
|
|
31698
32676
|
if (cachedAngularUserRoot !== undefined)
|
|
@@ -31700,14 +32678,14 @@ export default {};
|
|
|
31700
32678
|
cachedAngularUserRoot = configuredAngularUserRoot ?? null;
|
|
31701
32679
|
return cachedAngularUserRoot;
|
|
31702
32680
|
}, configuredAngularUserRoot, transformAndCacheSvelte = async (filePath, projectRoot, rewriter, stylePreprocessors) => {
|
|
31703
|
-
const
|
|
32681
|
+
const stat4 = statSync7(filePath);
|
|
31704
32682
|
const content = await transformSvelteFile(filePath, projectRoot, rewriter, stylePreprocessors);
|
|
31705
|
-
setTransformed(filePath, content,
|
|
32683
|
+
setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
|
|
31706
32684
|
return jsResponse(content);
|
|
31707
32685
|
}, transformAndCacheVue = async (filePath, projectRoot, rewriter, vueDir, stylePreprocessors) => {
|
|
31708
|
-
const
|
|
32686
|
+
const stat4 = statSync7(filePath);
|
|
31709
32687
|
const content = await transformVueFile(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
|
|
31710
|
-
setTransformed(filePath, content,
|
|
32688
|
+
setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
|
|
31711
32689
|
return jsResponse(content);
|
|
31712
32690
|
}, transformErrorResponse = (err) => {
|
|
31713
32691
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -31732,7 +32710,7 @@ export default {};
|
|
|
31732
32710
|
const relPath = pathname.slice(SRC_PREFIX.length);
|
|
31733
32711
|
if (relPath === "bun:wrap" || relPath.startsWith("bun:wrap?"))
|
|
31734
32712
|
return handleBunWrapRequest();
|
|
31735
|
-
const virtualCssResponse = handleVirtualSvelteCss(
|
|
32713
|
+
const virtualCssResponse = handleVirtualSvelteCss(resolve50(projectRoot, relPath));
|
|
31736
32714
|
if (virtualCssResponse)
|
|
31737
32715
|
return virtualCssResponse;
|
|
31738
32716
|
const { filePath, ext } = resolveSourcePath2(relPath, projectRoot);
|
|
@@ -31748,11 +32726,11 @@ export default {};
|
|
|
31748
32726
|
SRC_IMPORT_RE.lastIndex = 0;
|
|
31749
32727
|
while ((match = SRC_IMPORT_RE.exec(content)) !== null) {
|
|
31750
32728
|
if (match[1])
|
|
31751
|
-
files.push(
|
|
32729
|
+
files.push(resolve50(projectRoot, match[1]));
|
|
31752
32730
|
}
|
|
31753
32731
|
return files;
|
|
31754
32732
|
}, invalidateModule = (filePath) => {
|
|
31755
|
-
const resolved =
|
|
32733
|
+
const resolved = resolve50(filePath);
|
|
31756
32734
|
invalidate(filePath);
|
|
31757
32735
|
if (resolved !== filePath)
|
|
31758
32736
|
invalidate(resolved);
|
|
@@ -31815,7 +32793,7 @@ export default {};
|
|
|
31815
32793
|
return false;
|
|
31816
32794
|
}
|
|
31817
32795
|
const { patchManifestIndexes: patchManifestIndexes2 } = await Promise.resolve().then(() => (init_prepare(), exports_prepare));
|
|
31818
|
-
patchManifestIndexes2(cached.manifest,
|
|
32796
|
+
patchManifestIndexes2(cached.manifest, resolve50(state.resolvedPaths.buildDir, "_src_indexes"), SRC_PREFIX);
|
|
31819
32797
|
logPageBuild(entry.source, entry.framework, Math.round(durationMs));
|
|
31820
32798
|
logStartupTimingBlock("AbsoluteJS on-demand page build", [
|
|
31821
32799
|
{ durationMs, label: entry.name }
|
|
@@ -31947,7 +32925,7 @@ __export(exports_rewriteImports, {
|
|
|
31947
32925
|
rewriteVendorDirectories: () => rewriteVendorDirectories2
|
|
31948
32926
|
});
|
|
31949
32927
|
var rewriteImports2 = async (outputPaths, vendorPaths) => {
|
|
31950
|
-
const jsFiles = outputPaths.filter((
|
|
32928
|
+
const jsFiles = outputPaths.filter((path2) => path2.endsWith(".js"));
|
|
31951
32929
|
if (jsFiles.length === 0)
|
|
31952
32930
|
return;
|
|
31953
32931
|
if (Object.keys(vendorPaths).length === 0)
|
|
@@ -31981,13 +32959,13 @@ var init_rewriteImports = __esm(() => {
|
|
|
31981
32959
|
});
|
|
31982
32960
|
|
|
31983
32961
|
// src/core/pageResponseCache.ts
|
|
31984
|
-
import { createHash as
|
|
32962
|
+
import { createHash as createHash11 } from "crypto";
|
|
31985
32963
|
var STREAMING_PAGE_HEADER = "x-absolute-stream", HTML_CONTENT_TYPE = "text/html", streamingPageHeaders = (extra) => {
|
|
31986
32964
|
const headers = new Headers(extra);
|
|
31987
32965
|
headers.set("content-type", HTML_CONTENT_TYPE);
|
|
31988
32966
|
headers.set(STREAMING_PAGE_HEADER, "1");
|
|
31989
32967
|
return headers;
|
|
31990
|
-
}, computeEtag = (html) => `W/"${
|
|
32968
|
+
}, computeEtag = (html) => `W/"${createHash11("sha1").update(html).digest("base64url")}"`, withPageCacheHeaders = async (response, request, options) => {
|
|
31991
32969
|
const contentType = response.headers.get("content-type") ?? "";
|
|
31992
32970
|
if (!contentType.includes(HTML_CONTENT_TYPE))
|
|
31993
32971
|
return response;
|
|
@@ -32055,7 +33033,7 @@ var init_routeAssets = __esm(() => {
|
|
|
32055
33033
|
});
|
|
32056
33034
|
|
|
32057
33035
|
// src/ember/pageHandler.ts
|
|
32058
|
-
import { pathToFileURL as
|
|
33036
|
+
import { pathToFileURL as pathToFileURL5 } from "url";
|
|
32059
33037
|
var resolveRequestPathname2 = (request) => {
|
|
32060
33038
|
if (!request)
|
|
32061
33039
|
return;
|
|
@@ -32077,7 +33055,7 @@ var resolveRequestPathname2 = (request) => {
|
|
|
32077
33055
|
}, emberCacheBuster = 0, buildRuntimeModuleSpecifier = (modulePath) => {
|
|
32078
33056
|
if (emberCacheBuster === 0)
|
|
32079
33057
|
return modulePath;
|
|
32080
|
-
const moduleUrl = new URL(
|
|
33058
|
+
const moduleUrl = new URL(pathToFileURL5(modulePath).href);
|
|
32081
33059
|
moduleUrl.searchParams.set("t", String(emberCacheBuster));
|
|
32082
33060
|
return moduleUrl.href;
|
|
32083
33061
|
}, invalidateEmberSsrCache = () => {
|
|
@@ -32178,11 +33156,11 @@ var exports_simpleHTMLHMR = {};
|
|
|
32178
33156
|
__export(exports_simpleHTMLHMR, {
|
|
32179
33157
|
handleHTMLUpdate: () => handleHTMLUpdate
|
|
32180
33158
|
});
|
|
32181
|
-
import { resolve as
|
|
33159
|
+
import { resolve as resolve51 } from "path";
|
|
32182
33160
|
var handleHTMLUpdate = async (htmlFilePath) => {
|
|
32183
33161
|
let htmlContent;
|
|
32184
33162
|
try {
|
|
32185
|
-
const resolvedPath =
|
|
33163
|
+
const resolvedPath = resolve51(htmlFilePath);
|
|
32186
33164
|
const file5 = Bun.file(resolvedPath);
|
|
32187
33165
|
if (!await file5.exists()) {
|
|
32188
33166
|
return null;
|
|
@@ -32208,11 +33186,11 @@ var exports_simpleHTMXHMR = {};
|
|
|
32208
33186
|
__export(exports_simpleHTMXHMR, {
|
|
32209
33187
|
handleHTMXUpdate: () => handleHTMXUpdate
|
|
32210
33188
|
});
|
|
32211
|
-
import { resolve as
|
|
33189
|
+
import { resolve as resolve52 } from "path";
|
|
32212
33190
|
var handleHTMXUpdate = async (htmxFilePath) => {
|
|
32213
33191
|
let htmlContent;
|
|
32214
33192
|
try {
|
|
32215
|
-
const resolvedPath =
|
|
33193
|
+
const resolvedPath = resolve52(htmxFilePath);
|
|
32216
33194
|
const file5 = Bun.file(resolvedPath);
|
|
32217
33195
|
if (!await file5.exists()) {
|
|
32218
33196
|
return null;
|
|
@@ -32243,12 +33221,12 @@ __export(exports_rebuildTrigger, {
|
|
|
32243
33221
|
import { existsSync as existsSync47, readdirSync as readdirSync13, rmSync as rmSync4 } from "fs";
|
|
32244
33222
|
import {
|
|
32245
33223
|
basename as basename21,
|
|
32246
|
-
dirname as
|
|
32247
|
-
isAbsolute as
|
|
33224
|
+
dirname as dirname36,
|
|
33225
|
+
isAbsolute as isAbsolute9,
|
|
32248
33226
|
join as join60,
|
|
32249
|
-
relative as
|
|
33227
|
+
relative as relative23,
|
|
32250
33228
|
resolve as resolvePath4,
|
|
32251
|
-
sep as
|
|
33229
|
+
sep as sep5
|
|
32252
33230
|
} from "path";
|
|
32253
33231
|
var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSsrCssCaches = () => {
|
|
32254
33232
|
clearSpaRouteCssCaches();
|
|
@@ -32607,14 +33585,14 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
32607
33585
|
const relFromDir = normalizedSource.slice(normalizedDir.length + 1);
|
|
32608
33586
|
const { buildDir } = state.resolvedPaths;
|
|
32609
33587
|
const destPath = resolvePath4(buildDir, urlPrefix ? `${urlPrefix}/${relFromDir}` : relFromDir);
|
|
32610
|
-
const { mkdir:
|
|
32611
|
-
await
|
|
33588
|
+
const { mkdir: mkdir16, copyFile, readFile: readFile12 } = await import("fs/promises");
|
|
33589
|
+
await mkdir16(dirname36(destPath), { recursive: true });
|
|
32612
33590
|
await copyFile(absSource, destPath);
|
|
32613
|
-
const bytes = await
|
|
33591
|
+
const bytes = await readFile12(destPath);
|
|
32614
33592
|
const webPath = urlPrefix ? `/${urlPrefix}/${relFromDir}` : `/${relFromDir}`;
|
|
32615
33593
|
state.assetStore.set(webPath, new Uint8Array(bytes));
|
|
32616
33594
|
state.fileHashes.set(absSource, currentHash);
|
|
32617
|
-
logHmrUpdate(
|
|
33595
|
+
logHmrUpdate(relative23(process.cwd(), filePath));
|
|
32618
33596
|
broadcastToClients(state, {
|
|
32619
33597
|
data: {
|
|
32620
33598
|
framework: urlPrefix || "public",
|
|
@@ -32634,7 +33612,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
32634
33612
|
return;
|
|
32635
33613
|
if (framework === "unknown") {
|
|
32636
33614
|
invalidate(resolvePath4(filePath));
|
|
32637
|
-
const relPath =
|
|
33615
|
+
const relPath = relative23(process.cwd(), filePath);
|
|
32638
33616
|
logHmrUpdate(relPath);
|
|
32639
33617
|
const { angularDir } = state.resolvedPaths;
|
|
32640
33618
|
let hasAngularDependent = false;
|
|
@@ -32790,7 +33768,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
32790
33768
|
const keepStemsByDir = new Map;
|
|
32791
33769
|
const prefixByDir = new Map;
|
|
32792
33770
|
for (const artifact of freshOutputs) {
|
|
32793
|
-
const dir =
|
|
33771
|
+
const dir = dirname36(artifact.path);
|
|
32794
33772
|
const name = basename21(artifact.path);
|
|
32795
33773
|
const [prefix] = name.split(".");
|
|
32796
33774
|
if (!prefix)
|
|
@@ -33156,8 +34134,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33156
34134
|
};
|
|
33157
34135
|
return ({ immediate = false } = {}) => {
|
|
33158
34136
|
if (!ctx.debouncedPromise) {
|
|
33159
|
-
ctx.debouncedPromise = new Promise((
|
|
33160
|
-
ctx.debouncedResolve =
|
|
34137
|
+
ctx.debouncedPromise = new Promise((resolve53) => {
|
|
34138
|
+
ctx.debouncedResolve = resolve53;
|
|
33161
34139
|
});
|
|
33162
34140
|
}
|
|
33163
34141
|
const scheduled = ctx.debouncedPromise;
|
|
@@ -33183,7 +34161,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33183
34161
|
const angularDirAbs = resolvePath4(angularDir);
|
|
33184
34162
|
const filesUnderAngular = Array.from(editedFiles).filter((file5) => {
|
|
33185
34163
|
const abs = resolvePath4(file5);
|
|
33186
|
-
return abs === angularDirAbs || abs.startsWith(angularDirAbs +
|
|
34164
|
+
return abs === angularDirAbs || abs.startsWith(angularDirAbs + sep5);
|
|
33187
34165
|
});
|
|
33188
34166
|
if (filesUnderAngular.length === 0)
|
|
33189
34167
|
return;
|
|
@@ -33226,7 +34204,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33226
34204
|
try {
|
|
33227
34205
|
const { invalidateModule: invalidateModule2 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
|
|
33228
34206
|
for (const tsFile of tsFilesToRefresh) {
|
|
33229
|
-
const rel =
|
|
34207
|
+
const rel = relative23(angularDirAbs, tsFile).replace(/\\/g, "/").replace(/\.[tj]sx?$/, ".js");
|
|
33230
34208
|
const compiledFile = resolvePath4(compiledRoot, rel);
|
|
33231
34209
|
invalidateModule2(compiledFile);
|
|
33232
34210
|
}
|
|
@@ -33381,7 +34359,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33381
34359
|
}, getModuleUrl = async (pageFile) => {
|
|
33382
34360
|
const { invalidateModule: invalidateModule2, warmCache: warmCache2, SRC_URL_PREFIX: SRC_URL_PREFIX3 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
|
|
33383
34361
|
invalidateModule2(pageFile);
|
|
33384
|
-
const rel =
|
|
34362
|
+
const rel = relative23(process.cwd(), pageFile).replace(/\\/g, "/");
|
|
33385
34363
|
const url = `${SRC_URL_PREFIX3}${rel}`;
|
|
33386
34364
|
await warmCache2(url);
|
|
33387
34365
|
return url;
|
|
@@ -33409,7 +34387,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33409
34387
|
const pageModuleUrl = await getReactModuleUrl(broadcastTarget);
|
|
33410
34388
|
if (pageModuleUrl) {
|
|
33411
34389
|
const serverDuration = Date.now() - startTime;
|
|
33412
|
-
state.lastHmrPath =
|
|
34390
|
+
state.lastHmrPath = relative23(process.cwd(), primaryFile).replace(/\\/g, "/");
|
|
33413
34391
|
state.lastHmrFramework = "react";
|
|
33414
34392
|
broadcastToClients(state, {
|
|
33415
34393
|
data: {
|
|
@@ -33702,8 +34680,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33702
34680
|
};
|
|
33703
34681
|
return () => {
|
|
33704
34682
|
if (!ctx.debouncedPromise) {
|
|
33705
|
-
ctx.debouncedPromise = new Promise((
|
|
33706
|
-
ctx.debouncedResolve =
|
|
34683
|
+
ctx.debouncedPromise = new Promise((resolve53) => {
|
|
34684
|
+
ctx.debouncedResolve = resolve53;
|
|
33707
34685
|
});
|
|
33708
34686
|
}
|
|
33709
34687
|
if (ctx.debounceTimer)
|
|
@@ -33914,7 +34892,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33914
34892
|
if (vueSpaRoutesBySource.size > 0) {
|
|
33915
34893
|
const spaManifestEntries = await writeSpaSideManifests(vueSpaRoutesBySource, (pascalName) => {
|
|
33916
34894
|
const fromManifest = state.manifest[pascalName];
|
|
33917
|
-
return typeof fromManifest === "string" &&
|
|
34895
|
+
return typeof fromManifest === "string" && isAbsolute9(fromManifest) && fromManifest.endsWith(".js") ? fromManifest : undefined;
|
|
33918
34896
|
});
|
|
33919
34897
|
Object.assign(state.manifest, spaManifestEntries);
|
|
33920
34898
|
}
|
|
@@ -33984,8 +34962,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33984
34962
|
};
|
|
33985
34963
|
return () => {
|
|
33986
34964
|
if (!ctx.debouncedPromise) {
|
|
33987
|
-
ctx.debouncedPromise = new Promise((
|
|
33988
|
-
ctx.debouncedResolve =
|
|
34965
|
+
ctx.debouncedPromise = new Promise((resolve53) => {
|
|
34966
|
+
ctx.debouncedResolve = resolve53;
|
|
33989
34967
|
});
|
|
33990
34968
|
}
|
|
33991
34969
|
if (ctx.debounceTimer)
|
|
@@ -34038,7 +35016,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
34038
35016
|
const duration = Date.now() - startTime;
|
|
34039
35017
|
const [primary] = emberFiles;
|
|
34040
35018
|
if (primary) {
|
|
34041
|
-
state.lastHmrPath =
|
|
35019
|
+
state.lastHmrPath = relative23(process.cwd(), primary).replace(/\\/g, "/");
|
|
34042
35020
|
state.lastHmrFramework = "ember";
|
|
34043
35021
|
logHmrUpdate(primary, "ember", duration);
|
|
34044
35022
|
}
|
|
@@ -34135,7 +35113,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
34135
35113
|
if (!buildReference?.source) {
|
|
34136
35114
|
return;
|
|
34137
35115
|
}
|
|
34138
|
-
const sourcePath = buildReference.source.startsWith("file://") ? new URL(buildReference.source).pathname : resolvePath4(
|
|
35116
|
+
const sourcePath = buildReference.source.startsWith("file://") ? new URL(buildReference.source).pathname : resolvePath4(dirname36(buildInfo.resolvedRegistryPath), buildReference.source);
|
|
34139
35117
|
islandFiles.add(resolvePath4(sourcePath));
|
|
34140
35118
|
}, resolveIslandSourceFiles = async (config) => {
|
|
34141
35119
|
const registryPath = config.islands?.registry;
|
|
@@ -34307,7 +35285,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
34307
35285
|
const baseName = fileName.replace(/\.vue$/, "");
|
|
34308
35286
|
const pascalName = toPascal(baseName);
|
|
34309
35287
|
const vueRoot = config.vueDirectory;
|
|
34310
|
-
const hmrId = vueRoot ?
|
|
35288
|
+
const hmrId = vueRoot ? relative23(vueRoot, vuePagePath).replace(/\\/g, "/").replace(/\.vue$/, "") : baseName;
|
|
34311
35289
|
const cssKey = `${pascalName}CSS`;
|
|
34312
35290
|
const cssUrl = manifest[cssKey] || null;
|
|
34313
35291
|
const { vueHmrMetadata: vueHmrMetadata2 } = await Promise.resolve().then(() => (init_compileVue(), exports_compileVue));
|
|
@@ -34521,10 +35499,10 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
34521
35499
|
if (sourceVersion !== undefined) {
|
|
34522
35500
|
moduleVersions[update.sourceFile] = sourceVersion;
|
|
34523
35501
|
}
|
|
34524
|
-
Object.values(update.modulePaths).forEach((
|
|
34525
|
-
const pathVersion = moduleVersionsStore.get(
|
|
35502
|
+
Object.values(update.modulePaths).forEach((path2) => {
|
|
35503
|
+
const pathVersion = moduleVersionsStore.get(path2);
|
|
34526
35504
|
if (pathVersion !== undefined) {
|
|
34527
|
-
moduleVersions[
|
|
35505
|
+
moduleVersions[path2] = pathVersion;
|
|
34528
35506
|
}
|
|
34529
35507
|
});
|
|
34530
35508
|
}, handleModuleUpdates = (state, allModuleUpdates, manifest) => {
|
|
@@ -34986,7 +35964,7 @@ var toSafeFileName6 = (specifier) => {
|
|
|
34986
35964
|
} catch {
|
|
34987
35965
|
return false;
|
|
34988
35966
|
}
|
|
34989
|
-
}, isBareSpecifier3 = (spec) => !spec.startsWith(".") && !spec.startsWith("/") && !spec.startsWith("@src/"), isAbsolutePackageSpecifier = (spec) => spec === "@absolutejs/absolute" || spec.startsWith("@absolutejs/absolute/"), FRAMEWORK_SPECIFIERS, FRAMEWORK_NAMESPACE_PREFIXES, isFrameworkSpecifier = (spec) => FRAMEWORK_SPECIFIERS.has(spec) || FRAMEWORK_NAMESPACE_PREFIXES.some((prefix) => spec.startsWith(prefix)), FRAMEWORK_EXTERNALS, isSkippedFile = (file5) => file5.includes("node_modules") || file5.includes("/build/") || file5.includes("/dist/") || file5.includes("/indexes/") || isTestSourcePath(file5), isDepSpecifier = (
|
|
35967
|
+
}, isBareSpecifier3 = (spec) => !spec.startsWith(".") && !spec.startsWith("/") && !spec.startsWith("@src/"), isAbsolutePackageSpecifier = (spec) => spec === "@absolutejs/absolute" || spec.startsWith("@absolutejs/absolute/"), FRAMEWORK_SPECIFIERS, FRAMEWORK_NAMESPACE_PREFIXES, isFrameworkSpecifier = (spec) => FRAMEWORK_SPECIFIERS.has(spec) || FRAMEWORK_NAMESPACE_PREFIXES.some((prefix) => spec.startsWith(prefix)), FRAMEWORK_EXTERNALS, isSkippedFile = (file5) => file5.includes("node_modules") || file5.includes("/build/") || file5.includes("/dist/") || file5.includes("/indexes/") || isTestSourcePath(file5), isDepSpecifier = (path2) => isBareSpecifier3(path2) && !isBuiltin2(path2) && !isFrameworkSpecifier(path2) && !isAbsolutePackageSpecifier(path2), isFrameworkRootCandidate = (path2) => isBareSpecifier3(path2) && isFrameworkSpecifier(path2) && !isAbsolutePackageSpecifier(path2), readFileSpecifiers = async (file5, transpiler7) => {
|
|
34990
35968
|
const dep = [];
|
|
34991
35969
|
const framework = [];
|
|
34992
35970
|
try {
|
|
@@ -35030,22 +36008,22 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35030
36008
|
};
|
|
35031
36009
|
}, collectBareImportsFromFile = async (entryPath, transpiler7, maxDepth = 8) => {
|
|
35032
36010
|
const { readFileSync: readFileSync41 } = await import("fs");
|
|
35033
|
-
const { dirname:
|
|
36011
|
+
const { dirname: dirname37 } = await import("path");
|
|
35034
36012
|
const seenFiles = new Set;
|
|
35035
36013
|
const bareOut = new Set;
|
|
35036
36014
|
const queue = [
|
|
35037
36015
|
{ depth: 0, path: entryPath }
|
|
35038
36016
|
];
|
|
35039
36017
|
while (queue.length > 0) {
|
|
35040
|
-
const { path, depth } = queue.shift();
|
|
35041
|
-
if (seenFiles.has(
|
|
36018
|
+
const { path: path2, depth } = queue.shift();
|
|
36019
|
+
if (seenFiles.has(path2))
|
|
35042
36020
|
continue;
|
|
35043
|
-
seenFiles.add(
|
|
36021
|
+
seenFiles.add(path2);
|
|
35044
36022
|
if (depth > maxDepth)
|
|
35045
36023
|
continue;
|
|
35046
36024
|
let content;
|
|
35047
36025
|
try {
|
|
35048
|
-
content = readFileSync41(
|
|
36026
|
+
content = readFileSync41(path2, "utf-8");
|
|
35049
36027
|
} catch {
|
|
35050
36028
|
continue;
|
|
35051
36029
|
}
|
|
@@ -35055,7 +36033,7 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35055
36033
|
} catch {
|
|
35056
36034
|
continue;
|
|
35057
36035
|
}
|
|
35058
|
-
const fromDir =
|
|
36036
|
+
const fromDir = dirname37(path2);
|
|
35059
36037
|
for (const imp of imports) {
|
|
35060
36038
|
const child = imp.path;
|
|
35061
36039
|
if (child.startsWith(".") || child.startsWith("/")) {
|
|
@@ -35075,7 +36053,7 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35075
36053
|
}
|
|
35076
36054
|
return Array.from(bareOut);
|
|
35077
36055
|
}, MAX_DISCOVERY_FILES = 2000, collectTransitiveImports = async (specs, alreadyVendored, alreadyScanned) => {
|
|
35078
|
-
const { dirname:
|
|
36056
|
+
const { dirname: dirname37 } = await import("path");
|
|
35079
36057
|
const transpiler7 = new Bun.Transpiler({ loader: "js" });
|
|
35080
36058
|
const newSpecs = new Set;
|
|
35081
36059
|
const queue = [...specs].map((spec) => ({ from: process.cwd(), spec }));
|
|
@@ -35096,7 +36074,7 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35096
36074
|
}
|
|
35097
36075
|
visited += 1;
|
|
35098
36076
|
const bareImports = await collectBareImportsFromFile(resolved, transpiler7);
|
|
35099
|
-
const importerDirectory =
|
|
36077
|
+
const importerDirectory = dirname37(resolved);
|
|
35100
36078
|
for (const child of bareImports) {
|
|
35101
36079
|
if (!isBareSpecifier3(child))
|
|
35102
36080
|
continue;
|
|
@@ -35159,11 +36137,11 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35159
36137
|
const output = lastResult.outputs[0];
|
|
35160
36138
|
if (!output)
|
|
35161
36139
|
return lastResult;
|
|
35162
|
-
const
|
|
36140
|
+
const text3 = await output.text();
|
|
35163
36141
|
REQUIRE_CALL_RE.lastIndex = 0;
|
|
35164
36142
|
const requiredSpecs = new Set;
|
|
35165
36143
|
let match;
|
|
35166
|
-
while ((match = REQUIRE_CALL_RE.exec(
|
|
36144
|
+
while ((match = REQUIRE_CALL_RE.exec(text3)) !== null) {
|
|
35167
36145
|
const requiredSpec = match[1];
|
|
35168
36146
|
if (requiredSpec && externalsSet.has(requiredSpec)) {
|
|
35169
36147
|
requiredSpecs.add(requiredSpec);
|
|
@@ -35310,7 +36288,7 @@ __export(exports_vendorCache, {
|
|
|
35310
36288
|
saveVendorCache: () => saveVendorCache,
|
|
35311
36289
|
vendorCacheEnabled: () => vendorCacheEnabled
|
|
35312
36290
|
});
|
|
35313
|
-
import { createHash as
|
|
36291
|
+
import { createHash as createHash12 } from "crypto";
|
|
35314
36292
|
import {
|
|
35315
36293
|
copyFileSync as copyFileSync4,
|
|
35316
36294
|
existsSync as existsSync48,
|
|
@@ -35318,10 +36296,10 @@ import {
|
|
|
35318
36296
|
readdirSync as readdirSync14,
|
|
35319
36297
|
readFileSync as readFileSync41
|
|
35320
36298
|
} from "fs";
|
|
35321
|
-
import { mkdir as
|
|
35322
|
-
import { basename as basename22, join as join62, resolve as
|
|
36299
|
+
import { mkdir as mkdir16, readFile as readFile12, rename as rename7, rm as rm16, writeFile as writeFile13 } from "fs/promises";
|
|
36300
|
+
import { basename as basename22, join as join62, resolve as resolve53 } from "path";
|
|
35323
36301
|
var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeVendorCacheKey = (inputs) => {
|
|
35324
|
-
const hash =
|
|
36302
|
+
const hash = createHash12("sha256");
|
|
35325
36303
|
hash.update(String(CACHE_FORMAT_VERSION3));
|
|
35326
36304
|
hash.update("\x00");
|
|
35327
36305
|
hash.update(inputs.lockfileHash);
|
|
@@ -35339,19 +36317,19 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
|
|
|
35339
36317
|
}
|
|
35340
36318
|
for (const dir of inputs.vendorDirs) {
|
|
35341
36319
|
hash.update("\x00v");
|
|
35342
|
-
hash.update(basename22(
|
|
36320
|
+
hash.update(basename22(resolve53(dir, "..")));
|
|
35343
36321
|
}
|
|
35344
36322
|
return hash.digest("hex").slice(0, KEY_LENGTH);
|
|
35345
36323
|
}, readLockfileHash = (projectRoot = process.cwd()) => {
|
|
35346
|
-
const hash =
|
|
36324
|
+
const hash = createHash12("sha256");
|
|
35347
36325
|
let found = false;
|
|
35348
36326
|
for (const name of LOCKFILES) {
|
|
35349
|
-
const
|
|
35350
|
-
if (!existsSync48(
|
|
36327
|
+
const path2 = join62(projectRoot, name);
|
|
36328
|
+
if (!existsSync48(path2))
|
|
35351
36329
|
continue;
|
|
35352
36330
|
found = true;
|
|
35353
36331
|
hash.update(name);
|
|
35354
|
-
hash.update(readFileSync41(
|
|
36332
|
+
hash.update(readFileSync41(path2));
|
|
35355
36333
|
}
|
|
35356
36334
|
return found ? hash.digest("hex") : null;
|
|
35357
36335
|
}, vendorCacheEnabled = () => process.env.ABSOLUTE_DEV_VENDOR_CACHE !== "0", copyTree = (fromDir, toDir) => {
|
|
@@ -35378,13 +36356,13 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
|
|
|
35378
36356
|
continue;
|
|
35379
36357
|
copyTree(dir, join62(stagingDir, slotName(index, dir)));
|
|
35380
36358
|
}
|
|
35381
|
-
}, isVendorCachePayload = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "depPaths") === "object", cacheDirFor = (key, projectRoot) =>
|
|
36359
|
+
}, isVendorCachePayload = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "depPaths") === "object", cacheDirFor = (key, projectRoot) => resolve53(projectRoot, CACHE_ROOT2, key), slotName = (index, dir) => `${index}-${basename22(resolve53(dir, ".."))}`, restoreVendorCache = async (key, vendorDirs, projectRoot = process.cwd()) => {
|
|
35382
36360
|
const cacheDir2 = cacheDirFor(key, projectRoot);
|
|
35383
36361
|
const payloadPath = join62(cacheDir2, "payload.json");
|
|
35384
36362
|
if (!existsSync48(payloadPath))
|
|
35385
36363
|
return null;
|
|
35386
36364
|
try {
|
|
35387
|
-
const payload = JSON.parse(await
|
|
36365
|
+
const payload = JSON.parse(await readFile12(payloadPath, "utf8"));
|
|
35388
36366
|
if (!isVendorCachePayload(payload))
|
|
35389
36367
|
return null;
|
|
35390
36368
|
copySlotsInto(cacheDir2, vendorDirs);
|
|
@@ -35399,7 +36377,7 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
|
|
|
35399
36377
|
const stagingDir = `${cacheDir2}.${process.pid}.tmp`;
|
|
35400
36378
|
try {
|
|
35401
36379
|
await rm16(stagingDir, { force: true, recursive: true });
|
|
35402
|
-
await
|
|
36380
|
+
await mkdir16(stagingDir, { recursive: true });
|
|
35403
36381
|
copySlotsFrom(stagingDir, vendorDirs);
|
|
35404
36382
|
await writeFile13(join62(stagingDir, "payload.json"), JSON.stringify(payload));
|
|
35405
36383
|
await rm16(cacheDir2, { force: true, recursive: true });
|
|
@@ -35430,8 +36408,8 @@ __export(exports_devBuild, {
|
|
|
35430
36408
|
});
|
|
35431
36409
|
import { readdir as readdir6 } from "fs/promises";
|
|
35432
36410
|
import { existsSync as existsSync49, statSync as statSync8 } from "fs";
|
|
35433
|
-
import { resolve as
|
|
35434
|
-
var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () =>
|
|
36411
|
+
import { resolve as resolve54 } from "path";
|
|
36412
|
+
var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve54(import.meta.dir, "../dev/client"), collectDepVendorSourceDirs = (config) => {
|
|
35435
36413
|
const configuredDirs = [
|
|
35436
36414
|
...collectConfigVendorSourceDirs(config),
|
|
35437
36415
|
devClientVendorSourceDir()
|
|
@@ -35454,7 +36432,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35454
36432
|
return Object.keys(config).length > 0 ? config : null;
|
|
35455
36433
|
}, reloadConfig = async () => {
|
|
35456
36434
|
try {
|
|
35457
|
-
const configPath2 =
|
|
36435
|
+
const configPath2 = resolve54(process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
|
|
35458
36436
|
const source = await Bun.file(configPath2).text();
|
|
35459
36437
|
return parseDirectoryConfig(source);
|
|
35460
36438
|
} catch {
|
|
@@ -35506,7 +36484,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35506
36484
|
setEmberVendorPaths(computeEmberVendorPaths());
|
|
35507
36485
|
}
|
|
35508
36486
|
const newWatchPaths = getWatchPaths(state.config, state.resolvedPaths);
|
|
35509
|
-
const addedPaths = newWatchPaths.filter((
|
|
36487
|
+
const addedPaths = newWatchPaths.filter((path2) => !oldWatchPaths.has(path2));
|
|
35510
36488
|
if (addedPaths.length > 0) {
|
|
35511
36489
|
buildInitialDependencyGraph(state.dependencyGraph, addedPaths);
|
|
35512
36490
|
addFileWatchers(state, addedPaths, (filePath) => {
|
|
@@ -35569,7 +36547,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35569
36547
|
});
|
|
35570
36548
|
}
|
|
35571
36549
|
}, handleCachedReload = async () => {
|
|
35572
|
-
const serverMtime = statSync8(
|
|
36550
|
+
const serverMtime = statSync8(resolve54(Bun.main)).mtimeMs;
|
|
35573
36551
|
const lastMtime = globalThis.__hmrServerMtime;
|
|
35574
36552
|
globalThis.__hmrServerMtime = serverMtime;
|
|
35575
36553
|
const cached = globalThis.__hmrDevResult;
|
|
@@ -35601,8 +36579,8 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35601
36579
|
return;
|
|
35602
36580
|
await detectConfigChanges(cached);
|
|
35603
36581
|
await rebuildManifest(cached);
|
|
35604
|
-
}, tryReadPackageVersion = async (
|
|
35605
|
-
const pkg = await Bun.file(
|
|
36582
|
+
}, tryReadPackageVersion = async (path2) => {
|
|
36583
|
+
const pkg = await Bun.file(path2).json().catch(() => null);
|
|
35606
36584
|
if (!pkg || pkg.name !== "@absolutejs/absolute") {
|
|
35607
36585
|
return false;
|
|
35608
36586
|
}
|
|
@@ -35610,8 +36588,8 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35610
36588
|
return true;
|
|
35611
36589
|
}, resolveAbsoluteVersion2 = async () => {
|
|
35612
36590
|
const candidates = [
|
|
35613
|
-
|
|
35614
|
-
|
|
36591
|
+
resolve54(import.meta.dir, "..", "..", "package.json"),
|
|
36592
|
+
resolve54(import.meta.dir, "..", "package.json")
|
|
35615
36593
|
];
|
|
35616
36594
|
const [candidate, ...remaining] = candidates;
|
|
35617
36595
|
if (!candidate) {
|
|
@@ -35637,7 +36615,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35637
36615
|
const entries = await readdir6(vendorDir).catch(() => emptyStringArray);
|
|
35638
36616
|
await Promise.all(entries.filter((entry) => entry.endsWith(".js")).map(async (entry) => {
|
|
35639
36617
|
const webPath = `/${framework}/vendor/${entry}`;
|
|
35640
|
-
const bytes = await Bun.file(
|
|
36618
|
+
const bytes = await Bun.file(resolve54(vendorDir, entry)).bytes();
|
|
35641
36619
|
assetStore.set(webPath, bytes);
|
|
35642
36620
|
}));
|
|
35643
36621
|
}, devBuild = async (config) => {
|
|
@@ -35823,11 +36801,11 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35823
36801
|
}
|
|
35824
36802
|
stepStartedAt = performance.now();
|
|
35825
36803
|
setBootPhase("build vendor bundles");
|
|
35826
|
-
const reactVendorDir =
|
|
35827
|
-
const angularVendorDir =
|
|
35828
|
-
const svelteVendorDir =
|
|
35829
|
-
const vueVendorDir =
|
|
35830
|
-
const depVendorDir =
|
|
36804
|
+
const reactVendorDir = resolve54(state.resolvedPaths.buildDir, "react", "vendor");
|
|
36805
|
+
const angularVendorDir = resolve54(state.resolvedPaths.buildDir, "angular", "vendor");
|
|
36806
|
+
const svelteVendorDir = resolve54(state.resolvedPaths.buildDir, "svelte", "vendor");
|
|
36807
|
+
const vueVendorDir = resolve54(state.resolvedPaths.buildDir, "vue", "vendor");
|
|
36808
|
+
const depVendorDir = resolve54(state.resolvedPaths.buildDir, "vendor");
|
|
35831
36809
|
const { buildDepVendor: buildDepVendor2 } = await Promise.resolve().then(() => (init_buildDepVendor(), exports_buildDepVendor));
|
|
35832
36810
|
const activeVendorDirs = [
|
|
35833
36811
|
config.reactDirectory ? reactVendorDir : null,
|
|
@@ -35950,7 +36928,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35950
36928
|
manifest
|
|
35951
36929
|
};
|
|
35952
36930
|
globalThis.__hmrDevResult = result;
|
|
35953
|
-
globalThis.__hmrServerMtime = statSync8(
|
|
36931
|
+
globalThis.__hmrServerMtime = statSync8(resolve54(Bun.main)).mtimeMs;
|
|
35954
36932
|
return result;
|
|
35955
36933
|
};
|
|
35956
36934
|
var init_devBuild = __esm(() => {
|
|
@@ -35991,5 +36969,5 @@ export {
|
|
|
35991
36969
|
devBuild
|
|
35992
36970
|
};
|
|
35993
36971
|
|
|
35994
|
-
//# debugId=
|
|
36972
|
+
//# debugId=7849DC008DCD28AC64756E2164756E21
|
|
35995
36973
|
//# sourceMappingURL=build.js.map
|