@absolutejs/absolute 0.20.0-beta.80 → 0.20.0-beta.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build.js +1170 -222
- package/dist/build.js.map +7 -5
- package/dist/cli/{compile-x4hfth3p.js → compile-t73ac1zb.js} +2 -2
- package/dist/cli/{config-z8wwxatc.js → config-naw5fer4.js} +1 -1
- package/dist/cli/{dev-8vv459ty.js → dev-skb8dz33.js} +1 -1
- package/dist/cli/{index-w5y7wxn9.js → index-8gksmws3.js} +1 -1
- package/dist/cli/{index-6fb7k6dg.js → index-czw3jd8f.js} +47 -1
- package/dist/cli/{index-d4ar3mwd.js → index-q78x1k9q.js} +2 -2
- package/dist/cli/index.js +5 -5
- package/dist/cli/{mobile-mfp26v2d.js → mobile-rdwdcks1.js} +359 -136
- package/dist/cli/{start-dtrp1pry.js → start-jbgfw27x.js} +3 -3
- package/dist/index.js +2043 -1095
- package/dist/index.js.map +7 -5
- package/dist/mobile/index.js +946 -4
- package/dist/mobile/index.js.map +7 -5
- package/dist/mobile/remoteMacAgentEntry.js +205 -205
- package/dist/src/mobile/config.d.ts +8 -0
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/updateServer.d.ts +33 -0
- package/dist/types/build.d.ts +16 -0
- package/package.json +3 -2
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,889 @@ 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 !== 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 !== 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
|
+
return {
|
|
29219
|
+
metadata: serverMetadata(loaded.absoluteMobileUpdateServer),
|
|
29220
|
+
registry: registry2
|
|
29221
|
+
};
|
|
29222
|
+
}, expoSigningOptions = (config) => {
|
|
29223
|
+
if (!config.updates?.expoCodeSigning)
|
|
29224
|
+
return;
|
|
29225
|
+
const entries = Object.entries(config.updateServer?.expoCodeSigningKeys ?? {});
|
|
29226
|
+
const keys = Object.fromEntries(entries.map(([keyId, key]) => {
|
|
29227
|
+
const privateKey = process.env[key.privateKeyEnv];
|
|
29228
|
+
if (!privateKey)
|
|
29229
|
+
throw new TypeError(`Expo update serving requires ${key.privateKeyEnv} on the trusted server.`);
|
|
29230
|
+
try {
|
|
29231
|
+
const certificate = new X509Certificate3(key.certificatePem);
|
|
29232
|
+
const expected = certificate.publicKey.export({
|
|
29233
|
+
format: "der",
|
|
29234
|
+
type: "spki"
|
|
29235
|
+
});
|
|
29236
|
+
const actual = createPublicKey3(createPrivateKey2(privateKey)).export({
|
|
29237
|
+
format: "der",
|
|
29238
|
+
type: "spki"
|
|
29239
|
+
});
|
|
29240
|
+
if (!expected.equals(actual))
|
|
29241
|
+
throw new Error("key mismatch");
|
|
29242
|
+
} catch (error) {
|
|
29243
|
+
throw new TypeError(`${key.privateKeyEnv} must contain the RSA private key matching Expo update key ${keyId}.`, { cause: error });
|
|
29244
|
+
}
|
|
29245
|
+
return [keyId, { certificate: key.certificatePem, privateKey }];
|
|
29246
|
+
}));
|
|
29247
|
+
return { keys };
|
|
29248
|
+
}, createAbsoluteMobileUpdateServerPlugin = async (config, projectRoot, options = {}) => {
|
|
29249
|
+
const { updates, updateServer: server } = config;
|
|
29250
|
+
if (!updates || !server?.autoMount)
|
|
29251
|
+
return new Elysia5({ name: "absolutejs-mobile-updates-disabled" });
|
|
29252
|
+
const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, server.registryModule);
|
|
29253
|
+
if (options.production && module.metadata.storage !== "durable")
|
|
29254
|
+
throw new TypeError("Mobile production updates require durable object storage. Re-run `absolute mobile update provision --storage s3 --force` or configure a durable adapter.");
|
|
29255
|
+
const manifest = new URL(updates.manifestUrl);
|
|
29256
|
+
if (!manifest.pathname.endsWith("/update.json"))
|
|
29257
|
+
throw new TypeError("Auto-mounted mobile update manifests must end in /update.json.");
|
|
29258
|
+
const route = manifest.pathname.slice(0, -"/update.json".length);
|
|
29259
|
+
const { createMobileUpdateHandler: createMobileUpdateHandler2 } = await Promise.resolve().then(() => (init_mobileUpdate(), exports_mobileUpdate));
|
|
29260
|
+
const handler = createMobileUpdateHandler2({
|
|
29261
|
+
appId: config.appId,
|
|
29262
|
+
channel: updates.channel,
|
|
29263
|
+
...config.engine === "expo" ? { expoCodeSigning: expoSigningOptions(config) } : {},
|
|
29264
|
+
registry: module.registry,
|
|
29265
|
+
route
|
|
29266
|
+
});
|
|
29267
|
+
return new Elysia5({ name: "absolutejs-mobile-updates" }).all(`${route}/*`, ({ request }) => handler(request));
|
|
29268
|
+
}, inspectAbsoluteMobileUpdateServer = async (config, projectRoot) => {
|
|
29269
|
+
if (!config.updates)
|
|
29270
|
+
return;
|
|
29271
|
+
const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, config.updateServer?.registryModule);
|
|
29272
|
+
if (module.metadata.storage !== "durable")
|
|
29273
|
+
throw new TypeError("Mobile production updates require durable object storage; the configured registry is local-only.");
|
|
29274
|
+
if (config.engine === "expo")
|
|
29275
|
+
expoSigningOptions(config);
|
|
29276
|
+
return module.metadata;
|
|
29277
|
+
}, publicKeysSource = (publicKeys) => JSON.stringify(publicKeys, null, "\t"), renderAbsoluteMobileUpdateRegistry = (options) => {
|
|
29278
|
+
const metadata = `export const absoluteMobileUpdateServer = {
|
|
29279
|
+
format: 1,
|
|
29280
|
+
provider: '${options.storage}',
|
|
29281
|
+
storage: '${options.storage === "local" ? "local" : "durable"}'
|
|
29282
|
+
} as const;`;
|
|
29283
|
+
if (options.storage === "local")
|
|
29284
|
+
return `import { fileURLToPath } from 'node:url';
|
|
29285
|
+
import { localBlobStore } from '@absolutejs/blob/local';
|
|
29286
|
+
import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
|
|
29287
|
+
|
|
29288
|
+
${metadata}
|
|
29289
|
+
|
|
29290
|
+
const store = localBlobStore({
|
|
29291
|
+
root: process.env.ABSOLUTE_MOBILE_UPDATE_LOCAL_ROOT ??
|
|
29292
|
+
fileURLToPath(new URL('./.absolutejs/mobile/update-registry/', import.meta.url))
|
|
29293
|
+
});
|
|
29294
|
+
|
|
29295
|
+
export default createMobileUpdateRegistry({
|
|
29296
|
+
publicKeys: ${publicKeysSource(options.publicKeys)},
|
|
29297
|
+
store
|
|
29298
|
+
});
|
|
29299
|
+
`;
|
|
29300
|
+
return `import { S3Client } from '@aws-sdk/client-s3';
|
|
29301
|
+
import { awsS3BlobStore } from '@absolutejs/blob/aws-s3';
|
|
29302
|
+
import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
|
|
29303
|
+
|
|
29304
|
+
${metadata}
|
|
29305
|
+
|
|
29306
|
+
const required = (name: string) => {
|
|
29307
|
+
const value = process.env[name];
|
|
29308
|
+
if (!value) throw new Error(\`Missing \${name}\`);
|
|
29309
|
+
return value;
|
|
29310
|
+
};
|
|
29311
|
+
|
|
29312
|
+
const client = new S3Client({
|
|
29313
|
+
region: process.env.ABSOLUTE_MOBILE_UPDATE_S3_REGION ?? 'auto',
|
|
29314
|
+
forcePathStyle: process.env.ABSOLUTE_MOBILE_UPDATE_S3_FORCE_PATH_STYLE === '1',
|
|
29315
|
+
...(process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT
|
|
29316
|
+
? { endpoint: process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT }
|
|
29317
|
+
: {})
|
|
29318
|
+
});
|
|
29319
|
+
const store = awsS3BlobStore({
|
|
29320
|
+
bucket: required('ABSOLUTE_MOBILE_UPDATE_S3_BUCKET'),
|
|
29321
|
+
client
|
|
29322
|
+
});
|
|
29323
|
+
|
|
29324
|
+
export default createMobileUpdateRegistry({
|
|
29325
|
+
publicKeys: ${publicKeysSource(options.publicKeys)},
|
|
29326
|
+
store
|
|
29327
|
+
});
|
|
29328
|
+
`;
|
|
29329
|
+
}, writeAbsoluteMobileUpdateRegistry = async (options) => {
|
|
29330
|
+
const path2 = projectPath(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
|
|
29331
|
+
if (!options.force) {
|
|
29332
|
+
await access4(path2).then(() => {
|
|
29333
|
+
throw new TypeError(`Mobile update registry already exists: ${path2}. Pass --force to replace it.`);
|
|
29334
|
+
}, () => {
|
|
29335
|
+
return;
|
|
29336
|
+
});
|
|
29337
|
+
}
|
|
29338
|
+
await mkdir13(dirname31(path2), { recursive: true });
|
|
29339
|
+
await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
|
|
29340
|
+
publicKeys: options.publicKeys,
|
|
29341
|
+
storage: options.storage
|
|
29342
|
+
}));
|
|
29343
|
+
return path2;
|
|
29344
|
+
};
|
|
29345
|
+
var init_updateServer = () => {};
|
|
29346
|
+
|
|
28415
29347
|
// src/react/bridgeInternals.ts
|
|
28416
29348
|
var INTERNALS_KEYS, isRecord8 = (val) => typeof val === "object" && val !== null, findInternals = (mod) => {
|
|
28417
29349
|
for (const key of INTERNALS_KEYS) {
|
|
@@ -28457,10 +29389,10 @@ __export(exports_hmrCompiler, {
|
|
|
28457
29389
|
encodeHmrComponentId: () => encodeHmrComponentId,
|
|
28458
29390
|
getApplyMetadataModule: () => getApplyMetadataModule
|
|
28459
29391
|
});
|
|
28460
|
-
import { dirname as
|
|
29392
|
+
import { dirname as dirname32, relative as relative20, resolve as resolve47 } from "path";
|
|
28461
29393
|
import { performance as performance2 } from "perf_hooks";
|
|
28462
29394
|
var encodeHmrComponentId = (absoluteFilePath, className) => {
|
|
28463
|
-
const projectRel =
|
|
29395
|
+
const projectRel = relative20(process.cwd(), absoluteFilePath).replace(/\\/g, "/");
|
|
28464
29396
|
return `${projectRel}@${className}`;
|
|
28465
29397
|
}, getApplyMetadataModule = async (encodedId) => {
|
|
28466
29398
|
const decoded = decodeURIComponent(encodedId);
|
|
@@ -28469,8 +29401,8 @@ var encodeHmrComponentId = (absoluteFilePath, className) => {
|
|
|
28469
29401
|
return null;
|
|
28470
29402
|
const filePathRel = decoded.slice(0, separatorIndex);
|
|
28471
29403
|
const className = decoded.slice(separatorIndex + 1);
|
|
28472
|
-
const componentFilePath =
|
|
28473
|
-
const projectRelPath =
|
|
29404
|
+
const componentFilePath = resolve47(process.cwd(), filePathRel);
|
|
29405
|
+
const projectRelPath = relative20(process.cwd(), componentFilePath).replace(/\\/g, "/");
|
|
28474
29406
|
const cacheKey3 = encodeURIComponent(`${projectRelPath}@${className}`);
|
|
28475
29407
|
const { takePendingModule: takePendingModule2 } = await Promise.resolve().then(() => (init_fastHmrCompiler(), exports_fastHmrCompiler));
|
|
28476
29408
|
const cached = takePendingModule2(cacheKey3);
|
|
@@ -28480,7 +29412,7 @@ var encodeHmrComponentId = (absoluteFilePath, className) => {
|
|
|
28480
29412
|
const { resolveOwningComponents: resolveOwningComponents2 } = await Promise.resolve().then(() => (init_resolveOwningComponents(), exports_resolveOwningComponents));
|
|
28481
29413
|
const owners = resolveOwningComponents2({
|
|
28482
29414
|
changedFilePath: componentFilePath,
|
|
28483
|
-
userAngularRoot:
|
|
29415
|
+
userAngularRoot: dirname32(componentFilePath)
|
|
28484
29416
|
});
|
|
28485
29417
|
const owner = owners.find((o3) => o3.className === className);
|
|
28486
29418
|
const kind = owner?.kind ?? "component";
|
|
@@ -28502,7 +29434,7 @@ var exports_hmr = {};
|
|
|
28502
29434
|
__export(exports_hmr, {
|
|
28503
29435
|
hmr: () => hmr
|
|
28504
29436
|
});
|
|
28505
|
-
import
|
|
29437
|
+
import Elysia6 from "elysia";
|
|
28506
29438
|
import { websocket } from "elysia/websocket";
|
|
28507
29439
|
var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Reflect.get(globalThis, key), restoreStore = (store) => {
|
|
28508
29440
|
if (!store || typeof store !== "object")
|
|
@@ -28578,8 +29510,8 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
|
|
|
28578
29510
|
return null;
|
|
28579
29511
|
if (!pathname.startsWith("/"))
|
|
28580
29512
|
return null;
|
|
28581
|
-
const { resolve:
|
|
28582
|
-
const candidate =
|
|
29513
|
+
const { resolve: resolve48, normalize } = await import("path");
|
|
29514
|
+
const candidate = resolve48(buildDir, pathname.slice(1));
|
|
28583
29515
|
const normalizedBuild = normalize(buildDir);
|
|
28584
29516
|
if (!candidate.startsWith(normalizedBuild))
|
|
28585
29517
|
return null;
|
|
@@ -28598,7 +29530,7 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
|
|
|
28598
29530
|
return candidate;
|
|
28599
29531
|
}
|
|
28600
29532
|
return null;
|
|
28601
|
-
}, hmr = (hmrState, manifest, moduleServerHandler) => new
|
|
29533
|
+
}, hmr = (hmrState, manifest, moduleServerHandler) => new Elysia6({ name: "absolutejs-hmr" }).use(websocket({
|
|
28602
29534
|
idleTimeout: DEFAULT_WEBSOCKET_IDLE_TIMEOUT_SECONDS,
|
|
28603
29535
|
sendPings: true
|
|
28604
29536
|
})).request(async ({ request, store }) => {
|
|
@@ -28685,12 +29617,12 @@ __export(exports_devtoolsJson, {
|
|
|
28685
29617
|
resolveDevtoolsUuidCachePath: () => resolveDevtoolsUuidCachePath
|
|
28686
29618
|
});
|
|
28687
29619
|
import { existsSync as existsSync43, mkdirSync as mkdirSync14, readFileSync as readFileSync37, writeFileSync as writeFileSync10 } from "fs";
|
|
28688
|
-
import { dirname as
|
|
28689
|
-
import { Elysia as
|
|
29620
|
+
import { dirname as dirname33, join as join54, resolve as resolve48 } from "path";
|
|
29621
|
+
import { Elysia as Elysia7 } from "elysia";
|
|
28690
29622
|
var ENDPOINT = "/.well-known/appspecific/com.chrome.devtools.json", UUID_CACHE_KEY = "__absoluteDevtoolsWorkspaceUuid", getGlobalUuid = () => Reflect.get(globalThis, UUID_CACHE_KEY), setGlobalUuid = (uuid) => {
|
|
28691
29623
|
Reflect.set(globalThis, UUID_CACHE_KEY, uuid);
|
|
28692
29624
|
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) =>
|
|
29625
|
+
}, 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
29626
|
if (!existsSync43(cachePath))
|
|
28695
29627
|
return null;
|
|
28696
29628
|
try {
|
|
@@ -28712,14 +29644,14 @@ var ENDPOINT = "/.well-known/appspecific/com.chrome.devtools.json", UUID_CACHE_K
|
|
|
28712
29644
|
if (cachedUuid)
|
|
28713
29645
|
return setGlobalUuid(cachedUuid);
|
|
28714
29646
|
const uuid = crypto.randomUUID();
|
|
28715
|
-
mkdirSync14(
|
|
29647
|
+
mkdirSync14(dirname33(cachePath), { recursive: true });
|
|
28716
29648
|
writeFileSync10(cachePath, uuid, "utf-8");
|
|
28717
29649
|
return setGlobalUuid(uuid);
|
|
28718
29650
|
}, devtoolsJson = (buildDir, options = {}) => {
|
|
28719
|
-
const rootPath =
|
|
29651
|
+
const rootPath = resolve48(options.projectRoot ?? process.cwd());
|
|
28720
29652
|
const root = options.normalizeForWindowsContainer === false ? rootPath : normalizeDevtoolsWorkspaceRoot(rootPath);
|
|
28721
29653
|
const uuid = getOrCreateUuid(buildDir, options);
|
|
28722
|
-
return new
|
|
29654
|
+
return new Elysia7({ name: "absolute-devtools-json" }).get(ENDPOINT, () => ({
|
|
28723
29655
|
workspace: {
|
|
28724
29656
|
root,
|
|
28725
29657
|
uuid
|
|
@@ -28745,11 +29677,11 @@ __export(exports_imageOptimizer, {
|
|
|
28745
29677
|
imageOptimizer: () => imageOptimizer
|
|
28746
29678
|
});
|
|
28747
29679
|
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 = (
|
|
29680
|
+
import { resolve as resolve49 } from "path";
|
|
29681
|
+
import { Elysia as Elysia8 } from "elysia";
|
|
29682
|
+
var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avifInProgress, safeResolve = (path2, baseDir) => {
|
|
28751
29683
|
try {
|
|
28752
|
-
const resolved = validateSafePath(
|
|
29684
|
+
const resolved = validateSafePath(path2, baseDir);
|
|
28753
29685
|
if (existsSync44(resolved))
|
|
28754
29686
|
return resolved;
|
|
28755
29687
|
return null;
|
|
@@ -28758,7 +29690,7 @@ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avi
|
|
|
28758
29690
|
}
|
|
28759
29691
|
}, resolveLocalImage = (url, buildDir) => {
|
|
28760
29692
|
const cleanPath = url.startsWith("/") ? url.slice(1) : url;
|
|
28761
|
-
return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath,
|
|
29693
|
+
return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath, resolve49(process.cwd()));
|
|
28762
29694
|
}, parseQueryParams = (query, allowedSizes, defaultQuality) => {
|
|
28763
29695
|
const url = typeof query["url"] === "string" ? query["url"] : undefined;
|
|
28764
29696
|
const wParam = typeof query["w"] === "string" ? query["w"] : undefined;
|
|
@@ -28859,7 +29791,7 @@ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avi
|
|
|
28859
29791
|
}
|
|
28860
29792
|
});
|
|
28861
29793
|
}, imageOptimizer = (config, buildDir) => {
|
|
28862
|
-
const plugin = new
|
|
29794
|
+
const plugin = new Elysia8({ name: "image-optimizer" });
|
|
28863
29795
|
if (!config && config !== undefined)
|
|
28864
29796
|
return plugin;
|
|
28865
29797
|
if (config?.unoptimized)
|
|
@@ -28960,16 +29892,16 @@ var exports_requestInspector = {};
|
|
|
28960
29892
|
__export(exports_requestInspector, {
|
|
28961
29893
|
requestInspector: () => requestInspector
|
|
28962
29894
|
});
|
|
28963
|
-
import { Elysia as
|
|
29895
|
+
import { Elysia as Elysia9 } from "elysia";
|
|
28964
29896
|
var RING_MAX = 200, DEFAULT_STATUS = 200, ASSET_EXTENSION, requestLog = () => {
|
|
28965
29897
|
globalThis.__absoluteRequestLog ??= [];
|
|
28966
29898
|
return globalThis.__absoluteRequestLog;
|
|
28967
|
-
}, classify = (
|
|
28968
|
-
if (
|
|
29899
|
+
}, classify = (path2) => {
|
|
29900
|
+
if (path2.startsWith("/@") || path2.includes("/__hmr"))
|
|
28969
29901
|
return "hmr";
|
|
28970
|
-
if (
|
|
29902
|
+
if (path2.startsWith("/api"))
|
|
28971
29903
|
return "api";
|
|
28972
|
-
if (ASSET_EXTENSION.test(
|
|
29904
|
+
if (ASSET_EXTENSION.test(path2) || path2.startsWith("/assets/"))
|
|
28973
29905
|
return "asset";
|
|
28974
29906
|
return "page";
|
|
28975
29907
|
}, pathOf = (url) => {
|
|
@@ -28996,7 +29928,7 @@ var RING_MAX = 200, DEFAULT_STATUS = 200, ASSET_EXTENSION, requestLog = () => {
|
|
|
28996
29928
|
var init_requestInspector = __esm(() => {
|
|
28997
29929
|
ASSET_EXTENSION = /\.(?:avif|css|gif|ico|jpe?g|js|json|map|mjs|otf|png|svg|ttf|txt|wasm|webp|woff2?)$/i;
|
|
28998
29930
|
pending = new WeakMap;
|
|
28999
|
-
requestInspector = new
|
|
29931
|
+
requestInspector = new Elysia9({
|
|
29000
29932
|
name: "absolute-request-inspector"
|
|
29001
29933
|
}).get("/__absolute/requests", () => requestLog()).request(({ request }) => {
|
|
29002
29934
|
noteDevRequestStart();
|
|
@@ -29006,17 +29938,17 @@ var init_requestInspector = __esm(() => {
|
|
|
29006
29938
|
});
|
|
29007
29939
|
}).afterResponse(({ request, set, responseValue }) => {
|
|
29008
29940
|
noteDevRequestEnd();
|
|
29009
|
-
const
|
|
29010
|
-
if (
|
|
29941
|
+
const path2 = pathOf(request.url);
|
|
29942
|
+
if (path2.startsWith("/__absolute"))
|
|
29011
29943
|
return;
|
|
29012
29944
|
const entry = pending.get(request);
|
|
29013
29945
|
const log2 = requestLog();
|
|
29014
29946
|
log2.push({
|
|
29015
29947
|
at: Date.now(),
|
|
29016
29948
|
durationMs: entry === undefined ? 0 : performance.now() - entry.start,
|
|
29017
|
-
kind: classify(
|
|
29949
|
+
kind: classify(path2),
|
|
29018
29950
|
method: request.method,
|
|
29019
|
-
path,
|
|
29951
|
+
path: path2,
|
|
29020
29952
|
query: new URL(request.url).search,
|
|
29021
29953
|
requestHeaders: entry?.headers ?? {},
|
|
29022
29954
|
responseHeaders: toHeaderRecord(set.headers),
|
|
@@ -29029,7 +29961,7 @@ var init_requestInspector = __esm(() => {
|
|
|
29029
29961
|
});
|
|
29030
29962
|
|
|
29031
29963
|
// src/mobile/releaseArtifact.ts
|
|
29032
|
-
import { createHash as
|
|
29964
|
+
import { createHash as createHash7 } from "crypto";
|
|
29033
29965
|
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
29966
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
29035
29967
|
return false;
|
|
@@ -29066,7 +29998,7 @@ var ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT = 1, ABSOLUTE_MOBILE_RETAINED_GENERATIO
|
|
|
29066
29998
|
return normalizeCanonicalRecord(value, ancestors);
|
|
29067
29999
|
}
|
|
29068
30000
|
throw new TypeError("Compatibility metadata must contain only finite JSON values.");
|
|
29069
|
-
}, canonicalJson = (value) => JSON.stringify(normalizeCanonicalValue(value, new Set)), hashCanonicalValue = (value) =>
|
|
30001
|
+
}, canonicalJson = (value) => JSON.stringify(normalizeCanonicalValue(value, new Set)), hashCanonicalValue = (value) => createHash7(SHA_256).update(canonicalJson(value)).digest("hex"), requireNonEmpty = (value, field) => {
|
|
29070
30002
|
if (!value.trim()) {
|
|
29071
30003
|
throw new TypeError(`${field} must not be empty.`);
|
|
29072
30004
|
}
|
|
@@ -29255,11 +30187,11 @@ var init_releaseArtifact = __esm(() => {
|
|
|
29255
30187
|
});
|
|
29256
30188
|
|
|
29257
30189
|
// src/mobile/artifactStore.ts
|
|
29258
|
-
import { createHash as
|
|
30190
|
+
import { createHash as createHash8 } from "crypto";
|
|
29259
30191
|
import {
|
|
29260
|
-
mkdir as
|
|
30192
|
+
mkdir as mkdir14,
|
|
29261
30193
|
mkdtemp as mkdtemp2,
|
|
29262
|
-
readFile as
|
|
30194
|
+
readFile as readFile10,
|
|
29263
30195
|
readdir as readdir5,
|
|
29264
30196
|
rename as rename5,
|
|
29265
30197
|
rm as rm13,
|
|
@@ -29268,18 +30200,18 @@ import {
|
|
|
29268
30200
|
import { join as join55, resolve as resolvePath } from "path";
|
|
29269
30201
|
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
30202
|
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
29271
|
-
return
|
|
30203
|
+
return createHash8(SHA_2562).update(bytes).digest("hex");
|
|
29272
30204
|
}, blobFromBytes = (bytes) => {
|
|
29273
30205
|
const buffer = new ArrayBuffer(bytes.byteLength);
|
|
29274
30206
|
new Uint8Array(buffer).set(bytes);
|
|
29275
30207
|
return new Blob([buffer]);
|
|
29276
|
-
}, errorHasCode = (error, code2) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code2, appDirectoryName = (appId) =>
|
|
30208
|
+
}, 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
30209
|
if (!RELEASE_ID_PATTERN.test(releaseId)) {
|
|
29278
30210
|
throw new TypeError("Invalid mobile compatibility release id.");
|
|
29279
30211
|
}
|
|
29280
30212
|
return releaseId;
|
|
29281
30213
|
}, readStoredArtifact = async (releaseDirectory) => {
|
|
29282
|
-
const serialized = await
|
|
30214
|
+
const serialized = await readFile10(join55(releaseDirectory, ARTIFACT_FILE), "utf8");
|
|
29283
30215
|
const parsed = JSON.parse(serialized);
|
|
29284
30216
|
return parseAbsoluteMobileCompatibilityArtifact(parsed);
|
|
29285
30217
|
}, validateStoredIdentity = (artifact, appId, releaseId) => {
|
|
@@ -29423,11 +30355,11 @@ var DEFAULT_MAX_PRODUCER_BYTES = 134217728, SHA_2562 = "sha256", ARTIFACT_FILE =
|
|
|
29423
30355
|
const validatedArtifact = parseAbsoluteMobileCompatibilityArtifact(release.artifact);
|
|
29424
30356
|
const validated = await verifyAbsoluteMobileCompatibilityProducer({ artifact: validatedArtifact, producer: release.producer }, maxProducerBytes);
|
|
29425
30357
|
const parent = appDirectory(validated.artifact.appId);
|
|
29426
|
-
await
|
|
30358
|
+
await mkdir14(parent, { recursive: true });
|
|
29427
30359
|
const staging = await mkdtemp2(join55(parent, ".stage-"));
|
|
29428
30360
|
const producerPath = join55(staging, validated.artifact.producer.module);
|
|
29429
30361
|
try {
|
|
29430
|
-
await
|
|
30362
|
+
await mkdir14(resolvePath(producerPath, ".."), {
|
|
29431
30363
|
recursive: true
|
|
29432
30364
|
});
|
|
29433
30365
|
await Promise.all([
|
|
@@ -29467,24 +30399,24 @@ __export(exports_materializedBundle, {
|
|
|
29467
30399
|
materializeAbsoluteMobileCompatibilityBundle: () => materializeAbsoluteMobileCompatibilityBundle,
|
|
29468
30400
|
readAbsoluteMobileMaterializedReleases: () => readAbsoluteMobileMaterializedReleases
|
|
29469
30401
|
});
|
|
29470
|
-
import { createHash as
|
|
30402
|
+
import { createHash as createHash9 } from "crypto";
|
|
29471
30403
|
import {
|
|
29472
|
-
access as
|
|
29473
|
-
mkdir as
|
|
30404
|
+
access as access5,
|
|
30405
|
+
mkdir as mkdir15,
|
|
29474
30406
|
mkdtemp as mkdtemp3,
|
|
29475
|
-
readFile as
|
|
30407
|
+
readFile as readFile11,
|
|
29476
30408
|
rename as rename6,
|
|
29477
30409
|
rm as rm14,
|
|
29478
30410
|
writeFile as writeFile12
|
|
29479
30411
|
} from "fs/promises";
|
|
29480
|
-
import { dirname as
|
|
29481
|
-
import { pathToFileURL as
|
|
30412
|
+
import { dirname as dirname34, join as join56, resolve as resolvePath2 } from "path";
|
|
30413
|
+
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
29482
30414
|
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
30415
|
const identity = JSON.stringify({
|
|
29484
30416
|
currentReleaseId,
|
|
29485
30417
|
releases: releases.map(({ releaseId }) => releaseId)
|
|
29486
30418
|
});
|
|
29487
|
-
return `amb_${
|
|
30419
|
+
return `amb_${createHash9("sha256").update(identity).digest("hex")}`;
|
|
29488
30420
|
}, parseBundleIndex = (value) => {
|
|
29489
30421
|
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
30422
|
throw new TypeError("Invalid materialized mobile compatibility bundle.");
|
|
@@ -29510,7 +30442,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29510
30442
|
}, writeRelease = async (root, release) => {
|
|
29511
30443
|
const directory = join56(root, release.artifact.releaseId);
|
|
29512
30444
|
const producerPath = join56(directory, release.artifact.producer.module);
|
|
29513
|
-
await
|
|
30445
|
+
await mkdir15(dirname34(producerPath), { recursive: true });
|
|
29514
30446
|
await Promise.all([
|
|
29515
30447
|
writeFile12(join56(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
|
|
29516
30448
|
`),
|
|
@@ -29519,7 +30451,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29519
30451
|
}, installImmutableBundle = async (bundlesRoot, bundleId, releases) => {
|
|
29520
30452
|
const destination = join56(bundlesRoot, bundleId);
|
|
29521
30453
|
try {
|
|
29522
|
-
await
|
|
30454
|
+
await access5(destination);
|
|
29523
30455
|
return destination;
|
|
29524
30456
|
} catch (error) {
|
|
29525
30457
|
if (!errorHasCode2(error, "ENOENT"))
|
|
@@ -29537,7 +30469,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29537
30469
|
throw error;
|
|
29538
30470
|
}
|
|
29539
30471
|
return destination;
|
|
29540
|
-
}, readCompatibilityModule = (modulePath) => import(
|
|
30472
|
+
}, readCompatibilityModule = (modulePath) => import(pathToFileURL4(modulePath).href), resolveProducerHandler = (loaded, exportName) => {
|
|
29541
30473
|
const value = loaded[exportName];
|
|
29542
30474
|
if (!isRecord9(value) || typeof value.handle !== "function") {
|
|
29543
30475
|
throw new TypeError(`Compatibility producer export ${exportName} must expose handle(request).`);
|
|
@@ -29556,7 +30488,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29556
30488
|
};
|
|
29557
30489
|
}, loadAbsoluteMobileMaterializedBundle = async (root) => {
|
|
29558
30490
|
const resolvedRoot = resolvePath2(root);
|
|
29559
|
-
const serialized = await
|
|
30491
|
+
const serialized = await readFile11(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
|
|
29560
30492
|
const parsed = JSON.parse(serialized);
|
|
29561
30493
|
const index = parseBundleIndex(parsed);
|
|
29562
30494
|
const bundleRoot = join56(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
|
|
@@ -29591,7 +30523,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29591
30523
|
});
|
|
29592
30524
|
const root = resolvePath2(input.root);
|
|
29593
30525
|
const bundlesRoot = join56(root, BUNDLES_DIRECTORY);
|
|
29594
|
-
await
|
|
30526
|
+
await mkdir15(bundlesRoot, { recursive: true });
|
|
29595
30527
|
const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
|
|
29596
30528
|
await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
|
|
29597
30529
|
const index = {
|
|
@@ -29609,7 +30541,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
29609
30541
|
}, readAbsoluteMobileMaterializedReleases = async (root) => {
|
|
29610
30542
|
const resolvedRoot = resolvePath2(root);
|
|
29611
30543
|
try {
|
|
29612
|
-
const serialized = await
|
|
30544
|
+
const serialized = await readFile11(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
|
|
29613
30545
|
const parsed = JSON.parse(serialized);
|
|
29614
30546
|
const index = parseBundleIndex(parsed);
|
|
29615
30547
|
const bundleRoot = join56(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
|
|
@@ -30022,7 +30954,7 @@ var exports_compatibilityDispatcher = {};
|
|
|
30022
30954
|
__export(exports_compatibilityDispatcher, {
|
|
30023
30955
|
createAbsoluteMobileCompatibilityDispatcher: () => createAbsoluteMobileCompatibilityDispatcher
|
|
30024
30956
|
});
|
|
30025
|
-
import { Elysia as
|
|
30957
|
+
import { Elysia as Elysia10 } from "elysia";
|
|
30026
30958
|
var MOBILE_WEBVIEW_ORIGINS, MOBILE_REQUEST_HEADER_NAMES, MOBILE_CORS_ALLOW_HEADERS, MOBILE_CORS_METHODS, mobileWebViewOrigin = (request) => {
|
|
30027
30959
|
const origin = request.headers.get("origin");
|
|
30028
30960
|
return origin && MOBILE_WEBVIEW_ORIGINS.has(origin) ? origin : undefined;
|
|
@@ -30077,7 +31009,7 @@ var MOBILE_WEBVIEW_ORIGINS, MOBILE_REQUEST_HEADER_NAMES, MOBILE_CORS_ALLOW_HEADE
|
|
|
30077
31009
|
throw new TypeError("currentReleaseId must identify a retained compatibility artifact.");
|
|
30078
31010
|
}
|
|
30079
31011
|
const resolveProducer = createProducerResolver(options.loadProducer);
|
|
30080
|
-
return new
|
|
31012
|
+
return new Elysia10({ name: "absolutejs-mobile-compatibility-dispatcher" }).request(async ({ request }) => {
|
|
30081
31013
|
if (getCurrentAbsoluteMobileProducerContext())
|
|
30082
31014
|
return;
|
|
30083
31015
|
const preflight = mobilePreflightResponse(request);
|
|
@@ -30237,8 +31169,8 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
|
|
|
30237
31169
|
links.push(href);
|
|
30238
31170
|
}
|
|
30239
31171
|
return links;
|
|
30240
|
-
}, fetchRoute = async (baseUrl,
|
|
30241
|
-
const res = await fetchWithTimeout(`${baseUrl}${
|
|
31172
|
+
}, fetchRoute = async (baseUrl, path2) => {
|
|
31173
|
+
const res = await fetchWithTimeout(`${baseUrl}${path2}`, {
|
|
30242
31174
|
redirect: "manual"
|
|
30243
31175
|
});
|
|
30244
31176
|
if (!res.ok)
|
|
@@ -30252,21 +31184,21 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
|
|
|
30252
31184
|
const queue = ["/"];
|
|
30253
31185
|
const routes = [];
|
|
30254
31186
|
const crawlNextRoute = async () => {
|
|
30255
|
-
const
|
|
30256
|
-
if (!
|
|
31187
|
+
const path2 = queue.shift();
|
|
31188
|
+
if (!path2) {
|
|
30257
31189
|
return;
|
|
30258
31190
|
}
|
|
30259
|
-
if (visited.has(
|
|
31191
|
+
if (visited.has(path2)) {
|
|
30260
31192
|
await crawlNextRoute();
|
|
30261
31193
|
return;
|
|
30262
31194
|
}
|
|
30263
|
-
visited.add(
|
|
30264
|
-
const html = await fetchRoute(baseUrl,
|
|
31195
|
+
visited.add(path2);
|
|
31196
|
+
const html = await fetchRoute(baseUrl, path2).catch(() => null);
|
|
30265
31197
|
if (!html) {
|
|
30266
31198
|
await crawlNextRoute();
|
|
30267
31199
|
return;
|
|
30268
31200
|
}
|
|
30269
|
-
routes.push(
|
|
31201
|
+
routes.push(path2);
|
|
30270
31202
|
queue.push(...extractLinks(html, visited));
|
|
30271
31203
|
await crawlNextRoute();
|
|
30272
31204
|
};
|
|
@@ -30387,10 +31319,10 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
|
|
|
30387
31319
|
};
|
|
30388
31320
|
read();
|
|
30389
31321
|
}, formatServerOutput = (output) => {
|
|
30390
|
-
const
|
|
30391
|
-
if (!
|
|
31322
|
+
const text3 = output.join("").trim();
|
|
31323
|
+
if (!text3)
|
|
30392
31324
|
return "";
|
|
30393
|
-
return
|
|
31325
|
+
return text3.length > SERVER_OUTPUT_LIMIT ? text3.slice(-SERVER_OUTPUT_LIMIT) : text3;
|
|
30394
31326
|
}, createServerStartupError = (output) => {
|
|
30395
31327
|
const serverOutput = formatServerOutput(output);
|
|
30396
31328
|
const message = serverOutput ? `Server failed to start for pre-rendering.
|
|
@@ -30437,18 +31369,18 @@ __export(exports_prepare, {
|
|
|
30437
31369
|
prepare: () => prepare,
|
|
30438
31370
|
startDevPrebuild: () => startDevPrebuild
|
|
30439
31371
|
});
|
|
30440
|
-
import { createHash as
|
|
31372
|
+
import { createHash as createHash10 } from "crypto";
|
|
30441
31373
|
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(
|
|
31374
|
+
import { basename as basename19, join as join58, relative as relative21, resolve as resolvePath3 } from "path";
|
|
31375
|
+
import { Elysia as Elysia11, NotFound } from "elysia";
|
|
31376
|
+
var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_PLUGIN_RETRY_DELAY_MS = 50, waitForStaticPluginRetry = () => new Promise((resolve50) => {
|
|
31377
|
+
setTimeout(resolve50, STATIC_PLUGIN_RETRY_DELAY_MS);
|
|
30446
31378
|
}), retryStaticPlugin = async (createStaticPlugin, options) => {
|
|
30447
31379
|
try {
|
|
30448
31380
|
return await createStaticPlugin(options);
|
|
30449
31381
|
} catch (error) {
|
|
30450
31382
|
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
|
|
31383
|
+
return new Elysia11({ name: "absolutejs-static-fallback" });
|
|
30452
31384
|
}
|
|
30453
31385
|
}, mountStaticPlugin = async (createStaticPlugin, options) => {
|
|
30454
31386
|
try {
|
|
@@ -30459,7 +31391,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30459
31391
|
}
|
|
30460
31392
|
}, 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
31393
|
if (!mobile)
|
|
30462
|
-
return new
|
|
31394
|
+
return new Elysia11({ name: "absolutejs-mobile-disabled" });
|
|
30463
31395
|
const [
|
|
30464
31396
|
{ createAbsoluteMobileAssociationPlugin: createAbsoluteMobileAssociationPlugin2 },
|
|
30465
31397
|
{ createAbsoluteMobilePreviewPlugin: createAbsoluteMobilePreviewPlugin2 }
|
|
@@ -30470,19 +31402,33 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30470
31402
|
let nativeDevAdapterBundle;
|
|
30471
31403
|
const getNativeDevAdapterBundle = () => nativeDevAdapterBundle ??= Promise.resolve().then(() => (init_devDeviceAdapter(), exports_devDeviceAdapter)).then(({ buildAbsoluteNativeDevAdapter: buildAbsoluteNativeDevAdapter2 }) => buildAbsoluteNativeDevAdapter2(process.cwd(), mobile));
|
|
30472
31404
|
const getMobilePreviewClientBundle = () => Promise.resolve().then(() => (init_mobilePreviewClientBundle(), exports_mobilePreviewClientBundle)).then(({ getAbsoluteMobilePreviewClientBundle: getAbsoluteMobilePreviewClientBundle2 }) => getAbsoluteMobilePreviewClientBundle2());
|
|
30473
|
-
return new
|
|
31405
|
+
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
31406
|
headers: MOBILE_DEV_MODULE_HEADERS
|
|
30475
31407
|
})).get(MOBILE_PREVIEW_CLIENT_PATH, async () => new Response(await getMobilePreviewClientBundle(), {
|
|
30476
31408
|
headers: MOBILE_DEV_MODULE_HEADERS
|
|
30477
31409
|
}));
|
|
30478
31410
|
}, loadMobileAssociationPlugin = async (mobile) => {
|
|
30479
31411
|
if (!mobile) {
|
|
30480
|
-
return new
|
|
31412
|
+
return new Elysia11({ name: "absolutejs-mobile-associations-disabled" });
|
|
30481
31413
|
}
|
|
30482
31414
|
const { createAbsoluteMobileAssociationPlugin: createAbsoluteMobileAssociationPlugin2 } = await Promise.resolve().then(() => (init_associationFiles(), exports_associationFiles));
|
|
30483
31415
|
return createAbsoluteMobileAssociationPlugin2(mobile, process.cwd(), {
|
|
30484
31416
|
requireAll: true
|
|
30485
31417
|
});
|
|
31418
|
+
}, loadMobileUpdatePlugin = async (mobile, production) => {
|
|
31419
|
+
if (!mobile?.updates)
|
|
31420
|
+
return new Elysia11({ name: "absolutejs-mobile-updates-unconfigured" });
|
|
31421
|
+
const [
|
|
31422
|
+
{ normalizeAbsoluteMobileConfig: normalizeAbsoluteMobileConfig2 },
|
|
31423
|
+
{ createAbsoluteMobileUpdateServerPlugin: createAbsoluteMobileUpdateServerPlugin2 }
|
|
31424
|
+
] = await Promise.all([
|
|
31425
|
+
Promise.resolve().then(() => (init_config(), exports_config)),
|
|
31426
|
+
Promise.resolve().then(() => (init_updateServer(), exports_updateServer))
|
|
31427
|
+
]);
|
|
31428
|
+
const normalized = normalizeAbsoluteMobileConfig2(mobile, process.cwd());
|
|
31429
|
+
return createAbsoluteMobileUpdateServerPlugin2(normalized, process.cwd(), {
|
|
31430
|
+
production
|
|
31431
|
+
});
|
|
30486
31432
|
}, buildPrewarmDirs = (config) => {
|
|
30487
31433
|
const dirs = [];
|
|
30488
31434
|
if (config.svelteDirectory) {
|
|
@@ -30514,7 +31460,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30514
31460
|
return files;
|
|
30515
31461
|
}, PREWARM_MAX_PAUSE_MS = 60000, toWarmTasks = function* (files, warmCache, srcUrlPrefix) {
|
|
30516
31462
|
for (const file5 of files) {
|
|
30517
|
-
const rel =
|
|
31463
|
+
const rel = relative21(process.cwd(), file5).replace(/\\/g, "/");
|
|
30518
31464
|
yield () => warmCache(`${srcUrlPrefix}${rel}`);
|
|
30519
31465
|
}
|
|
30520
31466
|
}, builtPageSources = () => {
|
|
@@ -30555,7 +31501,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30555
31501
|
const srcPath = resolvePath3(devIndexDir, fileName);
|
|
30556
31502
|
if (!existsSync45(srcPath))
|
|
30557
31503
|
continue;
|
|
30558
|
-
const rel =
|
|
31504
|
+
const rel = relative21(process.cwd(), srcPath).replace(/\\/g, "/");
|
|
30559
31505
|
manifest[key] = `${SRC_URL_PREFIX2}${rel}`;
|
|
30560
31506
|
}
|
|
30561
31507
|
}, ICON_HASH_LENGTH = 8, registerIconVersioning = (buildDir) => {
|
|
@@ -30566,11 +31512,11 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30566
31512
|
const cached = cache2.get(href);
|
|
30567
31513
|
if (cached !== undefined)
|
|
30568
31514
|
return cached;
|
|
30569
|
-
const
|
|
30570
|
-
const filePath = join58(buildDir,
|
|
31515
|
+
const path2 = href.split("?")[0] ?? href;
|
|
31516
|
+
const filePath = join58(buildDir, path2);
|
|
30571
31517
|
let versioned = href;
|
|
30572
31518
|
if (existsSync45(filePath)) {
|
|
30573
|
-
const hash =
|
|
31519
|
+
const hash = createHash10("sha256").update(readFileSync39(filePath)).digest("hex").slice(0, ICON_HASH_LENGTH);
|
|
30574
31520
|
versioned = href.includes("?") ? `${href}&v=${hash}` : `${href}?v=${hash}`;
|
|
30575
31521
|
}
|
|
30576
31522
|
cache2.set(href, versioned);
|
|
@@ -30675,12 +31621,13 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30675
31621
|
const { requestInspector: requestInspector2 } = await Promise.resolve().then(() => (init_requestInspector(), exports_requestInspector));
|
|
30676
31622
|
const { serverTiming } = await import("@elysia/server-timing");
|
|
30677
31623
|
const mobileDevPlugin = await loadMobileDevPlugin(config.mobile);
|
|
30678
|
-
const
|
|
31624
|
+
const mobileUpdatePlugin = await loadMobileUpdatePlugin(config.mobile, false);
|
|
31625
|
+
const absolutejs = new Elysia11({ name: "absolutejs-runtime" }).use(requestInspector2).use(absoluteRequestContext).use(serverTiming()).use(devtoolsJson2(buildDir, {
|
|
30679
31626
|
normalizeForWindowsContainer: config.dev?.devtools?.normalizeForWindowsContainer,
|
|
30680
31627
|
projectRoot: config.dev?.devtools?.projectRoot,
|
|
30681
31628
|
uuid: config.dev?.devtools?.uuid,
|
|
30682
31629
|
uuidCachePath: config.dev?.devtools?.uuidCachePath
|
|
30683
|
-
})).use(imageOptimizer2(config.images, buildDir)).use(mobileDevPlugin).use(await mountStaticPlugin(staticPlugin, {
|
|
31630
|
+
})).use(imageOptimizer2(config.images, buildDir)).use(mobileDevPlugin).use(mobileUpdatePlugin).use(await mountStaticPlugin(staticPlugin, {
|
|
30684
31631
|
alwaysStatic: true,
|
|
30685
31632
|
assets: buildDir,
|
|
30686
31633
|
directive: "no-cache",
|
|
@@ -30719,7 +31666,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30719
31666
|
}, loadMobileCompatibilityPlugin = async (buildDir) => {
|
|
30720
31667
|
const root = join58(buildDir, ".absolutejs", "mobile-compatibility");
|
|
30721
31668
|
if (!existsSync45(join58(root, "current.json"))) {
|
|
30722
|
-
return new
|
|
31669
|
+
return new Elysia11({ name: "absolutejs-mobile-compatibility-empty" });
|
|
30723
31670
|
}
|
|
30724
31671
|
const [
|
|
30725
31672
|
{ loadAbsoluteMobileMaterializedBundle: loadAbsoluteMobileMaterializedBundle2 },
|
|
@@ -30730,12 +31677,12 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
|
|
|
30730
31677
|
]);
|
|
30731
31678
|
const options = await loadAbsoluteMobileMaterializedBundle2(root);
|
|
30732
31679
|
return createAbsoluteMobileCompatibilityDispatcher2(options);
|
|
30733
|
-
}, createNotFoundPlugin = () => new
|
|
31680
|
+
}, createNotFoundPlugin = () => new Elysia11({ name: "absolutejs-not-found" }).error("global", NotFound, async () => {
|
|
30734
31681
|
const response = await renderFirstNotFound();
|
|
30735
31682
|
if (response)
|
|
30736
31683
|
return response;
|
|
30737
31684
|
return;
|
|
30738
|
-
}), createBuildErrorRecoveryPlugin = () => new
|
|
31685
|
+
}), createBuildErrorRecoveryPlugin = () => new Elysia11({ name: "absolutejs-build-error-recovery" }).error("global", async ({ error }) => {
|
|
30739
31686
|
const message = error instanceof Error ? error.message : String(error);
|
|
30740
31687
|
const assetMatch = /^Asset "(.+)" not found in manifest\.$/.exec(message);
|
|
30741
31688
|
if (!assetMatch)
|
|
@@ -30802,11 +31749,11 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30802
31749
|
staticLimit: MAX_STATIC_ROUTE_COUNT
|
|
30803
31750
|
});
|
|
30804
31751
|
const generatedAssetsRoot = join58(buildDir, ".absolutejs");
|
|
30805
|
-
const generatedAssetsPlugin = new
|
|
31752
|
+
const generatedAssetsPlugin = new Elysia11({
|
|
30806
31753
|
name: "absolutejs-generated-assets"
|
|
30807
31754
|
}).get("/.absolutejs/*", async ({ params, set }) => {
|
|
30808
31755
|
const requestedPath = resolvePath3(generatedAssetsRoot, params["*"]);
|
|
30809
|
-
if (
|
|
31756
|
+
if (relative21(generatedAssetsRoot, requestedPath).startsWith("..")) {
|
|
30810
31757
|
set.status = 404;
|
|
30811
31758
|
return "Not Found";
|
|
30812
31759
|
}
|
|
@@ -30826,7 +31773,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30826
31773
|
const hash = base.match(/[.-]([0-9a-z]{6,12})\.[0-9a-z]+$/i)?.[1];
|
|
30827
31774
|
return hash ? /[0-9]/.test(hash) && /[a-z]/i.test(hash) : false;
|
|
30828
31775
|
};
|
|
30829
|
-
const assetCachePlugin = new
|
|
31776
|
+
const assetCachePlugin = new Elysia11({
|
|
30830
31777
|
name: "absolutejs-asset-cache"
|
|
30831
31778
|
}).afterHandle("global", ({ request, responseValue }) => {
|
|
30832
31779
|
if (!(responseValue instanceof Response))
|
|
@@ -30843,13 +31790,14 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30843
31790
|
const prerenderMap = loadPrerenderMap(prerenderDir);
|
|
30844
31791
|
const mobileCompatibilityPlugin = await loadMobileCompatibilityPlugin(buildDir);
|
|
30845
31792
|
const mobileAssociationPlugin = await loadMobileAssociationPlugin(config.mobile);
|
|
31793
|
+
const mobileUpdatePlugin = await loadMobileUpdatePlugin(config.mobile, true);
|
|
30846
31794
|
recordStep("load prerender map", stepStartedAt);
|
|
30847
31795
|
if (prerenderMap.size > 0) {
|
|
30848
31796
|
const { PRERENDER_BYPASS_HEADER: PRERENDER_BYPASS_HEADER2, readTimestamp: readTimestamp2, rerenderRoute: rerenderRoute2 } = await Promise.resolve().then(() => (init_prerender(), exports_prerender));
|
|
30849
31797
|
const revalidateMs = config.static?.revalidate ? config.static.revalidate * MS_PER_SECOND2 : 0;
|
|
30850
31798
|
const port = Number(process.env.PORT) || DEFAULT_PORT2;
|
|
30851
31799
|
const rerendering = new Set;
|
|
30852
|
-
const prerenderPlugin = new
|
|
31800
|
+
const prerenderPlugin = new Elysia11({
|
|
30853
31801
|
name: "prerendered-pages"
|
|
30854
31802
|
}).request(({ request }) => {
|
|
30855
31803
|
const url = new URL(request.url);
|
|
@@ -30872,7 +31820,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30872
31820
|
});
|
|
30873
31821
|
stepStartedAt = performance.now();
|
|
30874
31822
|
const { imageOptimizer: imageOptimizer3 } = await Promise.resolve().then(() => (init_imageOptimizer(), exports_imageOptimizer));
|
|
30875
|
-
const absolutejs2 = new
|
|
31823
|
+
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
31824
|
await withOpenApi(absolutejs2, config, process.cwd(), false);
|
|
30877
31825
|
await withTelemetry(absolutejs2, config, process.cwd());
|
|
30878
31826
|
recordStep("assemble production runtime", stepStartedAt);
|
|
@@ -30881,7 +31829,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
|
|
|
30881
31829
|
}
|
|
30882
31830
|
stepStartedAt = performance.now();
|
|
30883
31831
|
const { imageOptimizer: imageOptimizer2 } = await Promise.resolve().then(() => (init_imageOptimizer(), exports_imageOptimizer));
|
|
30884
|
-
const absolutejs = new
|
|
31832
|
+
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
31833
|
await withOpenApi(absolutejs, config, process.cwd(), false);
|
|
30886
31834
|
await withTelemetry(absolutejs, config, process.cwd());
|
|
30887
31835
|
recordStep("assemble production runtime", stepStartedAt);
|
|
@@ -30961,7 +31909,7 @@ __export(exports_moduleServer, {
|
|
|
30961
31909
|
warnIfReactFastRefreshUnsupported: () => warnIfReactFastRefreshUnsupported
|
|
30962
31910
|
});
|
|
30963
31911
|
import { existsSync as existsSync46, readFileSync as readFileSync40, realpathSync as realpathSync3, statSync as statSync7 } from "fs";
|
|
30964
|
-
import { basename as basename20, dirname as
|
|
31912
|
+
import { basename as basename20, dirname as dirname35, extname as extname15, join as join59, resolve as resolve50, relative as relative22 } from "path";
|
|
30965
31913
|
var SRC_PREFIX = "/@src/", BROWSER_DEFINE, jsTranspiler2, legacyDecoratorTsconfig, tsTranspiler2, tsxTranspiler, TRANSPILABLE, ALL_EXPORTS_RE, STRING_CONTENTS_RE, preserveTypeExports = (originalSource, transpiled, valueExports) => {
|
|
30966
31914
|
const codeOnly = originalSource.replace(STRING_CONTENTS_RE, '""');
|
|
30967
31915
|
const allExports = [];
|
|
@@ -30981,10 +31929,10 @@ var SRC_PREFIX = "/@src/", BROWSER_DEFINE, jsTranspiler2, legacyDecoratorTsconfi
|
|
|
30981
31929
|
${stubs}
|
|
30982
31930
|
`;
|
|
30983
31931
|
}, resolveRelativeExtension = (srcPath, projectRoot, extensions) => {
|
|
30984
|
-
const directHit = extensions.find((ext) => existsSync46(
|
|
31932
|
+
const directHit = extensions.find((ext) => existsSync46(resolve50(projectRoot, srcPath + ext)));
|
|
30985
31933
|
if (directHit)
|
|
30986
31934
|
return srcPath + directHit;
|
|
30987
|
-
const indexHit = extensions.find((ext) => existsSync46(
|
|
31935
|
+
const indexHit = extensions.find((ext) => existsSync46(resolve50(projectRoot, srcPath, `index${ext}`)));
|
|
30988
31936
|
if (indexHit)
|
|
30989
31937
|
return `${srcPath}/index${indexHit}`;
|
|
30990
31938
|
return srcPath;
|
|
@@ -31013,7 +31961,7 @@ ${stubs}
|
|
|
31013
31961
|
return invalidationVersion > 0 ? `${mtime}.${invalidationVersion}` : `${mtime}`;
|
|
31014
31962
|
}, srcUrl = (relPath, projectRoot) => {
|
|
31015
31963
|
const base = `${SRC_PREFIX}${relPath.replace(/\\/g, "/")}`;
|
|
31016
|
-
const absPath =
|
|
31964
|
+
const absPath = resolve50(projectRoot, relPath);
|
|
31017
31965
|
const cached = mtimeCache.get(absPath);
|
|
31018
31966
|
if (cached !== undefined)
|
|
31019
31967
|
return `${base}?v=${buildVersion(cached, absPath)}`;
|
|
@@ -31025,12 +31973,12 @@ ${stubs}
|
|
|
31025
31973
|
return base;
|
|
31026
31974
|
}
|
|
31027
31975
|
}, resolveRelativeImport = (relPath, fileDir, projectRoot, extensions) => {
|
|
31028
|
-
const absPath =
|
|
31029
|
-
const rel =
|
|
31976
|
+
const absPath = resolve50(fileDir, relPath);
|
|
31977
|
+
const rel = relative22(projectRoot, absPath);
|
|
31030
31978
|
const extension = extname15(rel);
|
|
31031
31979
|
let srcPath = RESOLVED_MODULE_EXTENSIONS.has(extension) ? rel : resolveRelativeExtension(rel, projectRoot, extensions);
|
|
31032
31980
|
if (extname15(srcPath) === ".svelte") {
|
|
31033
|
-
srcPath =
|
|
31981
|
+
srcPath = relative22(projectRoot, resolveSvelteModulePath(resolve50(projectRoot, srcPath)));
|
|
31034
31982
|
}
|
|
31035
31983
|
return srcUrl(srcPath, projectRoot);
|
|
31036
31984
|
}, NODE_BUILTIN_RE, resolveAbsoluteSpecifier = (specifier, projectRoot) => {
|
|
@@ -31042,27 +31990,27 @@ ${stubs}
|
|
|
31042
31990
|
"import"
|
|
31043
31991
|
]);
|
|
31044
31992
|
if (fromExports)
|
|
31045
|
-
return
|
|
31993
|
+
return relative22(projectRoot, fromExports);
|
|
31046
31994
|
try {
|
|
31047
31995
|
const isScoped = specifier.startsWith("@");
|
|
31048
31996
|
const parts = specifier.split("/");
|
|
31049
31997
|
const packageName = isScoped ? `${parts[0]}/${parts[1]}` : parts[0];
|
|
31050
31998
|
const subpath = isScoped ? parts.slice(2).join("/") : parts.slice(1).join("/");
|
|
31051
31999
|
if (!subpath) {
|
|
31052
|
-
const pkgDir =
|
|
32000
|
+
const pkgDir = resolve50(projectRoot, "node_modules", packageName ?? "");
|
|
31053
32001
|
const pkgJsonPath = join59(pkgDir, "package.json");
|
|
31054
32002
|
if (existsSync46(pkgJsonPath)) {
|
|
31055
32003
|
const pkg = JSON.parse(readFileSync40(pkgJsonPath, "utf-8"));
|
|
31056
32004
|
const esmEntry = typeof pkg.module === "string" && pkg.module || typeof pkg.browser === "string" && pkg.browser;
|
|
31057
32005
|
if (esmEntry) {
|
|
31058
|
-
const resolved =
|
|
32006
|
+
const resolved = resolve50(pkgDir, esmEntry);
|
|
31059
32007
|
if (existsSync46(resolved))
|
|
31060
|
-
return
|
|
32008
|
+
return relative22(projectRoot, resolved);
|
|
31061
32009
|
}
|
|
31062
32010
|
}
|
|
31063
32011
|
}
|
|
31064
32012
|
} catch {}
|
|
31065
|
-
return
|
|
32013
|
+
return relative22(projectRoot, Bun.resolveSync(specifier, projectRoot));
|
|
31066
32014
|
} catch {
|
|
31067
32015
|
return;
|
|
31068
32016
|
}
|
|
@@ -31095,28 +32043,28 @@ ${stubs}
|
|
|
31095
32043
|
};
|
|
31096
32044
|
result = result.replace(/^((?:import\s+[^"'`;]+?\s+from|export\s+[^"'`;]+?\s+from|import)\s*["'])([^"'./][^"']*)(["'])/gm, stubReplace);
|
|
31097
32045
|
result = result.replace(/(import\s*\(\s*["'])([^"'./][^"']*)(["']\s*\))/g, stubReplace);
|
|
31098
|
-
const fileDir =
|
|
32046
|
+
const fileDir = dirname35(filePath);
|
|
31099
32047
|
result = result.replace(/(from\s*["'])(\.\.?\/[^"']+)(["'])/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, IMPORT_EXTENSIONS)}${suffix}` : _match);
|
|
31100
32048
|
result = result.replace(/(import\s*\(\s*["'])(\.\.?\/[^"']+)(["']\s*\))/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, IMPORT_EXTENSIONS)}${suffix}` : _match);
|
|
31101
32049
|
result = result.replace(/(import\s*["'])(\.\.?\/[^"']+)(["']\s*;?)/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, SIDE_EFFECT_EXTENSIONS)}${suffix}` : _match);
|
|
31102
32050
|
const rewriteAbsoluteToSrc = (_match, prefix, absPath, _ext, suffix) => {
|
|
31103
32051
|
if (absPath.startsWith(projectRoot)) {
|
|
31104
|
-
const rel2 =
|
|
32052
|
+
const rel2 = relative22(projectRoot, absPath).replace(/\\/g, "/");
|
|
31105
32053
|
return `${prefix}${srcUrl(rel2, projectRoot)}${suffix}`;
|
|
31106
32054
|
}
|
|
31107
|
-
const rel =
|
|
32055
|
+
const rel = relative22(projectRoot, absPath).replace(/\\/g, "/");
|
|
31108
32056
|
return `${prefix}${srcUrl(rel, projectRoot)}${suffix}`;
|
|
31109
32057
|
};
|
|
31110
32058
|
result = result.replace(/((?:from|import)\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["'])/g, rewriteAbsoluteToSrc);
|
|
31111
32059
|
result = result.replace(/(import\s*\(\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["']\s*\))/g, rewriteAbsoluteToSrc);
|
|
31112
32060
|
result = result.replace(/new\s+URL\(\s*["'](\.\.?\/[^"']+)["']\s*,\s*import\.meta\.url\s*\)/g, (_match, relPath) => {
|
|
31113
|
-
const absPath =
|
|
31114
|
-
const rel =
|
|
32061
|
+
const absPath = resolve50(fileDir, relPath);
|
|
32062
|
+
const rel = relative22(projectRoot, absPath);
|
|
31115
32063
|
return `new URL('${srcUrl(rel, projectRoot)}', import.meta.url)`;
|
|
31116
32064
|
});
|
|
31117
32065
|
result = result.replace(/import\.meta\.resolve\(\s*["'](\.\.?\/[^"']+)["']\s*\)/g, (_match, relPath) => {
|
|
31118
|
-
const absPath =
|
|
31119
|
-
const rel =
|
|
32066
|
+
const absPath = resolve50(fileDir, relPath);
|
|
32067
|
+
const rel = relative22(projectRoot, absPath);
|
|
31120
32068
|
return `'${srcUrl(rel, projectRoot)}'`;
|
|
31121
32069
|
});
|
|
31122
32070
|
return result;
|
|
@@ -31172,7 +32120,7 @@ ${code2}`;
|
|
|
31172
32120
|
transpiled = `var $RefreshReg$ = window.$RefreshReg$ || function(){};
|
|
31173
32121
|
` + `var $RefreshSig$ = window.$RefreshSig$ || function(){ return function(t){ return t; }; };
|
|
31174
32122
|
${transpiled}`;
|
|
31175
|
-
const relPath =
|
|
32123
|
+
const relPath = relative22(projectRoot, filePath).replace(/\\/g, "/");
|
|
31176
32124
|
transpiled = transpiled.replace(/\binput\.tsx:/g, `${relPath}:`);
|
|
31177
32125
|
transpiled += buildIslandMetadataExports(raw);
|
|
31178
32126
|
return rewriteImports(transpiled, filePath, projectRoot, rewriter);
|
|
@@ -31333,11 +32281,11 @@ ${code2}`;
|
|
|
31333
32281
|
if (compiled.css?.code) {
|
|
31334
32282
|
const cssPath = `${filePath}.css`;
|
|
31335
32283
|
svelteExternalCss.set(cssPath, compiled.css.code);
|
|
31336
|
-
const cssUrl = srcUrl(
|
|
32284
|
+
const cssUrl = srcUrl(relative22(projectRoot, cssPath), projectRoot);
|
|
31337
32285
|
code2 = `import "${cssUrl}";
|
|
31338
32286
|
${code2}`;
|
|
31339
32287
|
}
|
|
31340
|
-
const moduleUrl = `${SRC_PREFIX}${
|
|
32288
|
+
const moduleUrl = `${SRC_PREFIX}${relative22(projectRoot, filePath).replace(/\\/g, "/")}`;
|
|
31341
32289
|
code2 = code2.replace(/if\s*\(import\.meta\.hot\)\s*\{/, `if (typeof window !== "undefined") {
|
|
31342
32290
|
` + ` if (!window.__SVELTE_HMR_ACCEPT__) window.__SVELTE_HMR_ACCEPT__ = {};
|
|
31343
32291
|
` + ` var __hmr_accept = function(cb) { window.__SVELTE_HMR_ACCEPT__[${JSON.stringify(moduleUrl)}] = cb; };`);
|
|
@@ -31437,8 +32385,8 @@ ${code2}`;
|
|
|
31437
32385
|
code2 = injectVueHmr(code2, filePath, projectRoot, vueDir);
|
|
31438
32386
|
return rewriteImports(code2, filePath, projectRoot, rewriter);
|
|
31439
32387
|
}, injectVueHmr = (code2, filePath, projectRoot, vueDir) => {
|
|
31440
|
-
const hmrBase = vueDir ?
|
|
31441
|
-
const hmrId =
|
|
32388
|
+
const hmrBase = vueDir ? resolve50(vueDir) : projectRoot;
|
|
32389
|
+
const hmrId = relative22(hmrBase, filePath).replace(/\\/g, "/").replace(/\.vue$/, "");
|
|
31442
32390
|
let result = code2.replace(/export\s+default\s+/, "var __hmr_comp__ = ");
|
|
31443
32391
|
result += [
|
|
31444
32392
|
"",
|
|
@@ -31451,14 +32399,14 @@ ${code2}`;
|
|
|
31451
32399
|
].join(`
|
|
31452
32400
|
`);
|
|
31453
32401
|
return result;
|
|
31454
|
-
}, resolveSvelteModulePath = (
|
|
31455
|
-
if (existsSync46(
|
|
31456
|
-
return
|
|
31457
|
-
if (existsSync46(`${
|
|
31458
|
-
return `${
|
|
31459
|
-
if (existsSync46(`${
|
|
31460
|
-
return `${
|
|
31461
|
-
return
|
|
32402
|
+
}, resolveSvelteModulePath = (path2) => {
|
|
32403
|
+
if (existsSync46(path2))
|
|
32404
|
+
return path2;
|
|
32405
|
+
if (existsSync46(`${path2}.ts`))
|
|
32406
|
+
return `${path2}.ts`;
|
|
32407
|
+
if (existsSync46(`${path2}.js`))
|
|
32408
|
+
return `${path2}.js`;
|
|
32409
|
+
return path2;
|
|
31462
32410
|
}, jsResponse = (body) => {
|
|
31463
32411
|
const etag = `"${Bun.hash(body).toString(BASE_36_RADIX)}"`;
|
|
31464
32412
|
return new Response(body, {
|
|
@@ -31598,7 +32546,7 @@ export default {};
|
|
|
31598
32546
|
const escaped = virtualCss.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
|
|
31599
32547
|
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
32548
|
}, resolveSourcePath2 = (relPath, projectRoot) => {
|
|
31601
|
-
const filePath =
|
|
32549
|
+
const filePath = resolve50(projectRoot, relPath);
|
|
31602
32550
|
const ext = extname15(filePath);
|
|
31603
32551
|
if (ext === ".svelte")
|
|
31604
32552
|
return { ext, filePath: resolveSvelteModulePath(filePath) };
|
|
@@ -31616,10 +32564,10 @@ export default {};
|
|
|
31616
32564
|
return jsResponse(handleCssRequest(filePath));
|
|
31617
32565
|
if (ext === ".json") {
|
|
31618
32566
|
try {
|
|
31619
|
-
const { readFile:
|
|
32567
|
+
const { readFile: readFile12, stat: stat5 } = await import("fs/promises");
|
|
31620
32568
|
const fileExists2 = async (p2) => {
|
|
31621
32569
|
try {
|
|
31622
|
-
await
|
|
32570
|
+
await stat5(p2);
|
|
31623
32571
|
return true;
|
|
31624
32572
|
} catch {
|
|
31625
32573
|
return false;
|
|
@@ -31635,14 +32583,14 @@ export default {};
|
|
|
31635
32583
|
const absoluteCandidate = `/${tail.replace(/^\/+/, "")}`;
|
|
31636
32584
|
const candidates = [
|
|
31637
32585
|
absoluteCandidate,
|
|
31638
|
-
|
|
32586
|
+
resolve50(projectRoot, tail)
|
|
31639
32587
|
];
|
|
31640
32588
|
try {
|
|
31641
32589
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_loadConfig(), exports_loadConfig));
|
|
31642
32590
|
const cfg = await loadConfig2();
|
|
31643
|
-
const angularDir = cfg.angularDirectory &&
|
|
32591
|
+
const angularDir = cfg.angularDirectory && resolve50(projectRoot, cfg.angularDirectory);
|
|
31644
32592
|
if (angularDir)
|
|
31645
|
-
candidates.push(
|
|
32593
|
+
candidates.push(resolve50(angularDir, tail));
|
|
31646
32594
|
} catch {}
|
|
31647
32595
|
for (const candidate of candidates) {
|
|
31648
32596
|
if (await fileExists2(candidate)) {
|
|
@@ -31652,9 +32600,9 @@ export default {};
|
|
|
31652
32600
|
}
|
|
31653
32601
|
}
|
|
31654
32602
|
}
|
|
31655
|
-
const
|
|
31656
|
-
JSON.parse(
|
|
31657
|
-
return jsResponse(`export default ${
|
|
32603
|
+
const text3 = await readFile12(sourcePath, "utf-8");
|
|
32604
|
+
JSON.parse(text3);
|
|
32605
|
+
return jsResponse(`export default ${text3};`);
|
|
31658
32606
|
} catch (err) {
|
|
31659
32607
|
return new Response(`console.error('[ModuleServer] JSON load error in ${filePath}:', ${JSON.stringify(String(err))});`, {
|
|
31660
32608
|
headers: { "Content-Type": "application/javascript" },
|
|
@@ -31672,8 +32620,8 @@ export default {};
|
|
|
31672
32620
|
return transformAndCacheVue(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
|
|
31673
32621
|
if (!TRANSPILABLE.has(ext))
|
|
31674
32622
|
return;
|
|
31675
|
-
const
|
|
31676
|
-
const resolvedVueDir = vueDir ?
|
|
32623
|
+
const stat4 = statSync7(filePath);
|
|
32624
|
+
const resolvedVueDir = vueDir ? resolve50(vueDir) : undefined;
|
|
31677
32625
|
let content = REACT_EXTENSIONS.has(ext) ? transformReactFile(filePath, projectRoot, rewriter) : transformPlainFile(filePath, projectRoot, rewriter, resolvedVueDir);
|
|
31678
32626
|
const isAngularGeneratedJs = ext === ".js" && filePath.replace(/\\/g, "/").includes("/.absolutejs/generated/angular/");
|
|
31679
32627
|
if (isAngularGeneratedJs) {
|
|
@@ -31692,7 +32640,7 @@ export default {};
|
|
|
31692
32640
|
}
|
|
31693
32641
|
}
|
|
31694
32642
|
}
|
|
31695
|
-
setTransformed(filePath, content,
|
|
32643
|
+
setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
|
|
31696
32644
|
return jsResponse(content);
|
|
31697
32645
|
}, cachedAngularUserRoot, getAngularUserRoot = async (_projectRoot) => {
|
|
31698
32646
|
if (cachedAngularUserRoot !== undefined)
|
|
@@ -31700,14 +32648,14 @@ export default {};
|
|
|
31700
32648
|
cachedAngularUserRoot = configuredAngularUserRoot ?? null;
|
|
31701
32649
|
return cachedAngularUserRoot;
|
|
31702
32650
|
}, configuredAngularUserRoot, transformAndCacheSvelte = async (filePath, projectRoot, rewriter, stylePreprocessors) => {
|
|
31703
|
-
const
|
|
32651
|
+
const stat4 = statSync7(filePath);
|
|
31704
32652
|
const content = await transformSvelteFile(filePath, projectRoot, rewriter, stylePreprocessors);
|
|
31705
|
-
setTransformed(filePath, content,
|
|
32653
|
+
setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
|
|
31706
32654
|
return jsResponse(content);
|
|
31707
32655
|
}, transformAndCacheVue = async (filePath, projectRoot, rewriter, vueDir, stylePreprocessors) => {
|
|
31708
|
-
const
|
|
32656
|
+
const stat4 = statSync7(filePath);
|
|
31709
32657
|
const content = await transformVueFile(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
|
|
31710
|
-
setTransformed(filePath, content,
|
|
32658
|
+
setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
|
|
31711
32659
|
return jsResponse(content);
|
|
31712
32660
|
}, transformErrorResponse = (err) => {
|
|
31713
32661
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -31732,7 +32680,7 @@ export default {};
|
|
|
31732
32680
|
const relPath = pathname.slice(SRC_PREFIX.length);
|
|
31733
32681
|
if (relPath === "bun:wrap" || relPath.startsWith("bun:wrap?"))
|
|
31734
32682
|
return handleBunWrapRequest();
|
|
31735
|
-
const virtualCssResponse = handleVirtualSvelteCss(
|
|
32683
|
+
const virtualCssResponse = handleVirtualSvelteCss(resolve50(projectRoot, relPath));
|
|
31736
32684
|
if (virtualCssResponse)
|
|
31737
32685
|
return virtualCssResponse;
|
|
31738
32686
|
const { filePath, ext } = resolveSourcePath2(relPath, projectRoot);
|
|
@@ -31748,11 +32696,11 @@ export default {};
|
|
|
31748
32696
|
SRC_IMPORT_RE.lastIndex = 0;
|
|
31749
32697
|
while ((match = SRC_IMPORT_RE.exec(content)) !== null) {
|
|
31750
32698
|
if (match[1])
|
|
31751
|
-
files.push(
|
|
32699
|
+
files.push(resolve50(projectRoot, match[1]));
|
|
31752
32700
|
}
|
|
31753
32701
|
return files;
|
|
31754
32702
|
}, invalidateModule = (filePath) => {
|
|
31755
|
-
const resolved =
|
|
32703
|
+
const resolved = resolve50(filePath);
|
|
31756
32704
|
invalidate(filePath);
|
|
31757
32705
|
if (resolved !== filePath)
|
|
31758
32706
|
invalidate(resolved);
|
|
@@ -31815,7 +32763,7 @@ export default {};
|
|
|
31815
32763
|
return false;
|
|
31816
32764
|
}
|
|
31817
32765
|
const { patchManifestIndexes: patchManifestIndexes2 } = await Promise.resolve().then(() => (init_prepare(), exports_prepare));
|
|
31818
|
-
patchManifestIndexes2(cached.manifest,
|
|
32766
|
+
patchManifestIndexes2(cached.manifest, resolve50(state.resolvedPaths.buildDir, "_src_indexes"), SRC_PREFIX);
|
|
31819
32767
|
logPageBuild(entry.source, entry.framework, Math.round(durationMs));
|
|
31820
32768
|
logStartupTimingBlock("AbsoluteJS on-demand page build", [
|
|
31821
32769
|
{ durationMs, label: entry.name }
|
|
@@ -31947,7 +32895,7 @@ __export(exports_rewriteImports, {
|
|
|
31947
32895
|
rewriteVendorDirectories: () => rewriteVendorDirectories2
|
|
31948
32896
|
});
|
|
31949
32897
|
var rewriteImports2 = async (outputPaths, vendorPaths) => {
|
|
31950
|
-
const jsFiles = outputPaths.filter((
|
|
32898
|
+
const jsFiles = outputPaths.filter((path2) => path2.endsWith(".js"));
|
|
31951
32899
|
if (jsFiles.length === 0)
|
|
31952
32900
|
return;
|
|
31953
32901
|
if (Object.keys(vendorPaths).length === 0)
|
|
@@ -31981,13 +32929,13 @@ var init_rewriteImports = __esm(() => {
|
|
|
31981
32929
|
});
|
|
31982
32930
|
|
|
31983
32931
|
// src/core/pageResponseCache.ts
|
|
31984
|
-
import { createHash as
|
|
32932
|
+
import { createHash as createHash11 } from "crypto";
|
|
31985
32933
|
var STREAMING_PAGE_HEADER = "x-absolute-stream", HTML_CONTENT_TYPE = "text/html", streamingPageHeaders = (extra) => {
|
|
31986
32934
|
const headers = new Headers(extra);
|
|
31987
32935
|
headers.set("content-type", HTML_CONTENT_TYPE);
|
|
31988
32936
|
headers.set(STREAMING_PAGE_HEADER, "1");
|
|
31989
32937
|
return headers;
|
|
31990
|
-
}, computeEtag = (html) => `W/"${
|
|
32938
|
+
}, computeEtag = (html) => `W/"${createHash11("sha1").update(html).digest("base64url")}"`, withPageCacheHeaders = async (response, request, options) => {
|
|
31991
32939
|
const contentType = response.headers.get("content-type") ?? "";
|
|
31992
32940
|
if (!contentType.includes(HTML_CONTENT_TYPE))
|
|
31993
32941
|
return response;
|
|
@@ -32055,7 +33003,7 @@ var init_routeAssets = __esm(() => {
|
|
|
32055
33003
|
});
|
|
32056
33004
|
|
|
32057
33005
|
// src/ember/pageHandler.ts
|
|
32058
|
-
import { pathToFileURL as
|
|
33006
|
+
import { pathToFileURL as pathToFileURL5 } from "url";
|
|
32059
33007
|
var resolveRequestPathname2 = (request) => {
|
|
32060
33008
|
if (!request)
|
|
32061
33009
|
return;
|
|
@@ -32077,7 +33025,7 @@ var resolveRequestPathname2 = (request) => {
|
|
|
32077
33025
|
}, emberCacheBuster = 0, buildRuntimeModuleSpecifier = (modulePath) => {
|
|
32078
33026
|
if (emberCacheBuster === 0)
|
|
32079
33027
|
return modulePath;
|
|
32080
|
-
const moduleUrl = new URL(
|
|
33028
|
+
const moduleUrl = new URL(pathToFileURL5(modulePath).href);
|
|
32081
33029
|
moduleUrl.searchParams.set("t", String(emberCacheBuster));
|
|
32082
33030
|
return moduleUrl.href;
|
|
32083
33031
|
}, invalidateEmberSsrCache = () => {
|
|
@@ -32178,11 +33126,11 @@ var exports_simpleHTMLHMR = {};
|
|
|
32178
33126
|
__export(exports_simpleHTMLHMR, {
|
|
32179
33127
|
handleHTMLUpdate: () => handleHTMLUpdate
|
|
32180
33128
|
});
|
|
32181
|
-
import { resolve as
|
|
33129
|
+
import { resolve as resolve51 } from "path";
|
|
32182
33130
|
var handleHTMLUpdate = async (htmlFilePath) => {
|
|
32183
33131
|
let htmlContent;
|
|
32184
33132
|
try {
|
|
32185
|
-
const resolvedPath =
|
|
33133
|
+
const resolvedPath = resolve51(htmlFilePath);
|
|
32186
33134
|
const file5 = Bun.file(resolvedPath);
|
|
32187
33135
|
if (!await file5.exists()) {
|
|
32188
33136
|
return null;
|
|
@@ -32208,11 +33156,11 @@ var exports_simpleHTMXHMR = {};
|
|
|
32208
33156
|
__export(exports_simpleHTMXHMR, {
|
|
32209
33157
|
handleHTMXUpdate: () => handleHTMXUpdate
|
|
32210
33158
|
});
|
|
32211
|
-
import { resolve as
|
|
33159
|
+
import { resolve as resolve52 } from "path";
|
|
32212
33160
|
var handleHTMXUpdate = async (htmxFilePath) => {
|
|
32213
33161
|
let htmlContent;
|
|
32214
33162
|
try {
|
|
32215
|
-
const resolvedPath =
|
|
33163
|
+
const resolvedPath = resolve52(htmxFilePath);
|
|
32216
33164
|
const file5 = Bun.file(resolvedPath);
|
|
32217
33165
|
if (!await file5.exists()) {
|
|
32218
33166
|
return null;
|
|
@@ -32243,12 +33191,12 @@ __export(exports_rebuildTrigger, {
|
|
|
32243
33191
|
import { existsSync as existsSync47, readdirSync as readdirSync13, rmSync as rmSync4 } from "fs";
|
|
32244
33192
|
import {
|
|
32245
33193
|
basename as basename21,
|
|
32246
|
-
dirname as
|
|
32247
|
-
isAbsolute as
|
|
33194
|
+
dirname as dirname36,
|
|
33195
|
+
isAbsolute as isAbsolute9,
|
|
32248
33196
|
join as join60,
|
|
32249
|
-
relative as
|
|
33197
|
+
relative as relative23,
|
|
32250
33198
|
resolve as resolvePath4,
|
|
32251
|
-
sep as
|
|
33199
|
+
sep as sep5
|
|
32252
33200
|
} from "path";
|
|
32253
33201
|
var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSsrCssCaches = () => {
|
|
32254
33202
|
clearSpaRouteCssCaches();
|
|
@@ -32607,14 +33555,14 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
32607
33555
|
const relFromDir = normalizedSource.slice(normalizedDir.length + 1);
|
|
32608
33556
|
const { buildDir } = state.resolvedPaths;
|
|
32609
33557
|
const destPath = resolvePath4(buildDir, urlPrefix ? `${urlPrefix}/${relFromDir}` : relFromDir);
|
|
32610
|
-
const { mkdir:
|
|
32611
|
-
await
|
|
33558
|
+
const { mkdir: mkdir16, copyFile, readFile: readFile12 } = await import("fs/promises");
|
|
33559
|
+
await mkdir16(dirname36(destPath), { recursive: true });
|
|
32612
33560
|
await copyFile(absSource, destPath);
|
|
32613
|
-
const bytes = await
|
|
33561
|
+
const bytes = await readFile12(destPath);
|
|
32614
33562
|
const webPath = urlPrefix ? `/${urlPrefix}/${relFromDir}` : `/${relFromDir}`;
|
|
32615
33563
|
state.assetStore.set(webPath, new Uint8Array(bytes));
|
|
32616
33564
|
state.fileHashes.set(absSource, currentHash);
|
|
32617
|
-
logHmrUpdate(
|
|
33565
|
+
logHmrUpdate(relative23(process.cwd(), filePath));
|
|
32618
33566
|
broadcastToClients(state, {
|
|
32619
33567
|
data: {
|
|
32620
33568
|
framework: urlPrefix || "public",
|
|
@@ -32634,7 +33582,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
32634
33582
|
return;
|
|
32635
33583
|
if (framework === "unknown") {
|
|
32636
33584
|
invalidate(resolvePath4(filePath));
|
|
32637
|
-
const relPath =
|
|
33585
|
+
const relPath = relative23(process.cwd(), filePath);
|
|
32638
33586
|
logHmrUpdate(relPath);
|
|
32639
33587
|
const { angularDir } = state.resolvedPaths;
|
|
32640
33588
|
let hasAngularDependent = false;
|
|
@@ -32790,7 +33738,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
32790
33738
|
const keepStemsByDir = new Map;
|
|
32791
33739
|
const prefixByDir = new Map;
|
|
32792
33740
|
for (const artifact of freshOutputs) {
|
|
32793
|
-
const dir =
|
|
33741
|
+
const dir = dirname36(artifact.path);
|
|
32794
33742
|
const name = basename21(artifact.path);
|
|
32795
33743
|
const [prefix] = name.split(".");
|
|
32796
33744
|
if (!prefix)
|
|
@@ -33156,8 +34104,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33156
34104
|
};
|
|
33157
34105
|
return ({ immediate = false } = {}) => {
|
|
33158
34106
|
if (!ctx.debouncedPromise) {
|
|
33159
|
-
ctx.debouncedPromise = new Promise((
|
|
33160
|
-
ctx.debouncedResolve =
|
|
34107
|
+
ctx.debouncedPromise = new Promise((resolve53) => {
|
|
34108
|
+
ctx.debouncedResolve = resolve53;
|
|
33161
34109
|
});
|
|
33162
34110
|
}
|
|
33163
34111
|
const scheduled = ctx.debouncedPromise;
|
|
@@ -33183,7 +34131,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33183
34131
|
const angularDirAbs = resolvePath4(angularDir);
|
|
33184
34132
|
const filesUnderAngular = Array.from(editedFiles).filter((file5) => {
|
|
33185
34133
|
const abs = resolvePath4(file5);
|
|
33186
|
-
return abs === angularDirAbs || abs.startsWith(angularDirAbs +
|
|
34134
|
+
return abs === angularDirAbs || abs.startsWith(angularDirAbs + sep5);
|
|
33187
34135
|
});
|
|
33188
34136
|
if (filesUnderAngular.length === 0)
|
|
33189
34137
|
return;
|
|
@@ -33226,7 +34174,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33226
34174
|
try {
|
|
33227
34175
|
const { invalidateModule: invalidateModule2 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
|
|
33228
34176
|
for (const tsFile of tsFilesToRefresh) {
|
|
33229
|
-
const rel =
|
|
34177
|
+
const rel = relative23(angularDirAbs, tsFile).replace(/\\/g, "/").replace(/\.[tj]sx?$/, ".js");
|
|
33230
34178
|
const compiledFile = resolvePath4(compiledRoot, rel);
|
|
33231
34179
|
invalidateModule2(compiledFile);
|
|
33232
34180
|
}
|
|
@@ -33381,7 +34329,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33381
34329
|
}, getModuleUrl = async (pageFile) => {
|
|
33382
34330
|
const { invalidateModule: invalidateModule2, warmCache: warmCache2, SRC_URL_PREFIX: SRC_URL_PREFIX3 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
|
|
33383
34331
|
invalidateModule2(pageFile);
|
|
33384
|
-
const rel =
|
|
34332
|
+
const rel = relative23(process.cwd(), pageFile).replace(/\\/g, "/");
|
|
33385
34333
|
const url = `${SRC_URL_PREFIX3}${rel}`;
|
|
33386
34334
|
await warmCache2(url);
|
|
33387
34335
|
return url;
|
|
@@ -33409,7 +34357,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33409
34357
|
const pageModuleUrl = await getReactModuleUrl(broadcastTarget);
|
|
33410
34358
|
if (pageModuleUrl) {
|
|
33411
34359
|
const serverDuration = Date.now() - startTime;
|
|
33412
|
-
state.lastHmrPath =
|
|
34360
|
+
state.lastHmrPath = relative23(process.cwd(), primaryFile).replace(/\\/g, "/");
|
|
33413
34361
|
state.lastHmrFramework = "react";
|
|
33414
34362
|
broadcastToClients(state, {
|
|
33415
34363
|
data: {
|
|
@@ -33702,8 +34650,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33702
34650
|
};
|
|
33703
34651
|
return () => {
|
|
33704
34652
|
if (!ctx.debouncedPromise) {
|
|
33705
|
-
ctx.debouncedPromise = new Promise((
|
|
33706
|
-
ctx.debouncedResolve =
|
|
34653
|
+
ctx.debouncedPromise = new Promise((resolve53) => {
|
|
34654
|
+
ctx.debouncedResolve = resolve53;
|
|
33707
34655
|
});
|
|
33708
34656
|
}
|
|
33709
34657
|
if (ctx.debounceTimer)
|
|
@@ -33914,7 +34862,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33914
34862
|
if (vueSpaRoutesBySource.size > 0) {
|
|
33915
34863
|
const spaManifestEntries = await writeSpaSideManifests(vueSpaRoutesBySource, (pascalName) => {
|
|
33916
34864
|
const fromManifest = state.manifest[pascalName];
|
|
33917
|
-
return typeof fromManifest === "string" &&
|
|
34865
|
+
return typeof fromManifest === "string" && isAbsolute9(fromManifest) && fromManifest.endsWith(".js") ? fromManifest : undefined;
|
|
33918
34866
|
});
|
|
33919
34867
|
Object.assign(state.manifest, spaManifestEntries);
|
|
33920
34868
|
}
|
|
@@ -33984,8 +34932,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
33984
34932
|
};
|
|
33985
34933
|
return () => {
|
|
33986
34934
|
if (!ctx.debouncedPromise) {
|
|
33987
|
-
ctx.debouncedPromise = new Promise((
|
|
33988
|
-
ctx.debouncedResolve =
|
|
34935
|
+
ctx.debouncedPromise = new Promise((resolve53) => {
|
|
34936
|
+
ctx.debouncedResolve = resolve53;
|
|
33989
34937
|
});
|
|
33990
34938
|
}
|
|
33991
34939
|
if (ctx.debounceTimer)
|
|
@@ -34038,7 +34986,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
34038
34986
|
const duration = Date.now() - startTime;
|
|
34039
34987
|
const [primary] = emberFiles;
|
|
34040
34988
|
if (primary) {
|
|
34041
|
-
state.lastHmrPath =
|
|
34989
|
+
state.lastHmrPath = relative23(process.cwd(), primary).replace(/\\/g, "/");
|
|
34042
34990
|
state.lastHmrFramework = "ember";
|
|
34043
34991
|
logHmrUpdate(primary, "ember", duration);
|
|
34044
34992
|
}
|
|
@@ -34135,7 +35083,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
34135
35083
|
if (!buildReference?.source) {
|
|
34136
35084
|
return;
|
|
34137
35085
|
}
|
|
34138
|
-
const sourcePath = buildReference.source.startsWith("file://") ? new URL(buildReference.source).pathname : resolvePath4(
|
|
35086
|
+
const sourcePath = buildReference.source.startsWith("file://") ? new URL(buildReference.source).pathname : resolvePath4(dirname36(buildInfo.resolvedRegistryPath), buildReference.source);
|
|
34139
35087
|
islandFiles.add(resolvePath4(sourcePath));
|
|
34140
35088
|
}, resolveIslandSourceFiles = async (config) => {
|
|
34141
35089
|
const registryPath = config.islands?.registry;
|
|
@@ -34307,7 +35255,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
34307
35255
|
const baseName = fileName.replace(/\.vue$/, "");
|
|
34308
35256
|
const pascalName = toPascal(baseName);
|
|
34309
35257
|
const vueRoot = config.vueDirectory;
|
|
34310
|
-
const hmrId = vueRoot ?
|
|
35258
|
+
const hmrId = vueRoot ? relative23(vueRoot, vuePagePath).replace(/\\/g, "/").replace(/\.vue$/, "") : baseName;
|
|
34311
35259
|
const cssKey = `${pascalName}CSS`;
|
|
34312
35260
|
const cssUrl = manifest[cssKey] || null;
|
|
34313
35261
|
const { vueHmrMetadata: vueHmrMetadata2 } = await Promise.resolve().then(() => (init_compileVue(), exports_compileVue));
|
|
@@ -34521,10 +35469,10 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
|
|
|
34521
35469
|
if (sourceVersion !== undefined) {
|
|
34522
35470
|
moduleVersions[update.sourceFile] = sourceVersion;
|
|
34523
35471
|
}
|
|
34524
|
-
Object.values(update.modulePaths).forEach((
|
|
34525
|
-
const pathVersion = moduleVersionsStore.get(
|
|
35472
|
+
Object.values(update.modulePaths).forEach((path2) => {
|
|
35473
|
+
const pathVersion = moduleVersionsStore.get(path2);
|
|
34526
35474
|
if (pathVersion !== undefined) {
|
|
34527
|
-
moduleVersions[
|
|
35475
|
+
moduleVersions[path2] = pathVersion;
|
|
34528
35476
|
}
|
|
34529
35477
|
});
|
|
34530
35478
|
}, handleModuleUpdates = (state, allModuleUpdates, manifest) => {
|
|
@@ -34986,7 +35934,7 @@ var toSafeFileName6 = (specifier) => {
|
|
|
34986
35934
|
} catch {
|
|
34987
35935
|
return false;
|
|
34988
35936
|
}
|
|
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 = (
|
|
35937
|
+
}, 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
35938
|
const dep = [];
|
|
34991
35939
|
const framework = [];
|
|
34992
35940
|
try {
|
|
@@ -35030,22 +35978,22 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35030
35978
|
};
|
|
35031
35979
|
}, collectBareImportsFromFile = async (entryPath, transpiler7, maxDepth = 8) => {
|
|
35032
35980
|
const { readFileSync: readFileSync41 } = await import("fs");
|
|
35033
|
-
const { dirname:
|
|
35981
|
+
const { dirname: dirname37 } = await import("path");
|
|
35034
35982
|
const seenFiles = new Set;
|
|
35035
35983
|
const bareOut = new Set;
|
|
35036
35984
|
const queue = [
|
|
35037
35985
|
{ depth: 0, path: entryPath }
|
|
35038
35986
|
];
|
|
35039
35987
|
while (queue.length > 0) {
|
|
35040
|
-
const { path, depth } = queue.shift();
|
|
35041
|
-
if (seenFiles.has(
|
|
35988
|
+
const { path: path2, depth } = queue.shift();
|
|
35989
|
+
if (seenFiles.has(path2))
|
|
35042
35990
|
continue;
|
|
35043
|
-
seenFiles.add(
|
|
35991
|
+
seenFiles.add(path2);
|
|
35044
35992
|
if (depth > maxDepth)
|
|
35045
35993
|
continue;
|
|
35046
35994
|
let content;
|
|
35047
35995
|
try {
|
|
35048
|
-
content = readFileSync41(
|
|
35996
|
+
content = readFileSync41(path2, "utf-8");
|
|
35049
35997
|
} catch {
|
|
35050
35998
|
continue;
|
|
35051
35999
|
}
|
|
@@ -35055,7 +36003,7 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35055
36003
|
} catch {
|
|
35056
36004
|
continue;
|
|
35057
36005
|
}
|
|
35058
|
-
const fromDir =
|
|
36006
|
+
const fromDir = dirname37(path2);
|
|
35059
36007
|
for (const imp of imports) {
|
|
35060
36008
|
const child = imp.path;
|
|
35061
36009
|
if (child.startsWith(".") || child.startsWith("/")) {
|
|
@@ -35075,7 +36023,7 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35075
36023
|
}
|
|
35076
36024
|
return Array.from(bareOut);
|
|
35077
36025
|
}, MAX_DISCOVERY_FILES = 2000, collectTransitiveImports = async (specs, alreadyVendored, alreadyScanned) => {
|
|
35078
|
-
const { dirname:
|
|
36026
|
+
const { dirname: dirname37 } = await import("path");
|
|
35079
36027
|
const transpiler7 = new Bun.Transpiler({ loader: "js" });
|
|
35080
36028
|
const newSpecs = new Set;
|
|
35081
36029
|
const queue = [...specs].map((spec) => ({ from: process.cwd(), spec }));
|
|
@@ -35096,7 +36044,7 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35096
36044
|
}
|
|
35097
36045
|
visited += 1;
|
|
35098
36046
|
const bareImports = await collectBareImportsFromFile(resolved, transpiler7);
|
|
35099
|
-
const importerDirectory =
|
|
36047
|
+
const importerDirectory = dirname37(resolved);
|
|
35100
36048
|
for (const child of bareImports) {
|
|
35101
36049
|
if (!isBareSpecifier3(child))
|
|
35102
36050
|
continue;
|
|
@@ -35159,11 +36107,11 @@ var toSafeFileName6 = (specifier) => {
|
|
|
35159
36107
|
const output = lastResult.outputs[0];
|
|
35160
36108
|
if (!output)
|
|
35161
36109
|
return lastResult;
|
|
35162
|
-
const
|
|
36110
|
+
const text3 = await output.text();
|
|
35163
36111
|
REQUIRE_CALL_RE.lastIndex = 0;
|
|
35164
36112
|
const requiredSpecs = new Set;
|
|
35165
36113
|
let match;
|
|
35166
|
-
while ((match = REQUIRE_CALL_RE.exec(
|
|
36114
|
+
while ((match = REQUIRE_CALL_RE.exec(text3)) !== null) {
|
|
35167
36115
|
const requiredSpec = match[1];
|
|
35168
36116
|
if (requiredSpec && externalsSet.has(requiredSpec)) {
|
|
35169
36117
|
requiredSpecs.add(requiredSpec);
|
|
@@ -35310,7 +36258,7 @@ __export(exports_vendorCache, {
|
|
|
35310
36258
|
saveVendorCache: () => saveVendorCache,
|
|
35311
36259
|
vendorCacheEnabled: () => vendorCacheEnabled
|
|
35312
36260
|
});
|
|
35313
|
-
import { createHash as
|
|
36261
|
+
import { createHash as createHash12 } from "crypto";
|
|
35314
36262
|
import {
|
|
35315
36263
|
copyFileSync as copyFileSync4,
|
|
35316
36264
|
existsSync as existsSync48,
|
|
@@ -35318,10 +36266,10 @@ import {
|
|
|
35318
36266
|
readdirSync as readdirSync14,
|
|
35319
36267
|
readFileSync as readFileSync41
|
|
35320
36268
|
} from "fs";
|
|
35321
|
-
import { mkdir as
|
|
35322
|
-
import { basename as basename22, join as join62, resolve as
|
|
36269
|
+
import { mkdir as mkdir16, readFile as readFile12, rename as rename7, rm as rm16, writeFile as writeFile13 } from "fs/promises";
|
|
36270
|
+
import { basename as basename22, join as join62, resolve as resolve53 } from "path";
|
|
35323
36271
|
var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeVendorCacheKey = (inputs) => {
|
|
35324
|
-
const hash =
|
|
36272
|
+
const hash = createHash12("sha256");
|
|
35325
36273
|
hash.update(String(CACHE_FORMAT_VERSION3));
|
|
35326
36274
|
hash.update("\x00");
|
|
35327
36275
|
hash.update(inputs.lockfileHash);
|
|
@@ -35339,19 +36287,19 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
|
|
|
35339
36287
|
}
|
|
35340
36288
|
for (const dir of inputs.vendorDirs) {
|
|
35341
36289
|
hash.update("\x00v");
|
|
35342
|
-
hash.update(basename22(
|
|
36290
|
+
hash.update(basename22(resolve53(dir, "..")));
|
|
35343
36291
|
}
|
|
35344
36292
|
return hash.digest("hex").slice(0, KEY_LENGTH);
|
|
35345
36293
|
}, readLockfileHash = (projectRoot = process.cwd()) => {
|
|
35346
|
-
const hash =
|
|
36294
|
+
const hash = createHash12("sha256");
|
|
35347
36295
|
let found = false;
|
|
35348
36296
|
for (const name of LOCKFILES) {
|
|
35349
|
-
const
|
|
35350
|
-
if (!existsSync48(
|
|
36297
|
+
const path2 = join62(projectRoot, name);
|
|
36298
|
+
if (!existsSync48(path2))
|
|
35351
36299
|
continue;
|
|
35352
36300
|
found = true;
|
|
35353
36301
|
hash.update(name);
|
|
35354
|
-
hash.update(readFileSync41(
|
|
36302
|
+
hash.update(readFileSync41(path2));
|
|
35355
36303
|
}
|
|
35356
36304
|
return found ? hash.digest("hex") : null;
|
|
35357
36305
|
}, vendorCacheEnabled = () => process.env.ABSOLUTE_DEV_VENDOR_CACHE !== "0", copyTree = (fromDir, toDir) => {
|
|
@@ -35378,13 +36326,13 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
|
|
|
35378
36326
|
continue;
|
|
35379
36327
|
copyTree(dir, join62(stagingDir, slotName(index, dir)));
|
|
35380
36328
|
}
|
|
35381
|
-
}, isVendorCachePayload = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "depPaths") === "object", cacheDirFor = (key, projectRoot) =>
|
|
36329
|
+
}, 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
36330
|
const cacheDir2 = cacheDirFor(key, projectRoot);
|
|
35383
36331
|
const payloadPath = join62(cacheDir2, "payload.json");
|
|
35384
36332
|
if (!existsSync48(payloadPath))
|
|
35385
36333
|
return null;
|
|
35386
36334
|
try {
|
|
35387
|
-
const payload = JSON.parse(await
|
|
36335
|
+
const payload = JSON.parse(await readFile12(payloadPath, "utf8"));
|
|
35388
36336
|
if (!isVendorCachePayload(payload))
|
|
35389
36337
|
return null;
|
|
35390
36338
|
copySlotsInto(cacheDir2, vendorDirs);
|
|
@@ -35399,7 +36347,7 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
|
|
|
35399
36347
|
const stagingDir = `${cacheDir2}.${process.pid}.tmp`;
|
|
35400
36348
|
try {
|
|
35401
36349
|
await rm16(stagingDir, { force: true, recursive: true });
|
|
35402
|
-
await
|
|
36350
|
+
await mkdir16(stagingDir, { recursive: true });
|
|
35403
36351
|
copySlotsFrom(stagingDir, vendorDirs);
|
|
35404
36352
|
await writeFile13(join62(stagingDir, "payload.json"), JSON.stringify(payload));
|
|
35405
36353
|
await rm16(cacheDir2, { force: true, recursive: true });
|
|
@@ -35430,8 +36378,8 @@ __export(exports_devBuild, {
|
|
|
35430
36378
|
});
|
|
35431
36379
|
import { readdir as readdir6 } from "fs/promises";
|
|
35432
36380
|
import { existsSync as existsSync49, statSync as statSync8 } from "fs";
|
|
35433
|
-
import { resolve as
|
|
35434
|
-
var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () =>
|
|
36381
|
+
import { resolve as resolve54 } from "path";
|
|
36382
|
+
var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve54(import.meta.dir, "../dev/client"), collectDepVendorSourceDirs = (config) => {
|
|
35435
36383
|
const configuredDirs = [
|
|
35436
36384
|
...collectConfigVendorSourceDirs(config),
|
|
35437
36385
|
devClientVendorSourceDir()
|
|
@@ -35454,7 +36402,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35454
36402
|
return Object.keys(config).length > 0 ? config : null;
|
|
35455
36403
|
}, reloadConfig = async () => {
|
|
35456
36404
|
try {
|
|
35457
|
-
const configPath2 =
|
|
36405
|
+
const configPath2 = resolve54(process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
|
|
35458
36406
|
const source = await Bun.file(configPath2).text();
|
|
35459
36407
|
return parseDirectoryConfig(source);
|
|
35460
36408
|
} catch {
|
|
@@ -35506,7 +36454,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35506
36454
|
setEmberVendorPaths(computeEmberVendorPaths());
|
|
35507
36455
|
}
|
|
35508
36456
|
const newWatchPaths = getWatchPaths(state.config, state.resolvedPaths);
|
|
35509
|
-
const addedPaths = newWatchPaths.filter((
|
|
36457
|
+
const addedPaths = newWatchPaths.filter((path2) => !oldWatchPaths.has(path2));
|
|
35510
36458
|
if (addedPaths.length > 0) {
|
|
35511
36459
|
buildInitialDependencyGraph(state.dependencyGraph, addedPaths);
|
|
35512
36460
|
addFileWatchers(state, addedPaths, (filePath) => {
|
|
@@ -35569,7 +36517,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35569
36517
|
});
|
|
35570
36518
|
}
|
|
35571
36519
|
}, handleCachedReload = async () => {
|
|
35572
|
-
const serverMtime = statSync8(
|
|
36520
|
+
const serverMtime = statSync8(resolve54(Bun.main)).mtimeMs;
|
|
35573
36521
|
const lastMtime = globalThis.__hmrServerMtime;
|
|
35574
36522
|
globalThis.__hmrServerMtime = serverMtime;
|
|
35575
36523
|
const cached = globalThis.__hmrDevResult;
|
|
@@ -35601,8 +36549,8 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35601
36549
|
return;
|
|
35602
36550
|
await detectConfigChanges(cached);
|
|
35603
36551
|
await rebuildManifest(cached);
|
|
35604
|
-
}, tryReadPackageVersion = async (
|
|
35605
|
-
const pkg = await Bun.file(
|
|
36552
|
+
}, tryReadPackageVersion = async (path2) => {
|
|
36553
|
+
const pkg = await Bun.file(path2).json().catch(() => null);
|
|
35606
36554
|
if (!pkg || pkg.name !== "@absolutejs/absolute") {
|
|
35607
36555
|
return false;
|
|
35608
36556
|
}
|
|
@@ -35610,8 +36558,8 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35610
36558
|
return true;
|
|
35611
36559
|
}, resolveAbsoluteVersion2 = async () => {
|
|
35612
36560
|
const candidates = [
|
|
35613
|
-
|
|
35614
|
-
|
|
36561
|
+
resolve54(import.meta.dir, "..", "..", "package.json"),
|
|
36562
|
+
resolve54(import.meta.dir, "..", "package.json")
|
|
35615
36563
|
];
|
|
35616
36564
|
const [candidate, ...remaining] = candidates;
|
|
35617
36565
|
if (!candidate) {
|
|
@@ -35637,7 +36585,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35637
36585
|
const entries = await readdir6(vendorDir).catch(() => emptyStringArray);
|
|
35638
36586
|
await Promise.all(entries.filter((entry) => entry.endsWith(".js")).map(async (entry) => {
|
|
35639
36587
|
const webPath = `/${framework}/vendor/${entry}`;
|
|
35640
|
-
const bytes = await Bun.file(
|
|
36588
|
+
const bytes = await Bun.file(resolve54(vendorDir, entry)).bytes();
|
|
35641
36589
|
assetStore.set(webPath, bytes);
|
|
35642
36590
|
}));
|
|
35643
36591
|
}, devBuild = async (config) => {
|
|
@@ -35823,11 +36771,11 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35823
36771
|
}
|
|
35824
36772
|
stepStartedAt = performance.now();
|
|
35825
36773
|
setBootPhase("build vendor bundles");
|
|
35826
|
-
const reactVendorDir =
|
|
35827
|
-
const angularVendorDir =
|
|
35828
|
-
const svelteVendorDir =
|
|
35829
|
-
const vueVendorDir =
|
|
35830
|
-
const depVendorDir =
|
|
36774
|
+
const reactVendorDir = resolve54(state.resolvedPaths.buildDir, "react", "vendor");
|
|
36775
|
+
const angularVendorDir = resolve54(state.resolvedPaths.buildDir, "angular", "vendor");
|
|
36776
|
+
const svelteVendorDir = resolve54(state.resolvedPaths.buildDir, "svelte", "vendor");
|
|
36777
|
+
const vueVendorDir = resolve54(state.resolvedPaths.buildDir, "vue", "vendor");
|
|
36778
|
+
const depVendorDir = resolve54(state.resolvedPaths.buildDir, "vendor");
|
|
35831
36779
|
const { buildDepVendor: buildDepVendor2 } = await Promise.resolve().then(() => (init_buildDepVendor(), exports_buildDepVendor));
|
|
35832
36780
|
const activeVendorDirs = [
|
|
35833
36781
|
config.reactDirectory ? reactVendorDir : null,
|
|
@@ -35950,7 +36898,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
|
|
|
35950
36898
|
manifest
|
|
35951
36899
|
};
|
|
35952
36900
|
globalThis.__hmrDevResult = result;
|
|
35953
|
-
globalThis.__hmrServerMtime = statSync8(
|
|
36901
|
+
globalThis.__hmrServerMtime = statSync8(resolve54(Bun.main)).mtimeMs;
|
|
35954
36902
|
return result;
|
|
35955
36903
|
};
|
|
35956
36904
|
var init_devBuild = __esm(() => {
|
|
@@ -35991,5 +36939,5 @@ export {
|
|
|
35991
36939
|
devBuild
|
|
35992
36940
|
};
|
|
35993
36941
|
|
|
35994
|
-
//# debugId=
|
|
36942
|
+
//# debugId=C21B5771D51EC59A64756E2164756E21
|
|
35995
36943
|
//# sourceMappingURL=build.js.map
|