@absolutejs/absolute 0.20.0-beta.39 → 0.20.0-beta.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +1274 -620
- package/dist/index.js +25 -3
- package/dist/index.js.map +3 -3
- package/dist/mobile/index.js +833 -97
- package/dist/mobile/index.js.map +9 -7
- package/dist/mobile/remoteMacAgentEntry.js +7 -7
- package/dist/mobile/shellBootstrap.js +36 -5
- package/dist/mobile/shellExpoDevices.js +99 -0
- package/dist/src/mobile/config.d.ts +3 -1
- package/dist/src/mobile/expoBridge.d.ts +91 -0
- package/dist/src/mobile/expoProject.d.ts +16 -0
- package/dist/src/mobile/index.d.ts +2 -0
- package/dist/src/mobile/mobileInspect.d.ts +2 -2
- package/dist/src/mobile/releaseDoctor.d.ts +1 -1
- package/dist/src/mobile/shellBootstrap.d.ts +1 -0
- package/dist/src/mobile/shellExpoDevices.d.ts +3 -0
- package/dist/types/build.d.ts +21 -3
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -791,7 +791,26 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
|
|
|
791
791
|
}
|
|
792
792
|
return value.match(/.{2}/g)?.join(":") ?? value;
|
|
793
793
|
}))
|
|
794
|
-
].sort(),
|
|
794
|
+
].sort(), normalizeExpoNativeRoutes = (config, projectRoot) => {
|
|
795
|
+
if (config.engine !== "expo")
|
|
796
|
+
return {};
|
|
797
|
+
const routes = config.routes?.native ?? {};
|
|
798
|
+
const normalized = {};
|
|
799
|
+
for (const [route, module] of Object.entries(routes)) {
|
|
800
|
+
const path = normalizeEntry(route);
|
|
801
|
+
if (path.includes("?") || path.includes("#") || path !== "/" && path.endsWith("/")) {
|
|
802
|
+
throw new TypeError(`mobile.routes.native route ${path} must be a canonical path without a query, fragment, or trailing slash.`);
|
|
803
|
+
}
|
|
804
|
+
if (path === "/__absolute/native") {
|
|
805
|
+
throw new TypeError("mobile.routes.native reserves /__absolute/native for the Expo diagnostic screen.");
|
|
806
|
+
}
|
|
807
|
+
if (path.includes("*") || path.includes(":")) {
|
|
808
|
+
throw new TypeError(`mobile.routes.native route ${path} must be static during the Expo experiment; parameters and wildcards are not supported yet.`);
|
|
809
|
+
}
|
|
810
|
+
normalized[path] = resolveProjectPath(projectRoot, requireText(module, `mobile.routes.native[${path}]`), `mobile.routes.native[${path}]`);
|
|
811
|
+
}
|
|
812
|
+
return Object.fromEntries(Object.entries(normalized).sort(([left], [right]) => left.localeCompare(right)));
|
|
813
|
+
}, normalizeAbsoluteMobileConfig = (config, projectRoot) => {
|
|
795
814
|
const appId = requireText(config.appId, "mobile.appId");
|
|
796
815
|
if (!APP_ID_PATTERN.test(appId)) {
|
|
797
816
|
throw new TypeError("mobile.appId must use reverse-domain notation, for example com.example.app.");
|
|
@@ -809,10 +828,12 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
|
|
|
809
828
|
bundleDirectory: resolveProjectPath(projectRoot, config.bundleDirectory ?? ".absolutejs/mobile/web", "mobile.bundleDirectory"),
|
|
810
829
|
deepLinkHosts: normalizeHosts(config.deepLinks?.hosts, productionOrigin),
|
|
811
830
|
deepLinkScheme,
|
|
812
|
-
engine: "capacitor",
|
|
831
|
+
engine: config.engine ?? "capacitor",
|
|
813
832
|
entry: normalizeEntry(config.entry),
|
|
833
|
+
expoNativeRoutes: normalizeExpoNativeRoutes(config, projectRoot),
|
|
834
|
+
...config.engine === "expo" ? { expoSdkVersion: config.expo?.sdkVersion ?? 57 } : {},
|
|
814
835
|
iosVersion: normalizeIosVersion(config.ios?.version),
|
|
815
|
-
nativeProjectDirectory: resolveProjectPath(projectRoot, config.nativeProject?.directory ?? "mobile", "mobile.nativeProject.directory"),
|
|
836
|
+
nativeProjectDirectory: resolveProjectPath(projectRoot, config.nativeProject?.directory ?? (config.engine === "expo" ? ".absolutejs/mobile/expo" : "mobile"), "mobile.nativeProject.directory"),
|
|
816
837
|
platforms: normalizePlatforms(config.platforms),
|
|
817
838
|
productionOrigin,
|
|
818
839
|
pushAndroidGoogleServicesFile: resolveProjectPath(projectRoot, config.pushNotifications?.android?.googleServicesFile ?? "google-services.json", "mobile.pushNotifications.android.googleServicesFile")
|
|
@@ -6420,6 +6441,11 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
6420
6441
|
if (candidate)
|
|
6421
6442
|
return candidate;
|
|
6422
6443
|
throw new TypeError("AbsoluteJS mobile push shell module is missing.");
|
|
6444
|
+
}, shellExpoDevicesModule = () => {
|
|
6445
|
+
const candidate = ["js", "ts"].map((extension) => join17(import.meta.dir, `shellExpoDevices.${extension}`)).find(existsSync9);
|
|
6446
|
+
if (candidate)
|
|
6447
|
+
return candidate;
|
|
6448
|
+
throw new TypeError("AbsoluteJS Expo device bridge module is missing.");
|
|
6423
6449
|
}, escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """), contentSecurityPolicy = (productionOrigin) => {
|
|
6424
6450
|
const backend = new URL(productionOrigin);
|
|
6425
6451
|
const socketOrigin = `${backend.protocol === "https:" ? "wss:" : "ws:"}//${backend.host}`;
|
|
@@ -6474,18 +6500,20 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
6474
6500
|
if (!resolved.startsWith(`${resolve14(packageDirectory)}/`))
|
|
6475
6501
|
throw new TypeError(`${specifier} has an unsafe import entry.`);
|
|
6476
6502
|
return resolved;
|
|
6477
|
-
}, buildShellBootstrap = async (staging, auth, sync, storagePrefix, deviceCapabilities, projectRoot) => {
|
|
6503
|
+
}, buildShellBootstrap = async (staging, auth, sync, storagePrefix, engine, deviceCapabilities, projectRoot) => {
|
|
6504
|
+
const capacitor = engine !== "expo";
|
|
6505
|
+
const shellCapabilities = capacitor ? deviceCapabilities.capabilities : [];
|
|
6478
6506
|
const modulePath = shellBootstrapModule();
|
|
6479
6507
|
const authImport = auth ? `import { createAbsoluteMobileShellAuth } from ${JSON.stringify(shellAuthModule())};
|
|
6480
6508
|
` : "";
|
|
6481
6509
|
const options = auth ? `{ createAuth: createAbsoluteMobileShellAuth${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
|
|
6482
6510
|
const syncImport = sync ? `import { installAbsoluteMobileShellSync } from ${JSON.stringify(shellSyncModule())};
|
|
6483
6511
|
` : "";
|
|
6484
|
-
const pushIndex =
|
|
6512
|
+
const pushIndex = shellCapabilities.indexOf("pushNotifications");
|
|
6485
6513
|
const push = pushIndex !== -1;
|
|
6486
6514
|
const pushImport = push ? `import { createAbsoluteMobileShellPush } from ${JSON.stringify(shellPushModule())};
|
|
6487
6515
|
` : "";
|
|
6488
|
-
const capabilityImports = (await Promise.all(
|
|
6516
|
+
const capabilityImports = (await Promise.all(shellCapabilities.map(async (name, index) => {
|
|
6489
6517
|
const provider = deviceCapabilities.providers[name];
|
|
6490
6518
|
if (!provider)
|
|
6491
6519
|
throw new TypeError(`Missing device capability provider ${name}.`);
|
|
@@ -6495,14 +6523,22 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
6495
6523
|
const pushSetup = push ? `const absoluteMobilePush = createAbsoluteMobileShellPush();
|
|
6496
6524
|
const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absoluteMobilePush.capabilityOptions);
|
|
6497
6525
|
` : "";
|
|
6498
|
-
const capabilityOptions =
|
|
6526
|
+
const capabilityOptions = shellCapabilities.map((name, index) => `${JSON.stringify(name)}: ${name === "pushNotifications" ? "absoluteMobilePushCapability" : `absoluteDeviceCapability${index}()`}`).join(", ");
|
|
6499
6527
|
const entryPath = join17(staging, ".absolute-mobile-entry.ts");
|
|
6500
|
-
const baseAdapterModule = await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor");
|
|
6528
|
+
const baseAdapterModule = capacitor ? await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor") : shellExpoDevicesModule();
|
|
6529
|
+
const adapterImport = capacitor ? `import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};` : `import { createAbsoluteExpoBridgeFetch, installAbsoluteExpoWebDeviceAdapter } from ${JSON.stringify(baseAdapterModule)};`;
|
|
6530
|
+
const adapterInstall = capacitor ? `installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });` : "installAbsoluteExpoWebDeviceAdapter();";
|
|
6531
|
+
let shellOptions = "{ createFetch: createAbsoluteExpoBridgeFetch }";
|
|
6532
|
+
if (capacitor)
|
|
6533
|
+
shellOptions = options;
|
|
6534
|
+
if (push) {
|
|
6535
|
+
shellOptions = `{ createAuth: (config, options) => createAbsoluteMobileShellAuth(config, options), beforeSignOut: absoluteMobilePush.beforeSignOut, connectPush: (auth) => absoluteMobilePush.connect(auth, absoluteMobilePushCapability)${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }`;
|
|
6536
|
+
}
|
|
6501
6537
|
await writeFile7(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
|
|
6502
|
-
|
|
6538
|
+
${adapterImport}
|
|
6503
6539
|
${authImport}${syncImport}${pushImport}${capabilityImports}
|
|
6504
|
-
${pushSetup}
|
|
6505
|
-
void startAbsoluteMobileShell(${
|
|
6540
|
+
${pushSetup}${adapterInstall}
|
|
6541
|
+
void startAbsoluteMobileShell(${shellOptions});
|
|
6506
6542
|
`);
|
|
6507
6543
|
const build = await Bun.build({
|
|
6508
6544
|
entrypoints: [entryPath],
|
|
@@ -6658,7 +6694,7 @@ void startAbsoluteMobileShell(${push ? `{ createAuth: (config, options) => creat
|
|
|
6658
6694
|
writeFile7(join17(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
6659
6695
|
`),
|
|
6660
6696
|
writeFile7(join17(staging, INDEX_FILE), indexHtml(options.config.appName, options.config.productionOrigin)),
|
|
6661
|
-
buildShellBootstrap(staging, options.auth !== undefined, options.auth !== undefined && options.sync === true, `absolutejs.${options.auth?.clientId ?? options.config.appId}.`, options.deviceCapabilities, options.projectRoot)
|
|
6697
|
+
buildShellBootstrap(staging, options.auth !== undefined, options.auth !== undefined && options.sync === true, `absolutejs.${options.auth?.clientId ?? options.config.appId}.`, options.config.engine, options.deviceCapabilities, options.projectRoot)
|
|
6662
6698
|
]);
|
|
6663
6699
|
await installBundle(staging, destination);
|
|
6664
6700
|
return manifest;
|
|
@@ -7509,9 +7545,523 @@ var init_deviceCapabilities = __esm(() => {
|
|
|
7509
7545
|
];
|
|
7510
7546
|
});
|
|
7511
7547
|
|
|
7548
|
+
// src/mobile/expoProject.ts
|
|
7549
|
+
import {
|
|
7550
|
+
access as access7,
|
|
7551
|
+
cp as cp3,
|
|
7552
|
+
mkdir as mkdir10,
|
|
7553
|
+
mkdtemp as mkdtemp5,
|
|
7554
|
+
readdir as readdir3,
|
|
7555
|
+
readFile as readFile11,
|
|
7556
|
+
rename as rename8,
|
|
7557
|
+
rm as rm7,
|
|
7558
|
+
writeFile as writeFile9
|
|
7559
|
+
} from "fs/promises";
|
|
7560
|
+
import { createHash as createHash11 } from "crypto";
|
|
7561
|
+
import { basename as basename8, dirname as dirname13, join as join21, relative as relative12, resolve as resolve17 } from "path";
|
|
7562
|
+
var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
7563
|
+
`, EXPO_ASSET_EXTENSION = ".absasset", EXPO_PROJECT_MARKER = ".absolutejs-expo-project", exists2 = async (path) => {
|
|
7564
|
+
try {
|
|
7565
|
+
await access7(path);
|
|
7566
|
+
return true;
|
|
7567
|
+
} catch {
|
|
7568
|
+
return false;
|
|
7569
|
+
}
|
|
7570
|
+
}, portableRelative2 = (from, destination) => {
|
|
7571
|
+
const value = relative12(from, destination).replaceAll("\\", "/");
|
|
7572
|
+
return value.startsWith(".") ? value : `./${value}`;
|
|
7573
|
+
}, routeSegments = (route) => route.split("/").filter(Boolean).map((segment) => {
|
|
7574
|
+
if (segment.startsWith(":"))
|
|
7575
|
+
return `[${segment.slice(1)}]`;
|
|
7576
|
+
if (segment === "." || segment === ".." || !/^[A-Za-z0-9._~-]+$/u.test(segment)) {
|
|
7577
|
+
throw new TypeError(`Expo native route ${route} contains an unsupported segment ${segment}.`);
|
|
7578
|
+
}
|
|
7579
|
+
return segment;
|
|
7580
|
+
}), routeFile = (project, route) => join21(project, "app", ...routeSegments(route), "index.tsx"), expoPackage = () => ({
|
|
7581
|
+
dependencies: {
|
|
7582
|
+
expo: "~57.0.9",
|
|
7583
|
+
"expo-asset": "~57.0.15",
|
|
7584
|
+
"expo-constants": "~57.0.16",
|
|
7585
|
+
"expo-file-system": "~57.0.6",
|
|
7586
|
+
"expo-haptics": "~57.0.2",
|
|
7587
|
+
"expo-linking": "~57.0.8",
|
|
7588
|
+
"expo-router": "~57.0.17",
|
|
7589
|
+
react: "19.2.3",
|
|
7590
|
+
"react-native": "0.86.3",
|
|
7591
|
+
"react-native-safe-area-context": "~5.7.0",
|
|
7592
|
+
"react-native-screens": "4.26.0",
|
|
7593
|
+
"react-native-webview": "13.16.1"
|
|
7594
|
+
},
|
|
7595
|
+
devDependencies: {
|
|
7596
|
+
"@types/react": "~19.2.2",
|
|
7597
|
+
typescript: "~6.0.3"
|
|
7598
|
+
},
|
|
7599
|
+
main: "expo-router/entry",
|
|
7600
|
+
name: "absolutejs-expo-shell",
|
|
7601
|
+
private: true,
|
|
7602
|
+
scripts: {
|
|
7603
|
+
android: "expo run:android",
|
|
7604
|
+
ios: "expo run:ios",
|
|
7605
|
+
start: "expo start --dev-client"
|
|
7606
|
+
},
|
|
7607
|
+
version: "0.0.0"
|
|
7608
|
+
}), expoAppConfig = (config) => ({
|
|
7609
|
+
expo: {
|
|
7610
|
+
android: {
|
|
7611
|
+
intentFilters: config.deepLinkHosts.map((host2) => ({
|
|
7612
|
+
action: "VIEW",
|
|
7613
|
+
autoVerify: true,
|
|
7614
|
+
category: ["BROWSABLE", "DEFAULT"],
|
|
7615
|
+
data: [{ host: host2, pathPrefix: "/", scheme: "https" }]
|
|
7616
|
+
})),
|
|
7617
|
+
package: config.appId
|
|
7618
|
+
},
|
|
7619
|
+
experiments: { typedRoutes: true },
|
|
7620
|
+
ios: {
|
|
7621
|
+
associatedDomains: config.deepLinkHosts.map((host2) => `applinks:${host2}`),
|
|
7622
|
+
bundleIdentifier: config.appId,
|
|
7623
|
+
...config.iosVersion ? { buildNumber: config.iosVersion } : {}
|
|
7624
|
+
},
|
|
7625
|
+
name: config.appName,
|
|
7626
|
+
plugins: ["expo-router"],
|
|
7627
|
+
runtimeVersion: { policy: "appVersion" },
|
|
7628
|
+
scheme: config.deepLinkScheme,
|
|
7629
|
+
slug: config.appId.toLowerCase().replaceAll(".", "-"),
|
|
7630
|
+
version: config.iosVersion ?? "0.1.0"
|
|
7631
|
+
}
|
|
7632
|
+
}), metroConfig = (projectRoot) => `${EXPO_GENERATED_HEADER}const { getDefaultConfig } = require('expo/metro-config');
|
|
7633
|
+
const path = require('node:path');
|
|
7634
|
+
|
|
7635
|
+
const projectRoot = __dirname;
|
|
7636
|
+
const appRoot = ${JSON.stringify(projectRoot)};
|
|
7637
|
+
const config = getDefaultConfig(projectRoot);
|
|
7638
|
+
config.resolver.assetExts.push('absasset');
|
|
7639
|
+
config.resolver.nodeModulesPaths = [
|
|
7640
|
+
path.join(projectRoot, 'node_modules'),
|
|
7641
|
+
path.join(appRoot, 'node_modules')
|
|
7642
|
+
];
|
|
7643
|
+
config.watchFolders = [appRoot];
|
|
7644
|
+
|
|
7645
|
+
module.exports = config;
|
|
7646
|
+
`, layoutSource, nativeDiagnosticSource, webHostSource = (config) => {
|
|
7647
|
+
const nativeRoutes = [
|
|
7648
|
+
"/__absolute/native",
|
|
7649
|
+
...Object.keys(config.expoNativeRoutes)
|
|
7650
|
+
];
|
|
7651
|
+
return `${EXPO_GENERATED_HEADER}import * as Haptics from 'expo-haptics';
|
|
7652
|
+
import * as Linking from 'expo-linking';
|
|
7653
|
+
import { router, usePathname } from 'expo-router';
|
|
7654
|
+
import { useEffect, useRef, useState } from 'react';
|
|
7655
|
+
import { ActivityIndicator, BackHandler, StyleSheet, View } from 'react-native';
|
|
7656
|
+
import { WebView, type WebViewMessageEvent } from 'react-native-webview';
|
|
7657
|
+
import { materializeAbsoluteWebBundle } from './webAssets';
|
|
7658
|
+
|
|
7659
|
+
const BRIDGE_FORMAT = 1;
|
|
7660
|
+
const MAX_MESSAGE_BYTES = 64 * 1024;
|
|
7661
|
+
const MAX_HTTP_BODY_BYTES = 48 * 1024;
|
|
7662
|
+
const NATIVE_ROUTES = new Set(${JSON.stringify(nativeRoutes)});
|
|
7663
|
+
const PRODUCTION_ORIGIN = ${JSON.stringify(config.productionOrigin)};
|
|
7664
|
+
|
|
7665
|
+
const bridgeBootstrap = (path: string) => \`(() => {
|
|
7666
|
+
const pending = new Map();
|
|
7667
|
+
let sequence = 0;
|
|
7668
|
+
let currentPath = \${JSON.stringify(path)};
|
|
7669
|
+
const send = value => {
|
|
7670
|
+
const source = JSON.stringify(value);
|
|
7671
|
+
if (new TextEncoder().encode(source).byteLength > 65536) throw new Error('Expo bridge message exceeds 64 KiB.');
|
|
7672
|
+
window.ReactNativeWebView.postMessage(source);
|
|
7673
|
+
};
|
|
7674
|
+
globalThis.__absoluteExpoReceive = source => {
|
|
7675
|
+
const message = JSON.parse(source);
|
|
7676
|
+
const operation = pending.get(message.id);
|
|
7677
|
+
if (!operation) return;
|
|
7678
|
+
pending.delete(message.id);
|
|
7679
|
+
clearTimeout(operation.timer);
|
|
7680
|
+
message.error ? operation.reject(new Error(message.error.message)) : operation.resolve(message.result);
|
|
7681
|
+
};
|
|
7682
|
+
globalThis.__absoluteExpoBridge = {
|
|
7683
|
+
request(method, params) {
|
|
7684
|
+
const id = 'web_' + Date.now().toString(36) + '_' + (++sequence).toString(36);
|
|
7685
|
+
send({ format: 1, id, kind: 'request', method, params, path: currentPath });
|
|
7686
|
+
return new Promise((resolve, reject) => {
|
|
7687
|
+
const timer = setTimeout(() => {
|
|
7688
|
+
pending.delete(id);
|
|
7689
|
+
reject(new Error('Expo bridge request timed out.'));
|
|
7690
|
+
}, 10000);
|
|
7691
|
+
pending.set(id, { reject, resolve, timer });
|
|
7692
|
+
});
|
|
7693
|
+
},
|
|
7694
|
+
setPath(path) {
|
|
7695
|
+
currentPath = path;
|
|
7696
|
+
send({ format: 1, kind: 'event', event: 'navigation', path });
|
|
7697
|
+
}
|
|
7698
|
+
};
|
|
7699
|
+
document.addEventListener('click', event => {
|
|
7700
|
+
const anchor = event.target instanceof Element ? event.target.closest('a[href]') : null;
|
|
7701
|
+
if (!anchor) return;
|
|
7702
|
+
const url = new URL(anchor.href, location.href);
|
|
7703
|
+
if (!${JSON.stringify(nativeRoutes)}.includes(url.pathname)) return;
|
|
7704
|
+
event.preventDefault();
|
|
7705
|
+
send({ format: 1, kind: 'event', event: 'navigation', path: url.pathname + url.search + url.hash });
|
|
7706
|
+
}, true);
|
|
7707
|
+
send({ format: 1, kind: 'event', event: 'ready', path: \${JSON.stringify(path)} });
|
|
7708
|
+
})(); true;\`;
|
|
7709
|
+
|
|
7710
|
+
const impact = async (params: Record<string, unknown>) => {
|
|
7711
|
+
const style = params.style;
|
|
7712
|
+
if (style === 'selection') return Haptics.selectionAsync();
|
|
7713
|
+
if (style === 'success' || style === 'warning' || style === 'error') {
|
|
7714
|
+
const value = style === 'success' ? Haptics.NotificationFeedbackType.Success : style === 'warning' ? Haptics.NotificationFeedbackType.Warning : Haptics.NotificationFeedbackType.Error;
|
|
7715
|
+
return Haptics.notificationAsync(value);
|
|
7716
|
+
}
|
|
7717
|
+
const value = style === 'light' ? Haptics.ImpactFeedbackStyle.Light : style === 'heavy' ? Haptics.ImpactFeedbackStyle.Heavy : Haptics.ImpactFeedbackStyle.Medium;
|
|
7718
|
+
return Haptics.impactAsync(value);
|
|
7719
|
+
};
|
|
7720
|
+
|
|
7721
|
+
const bridgeFetch = async (params: Record<string, unknown>) => {
|
|
7722
|
+
if (params.method !== 'GET' || typeof params.url !== 'string' || typeof params.headers !== 'object' || params.headers === null || Array.isArray(params.headers)) throw new Error('Expo bridge HTTP request is invalid.');
|
|
7723
|
+
const url = new URL(params.url);
|
|
7724
|
+
if (url.origin !== PRODUCTION_ORIGIN || url.username || url.password) throw new Error('Expo bridge HTTP request left productionOrigin.');
|
|
7725
|
+
const headers = new Headers();
|
|
7726
|
+
for (const [name, value] of Object.entries(params.headers as Record<string, unknown>)) {
|
|
7727
|
+
const normalized = name.toLowerCase();
|
|
7728
|
+
if (typeof value !== 'string' || (normalized !== 'accept' && !normalized.startsWith('x-absolute-mobile-'))) throw new Error('Expo bridge HTTP header is not allowed.');
|
|
7729
|
+
headers.set(normalized, value);
|
|
7730
|
+
}
|
|
7731
|
+
const response = await fetch(url, { headers, method: 'GET', redirect: 'manual' });
|
|
7732
|
+
if (new URL(response.url || url.href).origin !== PRODUCTION_ORIGIN || response.status >= 300 && response.status < 400) throw new Error('Expo bridge HTTP redirects are not allowed.');
|
|
7733
|
+
const body = await response.text();
|
|
7734
|
+
if (new TextEncoder().encode(body).byteLength > MAX_HTTP_BODY_BYTES) throw new Error('Expo bridge HTTP response exceeds 48 KiB.');
|
|
7735
|
+
const responseHeaders: Record<string, string> = {};
|
|
7736
|
+
for (const name of ['cache-control', 'content-type']) {
|
|
7737
|
+
const value = response.headers.get(name);
|
|
7738
|
+
if (value) responseHeaders[name] = value;
|
|
7739
|
+
}
|
|
7740
|
+
return { body, headers: responseHeaders, status: response.status };
|
|
7741
|
+
};
|
|
7742
|
+
|
|
7743
|
+
export function AbsoluteWebHost() {
|
|
7744
|
+
const pathname = usePathname() || '/';
|
|
7745
|
+
const webView = useRef<WebView>(null);
|
|
7746
|
+
const [indexUri, setIndexUri] = useState<string>();
|
|
7747
|
+
const [canGoBack, setCanGoBack] = useState(false);
|
|
7748
|
+
const activeWebPath = useRef(pathname);
|
|
7749
|
+
|
|
7750
|
+
useEffect(() => { void materializeAbsoluteWebBundle().then(setIndexUri); }, []);
|
|
7751
|
+
useEffect(() => {
|
|
7752
|
+
const subscription = BackHandler.addEventListener('hardwareBackPress', () => {
|
|
7753
|
+
if (!canGoBack) return false;
|
|
7754
|
+
webView.current?.goBack();
|
|
7755
|
+
return true;
|
|
7756
|
+
});
|
|
7757
|
+
return () => subscription.remove();
|
|
7758
|
+
}, [canGoBack]);
|
|
7759
|
+
|
|
7760
|
+
const respond = (message: Record<string, unknown>) => {
|
|
7761
|
+
const source = JSON.stringify(message).replaceAll('\\u2028', '\\\\u2028').replaceAll('\\u2029', '\\\\u2029');
|
|
7762
|
+
if (new TextEncoder().encode(source).byteLength > MAX_MESSAGE_BYTES) throw new Error('Expo bridge response exceeds 64 KiB.');
|
|
7763
|
+
webView.current?.injectJavaScript(\`globalThis.__absoluteExpoReceive(\${JSON.stringify(source)}); true;\`);
|
|
7764
|
+
};
|
|
7765
|
+
const onMessage = async (event: WebViewMessageEvent) => {
|
|
7766
|
+
const source = event.nativeEvent.data;
|
|
7767
|
+
if (new TextEncoder().encode(source).byteLength > MAX_MESSAGE_BYTES) return;
|
|
7768
|
+
let message: Record<string, unknown>;
|
|
7769
|
+
try { message = JSON.parse(source); } catch { return; }
|
|
7770
|
+
if (message.format !== BRIDGE_FORMAT || typeof message.path !== 'string' || !message.path.startsWith('/') || message.path.startsWith('//')) return;
|
|
7771
|
+
if (message.kind === 'event' && (message.event === 'navigation' || message.event === 'ready')) {
|
|
7772
|
+
const target = new URL(message.path, PRODUCTION_ORIGIN);
|
|
7773
|
+
if (target.origin !== PRODUCTION_ORIGIN) return;
|
|
7774
|
+
if (NATIVE_ROUTES.has(target.pathname)) router.push(message.path as never);
|
|
7775
|
+
else activeWebPath.current = message.path;
|
|
7776
|
+
return;
|
|
7777
|
+
}
|
|
7778
|
+
if (message.kind !== 'request' || typeof message.id !== 'string' || message.path !== activeWebPath.current) return;
|
|
7779
|
+
try {
|
|
7780
|
+
if (typeof message.params !== 'object' || message.params === null || Array.isArray(message.params)) throw new Error('Expo bridge method params are invalid.');
|
|
7781
|
+
if (message.method === 'devices.haptics.impact') {
|
|
7782
|
+
const style = (message.params as Record<string, unknown>).style;
|
|
7783
|
+
if (typeof style !== 'string' || !['error', 'heavy', 'light', 'medium', 'selection', 'success', 'vibrate', 'warning'].includes(style)) throw new Error('Expo bridge haptics style is invalid.');
|
|
7784
|
+
await impact(message.params as Record<string, unknown>);
|
|
7785
|
+
respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: null });
|
|
7786
|
+
} else if (message.method === 'http.fetch') {
|
|
7787
|
+
respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: await bridgeFetch(message.params as Record<string, unknown>) });
|
|
7788
|
+
} else {
|
|
7789
|
+
throw new Error('Expo bridge method is not allowed.');
|
|
7790
|
+
}
|
|
7791
|
+
} catch (error) {
|
|
7792
|
+
respond({ error: { code: 'failed', message: error instanceof Error ? error.message : 'Native operation failed.' }, format: BRIDGE_FORMAT, id: message.id, kind: 'response' });
|
|
7793
|
+
}
|
|
7794
|
+
};
|
|
7795
|
+
|
|
7796
|
+
if (!indexUri) return <View style={styles.loading}><ActivityIndicator /></View>;
|
|
7797
|
+
return <WebView
|
|
7798
|
+
allowFileAccess
|
|
7799
|
+
allowFileAccessFromFileURLs
|
|
7800
|
+
allowUniversalAccessFromFileURLs={false}
|
|
7801
|
+
allowingReadAccessToURL={indexUri.slice(0, indexUri.lastIndexOf('/') + 1)}
|
|
7802
|
+
injectedJavaScriptBeforeContentLoaded={bridgeBootstrap(pathname)}
|
|
7803
|
+
onMessage={onMessage}
|
|
7804
|
+
onNavigationStateChange={state => setCanGoBack(state.canGoBack)}
|
|
7805
|
+
onShouldStartLoadWithRequest={request => {
|
|
7806
|
+
if (request.url.startsWith('file:') || request.url.startsWith(PRODUCTION_ORIGIN)) return true;
|
|
7807
|
+
void Linking.openURL(request.url);
|
|
7808
|
+
return false;
|
|
7809
|
+
}}
|
|
7810
|
+
ref={webView}
|
|
7811
|
+
source={{ uri: indexUri + '?absolutePath=' + encodeURIComponent(pathname) }}
|
|
7812
|
+
style={styles.web}
|
|
7813
|
+
/>;
|
|
7814
|
+
}
|
|
7815
|
+
|
|
7816
|
+
const styles = StyleSheet.create({ loading: { alignItems: 'center', flex: 1, justifyContent: 'center' }, web: { flex: 1 } });
|
|
7817
|
+
`;
|
|
7818
|
+
}, webRouteSource, catchAllRouteSource, nativeWrapperSource = (wrapper, module) => `${EXPO_GENERATED_HEADER}export { default } from ${JSON.stringify(portableRelative2(dirname13(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
|
|
7819
|
+
`, expoTsConfig = (projectRoot, project) => ({
|
|
7820
|
+
compilerOptions: {
|
|
7821
|
+
paths: {
|
|
7822
|
+
"*": [
|
|
7823
|
+
"./node_modules/*",
|
|
7824
|
+
`${portableRelative2(project, projectRoot)}/node_modules/*`
|
|
7825
|
+
],
|
|
7826
|
+
react: ["./node_modules/@types/react/index.d.ts"],
|
|
7827
|
+
"react/*": ["./node_modules/@types/react/*"]
|
|
7828
|
+
},
|
|
7829
|
+
strict: true
|
|
7830
|
+
},
|
|
7831
|
+
extends: "expo/tsconfig.base"
|
|
7832
|
+
}), writeManagedFile = async (path, source, force) => {
|
|
7833
|
+
await mkdir10(dirname13(path), { recursive: true });
|
|
7834
|
+
if (await exists2(path)) {
|
|
7835
|
+
const current = await readFile11(path, "utf8");
|
|
7836
|
+
if (current === source)
|
|
7837
|
+
return false;
|
|
7838
|
+
if (!force && !current.startsWith(EXPO_GENERATED_HEADER)) {
|
|
7839
|
+
throw new TypeError(`Expo project file ${path} is not AbsoluteJS-managed; rerun with --force only after reviewing it.`);
|
|
7840
|
+
}
|
|
7841
|
+
}
|
|
7842
|
+
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
7843
|
+
await writeFile9(temporary, source, { flag: "wx" });
|
|
7844
|
+
await rename8(temporary, path);
|
|
7845
|
+
return true;
|
|
7846
|
+
}, jsonSource = (value) => `${JSON.stringify(value, null, "\t")}
|
|
7847
|
+
`, writeAbsoluteExpoProject = async (config, options) => {
|
|
7848
|
+
if (config.engine !== "expo")
|
|
7849
|
+
throw new TypeError("Expo project generation requires mobile.engine: expo.");
|
|
7850
|
+
const projectRoot = resolve17(options.projectRoot);
|
|
7851
|
+
const project = config.nativeProjectDirectory;
|
|
7852
|
+
const routeModules = Object.entries(config.expoNativeRoutes);
|
|
7853
|
+
const moduleChecks = await Promise.all(routeModules.map(async ([route, module]) => ({
|
|
7854
|
+
exists: await exists2(module),
|
|
7855
|
+
module,
|
|
7856
|
+
route
|
|
7857
|
+
})));
|
|
7858
|
+
const missing = moduleChecks.find((entry) => !entry.exists);
|
|
7859
|
+
if (missing) {
|
|
7860
|
+
throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
|
|
7861
|
+
}
|
|
7862
|
+
const marker = join21(project, EXPO_PROJECT_MARKER);
|
|
7863
|
+
if (await exists2(project) && !await exists2(marker)) {
|
|
7864
|
+
const entries = await readdir3(project);
|
|
7865
|
+
if (entries.length > 0 && !options.force) {
|
|
7866
|
+
throw new TypeError(`Expo project directory ${project} is not AbsoluteJS-managed; rerun with --force only after reviewing it.`);
|
|
7867
|
+
}
|
|
7868
|
+
}
|
|
7869
|
+
await mkdir10(project, { recursive: true });
|
|
7870
|
+
await writeFile9(marker, `format=1
|
|
7871
|
+
`);
|
|
7872
|
+
const files = new Map([
|
|
7873
|
+
[
|
|
7874
|
+
join21(project, ".gitignore"),
|
|
7875
|
+
`.expo/
|
|
7876
|
+
android/
|
|
7877
|
+
ios/
|
|
7878
|
+
node_modules/
|
|
7879
|
+
`
|
|
7880
|
+
],
|
|
7881
|
+
[join21(project, "app.json"), jsonSource(expoAppConfig(config))],
|
|
7882
|
+
[join21(project, "package.json"), jsonSource(expoPackage())],
|
|
7883
|
+
[join21(project, "metro.config.js"), metroConfig(projectRoot)],
|
|
7884
|
+
[
|
|
7885
|
+
join21(project, "tsconfig.json"),
|
|
7886
|
+
jsonSource(expoTsConfig(projectRoot, project))
|
|
7887
|
+
],
|
|
7888
|
+
[join21(project, "app", "_layout.tsx"), layoutSource],
|
|
7889
|
+
[
|
|
7890
|
+
join21(project, "app", "__absolute", "native", "index.tsx"),
|
|
7891
|
+
nativeDiagnosticSource
|
|
7892
|
+
],
|
|
7893
|
+
[
|
|
7894
|
+
join21(project, "src", "generated", "AbsoluteWebHost.tsx"),
|
|
7895
|
+
webHostSource(config)
|
|
7896
|
+
]
|
|
7897
|
+
]);
|
|
7898
|
+
if (!config.expoNativeRoutes["/"]) {
|
|
7899
|
+
files.set(join21(project, "app", "index.tsx"), webRouteSource);
|
|
7900
|
+
}
|
|
7901
|
+
files.set(join21(project, "app", "[...absolute].tsx"), catchAllRouteSource);
|
|
7902
|
+
for (const [route, module] of routeModules) {
|
|
7903
|
+
const wrapper = route === "/" ? join21(project, "app", "index.tsx") : routeFile(project, route);
|
|
7904
|
+
files.set(wrapper, nativeWrapperSource(wrapper, module));
|
|
7905
|
+
}
|
|
7906
|
+
const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
|
|
7907
|
+
const changed = changes.filter(Boolean).length;
|
|
7908
|
+
return { changed, path: project, written: [...files.keys()] };
|
|
7909
|
+
}, walkFiles = async (root, directory = root) => {
|
|
7910
|
+
const entries = await readdir3(directory, { withFileTypes: true });
|
|
7911
|
+
const nested = await Promise.all(entries.map((entry) => {
|
|
7912
|
+
const path = join21(directory, entry.name);
|
|
7913
|
+
if (entry.isDirectory())
|
|
7914
|
+
return walkFiles(root, path);
|
|
7915
|
+
if (entry.isFile())
|
|
7916
|
+
return [path];
|
|
7917
|
+
throw new TypeError(`Expo embedded bundle cannot contain a symbolic link or special file: ${path}.`);
|
|
7918
|
+
}));
|
|
7919
|
+
return nested.flat().sort();
|
|
7920
|
+
}, renameIfPresent = async (source, destination) => {
|
|
7921
|
+
try {
|
|
7922
|
+
await rename8(source, destination);
|
|
7923
|
+
return true;
|
|
7924
|
+
} catch (error) {
|
|
7925
|
+
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT") {
|
|
7926
|
+
return false;
|
|
7927
|
+
}
|
|
7928
|
+
throw error;
|
|
7929
|
+
}
|
|
7930
|
+
}, installStagedDirectory = async (staging, destination) => {
|
|
7931
|
+
const backup = `${destination}.previous-${crypto.randomUUID()}`;
|
|
7932
|
+
const moved = await renameIfPresent(destination, backup);
|
|
7933
|
+
try {
|
|
7934
|
+
await rename8(staging, destination);
|
|
7935
|
+
if (moved)
|
|
7936
|
+
await rm7(backup, { force: true, recursive: true });
|
|
7937
|
+
} catch (error) {
|
|
7938
|
+
if (moved)
|
|
7939
|
+
await rename8(backup, destination);
|
|
7940
|
+
throw error;
|
|
7941
|
+
}
|
|
7942
|
+
}, assetModuleSource = (assets, bundleId) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
|
|
7943
|
+
import { Directory, File, Paths } from 'expo-file-system';
|
|
7944
|
+
|
|
7945
|
+
declare const require: (path: string) => number;
|
|
7946
|
+
const BUNDLE_ID = ${JSON.stringify(bundleId)};
|
|
7947
|
+
const ASSETS = [
|
|
7948
|
+
${assets.map(({ asset, path }) => ` { module: require(${JSON.stringify(asset)}), path: ${JSON.stringify(path)} }`).join(`,
|
|
7949
|
+
`)}
|
|
7950
|
+
] as const;
|
|
7951
|
+
|
|
7952
|
+
export const materializeAbsoluteWebBundle = async () => {
|
|
7953
|
+
const root = new Directory(Paths.document, 'absolutejs-web', BUNDLE_ID);
|
|
7954
|
+
root.create({ idempotent: true, intermediates: true });
|
|
7955
|
+
for (const entry of ASSETS) {
|
|
7956
|
+
const parts = entry.path.split('/');
|
|
7957
|
+
const name = parts.pop();
|
|
7958
|
+
if (!name) throw new Error('AbsoluteJS embedded asset path is invalid.');
|
|
7959
|
+
const directory = new Directory(root, ...parts);
|
|
7960
|
+
directory.create({ idempotent: true, intermediates: true });
|
|
7961
|
+
const destination = new File(directory, name);
|
|
7962
|
+
if (destination.exists) continue;
|
|
7963
|
+
const asset = await Asset.fromModule(entry.module).downloadAsync();
|
|
7964
|
+
if (!asset.localUri) throw new Error('Expo did not materialize an embedded AbsoluteJS asset.');
|
|
7965
|
+
new File(asset.localUri).copy(destination);
|
|
7966
|
+
}
|
|
7967
|
+
|
|
7968
|
+
return new File(root, 'index.html').uri;
|
|
7969
|
+
};
|
|
7970
|
+
`, syncAbsoluteExpoWebAssets = async (config) => {
|
|
7971
|
+
if (config.engine !== "expo")
|
|
7972
|
+
throw new TypeError("Expo asset sync requires mobile.engine: expo.");
|
|
7973
|
+
const marker = join21(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
|
|
7974
|
+
if (!await exists2(marker)) {
|
|
7975
|
+
throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
|
|
7976
|
+
}
|
|
7977
|
+
const manifestPath = join21(config.bundleDirectory, "absolute-mobile-manifest.json");
|
|
7978
|
+
const manifest = JSON.parse(await readFile11(manifestPath, "utf8"));
|
|
7979
|
+
const appBuild = typeof manifest === "object" && manifest !== null && typeof Reflect.get(manifest, "appBuild") === "string" ? String(Reflect.get(manifest, "appBuild")) : undefined;
|
|
7980
|
+
if (!appBuild)
|
|
7981
|
+
throw new TypeError("AbsoluteJS mobile manifest has no appBuild.");
|
|
7982
|
+
const files = await walkFiles(config.bundleDirectory);
|
|
7983
|
+
const bundleHash = createHash11("sha256");
|
|
7984
|
+
const filesWithContents = await Promise.all(files.map(async (file) => ({ contents: await readFile11(file), file })));
|
|
7985
|
+
filesWithContents.forEach(({ contents, file }) => {
|
|
7986
|
+
bundleHash.update(relative12(config.bundleDirectory, file).replaceAll("\\", "/"));
|
|
7987
|
+
bundleHash.update("\x00");
|
|
7988
|
+
bundleHash.update(contents);
|
|
7989
|
+
bundleHash.update("\x00");
|
|
7990
|
+
});
|
|
7991
|
+
const bundleId = `amexpo_${bundleHash.digest("hex")}`;
|
|
7992
|
+
const destination = join21(config.nativeProjectDirectory, "assets", "absolute");
|
|
7993
|
+
await mkdir10(dirname13(destination), { recursive: true });
|
|
7994
|
+
const staging = await mkdtemp5(join21(dirname13(destination), `.${basename8(destination)}.stage-`));
|
|
7995
|
+
let assets;
|
|
7996
|
+
try {
|
|
7997
|
+
assets = await Promise.all(files.map(async (source, index) => {
|
|
7998
|
+
const name = `${String(index).padStart(6, "0")}${EXPO_ASSET_EXTENSION}`;
|
|
7999
|
+
await cp3(source, join21(staging, name));
|
|
8000
|
+
return {
|
|
8001
|
+
asset: portableRelative2(join21(config.nativeProjectDirectory, "src", "generated"), join21(destination, name)),
|
|
8002
|
+
path: relative12(config.bundleDirectory, source).replaceAll("\\", "/")
|
|
8003
|
+
};
|
|
8004
|
+
}));
|
|
8005
|
+
await installStagedDirectory(staging, destination);
|
|
8006
|
+
} catch (error) {
|
|
8007
|
+
await rm7(staging, { force: true, recursive: true });
|
|
8008
|
+
throw error;
|
|
8009
|
+
}
|
|
8010
|
+
const generated = join21(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
|
|
8011
|
+
await writeManagedFile(generated, assetModuleSource(assets, bundleId), true);
|
|
8012
|
+
return { appBuild, assets: assets.length, bundleId, path: destination };
|
|
8013
|
+
};
|
|
8014
|
+
var init_expoProject = __esm(() => {
|
|
8015
|
+
layoutSource = `${EXPO_GENERATED_HEADER}import { Stack } from 'expo-router';
|
|
8016
|
+
|
|
8017
|
+
export default function AbsoluteLayout() {
|
|
8018
|
+
return <Stack screenOptions={{ headerShown: false }} />;
|
|
8019
|
+
}
|
|
8020
|
+
`;
|
|
8021
|
+
nativeDiagnosticSource = `${EXPO_GENERATED_HEADER}import * as Haptics from 'expo-haptics';
|
|
8022
|
+
import { Link } from 'expo-router';
|
|
8023
|
+
import { Pressable, SafeAreaView, StyleSheet, Text, View } from 'react-native';
|
|
8024
|
+
|
|
8025
|
+
export default function AbsoluteNativeDiagnostic() {
|
|
8026
|
+
return (
|
|
8027
|
+
<SafeAreaView style={styles.page}>
|
|
8028
|
+
<View style={styles.card}>
|
|
8029
|
+
<Text style={styles.eyebrow}>ABSOLUTEJS \xB7 EXPO EXPERIMENT</Text>
|
|
8030
|
+
<Text style={styles.title}>This screen is native React UI.</Text>
|
|
8031
|
+
<Text style={styles.body}>Ordinary AbsoluteJS routes remain embedded web routes. Only explicitly owned routes use React Native.</Text>
|
|
8032
|
+
<Pressable style={styles.button} onPress={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium)}>
|
|
8033
|
+
<Text style={styles.buttonText}>Test native haptics</Text>
|
|
8034
|
+
</Pressable>
|
|
8035
|
+
<Link href="/" style={styles.link}>Open the AbsoluteJS app</Link>
|
|
8036
|
+
</View>
|
|
8037
|
+
</SafeAreaView>
|
|
8038
|
+
);
|
|
8039
|
+
}
|
|
8040
|
+
|
|
8041
|
+
const styles = StyleSheet.create({
|
|
8042
|
+
body: { color: '#cbd5e1', fontSize: 16, lineHeight: 24 },
|
|
8043
|
+
button: { backgroundColor: '#f8fafc', borderRadius: 12, padding: 14 },
|
|
8044
|
+
buttonText: { color: '#020617', fontSize: 16, fontWeight: '700', textAlign: 'center' },
|
|
8045
|
+
card: { backgroundColor: '#0f172a', borderRadius: 24, gap: 20, maxWidth: 560, padding: 28, width: '100%' },
|
|
8046
|
+
eyebrow: { color: '#38bdf8', fontSize: 12, fontWeight: '800', letterSpacing: 1.5 },
|
|
8047
|
+
link: { color: '#7dd3fc', fontSize: 16, textAlign: 'center' },
|
|
8048
|
+
page: { alignItems: 'center', backgroundColor: '#020617', flex: 1, justifyContent: 'center', padding: 20 },
|
|
8049
|
+
title: { color: '#f8fafc', fontSize: 32, fontWeight: '800' }
|
|
8050
|
+
});
|
|
8051
|
+
`;
|
|
8052
|
+
webRouteSource = `${EXPO_GENERATED_HEADER}import { AbsoluteWebHost } from '../src/generated/AbsoluteWebHost';
|
|
8053
|
+
|
|
8054
|
+
export default AbsoluteWebHost;
|
|
8055
|
+
`;
|
|
8056
|
+
catchAllRouteSource = `${EXPO_GENERATED_HEADER}import { AbsoluteWebHost } from '../src/generated/AbsoluteWebHost';
|
|
8057
|
+
|
|
8058
|
+
export default AbsoluteWebHost;
|
|
8059
|
+
`;
|
|
8060
|
+
});
|
|
8061
|
+
|
|
7512
8062
|
// src/mobile/buildPipeline.ts
|
|
7513
|
-
import { readFile as
|
|
7514
|
-
import { join as
|
|
8063
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
8064
|
+
import { join as join22, resolve as resolve18 } from "path";
|
|
7515
8065
|
import { pathToFileURL } from "url";
|
|
7516
8066
|
var isElysiaApp = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "compile") === "function" && Array.isArray(Reflect.get(value, "routes")), isStringRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string"), serverExportName = (loaded, app) => {
|
|
7517
8067
|
if (loaded.server === app)
|
|
@@ -7540,11 +8090,11 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
|
|
|
7540
8090
|
const exportName = serverExportName(loaded, app);
|
|
7541
8091
|
return { app, exportName };
|
|
7542
8092
|
}, finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
7543
|
-
const buildDirectory =
|
|
8093
|
+
const buildDirectory = resolve18(options.buildDirectory);
|
|
7544
8094
|
const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
|
|
7545
|
-
const root =
|
|
8095
|
+
const root = join22(buildDirectory, ".absolutejs", "mobile-compatibility");
|
|
7546
8096
|
const [manifestSource, previous] = await Promise.all([
|
|
7547
|
-
|
|
8097
|
+
readFile12(join22(buildDirectory, "manifest.json"), "utf8"),
|
|
7548
8098
|
readAbsoluteMobileMaterializedReleases(root)
|
|
7549
8099
|
]);
|
|
7550
8100
|
const manifest = JSON.parse(manifestSource);
|
|
@@ -7557,11 +8107,11 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
|
|
|
7557
8107
|
process.env.ABSOLUTE_BUILD_DIR = buildDirectory;
|
|
7558
8108
|
process.env.ABSOLUTE_COMPILED_RUNTIME = "1";
|
|
7559
8109
|
if (options.configPath) {
|
|
7560
|
-
process.env.ABSOLUTE_CONFIG =
|
|
8110
|
+
process.env.ABSOLUTE_CONFIG = resolve18(options.projectRoot, options.configPath);
|
|
7561
8111
|
}
|
|
7562
8112
|
let loaded;
|
|
7563
8113
|
try {
|
|
7564
|
-
loaded = await loadServerApp(
|
|
8114
|
+
loaded = await loadServerApp(resolve18(options.producerPath));
|
|
7565
8115
|
} finally {
|
|
7566
8116
|
restoreEnvironmentVariable("ABSOLUTE_BUILD_DIR", previousBuildDirectory);
|
|
7567
8117
|
restoreEnvironmentVariable("ABSOLUTE_COMPILED_RUNTIME", previousCompiledRuntime);
|
|
@@ -7574,19 +8124,27 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
|
|
|
7574
8124
|
manifest,
|
|
7575
8125
|
previousArtifacts: previous.map(({ artifact }) => artifact),
|
|
7576
8126
|
producerExport: loaded.exportName,
|
|
7577
|
-
producerPath:
|
|
8127
|
+
producerPath: resolve18(options.producerPath),
|
|
7578
8128
|
runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
|
|
7579
8129
|
});
|
|
7580
8130
|
const auth = resolveAbsoluteMobileAuthManifest(options.projectRoot, mobile);
|
|
8131
|
+
if (mobile.engine === "expo" && auth) {
|
|
8132
|
+
throw new TypeError("Expo mobile Auth is not released yet. The experimental Expo shell cannot safely substitute Capacitor credentials; remove engine: 'expo' or wait for @absolutejs/auth-expo.");
|
|
8133
|
+
}
|
|
7581
8134
|
const sync = auth !== undefined && projectUsesAbsoluteSync(options.projectRoot);
|
|
7582
8135
|
const syncSchema = sync ? discoverAbsoluteSyncSchema(options.projectRoot) : undefined;
|
|
7583
8136
|
const deviceCapabilities = resolveAbsoluteDeviceCapabilityPlan(options.projectRoot);
|
|
7584
8137
|
const usesPush = deviceCapabilities.capabilities.includes("pushNotifications");
|
|
8138
|
+
if (mobile.engine === "expo" && deviceCapabilities.capabilities.some((capability) => capability !== "haptics")) {
|
|
8139
|
+
throw new TypeError("Experimental Expo builds currently bridge only @absolutejs/devices haptics. Other detected device capabilities require their Expo adapters.");
|
|
8140
|
+
}
|
|
7585
8141
|
if (usesPush && !auth)
|
|
7586
8142
|
throw new TypeError("Portable push notifications require @absolutejs/auth so provider tokens can be registered without exposing identity controls to page code.");
|
|
7587
8143
|
if (usesPush && !loaded.app.routes.some((route) => route.path === "/auth/push" || route.path === "/auth/mobile/push"))
|
|
7588
8144
|
throw new TypeError("@absolutejs/devices pushNotifications is used, but Auth push is not configured. Pass a trusted server-side registrar to auth({ push: ... }).");
|
|
7589
|
-
|
|
8145
|
+
if (mobile.engine === "capacitor") {
|
|
8146
|
+
assertAbsoluteDeviceCapabilityPackages(options.projectRoot, deviceCapabilities);
|
|
8147
|
+
}
|
|
7590
8148
|
if (auth && !loaded.app.routes.some((route) => route.path === "/.well-known/openid-configuration")) {
|
|
7591
8149
|
throw new TypeError("@absolutejs/auth is installed, but its OIDC provider is not mounted. Native authentication requires the auth oidc configuration so AbsoluteJS can provision a public PKCE client.");
|
|
7592
8150
|
}
|
|
@@ -7610,6 +8168,12 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
|
|
|
7610
8168
|
...sync ? { sync: true } : {},
|
|
7611
8169
|
...syncSchema ? { syncSchema: { components: syncSchema.components } } : {}
|
|
7612
8170
|
});
|
|
8171
|
+
if (mobile.engine === "expo") {
|
|
8172
|
+
await writeAbsoluteExpoProject(mobile, {
|
|
8173
|
+
projectRoot: options.projectRoot
|
|
8174
|
+
});
|
|
8175
|
+
await syncAbsoluteExpoWebAssets(mobile);
|
|
8176
|
+
}
|
|
7613
8177
|
return current.artifact;
|
|
7614
8178
|
};
|
|
7615
8179
|
var init_buildPipeline = __esm(() => {
|
|
@@ -7622,13 +8186,14 @@ var init_buildPipeline = __esm(() => {
|
|
|
7622
8186
|
init_nativeAuth();
|
|
7623
8187
|
init_syncSchema();
|
|
7624
8188
|
init_deviceCapabilities();
|
|
8189
|
+
init_expoProject();
|
|
7625
8190
|
});
|
|
7626
8191
|
|
|
7627
8192
|
// src/mobile/routeMetadataTransform.ts
|
|
7628
8193
|
import { existsSync as existsSync10, readFileSync as readFileSync13 } from "fs";
|
|
7629
|
-
import { dirname as
|
|
8194
|
+
import { dirname as dirname14, extname as extname6, relative as relative13, resolve as resolve19 } from "path";
|
|
7630
8195
|
import ts5 from "typescript";
|
|
7631
|
-
var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLERS, posixPath = (value) => value.replace(/\\/g, "/"), findTsconfig = (entry, projectRoot) => ts5.findConfigFile(
|
|
8196
|
+
var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLERS, posixPath = (value) => value.replace(/\\/g, "/"), findTsconfig = (entry, projectRoot) => ts5.findConfigFile(dirname14(entry), existsSync10, "tsconfig.json") ?? ts5.findConfigFile(projectRoot, existsSync10, "tsconfig.json"), createProgram = (entry, projectRoot) => {
|
|
7632
8197
|
const configPath2 = findTsconfig(entry, projectRoot);
|
|
7633
8198
|
if (!configPath2) {
|
|
7634
8199
|
return ts5.createProgram([entry], {
|
|
@@ -7639,7 +8204,7 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLERS, posixPath = (value) => value.re
|
|
|
7639
8204
|
target: ts5.ScriptTarget.ESNext
|
|
7640
8205
|
});
|
|
7641
8206
|
}
|
|
7642
|
-
const parsed = ts5.parseJsonConfigFileContent(ts5.readConfigFile(configPath2, (path) => readFileSync13(path, "utf8")).config, ts5.sys,
|
|
8207
|
+
const parsed = ts5.parseJsonConfigFileContent(ts5.readConfigFile(configPath2, (path) => readFileSync13(path, "utf8")).config, ts5.sys, dirname14(configPath2));
|
|
7643
8208
|
if (!parsed.fileNames.includes(entry))
|
|
7644
8209
|
parsed.fileNames.push(entry);
|
|
7645
8210
|
return ts5.createProgram(parsed.fileNames, parsed.options);
|
|
@@ -7740,7 +8305,7 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLERS, posixPath = (value) => value.re
|
|
|
7740
8305
|
const declaration = symbol?.declarations?.[0];
|
|
7741
8306
|
const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
|
|
7742
8307
|
const exportedName = symbol?.name ?? expression.getText(sourceFile);
|
|
7743
|
-
const source = posixPath(
|
|
8308
|
+
const source = posixPath(relative13(projectRoot, file));
|
|
7744
8309
|
return `${source}#${exportedName}`;
|
|
7745
8310
|
}, resolveAlias = (symbol, checker) => {
|
|
7746
8311
|
if (!(symbol.flags & ts5.SymbolFlags.Alias))
|
|
@@ -7967,7 +8532,7 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLERS, posixPath = (value) => value.re
|
|
|
7967
8532
|
const checker = program.getTypeChecker();
|
|
7968
8533
|
const analyzed = new Map;
|
|
7969
8534
|
for (const sourceFile of program.getSourceFiles()) {
|
|
7970
|
-
const resolvedFile =
|
|
8535
|
+
const resolvedFile = resolve19(sourceFile.fileName);
|
|
7971
8536
|
if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
|
|
7972
8537
|
continue;
|
|
7973
8538
|
const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
|
|
@@ -8053,14 +8618,14 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLERS, posixPath = (value) => value.re
|
|
|
8053
8618
|
result.dispose();
|
|
8054
8619
|
}
|
|
8055
8620
|
}, createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
8056
|
-
const projectRoot =
|
|
8057
|
-
const entry =
|
|
8621
|
+
const projectRoot = resolve19(options.projectRoot ?? process.cwd());
|
|
8622
|
+
const entry = resolve19(options.entry);
|
|
8058
8623
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
8059
8624
|
return {
|
|
8060
8625
|
name: "absolute-mobile-route-metadata",
|
|
8061
8626
|
setup(build) {
|
|
8062
8627
|
build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
|
|
8063
|
-
const analysis = analyzed.get(
|
|
8628
|
+
const analysis = analyzed.get(resolve19(path));
|
|
8064
8629
|
if (!analysis)
|
|
8065
8630
|
return;
|
|
8066
8631
|
const source = await Bun.file(path).text();
|
|
@@ -8127,7 +8692,7 @@ var init_routeMetadataTransform = __esm(() => {
|
|
|
8127
8692
|
});
|
|
8128
8693
|
|
|
8129
8694
|
// src/cli/elysiaOpenApiTypeboxPlugin.ts
|
|
8130
|
-
import { dirname as
|
|
8695
|
+
import { dirname as dirname15, resolve as resolve20 } from "path";
|
|
8131
8696
|
var OPENAPI_TYPEBOX_PREFIX = "../node_modules/typebox/", OPENAPI_DISTRIBUTION_SEGMENT = "/@elysia/openapi/dist/", createElysiaOpenApiTypeboxPlugin = () => ({
|
|
8132
8697
|
name: "absolute-elysia-openapi-typebox",
|
|
8133
8698
|
setup(build) {
|
|
@@ -8137,9 +8702,9 @@ var OPENAPI_TYPEBOX_PREFIX = "../node_modules/typebox/", OPENAPI_DISTRIBUTION_SE
|
|
|
8137
8702
|
return;
|
|
8138
8703
|
}
|
|
8139
8704
|
const relativePath = args.path.slice(OPENAPI_TYPEBOX_PREFIX.length);
|
|
8140
|
-
const typeboxEntry = Bun.resolveSync("typebox",
|
|
8705
|
+
const typeboxEntry = Bun.resolveSync("typebox", dirname15(args.importer));
|
|
8141
8706
|
return {
|
|
8142
|
-
path:
|
|
8707
|
+
path: resolve20(dirname15(typeboxEntry), "..", relativePath)
|
|
8143
8708
|
};
|
|
8144
8709
|
});
|
|
8145
8710
|
}
|
|
@@ -8200,7 +8765,7 @@ __export(exports_prerender, {
|
|
|
8200
8765
|
PRERENDER_BYPASS_HEADER: () => PRERENDER_BYPASS_HEADER
|
|
8201
8766
|
});
|
|
8202
8767
|
import { mkdirSync as mkdirSync6, readFileSync as readFileSync14 } from "fs";
|
|
8203
|
-
import { join as
|
|
8768
|
+
import { join as join23 } from "path";
|
|
8204
8769
|
var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_TIMEOUT_MS = 30000, DEFAULT_FETCH_TIMEOUT_MS = 1e4, PRERENDER_BYPASS_HEADER = "X-Absolute-Prerender-Bypass", routeToFilename = (route) => route === "/" ? "index.html" : `${route.slice(1).replace(/\//g, "-")}.html`, writeTimestamp = async (htmlPath) => {
|
|
8205
8770
|
const metaPath = htmlPath.replace(/\.html$/, ".meta");
|
|
8206
8771
|
await Bun.write(metaPath, String(Date.now()));
|
|
@@ -8270,7 +8835,7 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
|
|
|
8270
8835
|
if (!isCompleteHtml(html))
|
|
8271
8836
|
return false;
|
|
8272
8837
|
const fileName = routeToFilename(route);
|
|
8273
|
-
const filePath =
|
|
8838
|
+
const filePath = join23(prerenderDir, fileName);
|
|
8274
8839
|
await Bun.write(filePath, html);
|
|
8275
8840
|
await writeTimestamp(filePath);
|
|
8276
8841
|
return true;
|
|
@@ -8300,13 +8865,13 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
|
|
|
8300
8865
|
return;
|
|
8301
8866
|
}
|
|
8302
8867
|
const fileName = routeToFilename(route);
|
|
8303
|
-
const filePath =
|
|
8868
|
+
const filePath = join23(prerenderDir, fileName);
|
|
8304
8869
|
await Bun.write(filePath, html);
|
|
8305
8870
|
await writeTimestamp(filePath);
|
|
8306
8871
|
result.routes.set(route, filePath);
|
|
8307
8872
|
log?.(` Pre-rendered ${route} \u2192 ${fileName} (${html.length} bytes)`);
|
|
8308
8873
|
}, prerender = async (port, outDir, staticConfig, log) => {
|
|
8309
|
-
const prerenderDir =
|
|
8874
|
+
const prerenderDir = join23(outDir, "_prerendered");
|
|
8310
8875
|
mkdirSync6(prerenderDir, { recursive: true });
|
|
8311
8876
|
const baseUrl = `http://localhost:${port}`;
|
|
8312
8877
|
let routes;
|
|
@@ -8682,7 +9247,7 @@ var init_maskLiterals = __esm(() => {
|
|
|
8682
9247
|
// src/build/nativeRewrite.ts
|
|
8683
9248
|
import { dlopen, FFIType, ptr } from "bun:ffi";
|
|
8684
9249
|
import { platform as platform4, arch as arch3 } from "os";
|
|
8685
|
-
import { resolve as
|
|
9250
|
+
import { resolve as resolve21 } from "path";
|
|
8686
9251
|
var ffiDefinition, nativeLib = null, loadNative = () => {
|
|
8687
9252
|
if (nativeLib !== null)
|
|
8688
9253
|
return nativeLib;
|
|
@@ -8700,7 +9265,7 @@ var ffiDefinition, nativeLib = null, loadNative = () => {
|
|
|
8700
9265
|
if (!libPath)
|
|
8701
9266
|
return null;
|
|
8702
9267
|
try {
|
|
8703
|
-
const fullPath =
|
|
9268
|
+
const fullPath = resolve21(import.meta.dir, "../../native/packages", libPath);
|
|
8704
9269
|
const lib = dlopen(fullPath, ffiDefinition);
|
|
8705
9270
|
nativeLib = lib.symbols;
|
|
8706
9271
|
return nativeLib;
|
|
@@ -8741,8 +9306,8 @@ var init_nativeRewrite = __esm(() => {
|
|
|
8741
9306
|
});
|
|
8742
9307
|
|
|
8743
9308
|
// src/build/rewriteImportsPlugin.ts
|
|
8744
|
-
import { readdir as
|
|
8745
|
-
import { join as
|
|
9309
|
+
import { readdir as readdir4 } from "fs/promises";
|
|
9310
|
+
import { join as join24 } from "path";
|
|
8746
9311
|
var escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), jsRewriteImports = (content, replacements) => {
|
|
8747
9312
|
let result = content;
|
|
8748
9313
|
for (const [specifier, webPath] of replacements) {
|
|
@@ -8818,10 +9383,10 @@ ${content}`;
|
|
|
8818
9383
|
const allFiles = [];
|
|
8819
9384
|
for (const dir of vendorDirs) {
|
|
8820
9385
|
try {
|
|
8821
|
-
const entries = await
|
|
9386
|
+
const entries = await readdir4(dir);
|
|
8822
9387
|
for (const entry of entries) {
|
|
8823
9388
|
if (entry.endsWith(".js"))
|
|
8824
|
-
allFiles.push(
|
|
9389
|
+
allFiles.push(join24(dir, entry));
|
|
8825
9390
|
}
|
|
8826
9391
|
} catch {}
|
|
8827
9392
|
}
|
|
@@ -8897,7 +9462,7 @@ var init_rewriteImports = __esm(() => {
|
|
|
8897
9462
|
// src/cli/scripts/start.ts
|
|
8898
9463
|
var {env: env2 } = globalThis.Bun;
|
|
8899
9464
|
import { existsSync as existsSync11, readFileSync as readFileSync15, rmSync as rmSync4 } from "fs";
|
|
8900
|
-
import { basename as
|
|
9465
|
+
import { basename as basename9, join as join25, resolve as resolve22 } from "path";
|
|
8901
9466
|
var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`, resolvePackageVersion = (candidates) => {
|
|
8902
9467
|
for (const candidate of candidates) {
|
|
8903
9468
|
const version2 = readPackageVersion2(candidate);
|
|
@@ -8946,18 +9511,18 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
8946
9511
|
process.exit(1);
|
|
8947
9512
|
}, resolveJsxDevRuntimeCompatPath = () => {
|
|
8948
9513
|
const candidates = [
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
9514
|
+
resolve22(import.meta.dir, "..", "..", "dist", "react", "jsxDevRuntimeCompat.js"),
|
|
9515
|
+
resolve22(import.meta.dir, "..", "..", "react", "jsxDevRuntimeCompat.js"),
|
|
9516
|
+
resolve22(import.meta.dir, "..", "..", "react", "jsxDevRuntimeCompat.ts"),
|
|
9517
|
+
resolve22(import.meta.dir, "..", "..", "..", "dist", "react", "jsxDevRuntimeCompat.js"),
|
|
9518
|
+
resolve22(import.meta.dir, "..", "..", "..", "react", "jsxDevRuntimeCompat.js"),
|
|
9519
|
+
resolve22(import.meta.dir, "..", "..", "..", "src", "react", "jsxDevRuntimeCompat.ts")
|
|
8955
9520
|
];
|
|
8956
9521
|
for (const candidate of candidates) {
|
|
8957
9522
|
if (existsSync11(candidate))
|
|
8958
9523
|
return candidate;
|
|
8959
9524
|
}
|
|
8960
|
-
return
|
|
9525
|
+
return resolve22(import.meta.dir, "..", "..", "react", "jsxDevRuntimeCompat.js");
|
|
8961
9526
|
}, jsxDevRuntimeCompatPath, prerenderStaticPages = async (outputPath, prerenderPort, resolvedOutdir, staticConfig, absoluteVersion, configPath2) => {
|
|
8962
9527
|
const prerenderStart = performance.now();
|
|
8963
9528
|
process.stdout.write(cliTag2("\x1B[36m", "Pre-rendering static pages"));
|
|
@@ -8991,7 +9556,7 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
8991
9556
|
serverEntry,
|
|
8992
9557
|
totalDuration
|
|
8993
9558
|
}) => {
|
|
8994
|
-
const usesDocker = existsSync11(
|
|
9559
|
+
const usesDocker = existsSync11(resolve22(COMPOSE_PATH));
|
|
8995
9560
|
const scripts = usesDocker ? await readDbScripts() : null;
|
|
8996
9561
|
if (scripts)
|
|
8997
9562
|
await startDatabase(scripts);
|
|
@@ -9081,11 +9646,11 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
9081
9646
|
}
|
|
9082
9647
|
const port = Number(env2.PORT) || DEFAULT_PORT;
|
|
9083
9648
|
killStaleProcesses(port);
|
|
9084
|
-
const entryName =
|
|
9085
|
-
const resolvedOutdir =
|
|
9649
|
+
const entryName = basename9(serverEntry).replace(/\.[^.]+$/, "");
|
|
9650
|
+
const resolvedOutdir = resolve22(outdir ?? "dist");
|
|
9086
9651
|
const absoluteVersion = resolvePackageVersion([
|
|
9087
|
-
|
|
9088
|
-
|
|
9652
|
+
resolve22(import.meta.dir, "..", "..", "..", "package.json"),
|
|
9653
|
+
resolve22(import.meta.dir, "..", "..", "package.json")
|
|
9089
9654
|
]);
|
|
9090
9655
|
const buildConfig = await loadConfig(configPath2);
|
|
9091
9656
|
buildConfig.buildDirectory = resolvedOutdir;
|
|
@@ -9100,7 +9665,7 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
9100
9665
|
buildConfig.vueDirectory && "vue",
|
|
9101
9666
|
buildConfig.angularDirectory && "angular"
|
|
9102
9667
|
].filter((val) => Boolean(val));
|
|
9103
|
-
const outputPath =
|
|
9668
|
+
const outputPath = resolve22(resolvedOutdir, `${entryName}.js`);
|
|
9104
9669
|
if (options.prebuilt) {
|
|
9105
9670
|
if (!existsSync11(outputPath)) {
|
|
9106
9671
|
throw new Error(`Prepared production server not found: ${outputPath}`);
|
|
@@ -9123,13 +9688,13 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
9123
9688
|
process.stdout.write(cliTag2("\x1B[36m", `Building assets`));
|
|
9124
9689
|
try {
|
|
9125
9690
|
const build = await resolveBuildModule([
|
|
9126
|
-
|
|
9127
|
-
|
|
9691
|
+
resolve22(import.meta.dir, "..", "..", "core", "build"),
|
|
9692
|
+
resolve22(import.meta.dir, "..", "build")
|
|
9128
9693
|
]);
|
|
9129
9694
|
if (!build)
|
|
9130
9695
|
throw new Error("Could not locate build module");
|
|
9131
9696
|
await build(buildConfig);
|
|
9132
|
-
rmSync4(
|
|
9697
|
+
rmSync4(join25(resolvedOutdir, "_prerendered"), {
|
|
9133
9698
|
force: true,
|
|
9134
9699
|
recursive: true
|
|
9135
9700
|
});
|
|
@@ -9206,17 +9771,17 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
9206
9771
|
}
|
|
9207
9772
|
};
|
|
9208
9773
|
const islandRegistrySpec = buildConfig.islands?.registry;
|
|
9209
|
-
const islandRegistryPlugin = islandRegistrySpec ? createIslandRegistryDefinitionPlugin(await loadIslandRegistryBuildInfo(
|
|
9774
|
+
const islandRegistryPlugin = islandRegistrySpec ? createIslandRegistryDefinitionPlugin(await loadIslandRegistryBuildInfo(resolve22(islandRegistrySpec))) : undefined;
|
|
9210
9775
|
const serverBundle = await Bun.build({
|
|
9211
9776
|
define: { "process.env.NODE_ENV": '"production"' },
|
|
9212
|
-
entrypoints: [
|
|
9777
|
+
entrypoints: [resolve22(serverEntry)],
|
|
9213
9778
|
external: resolveServerBundleExternals(buildConfig),
|
|
9214
9779
|
outdir: resolvedOutdir,
|
|
9215
9780
|
plugins: [
|
|
9216
9781
|
...islandRegistryPlugin ? [islandRegistryPlugin] : [],
|
|
9217
9782
|
...buildConfig.mobile ? [
|
|
9218
9783
|
createAbsoluteMobileRouteMetadataPlugin({
|
|
9219
|
-
entry:
|
|
9784
|
+
entry: resolve22(serverEntry)
|
|
9220
9785
|
})
|
|
9221
9786
|
] : [],
|
|
9222
9787
|
createElysiaOpenApiTypeboxPlugin(),
|
|
@@ -9233,9 +9798,9 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
9233
9798
|
console.error(cliTag2("\x1B[31m", `Expected output not found: ${outputPath}`));
|
|
9234
9799
|
process.exit(1);
|
|
9235
9800
|
}
|
|
9236
|
-
if (existsSync11(
|
|
9801
|
+
if (existsSync11(resolve22(resolvedOutdir, "angular", "vendor", "server"))) {
|
|
9237
9802
|
const { readdirSync: readdirSync2 } = await import("fs");
|
|
9238
|
-
const vendorDir =
|
|
9803
|
+
const vendorDir = resolve22(resolvedOutdir, "angular", "vendor", "server");
|
|
9239
9804
|
const vendorEntries = readdirSync2(vendorDir).filter((fileName) => fileName.endsWith(".js"));
|
|
9240
9805
|
const angularServerVendorPaths = {};
|
|
9241
9806
|
const { relative: pathRelative, dirname: pathDirname } = await import("path");
|
|
@@ -9245,7 +9810,7 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
9245
9810
|
if (scope !== "angular" || rest.length === 0)
|
|
9246
9811
|
continue;
|
|
9247
9812
|
const specifier = `@angular/${rest.join("/")}`;
|
|
9248
|
-
const relPath = pathRelative(pathDirname(outputPath),
|
|
9813
|
+
const relPath = pathRelative(pathDirname(outputPath), resolve22(vendorDir, file));
|
|
9249
9814
|
angularServerVendorPaths[specifier] = relPath.startsWith(".") ? relPath : `./${relPath}`;
|
|
9250
9815
|
}
|
|
9251
9816
|
if (Object.keys(angularServerVendorPaths).length > 0) {
|
|
@@ -9433,16 +9998,16 @@ __export(exports_build, {
|
|
|
9433
9998
|
build: () => build
|
|
9434
9999
|
});
|
|
9435
10000
|
import { existsSync as existsSync13, readdirSync as readdirSync3, readFileSync as readFileSync17 } from "fs";
|
|
9436
|
-
import { join as
|
|
10001
|
+
import { join as join26, resolve as resolve24 } from "path";
|
|
9437
10002
|
var PROFILE_TOP = 15, PROFILE_COL = 8, FRAMEWORK_KEYS, cliTag3 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`, printProfile = (buildDir) => {
|
|
9438
|
-
const traceDir =
|
|
10003
|
+
const traceDir = join26(buildDir, ".absolute-trace");
|
|
9439
10004
|
if (!existsSync13(traceDir))
|
|
9440
10005
|
return;
|
|
9441
10006
|
const files = readdirSync3(traceDir).filter((file) => file.endsWith(".json")).sort();
|
|
9442
10007
|
const latest = files[files.length - 1];
|
|
9443
10008
|
if (latest === undefined)
|
|
9444
10009
|
return;
|
|
9445
|
-
const trace = JSON.parse(readFileSync17(
|
|
10010
|
+
const trace = JSON.parse(readFileSync17(join26(traceDir, latest), "utf-8"));
|
|
9446
10011
|
const events = Array.isArray(trace.events) ? trace.events : [];
|
|
9447
10012
|
if (events.length === 0)
|
|
9448
10013
|
return;
|
|
@@ -9479,7 +10044,7 @@ var PROFILE_TOP = 15, PROFILE_COL = 8, FRAMEWORK_KEYS, cliTag3 = (color, message
|
|
|
9479
10044
|
}
|
|
9480
10045
|
return resolveBuildModule2(remaining);
|
|
9481
10046
|
}, build = async (outdir, configPath2, profile = false) => {
|
|
9482
|
-
const resolvedOutdir =
|
|
10047
|
+
const resolvedOutdir = resolve24(outdir ?? "build");
|
|
9483
10048
|
const buildStart = performance.now();
|
|
9484
10049
|
if (profile)
|
|
9485
10050
|
process.env.ABSOLUTE_BUILD_TRACE = "1";
|
|
@@ -9489,8 +10054,8 @@ var PROFILE_TOP = 15, PROFILE_COL = 8, FRAMEWORK_KEYS, cliTag3 = (color, message
|
|
|
9489
10054
|
buildConfig.mode = "production";
|
|
9490
10055
|
try {
|
|
9491
10056
|
const buildApp = await resolveBuildModule2([
|
|
9492
|
-
|
|
9493
|
-
|
|
10057
|
+
resolve24(import.meta.dir, "..", "..", "core", "build"),
|
|
10058
|
+
resolve24(import.meta.dir, "..", "build")
|
|
9494
10059
|
]);
|
|
9495
10060
|
if (!buildApp)
|
|
9496
10061
|
throw new Error("Could not locate build module");
|
|
@@ -9528,7 +10093,7 @@ __export(exports_lintProof, {
|
|
|
9528
10093
|
createLintProof: () => createLintProof
|
|
9529
10094
|
});
|
|
9530
10095
|
import {
|
|
9531
|
-
createHash as
|
|
10096
|
+
createHash as createHash12,
|
|
9532
10097
|
createPrivateKey,
|
|
9533
10098
|
createPublicKey,
|
|
9534
10099
|
sign,
|
|
@@ -9546,7 +10111,7 @@ import {
|
|
|
9546
10111
|
writeFileSync as writeFileSync7
|
|
9547
10112
|
} from "fs";
|
|
9548
10113
|
import { tmpdir as tmpdir3 } from "os";
|
|
9549
|
-
import { delimiter, dirname as
|
|
10114
|
+
import { delimiter, dirname as dirname16, relative as relative14, resolve as resolve25 } from "path";
|
|
9550
10115
|
var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSION = 2, FLAG_NOT_FOUND = -1, CHUNKED_FLAG = "--chunked", TSCONFIG_PATTERN, ABSOLUTE_BINARY, runGit = (args, options) => {
|
|
9551
10116
|
const proc = Bun.spawnSync(["git", ...args], {
|
|
9552
10117
|
cwd: options.cwd,
|
|
@@ -9559,8 +10124,8 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9559
10124
|
throw new Error(detail || `git ${args.join(" ")} failed`);
|
|
9560
10125
|
}
|
|
9561
10126
|
return proc.stdout.toString().trim();
|
|
9562
|
-
}, gitRoot = (cwd) =>
|
|
9563
|
-
const path =
|
|
10127
|
+
}, gitRoot = (cwd) => resolve25(runGit(["rev-parse", "--show-toplevel"], { cwd })), isInside3 = (parent, candidate) => {
|
|
10128
|
+
const path = relative14(parent, candidate);
|
|
9564
10129
|
return path === "" || !path.startsWith("../") && path !== "..";
|
|
9565
10130
|
}, attestationPayload = (proof) => Buffer.from([
|
|
9566
10131
|
"absolute-lint-proof-attestation:1",
|
|
@@ -9571,8 +10136,8 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9571
10136
|
lintFingerprint: proof.lintFingerprint,
|
|
9572
10137
|
sourceTree: proof.sourceTree
|
|
9573
10138
|
})
|
|
9574
|
-
].join("\x00")), publicKeyId = (key) =>
|
|
9575
|
-
const path =
|
|
10139
|
+
].join("\x00")), publicKeyId = (key) => createHash12("sha256").update(key.export({ format: "der", type: "spki" })).digest("hex"), readEd25519PrivateKey = (cwd, location) => {
|
|
10140
|
+
const path = resolve25(cwd, location);
|
|
9576
10141
|
if (isInside3(realpathSync(gitRoot(cwd)), realpathSync(path))) {
|
|
9577
10142
|
throw new Error("lint proof signing key must live outside the Git working tree");
|
|
9578
10143
|
}
|
|
@@ -9582,7 +10147,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9582
10147
|
}
|
|
9583
10148
|
return key;
|
|
9584
10149
|
}, readEd25519PublicKey = (cwd, location) => {
|
|
9585
|
-
const key = createPublicKey(readFileSync18(
|
|
10150
|
+
const key = createPublicKey(readFileSync18(resolve25(cwd, location)));
|
|
9586
10151
|
if (key.asymmetricKeyType !== "ed25519") {
|
|
9587
10152
|
throw new Error("trusted lint proof key must be an Ed25519 public key");
|
|
9588
10153
|
}
|
|
@@ -9610,7 +10175,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9610
10175
|
return null;
|
|
9611
10176
|
const auxiliary = gitVisibleFiles(root).filter((file) => TSCONFIG_PATTERN.test(file));
|
|
9612
10177
|
const configPath2 = findEslintConfigPath(root);
|
|
9613
|
-
const configRelative = configPath2 === null ? null :
|
|
10178
|
+
const configRelative = configPath2 === null ? null : relative14(root, configPath2).replaceAll("\\", "/");
|
|
9614
10179
|
return [
|
|
9615
10180
|
...new Set([
|
|
9616
10181
|
...resolveLintTargets(args, root),
|
|
@@ -9620,17 +10185,17 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9620
10185
|
].sort();
|
|
9621
10186
|
}, createLintSourceTree = (cwd = process.cwd(), proofLocation = DEFAULT_PROOF_LOCATION, command = []) => {
|
|
9622
10187
|
const root = gitRoot(cwd);
|
|
9623
|
-
const proofPath =
|
|
9624
|
-
const proofRelative =
|
|
10188
|
+
const proofPath = resolve25(cwd, proofLocation);
|
|
10189
|
+
const proofRelative = relative14(root, proofPath).replaceAll("\\", "/");
|
|
9625
10190
|
if (proofRelative === ".." || proofRelative.startsWith("../") || proofRelative === "") {
|
|
9626
10191
|
throw new Error("lint proof must live inside the Git working tree");
|
|
9627
10192
|
}
|
|
9628
|
-
const temporaryDirectory = mkdtempSync(
|
|
9629
|
-
const temporaryIndex =
|
|
9630
|
-
const temporaryObjects =
|
|
10193
|
+
const temporaryDirectory = mkdtempSync(resolve25(tmpdir3(), "absolute-lint-proof-"));
|
|
10194
|
+
const temporaryIndex = resolve25(temporaryDirectory, "index");
|
|
10195
|
+
const temporaryObjects = resolve25(temporaryDirectory, "objects");
|
|
9631
10196
|
mkdirSync8(temporaryObjects, { recursive: true });
|
|
9632
10197
|
const repositoryObjectsPath = runGit(["rev-parse", "--git-path", "objects"], { cwd: root });
|
|
9633
|
-
const repositoryObjects =
|
|
10198
|
+
const repositoryObjects = resolve25(root, repositoryObjectsPath);
|
|
9634
10199
|
const existingAlternates = process.env.GIT_ALTERNATE_OBJECT_DIRECTORIES?.trim();
|
|
9635
10200
|
const env3 = {
|
|
9636
10201
|
GIT_ALTERNATE_OBJECT_DIRECTORIES: [
|
|
@@ -9654,7 +10219,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9654
10219
|
if (!path || path === proofRelative)
|
|
9655
10220
|
return false;
|
|
9656
10221
|
try {
|
|
9657
|
-
lstatSync(
|
|
10222
|
+
lstatSync(resolve25(root, path));
|
|
9658
10223
|
return true;
|
|
9659
10224
|
} catch {
|
|
9660
10225
|
return false;
|
|
@@ -9665,7 +10230,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9665
10230
|
} finally {
|
|
9666
10231
|
rmSync5(temporaryDirectory, { force: true, recursive: true });
|
|
9667
10232
|
}
|
|
9668
|
-
}, proofFingerprint = (cwd) =>
|
|
10233
|
+
}, proofFingerprint = (cwd) => createHash12("sha256").update(`absolute-lint-proof:${PROOF_CONTRACT_VERSION}\x00`).update(createEslintCacheFingerprint(cwd)).update("\x00").update(createEslintConfigDigest(cwd)).digest("hex"), createLintProof = (command, options = {}) => {
|
|
9669
10234
|
const cwd = options.cwd ?? process.cwd();
|
|
9670
10235
|
const proofLocation = options.proofLocation ?? DEFAULT_PROOF_LOCATION;
|
|
9671
10236
|
return {
|
|
@@ -9678,7 +10243,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9678
10243
|
}, writeLintProof = (command, options = {}) => {
|
|
9679
10244
|
const cwd = options.cwd ?? process.cwd();
|
|
9680
10245
|
const proofLocation = options.proofLocation ?? DEFAULT_PROOF_LOCATION;
|
|
9681
|
-
const path =
|
|
10246
|
+
const path = resolve25(cwd, proofLocation);
|
|
9682
10247
|
const temporary = `${path}.${process.pid}.tmp`;
|
|
9683
10248
|
const proof = createLintProof(command, { cwd, proofLocation });
|
|
9684
10249
|
if (options.signingKeyLocation) {
|
|
@@ -9690,7 +10255,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9690
10255
|
signature: sign(null, attestationPayload(proof), privateKey).toString("base64")
|
|
9691
10256
|
};
|
|
9692
10257
|
}
|
|
9693
|
-
mkdirSync8(
|
|
10258
|
+
mkdirSync8(dirname16(path), { recursive: true });
|
|
9694
10259
|
writeFileSync7(temporary, `${JSON.stringify(proof, null, 2)}
|
|
9695
10260
|
`);
|
|
9696
10261
|
renameSync2(temporary, path);
|
|
@@ -9734,7 +10299,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
|
|
|
9734
10299
|
}, verifyLintProof = (command, options = {}) => {
|
|
9735
10300
|
const cwd = options.cwd ?? process.cwd();
|
|
9736
10301
|
const proofLocation = options.proofLocation ?? DEFAULT_PROOF_LOCATION;
|
|
9737
|
-
const path =
|
|
10302
|
+
const path = resolve25(cwd, proofLocation);
|
|
9738
10303
|
if (!existsSync14(path))
|
|
9739
10304
|
return { reason: `missing lint proof: ${proofLocation}`, valid: false };
|
|
9740
10305
|
let proof;
|
|
@@ -9850,11 +10415,11 @@ var init_lintProof = __esm(() => {
|
|
|
9850
10415
|
});
|
|
9851
10416
|
|
|
9852
10417
|
// src/build/scanConventions.ts
|
|
9853
|
-
import { basename as
|
|
10418
|
+
import { basename as basename10 } from "path";
|
|
9854
10419
|
var {Glob: Glob2 } = globalThis.Bun;
|
|
9855
10420
|
import { existsSync as existsSync15 } from "fs";
|
|
9856
10421
|
var CONVENTION_RE, classifyFile = (file, pageFiles, defaults, pages) => {
|
|
9857
|
-
const fileName =
|
|
10422
|
+
const fileName = basename10(file);
|
|
9858
10423
|
const match = CONVENTION_RE.exec(fileName);
|
|
9859
10424
|
if (!match) {
|
|
9860
10425
|
pageFiles.push(file);
|
|
@@ -9905,7 +10470,7 @@ __export(exports_ls, {
|
|
|
9905
10470
|
runLs: () => runLs
|
|
9906
10471
|
});
|
|
9907
10472
|
import { existsSync as existsSync16, readFileSync as readFileSync19, statSync } from "fs";
|
|
9908
|
-
import { basename as
|
|
10473
|
+
import { basename as basename11, extname as extname7, join as join27, relative as relative15 } from "path";
|
|
9909
10474
|
var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELDS, readStringField = (source, key) => {
|
|
9910
10475
|
const value = Reflect.get(source, key);
|
|
9911
10476
|
return typeof value === "string" ? value : undefined;
|
|
@@ -9920,24 +10485,24 @@ var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELD
|
|
|
9920
10485
|
} catch {
|
|
9921
10486
|
return null;
|
|
9922
10487
|
}
|
|
9923
|
-
}, relativeOrSelf = (target) =>
|
|
10488
|
+
}, relativeOrSelf = (target) => relative15(process.cwd(), target) || target, configCandidates = (raw) => isWorkspaceConfig(raw) ? Object.values(raw).map((service) => ({
|
|
9924
10489
|
baseDir: readStringField(service, "cwd") ?? ".",
|
|
9925
10490
|
source: service
|
|
9926
10491
|
})) : [{ baseDir: ".", source: raw }], specsFor = (source, baseDir) => FRAMEWORK_FIELDS.flatMap((framework) => {
|
|
9927
10492
|
const dir = readStringField(source, framework.field);
|
|
9928
10493
|
return dir === undefined ? [] : [
|
|
9929
10494
|
{
|
|
9930
|
-
dir:
|
|
10495
|
+
dir: join27(baseDir, dir),
|
|
9931
10496
|
label: framework.label,
|
|
9932
10497
|
pattern: framework.pattern
|
|
9933
10498
|
}
|
|
9934
10499
|
];
|
|
9935
10500
|
}), scanFramework = async (spec) => {
|
|
9936
|
-
const { pageFiles } = await scanConventions(
|
|
10501
|
+
const { pageFiles } = await scanConventions(join27(spec.dir, "pages"), spec.pattern);
|
|
9937
10502
|
if (pageFiles.length === 0)
|
|
9938
10503
|
return null;
|
|
9939
10504
|
const pages = pageFiles.map((file) => ({
|
|
9940
|
-
name:
|
|
10505
|
+
name: basename11(file, extname7(file)),
|
|
9941
10506
|
sizeBytes: null,
|
|
9942
10507
|
sourcePath: relativeOrSelf(file)
|
|
9943
10508
|
}));
|
|
@@ -9957,10 +10522,10 @@ var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELD
|
|
|
9957
10522
|
}, resolveDiskPath = (buildDir, value) => {
|
|
9958
10523
|
if (existsSync16(value))
|
|
9959
10524
|
return value;
|
|
9960
|
-
const underBuild =
|
|
10525
|
+
const underBuild = join27(buildDir, value);
|
|
9961
10526
|
if (existsSync16(underBuild))
|
|
9962
10527
|
return underBuild;
|
|
9963
|
-
return
|
|
10528
|
+
return join27(process.cwd(), value);
|
|
9964
10529
|
}, fileSize = (diskPath) => {
|
|
9965
10530
|
try {
|
|
9966
10531
|
return statSync(diskPath).size;
|
|
@@ -9968,7 +10533,7 @@ var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELD
|
|
|
9968
10533
|
return 0;
|
|
9969
10534
|
}
|
|
9970
10535
|
}, readManifestSizes = (manifestDir) => {
|
|
9971
|
-
const manifest = JSON.parse(readFileSync19(
|
|
10536
|
+
const manifest = JSON.parse(readFileSync19(join27(manifestDir, "manifest.json"), "utf-8"));
|
|
9972
10537
|
const sizes = new Map;
|
|
9973
10538
|
Object.entries(manifest).forEach(([key, value]) => {
|
|
9974
10539
|
sizes.set(key, fileSize(resolveDiskPath(manifestDir, value)));
|
|
@@ -9987,7 +10552,7 @@ var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELD
|
|
|
9987
10552
|
}))
|
|
9988
10553
|
})), manifestAge = (manifestPath) => getDurationString(Date.now() - statSync(manifestPath).mtimeMs), firstBuildDir = (candidates) => candidates.map((candidate) => {
|
|
9989
10554
|
const dir = readStringField(candidate.source, "buildDirectory");
|
|
9990
|
-
return dir === undefined ? undefined :
|
|
10555
|
+
return dir === undefined ? undefined : join27(candidate.baseDir, dir);
|
|
9991
10556
|
}).find((dir) => dir !== undefined), resolveSizesDir = (args, candidates) => parseFlagValue(args, "--outdir") ?? firstBuildDir(candidates) ?? DEFAULT_BUILD_DIR, formatSize = (bytes) => {
|
|
9992
10557
|
if (bytes === null || bytes === 0)
|
|
9993
10558
|
return "-";
|
|
@@ -10085,7 +10650,7 @@ ${colors.dim}${frameworkCount} ${frameworkCount === 1 ? "framework" : "framework
|
|
|
10085
10650
|
return;
|
|
10086
10651
|
}
|
|
10087
10652
|
const sizesDir = resolveSizesDir(args, candidates);
|
|
10088
|
-
const manifestPath =
|
|
10653
|
+
const manifestPath = join27(sizesDir, "manifest.json");
|
|
10089
10654
|
if (!existsSync16(manifestPath)) {
|
|
10090
10655
|
printDim(`No build at ${relativeOrSelf(manifestPath)}. Run \`absolute build\` first, or pass \`--outdir <dir>\`.`);
|
|
10091
10656
|
return;
|
|
@@ -10210,21 +10775,21 @@ var init_discoverInstances = __esm(() => {
|
|
|
10210
10775
|
import { createConnection as createConnection2 } from "net";
|
|
10211
10776
|
var {$: $4 } = globalThis.Bun;
|
|
10212
10777
|
var displayHost = (host2) => host2 === "0.0.0.0" || host2 === "::" ? "localhost" : host2, probePort = (host2, port) => {
|
|
10213
|
-
const { promise, resolve:
|
|
10778
|
+
const { promise, resolve: resolve26 } = Promise.withResolvers();
|
|
10214
10779
|
const socket = createConnection2({ host: displayHost(host2), port });
|
|
10215
10780
|
const timeout = setTimeout(() => {
|
|
10216
10781
|
socket.destroy();
|
|
10217
|
-
|
|
10782
|
+
resolve26(false);
|
|
10218
10783
|
}, INSTANCE_PROBE_TIMEOUT_MS);
|
|
10219
10784
|
socket.once("connect", () => {
|
|
10220
10785
|
clearTimeout(timeout);
|
|
10221
10786
|
socket.end();
|
|
10222
|
-
|
|
10787
|
+
resolve26(true);
|
|
10223
10788
|
});
|
|
10224
10789
|
socket.once("error", () => {
|
|
10225
10790
|
clearTimeout(timeout);
|
|
10226
10791
|
socket.destroy();
|
|
10227
|
-
|
|
10792
|
+
resolve26(false);
|
|
10228
10793
|
});
|
|
10229
10794
|
return promise;
|
|
10230
10795
|
}, probeStatus = async (record) => {
|
|
@@ -11094,10 +11659,10 @@ import {
|
|
|
11094
11659
|
statSync as statSync2,
|
|
11095
11660
|
writeFileSync as writeFileSync8
|
|
11096
11661
|
} from "fs";
|
|
11097
|
-
import { resolve as
|
|
11662
|
+
import { resolve as resolve26 } from "path";
|
|
11098
11663
|
var VIRTUAL_NAME = "__absolute_type_introspect__.ts", MAX_DEPTH = 6, isFrameworkRepo = (cwd) => {
|
|
11099
11664
|
try {
|
|
11100
|
-
const pkg = JSON.parse(readFileSync21(
|
|
11665
|
+
const pkg = JSON.parse(readFileSync21(resolve26(cwd, "package.json"), "utf-8"));
|
|
11101
11666
|
return pkg?.name === "@absolutejs/absolute";
|
|
11102
11667
|
} catch {
|
|
11103
11668
|
return false;
|
|
@@ -11118,10 +11683,10 @@ var VIRTUAL_NAME = "__absolute_type_introspect__.ts", MAX_DEPTH = 6, isFramework
|
|
|
11118
11683
|
};
|
|
11119
11684
|
}, SCHEMA_VERSION = 1, packageVersion = (cwd, specifier) => {
|
|
11120
11685
|
const candidates = specifier === "@absolutejs/absolute" ? [
|
|
11121
|
-
|
|
11122
|
-
|
|
11686
|
+
resolve26(cwd, "node_modules", "@absolutejs", "absolute", "package.json"),
|
|
11687
|
+
resolve26(cwd, "package.json")
|
|
11123
11688
|
] : [
|
|
11124
|
-
|
|
11689
|
+
resolve26(cwd, "node_modules", ...specifier.split("/"), "package.json")
|
|
11125
11690
|
];
|
|
11126
11691
|
for (const candidate of candidates) {
|
|
11127
11692
|
try {
|
|
@@ -11136,13 +11701,13 @@ var VIRTUAL_NAME = "__absolute_type_introspect__.ts", MAX_DEPTH = 6, isFramework
|
|
|
11136
11701
|
if (local) {
|
|
11137
11702
|
const file = typeName === "PackageJson" ? "packageJson.ts" : "build.ts";
|
|
11138
11703
|
try {
|
|
11139
|
-
signature += `:${statSync2(
|
|
11704
|
+
signature += `:${statSync2(resolve26(cwd, "types", file)).mtimeMs}`;
|
|
11140
11705
|
} catch {}
|
|
11141
11706
|
}
|
|
11142
11707
|
return signature;
|
|
11143
11708
|
}, cacheSlug = (specifier) => specifier.replace("@", "").split("/").join("-"), cacheFile = (cwd, typeName, specifier) => {
|
|
11144
11709
|
const name = specifier === "@absolutejs/absolute" ? typeName : `${typeName}.${cacheSlug(specifier)}`;
|
|
11145
|
-
return
|
|
11710
|
+
return resolve26(cwd, ".absolutejs", "config-schema", `${name}.json`);
|
|
11146
11711
|
}, readDiskCache = (cwd, typeName, signature, specifier) => {
|
|
11147
11712
|
try {
|
|
11148
11713
|
const cached = JSON.parse(readFileSync21(cacheFile(cwd, typeName, specifier), "utf-8"));
|
|
@@ -11153,7 +11718,7 @@ var VIRTUAL_NAME = "__absolute_type_introspect__.ts", MAX_DEPTH = 6, isFramework
|
|
|
11153
11718
|
return null;
|
|
11154
11719
|
}, writeDiskCache = (cwd, typeName, signature, fields, specifier) => {
|
|
11155
11720
|
try {
|
|
11156
|
-
mkdirSync9(
|
|
11721
|
+
mkdirSync9(resolve26(cwd, ".absolutejs", "config-schema"), {
|
|
11157
11722
|
recursive: true
|
|
11158
11723
|
});
|
|
11159
11724
|
writeFileSync8(cacheFile(cwd, typeName, specifier), JSON.stringify({ fields, signature }));
|
|
@@ -11240,7 +11805,7 @@ var VIRTUAL_NAME = "__absolute_type_introspect__.ts", MAX_DEPTH = 6, isFramework
|
|
|
11240
11805
|
}
|
|
11241
11806
|
return opaque();
|
|
11242
11807
|
}, introspectFrom = (cwd, specifier, typeName, options, exclude) => {
|
|
11243
|
-
const virtualPath =
|
|
11808
|
+
const virtualPath = resolve26(cwd, VIRTUAL_NAME);
|
|
11244
11809
|
const source = `import type { ${typeName} } from '${specifier}';
|
|
11245
11810
|
declare const value: ${typeName};
|
|
11246
11811
|
export { value };
|
|
@@ -11250,8 +11815,8 @@ export { value };
|
|
|
11250
11815
|
host2.getSourceFile = (fileName, languageVersion, onError, shouldCreate) => fileName === virtualPath ? ts6.createSourceFile(fileName, source, languageVersion, true) : getSourceFile(fileName, languageVersion, onError, shouldCreate);
|
|
11251
11816
|
const fileExists = host2.fileExists.bind(host2);
|
|
11252
11817
|
host2.fileExists = (fileName) => fileName === virtualPath ? true : fileExists(fileName);
|
|
11253
|
-
const
|
|
11254
|
-
host2.readFile = (fileName) => fileName === virtualPath ? source :
|
|
11818
|
+
const readFile13 = host2.readFile.bind(host2);
|
|
11819
|
+
host2.readFile = (fileName) => fileName === virtualPath ? source : readFile13(fileName);
|
|
11255
11820
|
const program = ts6.createProgram([virtualPath], options, host2);
|
|
11256
11821
|
const checker = program.getTypeChecker();
|
|
11257
11822
|
const sourceFile = program.getSourceFile(virtualPath);
|
|
@@ -11283,7 +11848,7 @@ export { value };
|
|
|
11283
11848
|
const cached = cache.get(cacheKey);
|
|
11284
11849
|
if (cached)
|
|
11285
11850
|
return cached;
|
|
11286
|
-
const local = specifier === "@absolutejs/absolute" && isFrameworkRepo(cwd) && existsSync18(
|
|
11851
|
+
const local = specifier === "@absolutejs/absolute" && isFrameworkRepo(cwd) && existsSync18(resolve26(cwd, "types/index.ts"));
|
|
11287
11852
|
const signature = cacheSignature(cwd, typeName, local, specifier);
|
|
11288
11853
|
const fromDisk = readDiskCache(cwd, typeName, signature, specifier);
|
|
11289
11854
|
if (fromDisk) {
|
|
@@ -11312,14 +11877,14 @@ var init_fromType = __esm(() => {
|
|
|
11312
11877
|
// src/cli/config/absolute/resolveAbsoluteConfig.ts
|
|
11313
11878
|
import ts7 from "typescript";
|
|
11314
11879
|
import { existsSync as existsSync19, readFileSync as readFileSync22 } from "fs";
|
|
11315
|
-
import { resolve as
|
|
11880
|
+
import { resolve as resolve27 } from "path";
|
|
11316
11881
|
var CONFIG_CANDIDATES2, RUNTIME_FIELDS, findConfigPath = (cwd, override) => {
|
|
11317
11882
|
if (override) {
|
|
11318
|
-
const resolved =
|
|
11883
|
+
const resolved = resolve27(cwd, override);
|
|
11319
11884
|
return existsSync19(resolved) ? resolved : null;
|
|
11320
11885
|
}
|
|
11321
11886
|
for (const name of CONFIG_CANDIDATES2) {
|
|
11322
|
-
const candidate =
|
|
11887
|
+
const candidate = resolve27(cwd, name);
|
|
11323
11888
|
if (existsSync19(candidate))
|
|
11324
11889
|
return candidate;
|
|
11325
11890
|
}
|
|
@@ -11552,8 +12117,8 @@ var init_frameworks = __esm(() => {
|
|
|
11552
12117
|
});
|
|
11553
12118
|
|
|
11554
12119
|
// src/cli/generate/context.ts
|
|
11555
|
-
import { dirname as
|
|
11556
|
-
var asString = (value) => typeof value === "string" ? value : undefined, isRecord10 = (value) => typeof value === "object" && value !== null, resolveDir = (cwd, value) => isAbsolute5(value) ? value :
|
|
12120
|
+
import { dirname as dirname17, isAbsolute as isAbsolute5, join as join28, relative as relative16, resolve as resolve28 } from "path";
|
|
12121
|
+
var asString = (value) => typeof value === "string" ? value : undefined, isRecord10 = (value) => typeof value === "object" && value !== null, resolveDir = (cwd, value) => isAbsolute5(value) ? value : resolve28(cwd, value), resolveStylesDir = (cwd, config) => {
|
|
11557
12122
|
const styles = config.stylesConfig;
|
|
11558
12123
|
if (typeof styles === "string")
|
|
11559
12124
|
return resolveDir(cwd, styles);
|
|
@@ -11562,10 +12127,10 @@ var asString = (value) => typeof value === "string" ? value : undefined, isRecor
|
|
|
11562
12127
|
if (indexes)
|
|
11563
12128
|
return resolveDir(cwd, indexes);
|
|
11564
12129
|
}
|
|
11565
|
-
return
|
|
12130
|
+
return resolve28(cwd, "src/frontend/styles/indexes");
|
|
11566
12131
|
}, configuredFrameworks = (project) => FRAMEWORK_KEYS2.filter((key) => project.frameworkDirs[key] !== undefined), frontendRootFor = (project, framework) => {
|
|
11567
12132
|
const dir = project.frameworkDirs[framework];
|
|
11568
|
-
return dir ?
|
|
12133
|
+
return dir ? dirname17(dir) : resolve28(project.cwd, "src/frontend");
|
|
11569
12134
|
}, resolveProject = async (cwd, configOverride) => {
|
|
11570
12135
|
const loaded = await loadConfig(configOverride);
|
|
11571
12136
|
const config = isRecord10(loaded) ? loaded : {};
|
|
@@ -11615,8 +12180,8 @@ var asString = (value) => typeof value === "string" ? value : undefined, isRecor
|
|
|
11615
12180
|
message: `Multiple frameworks configured (${configured.join(", ")}). Pass --framework <name>.`,
|
|
11616
12181
|
ok: false
|
|
11617
12182
|
};
|
|
11618
|
-
}, sharedDirFor = (project, framework) =>
|
|
11619
|
-
const rel =
|
|
12183
|
+
}, sharedDirFor = (project, framework) => join28(frontendRootFor(project, framework), "shared"), toModuleSpecifier = (fromDir, toFileNoExt) => {
|
|
12184
|
+
const rel = relative16(fromDir, toFileNoExt).split("\\").join("/");
|
|
11620
12185
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
11621
12186
|
};
|
|
11622
12187
|
var init_context = __esm(() => {
|
|
@@ -11645,7 +12210,7 @@ var emptyOutcome = () => ({
|
|
|
11645
12210
|
// src/cli/generate/routeWiring.ts
|
|
11646
12211
|
import ts8 from "typescript";
|
|
11647
12212
|
import { existsSync as existsSync20, readFileSync as readFileSync23, readdirSync as readdirSync4, writeFileSync as writeFileSync9 } from "fs";
|
|
11648
|
-
import { dirname as
|
|
12213
|
+
import { dirname as dirname18, join as join29 } from "path";
|
|
11649
12214
|
var DEFAULT_SEPARATOR = `
|
|
11650
12215
|
`, BOUNDARY_USE, applyEdits = (text2, edits) => {
|
|
11651
12216
|
const ordered = [...edits].sort((first, second) => second.start - first.start);
|
|
@@ -11804,14 +12369,14 @@ ${newLines.join(`
|
|
|
11804
12369
|
for (const name of readdirSync4(pluginsDir)) {
|
|
11805
12370
|
if (!name.endsWith(".ts"))
|
|
11806
12371
|
continue;
|
|
11807
|
-
const candidate =
|
|
12372
|
+
const candidate = join29(pluginsDir, name);
|
|
11808
12373
|
if (hasChain(candidate))
|
|
11809
12374
|
return candidate;
|
|
11810
12375
|
}
|
|
11811
12376
|
return null;
|
|
11812
12377
|
}, findRoutingFile = (serverEntry) => {
|
|
11813
|
-
const pluginsDir =
|
|
11814
|
-
const preferred =
|
|
12378
|
+
const pluginsDir = join29(dirname18(serverEntry), "plugins");
|
|
12379
|
+
const preferred = join29(pluginsDir, "pagesPlugin.ts");
|
|
11815
12380
|
if (hasChain(preferred))
|
|
11816
12381
|
return preferred;
|
|
11817
12382
|
const scanned = firstChainFile(pluginsDir);
|
|
@@ -11821,7 +12386,7 @@ ${newLines.join(`
|
|
|
11821
12386
|
return serverEntry;
|
|
11822
12387
|
return null;
|
|
11823
12388
|
}, buildRouteContext = (input, routingFile) => {
|
|
11824
|
-
const specifier = `${toModuleSpecifier(
|
|
12389
|
+
const specifier = `${toModuleSpecifier(dirname18(routingFile), stripExtension(input.pageFileAbs))}${input.def.pageImportExtension ?? ""}`;
|
|
11825
12390
|
return {
|
|
11826
12391
|
cssAssetKey: input.cssAssetKey,
|
|
11827
12392
|
indexKey: input.indexKey,
|
|
@@ -11903,7 +12468,7 @@ var init_routeWiring = __esm(() => {
|
|
|
11903
12468
|
|
|
11904
12469
|
// src/cli/generate/generateApi.ts
|
|
11905
12470
|
import { existsSync as existsSync21, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
11906
|
-
import { dirname as
|
|
12471
|
+
import { dirname as dirname19, join as join30 } from "path";
|
|
11907
12472
|
var apiPluginTemplate = (pluginName, base) => `import { Elysia } from 'elysia';
|
|
11908
12473
|
|
|
11909
12474
|
export const ${pluginName} = new Elysia()
|
|
@@ -11915,8 +12480,8 @@ export const ${pluginName} = new Elysia()
|
|
|
11915
12480
|
const pluginName = `${camel}Plugin`;
|
|
11916
12481
|
const base = `/api/${kebab}`;
|
|
11917
12482
|
const outcome = { ...emptyOutcome(), route: base };
|
|
11918
|
-
const pluginsDir =
|
|
11919
|
-
const fileAbs =
|
|
12483
|
+
const pluginsDir = join30(dirname19(project.serverEntry), "plugins");
|
|
12484
|
+
const fileAbs = join30(pluginsDir, `${pluginName}.ts`);
|
|
11920
12485
|
if (existsSync21(fileAbs)) {
|
|
11921
12486
|
outcome.notes.push(`${pluginName} already exists at ${fileAbs} \u2014 skipped.`);
|
|
11922
12487
|
return outcome;
|
|
@@ -11924,7 +12489,7 @@ export const ${pluginName} = new Elysia()
|
|
|
11924
12489
|
mkdirSync10(pluginsDir, { recursive: true });
|
|
11925
12490
|
writeFileSync10(fileAbs, apiPluginTemplate(pluginName, base), "utf-8");
|
|
11926
12491
|
outcome.created.push(fileAbs);
|
|
11927
|
-
const specifier = toModuleSpecifier(
|
|
12492
|
+
const specifier = toModuleSpecifier(dirname19(project.serverEntry), fileAbs.replace(/\.ts$/, ""));
|
|
11928
12493
|
const wired = wirePluginUse(project.serverEntry, pluginName, specifier);
|
|
11929
12494
|
if (wired.kind === "edited")
|
|
11930
12495
|
outcome.updated.push(wired.routingFile);
|
|
@@ -11991,7 +12556,7 @@ var init_componentTemplates = __esm(() => {
|
|
|
11991
12556
|
|
|
11992
12557
|
// src/cli/generate/generateComponent.ts
|
|
11993
12558
|
import { existsSync as existsSync22, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
|
|
11994
|
-
import { dirname as
|
|
12559
|
+
import { dirname as dirname20, join as join31 } from "path";
|
|
11995
12560
|
var generateComponent = (project, framework, rawName) => {
|
|
11996
12561
|
const def = frameworks6[framework];
|
|
11997
12562
|
const pascal = toPascalCase(rawName);
|
|
@@ -12002,12 +12567,12 @@ var generateComponent = (project, framework, rawName) => {
|
|
|
12002
12567
|
outcome.manual = { reason: "framework directory missing", snippet: "" };
|
|
12003
12568
|
return outcome;
|
|
12004
12569
|
}
|
|
12005
|
-
const fileAbs =
|
|
12570
|
+
const fileAbs = join31(frameworkDir, "components", def.componentFile({ kebab, pascal }));
|
|
12006
12571
|
if (existsSync22(fileAbs)) {
|
|
12007
12572
|
outcome.notes.push(`${pascal} already exists at ${fileAbs} \u2014 skipped.`);
|
|
12008
12573
|
return outcome;
|
|
12009
12574
|
}
|
|
12010
|
-
mkdirSync11(
|
|
12575
|
+
mkdirSync11(dirname20(fileAbs), { recursive: true });
|
|
12011
12576
|
writeFileSync11(fileAbs, componentTemplates[framework]({
|
|
12012
12577
|
kebab,
|
|
12013
12578
|
pascal,
|
|
@@ -12024,7 +12589,7 @@ var init_generateComponent = __esm(() => {
|
|
|
12024
12589
|
// src/cli/generate/cssStrategy.ts
|
|
12025
12590
|
import ts9 from "typescript";
|
|
12026
12591
|
import { existsSync as existsSync23 } from "fs";
|
|
12027
|
-
import { join as
|
|
12592
|
+
import { join as join32 } from "path";
|
|
12028
12593
|
var CSS_SUFFIX = "CSS", SHARED_MIN_USES = 2, DEFAULT_CSS = `main {
|
|
12029
12594
|
margin: 0 auto;
|
|
12030
12595
|
max-width: 64rem;
|
|
@@ -12063,7 +12628,7 @@ var CSS_SUFFIX = "CSS", SHARED_MIN_USES = 2, DEFAULT_CSS = `main {
|
|
|
12063
12628
|
return null;
|
|
12064
12629
|
}, fileForKey = (stylesDir, assetKey2) => {
|
|
12065
12630
|
const base = assetKey2.endsWith(CSS_SUFFIX) ? assetKey2.slice(0, -CSS_SUFFIX.length) : assetKey2;
|
|
12066
|
-
return
|
|
12631
|
+
return join32(stylesDir, `${toKebabCase(base)}.css`);
|
|
12067
12632
|
}, planCss = (routingText, stylesDir, pascal, kebab) => {
|
|
12068
12633
|
const sharedKey = detectSharedKey(routingText);
|
|
12069
12634
|
if (sharedKey) {
|
|
@@ -12076,7 +12641,7 @@ var CSS_SUFFIX = "CSS", SHARED_MIN_USES = 2, DEFAULT_CSS = `main {
|
|
|
12076
12641
|
shared: true
|
|
12077
12642
|
};
|
|
12078
12643
|
}
|
|
12079
|
-
const cssFileAbs =
|
|
12644
|
+
const cssFileAbs = join32(stylesDir, `${kebab}.css`);
|
|
12080
12645
|
return {
|
|
12081
12646
|
assetKey: `${pascal}${CSS_SUFFIX}`,
|
|
12082
12647
|
contents: DEFAULT_CSS,
|
|
@@ -12090,7 +12655,7 @@ var init_cssStrategy = () => {};
|
|
|
12090
12655
|
// src/cli/generate/navData.ts
|
|
12091
12656
|
import ts10 from "typescript";
|
|
12092
12657
|
import { existsSync as existsSync24, mkdirSync as mkdirSync12, readFileSync as readFileSync24, writeFileSync as writeFileSync12 } from "fs";
|
|
12093
|
-
import { dirname as
|
|
12658
|
+
import { dirname as dirname21 } from "path";
|
|
12094
12659
|
var NAV_DATA_TEMPLATE = `type NavItem = {
|
|
12095
12660
|
href: string;
|
|
12096
12661
|
label: string;
|
|
@@ -12167,7 +12732,7 @@ ${indent}${entry}`;
|
|
|
12167
12732
|
}, upsertNavItem = (navDataPath, item) => {
|
|
12168
12733
|
const created = !existsSync24(navDataPath);
|
|
12169
12734
|
if (created) {
|
|
12170
|
-
mkdirSync12(
|
|
12735
|
+
mkdirSync12(dirname21(navDataPath), { recursive: true });
|
|
12171
12736
|
writeFileSync12(navDataPath, NAV_DATA_TEMPLATE, "utf-8");
|
|
12172
12737
|
}
|
|
12173
12738
|
const existing = readNavItems(navDataPath);
|
|
@@ -12337,14 +12902,14 @@ import {
|
|
|
12337
12902
|
readdirSync as readdirSync5,
|
|
12338
12903
|
writeFileSync as writeFileSync13
|
|
12339
12904
|
} from "fs";
|
|
12340
|
-
import { dirname as
|
|
12905
|
+
import { dirname as dirname22, join as join33, relative as relative17 } from "path";
|
|
12341
12906
|
var writeNew = (path, contents) => {
|
|
12342
|
-
mkdirSync13(
|
|
12907
|
+
mkdirSync13(dirname22(path), { recursive: true });
|
|
12343
12908
|
writeFileSync13(path, contents, "utf-8");
|
|
12344
12909
|
}, toHref = (fromDir, toFile) => {
|
|
12345
|
-
const rel =
|
|
12910
|
+
const rel = relative17(fromDir, toFile).split("\\").join("/");
|
|
12346
12911
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
12347
|
-
}, staticPageFiles = (project) => ["html", "htmx"].map((key) => project.frameworkDirs[key]).map((dir) => dir ?
|
|
12912
|
+
}, staticPageFiles = (project) => ["html", "htmx"].map((key) => project.frameworkDirs[key]).map((dir) => dir ? join33(dir, "pages") : null).filter((pagesDir) => pagesDir !== null && existsSync25(pagesDir)).flatMap((pagesDir) => readdirSync5(pagesDir).filter((name) => name.endsWith(".html")).map((name) => join33(pagesDir, name))), resyncPage = (file, items) => {
|
|
12348
12913
|
const html = readFileSync25(file, "utf-8");
|
|
12349
12914
|
const synced = syncStaticNav(html, items);
|
|
12350
12915
|
if (synced === null || synced === html)
|
|
@@ -12372,7 +12937,7 @@ var writeNew = (path, contents) => {
|
|
|
12372
12937
|
outcome.manual = { reason: "framework directory missing", snippet: "" };
|
|
12373
12938
|
return outcome;
|
|
12374
12939
|
}
|
|
12375
|
-
const pageFileAbs =
|
|
12940
|
+
const pageFileAbs = join33(frameworkDir, "pages", def.pageFile({ kebab, pascal }));
|
|
12376
12941
|
if (existsSync25(pageFileAbs)) {
|
|
12377
12942
|
outcome.notes.push(`${pascal} already exists at ${pageFileAbs} \u2014 skipped.`);
|
|
12378
12943
|
return outcome;
|
|
@@ -12380,11 +12945,11 @@ var writeNew = (path, contents) => {
|
|
|
12380
12945
|
const routingFile = findRoutingFile(project.serverEntry);
|
|
12381
12946
|
const routingText = routingFile ? readFileSync25(routingFile, "utf-8") : "";
|
|
12382
12947
|
const css = planCss(routingText, project.stylesDir, pascal, kebab);
|
|
12383
|
-
const navDataPath =
|
|
12948
|
+
const navDataPath = join33(sharedDirFor(project, framework), "navData.ts");
|
|
12384
12949
|
const nav = upsertNavItem(navDataPath, { href: route, label: title });
|
|
12385
|
-
const navImportPath = toModuleSpecifier(
|
|
12950
|
+
const navImportPath = toModuleSpecifier(dirname22(pageFileAbs), navDataPath.replace(/\.ts$/, ""));
|
|
12386
12951
|
writeNew(pageFileAbs, pageTemplates[framework]({
|
|
12387
|
-
cssHref: toHref(
|
|
12952
|
+
cssHref: toHref(dirname22(pageFileAbs), css.cssFileAbs),
|
|
12388
12953
|
kebab,
|
|
12389
12954
|
navImportPath,
|
|
12390
12955
|
navItems: nav.items,
|
|
@@ -12434,7 +12999,7 @@ var exports_generate = {};
|
|
|
12434
12999
|
__export(exports_generate, {
|
|
12435
13000
|
runGenerate: () => runGenerate
|
|
12436
13001
|
});
|
|
12437
|
-
import { relative as
|
|
13002
|
+
import { relative as relative18 } from "path";
|
|
12438
13003
|
var SUBCOMMANDS, write = (text2) => process.stdout.write(`${text2}
|
|
12439
13004
|
`), fail = (message) => {
|
|
12440
13005
|
process.stdout.write(`${colors.red}${message}${colors.reset}
|
|
@@ -12466,7 +13031,7 @@ var SUBCOMMANDS, write = (text2) => process.stdout.write(`${text2}
|
|
|
12466
13031
|
return;
|
|
12467
13032
|
write(` ${colors.dim}${label}${colors.reset}`);
|
|
12468
13033
|
for (const path of paths)
|
|
12469
|
-
write(` ${
|
|
13034
|
+
write(` ${relative18(cwd, path)}`);
|
|
12470
13035
|
}, printSummary = (title, outcome, cwd) => {
|
|
12471
13036
|
for (const note of outcome.notes) {
|
|
12472
13037
|
write(`${colors.yellow}!${colors.reset} ${note}`);
|
|
@@ -12760,9 +13325,9 @@ var init_catalog = __esm(() => {
|
|
|
12760
13325
|
|
|
12761
13326
|
// src/cli/integrations/addPlugin.ts
|
|
12762
13327
|
import { existsSync as existsSync26, readFileSync as readFileSync27 } from "fs";
|
|
12763
|
-
import { join as
|
|
13328
|
+
import { join as join34 } from "path";
|
|
12764
13329
|
var isRecord11 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readPackageJson = (cwd) => {
|
|
12765
|
-
const path =
|
|
13330
|
+
const path = join34(cwd, "package.json");
|
|
12766
13331
|
if (!existsSync26(path))
|
|
12767
13332
|
return null;
|
|
12768
13333
|
try {
|
|
@@ -13259,14 +13824,14 @@ var init_authCatalog = __esm(() => {
|
|
|
13259
13824
|
// src/cli/config/auth/resolveAuthSettings.ts
|
|
13260
13825
|
import ts12 from "typescript";
|
|
13261
13826
|
import { existsSync as existsSync27, readFileSync as readFileSync28 } from "fs";
|
|
13262
|
-
import { resolve as
|
|
13827
|
+
import { resolve as resolve29 } from "path";
|
|
13263
13828
|
var AUTH_PACKAGE = "@absolutejs/auth", CONFIG_CANDIDATES3, findAuthSettingsPath = (cwd, override) => {
|
|
13264
13829
|
if (override) {
|
|
13265
|
-
const resolved =
|
|
13830
|
+
const resolved = resolve29(cwd, override);
|
|
13266
13831
|
return existsSync27(resolved) ? resolved : null;
|
|
13267
13832
|
}
|
|
13268
13833
|
for (const name of CONFIG_CANDIDATES3) {
|
|
13269
|
-
const candidate =
|
|
13834
|
+
const candidate = resolve29(cwd, name);
|
|
13270
13835
|
if (existsSync27(candidate))
|
|
13271
13836
|
return candidate;
|
|
13272
13837
|
}
|
|
@@ -13364,7 +13929,7 @@ var init_resolveAuthSettings = __esm(() => {
|
|
|
13364
13929
|
// src/cli/config/auth/resolveAuthState.ts
|
|
13365
13930
|
import ts13 from "typescript";
|
|
13366
13931
|
import { existsSync as existsSync28, readdirSync as readdirSync6, readFileSync as readFileSync29 } from "fs";
|
|
13367
|
-
import { join as
|
|
13932
|
+
import { join as join35, relative as relative19, resolve as resolve30 } from "path";
|
|
13368
13933
|
var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutejs/absolute-auth", NPM_URL = "https://www.npmjs.com/package/@absolutejs/auth", SKIP_DIRS, MAX_FILES = 4000, SETUP_EXPORTS, isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readJson2 = (path) => {
|
|
13369
13934
|
if (!existsSync28(path))
|
|
13370
13935
|
return null;
|
|
@@ -13378,7 +13943,7 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
|
|
|
13378
13943
|
const value = record?.[key];
|
|
13379
13944
|
return typeof value === "string" ? value : null;
|
|
13380
13945
|
}, declaredVersionFor = (cwd) => {
|
|
13381
|
-
const pkg = readJson2(
|
|
13946
|
+
const pkg = readJson2(join35(cwd, "package.json"));
|
|
13382
13947
|
if (!pkg)
|
|
13383
13948
|
return null;
|
|
13384
13949
|
for (const field of ["dependencies", "devDependencies"]) {
|
|
@@ -13390,14 +13955,14 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
|
|
|
13390
13955
|
return version2;
|
|
13391
13956
|
}
|
|
13392
13957
|
return null;
|
|
13393
|
-
}, installedVersionFor = (cwd) => stringField(readJson2(
|
|
13958
|
+
}, installedVersionFor = (cwd) => stringField(readJson2(join35(cwd, "node_modules", AUTH_PACKAGE2, "package.json")), "version"), SOURCE_FILE, safeReaddir = (dir) => {
|
|
13394
13959
|
try {
|
|
13395
13960
|
return readdirSync6(dir, { withFileTypes: true });
|
|
13396
13961
|
} catch {
|
|
13397
13962
|
return [];
|
|
13398
13963
|
}
|
|
13399
13964
|
}, sortEntry = (dir, entry, found, dirs) => {
|
|
13400
|
-
const full =
|
|
13965
|
+
const full = join35(dir, entry.name);
|
|
13401
13966
|
if (entry.isDirectory()) {
|
|
13402
13967
|
if (SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))
|
|
13403
13968
|
return;
|
|
@@ -13495,7 +14060,7 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
|
|
|
13495
14060
|
scaffoldable: isScaffoldableFeature(feature.id)
|
|
13496
14061
|
})), resolveAuthState = (cwd) => {
|
|
13497
14062
|
const installedVersion = installedVersionFor(cwd);
|
|
13498
|
-
const root = existsSync28(
|
|
14063
|
+
const root = existsSync28(join35(cwd, "src")) ? join35(cwd, "src") : cwd;
|
|
13499
14064
|
let match = null;
|
|
13500
14065
|
let setupPath = null;
|
|
13501
14066
|
for (const file of candidateFiles(root)) {
|
|
@@ -13503,7 +14068,7 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
|
|
|
13503
14068
|
if (found === null)
|
|
13504
14069
|
continue;
|
|
13505
14070
|
match = found;
|
|
13506
|
-
setupPath =
|
|
14071
|
+
setupPath = relative19(cwd, resolve30(file));
|
|
13507
14072
|
break;
|
|
13508
14073
|
}
|
|
13509
14074
|
const keys = match?.keys ?? new Set;
|
|
@@ -13541,7 +14106,7 @@ var init_resolveAuthState = __esm(() => {
|
|
|
13541
14106
|
|
|
13542
14107
|
// src/cli/config/auth/scaffoldAuthFeature.ts
|
|
13543
14108
|
import { existsSync as existsSync29, writeFileSync as writeFileSync15 } from "fs";
|
|
13544
|
-
import { dirname as
|
|
14109
|
+
import { dirname as dirname23, join as join36, relative as relative20, resolve as resolve31 } from "path";
|
|
13545
14110
|
var renderScaffold = (scaffold) => {
|
|
13546
14111
|
const importNames = [...scaffold.imports, `type ${scaffold.typeName}`];
|
|
13547
14112
|
const importLine = `import { ${importNames.join(", ")} } from '@absolutejs/auth';`;
|
|
@@ -13566,8 +14131,8 @@ ${body}
|
|
|
13566
14131
|
}, targetDir = (cwd) => {
|
|
13567
14132
|
const { setupPath } = resolveAuthState(cwd);
|
|
13568
14133
|
if (setupPath)
|
|
13569
|
-
return
|
|
13570
|
-
const src =
|
|
14134
|
+
return dirname23(resolve31(cwd, setupPath));
|
|
14135
|
+
const src = join36(cwd, "src");
|
|
13571
14136
|
return existsSync29(src) ? src : cwd;
|
|
13572
14137
|
}, spreadFor = (scaffold) => `import { ${scaffold.exportName} } from './${scaffold.exportName}';
|
|
13573
14138
|
// add to your auth() call:
|
|
@@ -13581,8 +14146,8 @@ ${scaffold.configKey}: ${scaffold.exportName}`, failure2 = (message) => ({
|
|
|
13581
14146
|
const scaffold = AUTH_SCAFFOLDS[id];
|
|
13582
14147
|
if (!scaffold)
|
|
13583
14148
|
return failure2(`Unknown auth feature "${id}".`);
|
|
13584
|
-
const filePath =
|
|
13585
|
-
const relPath =
|
|
14149
|
+
const filePath = join36(targetDir(cwd), `${scaffold.exportName}.ts`);
|
|
14150
|
+
const relPath = relative20(cwd, filePath);
|
|
13586
14151
|
if (existsSync29(filePath)) {
|
|
13587
14152
|
return {
|
|
13588
14153
|
created: null,
|
|
@@ -13611,11 +14176,11 @@ var init_scaffoldAuthFeature = __esm(() => {
|
|
|
13611
14176
|
|
|
13612
14177
|
// src/cli/htmx/install.ts
|
|
13613
14178
|
import { existsSync as existsSync30, mkdirSync as mkdirSync14, readFileSync as readFileSync30, writeFileSync as writeFileSync16 } from "fs";
|
|
13614
|
-
import { join as
|
|
14179
|
+
import { join as join37 } from "path";
|
|
13615
14180
|
var VENDORED_HTMX_VERSION = "2.0.6", vendoredHtmxFile = () => [
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
14181
|
+
join37(import.meta.dir, "htmx.min.js"),
|
|
14182
|
+
join37(import.meta.dir, "htmx", "htmx.min.js"),
|
|
14183
|
+
join37(import.meta.dir, "..", "htmx", "htmx.min.js")
|
|
13619
14184
|
].find((path) => existsSync30(path)) ?? null, detectHtmxVersion = (content) => {
|
|
13620
14185
|
const match = content.match(/version:"([0-9.]+)"/);
|
|
13621
14186
|
return match ? match[1] : null;
|
|
@@ -13627,7 +14192,7 @@ var VENDORED_HTMX_VERSION = "2.0.6", vendoredHtmxFile = () => [
|
|
|
13627
14192
|
}
|
|
13628
14193
|
return response.text();
|
|
13629
14194
|
}, installedHtmxVersion = (htmxDir) => {
|
|
13630
|
-
const file =
|
|
14195
|
+
const file = join37(htmxDir, "htmx.min.js");
|
|
13631
14196
|
if (!existsSync30(file))
|
|
13632
14197
|
return null;
|
|
13633
14198
|
return detectHtmxVersion(readFileSync30(file, "utf-8"));
|
|
@@ -13636,7 +14201,7 @@ var VENDORED_HTMX_VERSION = "2.0.6", vendoredHtmxFile = () => [
|
|
|
13636
14201
|
return file ? readFileSync30(file, "utf-8") : null;
|
|
13637
14202
|
}, writeHtmx = (htmxDir, content) => {
|
|
13638
14203
|
mkdirSync14(htmxDir, { recursive: true });
|
|
13639
|
-
const file =
|
|
14204
|
+
const file = join37(htmxDir, "htmx.min.js");
|
|
13640
14205
|
writeFileSync16(file, content, "utf-8");
|
|
13641
14206
|
return file;
|
|
13642
14207
|
};
|
|
@@ -13647,7 +14212,7 @@ var exports_add = {};
|
|
|
13647
14212
|
__export(exports_add, {
|
|
13648
14213
|
runAdd: () => runAdd
|
|
13649
14214
|
});
|
|
13650
|
-
import { dirname as
|
|
14215
|
+
import { dirname as dirname24, join as join38, relative as relative21 } from "path";
|
|
13651
14216
|
var write2 = (text2) => process.stdout.write(`${text2}
|
|
13652
14217
|
`), fail2 = (message) => {
|
|
13653
14218
|
process.stdout.write(`${colors.red}${message}${colors.reset}
|
|
@@ -13658,11 +14223,11 @@ var write2 = (text2) => process.stdout.write(`${text2}
|
|
|
13658
14223
|
return;
|
|
13659
14224
|
write2(` ${colors.dim}${label}${colors.reset}`);
|
|
13660
14225
|
for (const path of paths)
|
|
13661
|
-
write2(` ${
|
|
14226
|
+
write2(` ${relative21(cwd, path)}`);
|
|
13662
14227
|
}, frontendRoot = (project, cwd) => {
|
|
13663
14228
|
const [firstKey] = configuredFrameworks(project);
|
|
13664
14229
|
const firstDir = firstKey ? project.frameworkDirs[firstKey] : undefined;
|
|
13665
|
-
return firstDir ?
|
|
14230
|
+
return firstDir ? dirname24(firstDir) : join38(cwd, "src", "frontend");
|
|
13666
14231
|
}, addIntegrationCli = (id, install) => {
|
|
13667
14232
|
const result = addIntegration(process.cwd(), id, { install });
|
|
13668
14233
|
if (!result.ok) {
|
|
@@ -13726,8 +14291,8 @@ var write2 = (text2) => process.stdout.write(`${text2}
|
|
|
13726
14291
|
write2(`${colors.yellow}!${colors.reset} ${frameworks6[framework].label} is already configured \u2014 nothing to do.`);
|
|
13727
14292
|
return;
|
|
13728
14293
|
}
|
|
13729
|
-
const dirAbs =
|
|
13730
|
-
const dirRel = `./${
|
|
14294
|
+
const dirAbs = join38(frontendRoot(project, cwd), framework);
|
|
14295
|
+
const dirRel = `./${relative21(cwd, dirAbs).split("\\").join("/")}`;
|
|
13731
14296
|
let depNote = "Skipped dependency install (--no-install).";
|
|
13732
14297
|
if (!noInstall) {
|
|
13733
14298
|
write2(`${colors.dim}Installing ${frameworks6[framework].label} dependencies\u2026${colors.reset}`);
|
|
@@ -13797,7 +14362,7 @@ __export(exports_analyze, {
|
|
|
13797
14362
|
runAnalyze: () => runAnalyze
|
|
13798
14363
|
});
|
|
13799
14364
|
import { existsSync as existsSync31, readFileSync as readFileSync31, statSync as statSync3, writeFileSync as writeFileSync17 } from "fs";
|
|
13800
|
-
import { join as
|
|
14365
|
+
import { join as join39, resolve as resolve32 } from "path";
|
|
13801
14366
|
var BASELINE_FILE = ".absolute-size-baseline.json", TOP_CHANGES = 12, CATEGORY_WIDTH = 16, SIZE_WIDTH = 12, CHANGE_WIDTH = 10, CATEGORY_ORDER, categoryOf = (key) => {
|
|
13802
14367
|
if (key.startsWith("Island"))
|
|
13803
14368
|
return "Islands";
|
|
@@ -13817,17 +14382,17 @@ var BASELINE_FILE = ".absolute-size-baseline.json", TOP_CHANGES = 12, CATEGORY_W
|
|
|
13817
14382
|
return 0;
|
|
13818
14383
|
}
|
|
13819
14384
|
}, readSizes = (manifestDir) => {
|
|
13820
|
-
const manifestPath =
|
|
14385
|
+
const manifestPath = join39(manifestDir, "manifest.json");
|
|
13821
14386
|
if (!existsSync31(manifestPath))
|
|
13822
14387
|
return null;
|
|
13823
14388
|
const manifest = JSON.parse(readFileSync31(manifestPath, "utf-8"));
|
|
13824
14389
|
const sizes = {};
|
|
13825
14390
|
for (const [key, value] of Object.entries(manifest)) {
|
|
13826
|
-
sizes[key] = fileSize2(
|
|
14391
|
+
sizes[key] = fileSize2(join39(manifestDir, value.replace(/^\//, "")));
|
|
13827
14392
|
}
|
|
13828
14393
|
return sizes;
|
|
13829
14394
|
}, readBaseline = (cwd) => {
|
|
13830
|
-
const path =
|
|
14395
|
+
const path = join39(cwd, BASELINE_FILE);
|
|
13831
14396
|
if (!existsSync31(path))
|
|
13832
14397
|
return null;
|
|
13833
14398
|
try {
|
|
@@ -13909,14 +14474,14 @@ var BASELINE_FILE = ".absolute-size-baseline.json", TOP_CHANGES = 12, CATEGORY_W
|
|
|
13909
14474
|
const config = await loadConfig(configIndex >= 0 ? args[configIndex + 1] : undefined);
|
|
13910
14475
|
const outdirIndex = args.indexOf("--outdir");
|
|
13911
14476
|
const outdir = outdirIndex >= 0 ? args[outdirIndex + 1] : config.buildDirectory;
|
|
13912
|
-
const sizes = readSizes(
|
|
14477
|
+
const sizes = readSizes(resolve32(cwd, outdir ?? "build"));
|
|
13913
14478
|
if (sizes === null) {
|
|
13914
14479
|
process.stdout.write(`${colors.dim}No build found. Run \`absolute build\` first.${colors.reset}
|
|
13915
14480
|
`);
|
|
13916
14481
|
return;
|
|
13917
14482
|
}
|
|
13918
14483
|
if (args.includes("--save")) {
|
|
13919
|
-
writeFileSync17(
|
|
14484
|
+
writeFileSync17(join39(cwd, BASELINE_FILE), `${JSON.stringify(sizes, null, 2)}
|
|
13920
14485
|
`);
|
|
13921
14486
|
process.stdout.write(`${colors.green}\u2713${colors.reset} Saved size baseline (${Object.keys(sizes).length} entries) to ${BASELINE_FILE}
|
|
13922
14487
|
`);
|
|
@@ -14163,7 +14728,7 @@ __export(exports_remove, {
|
|
|
14163
14728
|
runRemove: () => runRemove
|
|
14164
14729
|
});
|
|
14165
14730
|
import { existsSync as existsSync32, readFileSync as readFileSync32 } from "fs";
|
|
14166
|
-
import { relative as
|
|
14731
|
+
import { relative as relative22 } from "path";
|
|
14167
14732
|
var write3 = (text2) => process.stdout.write(`${text2}
|
|
14168
14733
|
`), fail3 = (message) => {
|
|
14169
14734
|
process.stdout.write(`${colors.red}${message}${colors.reset}
|
|
@@ -14212,10 +14777,10 @@ var write3 = (text2) => process.stdout.write(`${text2}
|
|
|
14212
14777
|
}
|
|
14213
14778
|
write3(`${colors.green}\u2713${colors.reset} Removed ${framework}Directory from absolute.config.ts
|
|
14214
14779
|
`);
|
|
14215
|
-
write3(` ${colors.dim}Kept${colors.reset} ${
|
|
14780
|
+
write3(` ${colors.dim}Kept${colors.reset} ${relative22(cwd, frameworkDir)} \u2014 delete its source manually if no longer needed.`);
|
|
14216
14781
|
const refs = referencingFiles(project.serverEntry, HANDLER_NAME[framework]);
|
|
14217
14782
|
for (const file of refs) {
|
|
14218
|
-
write3(` ${colors.yellow}Still references${colors.reset} ${
|
|
14783
|
+
write3(` ${colors.yellow}Still references${colors.reset} ${relative22(cwd, file)} (calls ${HANDLER_NAME[framework]})`);
|
|
14219
14784
|
}
|
|
14220
14785
|
const deps = frameworkDependencyNames(framework);
|
|
14221
14786
|
if (prune && deps.length > 0) {
|
|
@@ -14304,9 +14869,9 @@ __export(exports_env, {
|
|
|
14304
14869
|
collectEnvVars: () => collectEnvVars
|
|
14305
14870
|
});
|
|
14306
14871
|
import { existsSync as existsSync33, readFileSync as readFileSync33 } from "fs";
|
|
14307
|
-
import { join as
|
|
14872
|
+
import { join as join40 } from "path";
|
|
14308
14873
|
var {env: env3, Glob: Glob3 } = globalThis.Bun;
|
|
14309
|
-
var EXTENSIONS = "ts,tsx,js,jsx,mjs,cjs,svelte,vue", STATUS_WIDTH2, keysInFile = (text2) => [...text2.matchAll(/getEnv\(\s*['"]([^'"]+)['"]\s*\)/g)].map((match) => match[1]).filter((key) => key !== undefined), scanPatterns = () => existsSync33(
|
|
14874
|
+
var EXTENSIONS = "ts,tsx,js,jsx,mjs,cjs,svelte,vue", STATUS_WIDTH2, keysInFile = (text2) => [...text2.matchAll(/getEnv\(\s*['"]([^'"]+)['"]\s*\)/g)].map((match) => match[1]).filter((key) => key !== undefined), scanPatterns = () => existsSync33(join40(process.cwd(), "src")) ? [`src/**/*.{${EXTENSIONS}}`] : [`*.{${EXTENSIONS}}`], scanEnvUsage = async () => {
|
|
14310
14875
|
const scans = scanPatterns().map((pattern) => Array.fromAsync(new Glob3(pattern).scan({ cwd: process.cwd() })));
|
|
14311
14876
|
const files = (await Promise.all(scans)).flat();
|
|
14312
14877
|
const usage = new Map;
|
|
@@ -14373,7 +14938,7 @@ __export(exports_db, {
|
|
|
14373
14938
|
chunkRows: () => chunkRows
|
|
14374
14939
|
});
|
|
14375
14940
|
import { existsSync as existsSync34, mkdirSync as mkdirSync15, readFileSync as readFileSync34, writeFileSync as writeFileSync18 } from "fs";
|
|
14376
|
-
import { join as
|
|
14941
|
+
import { join as join41 } from "path";
|
|
14377
14942
|
var {env: env4, spawn: spawn2, SQL } = globalThis.Bun;
|
|
14378
14943
|
var BACKUP_FORMAT_VERSION = 1, RESTORE_CHUNK_ROWS = 500, URL_ENV_KEYS, JSON_DATA_TYPES, SEED_CANDIDATES, VALUE_FLAGS, paint = (text2, color) => `${color}${text2}${colors.reset}`, chunkRows = (items, size) => Array.from({ length: Math.ceil(items.length / size) }, (_, idx) => items.slice(idx * size, idx * size + size)), quoteIdent = (name) => `"${name.replace(/"/g, '""')}"`, resolveUrl = (explicit) => {
|
|
14379
14944
|
const found = explicit ?? URL_ENV_KEYS.map((key) => env4[key]).find((value) => typeof value === "string" && value !== "");
|
|
@@ -14483,12 +15048,12 @@ var BACKUP_FORMAT_VERSION = 1, RESTORE_CHUNK_ROWS = 500, URL_ENV_KEYS, JSON_DATA
|
|
|
14483
15048
|
tables,
|
|
14484
15049
|
v: BACKUP_FORMAT_VERSION
|
|
14485
15050
|
};
|
|
14486
|
-
const dir = options.out ??
|
|
15051
|
+
const dir = options.out ?? join41(process.cwd(), "backups");
|
|
14487
15052
|
mkdirSync15(dir, { recursive: true });
|
|
14488
15053
|
const json = JSON.stringify(payload, (_, value) => typeof value === "bigint" ? value.toString() : value);
|
|
14489
|
-
const file =
|
|
15054
|
+
const file = join41(dir, `backup-${payload.at.replace(/[:.]/g, "-")}.json`);
|
|
14490
15055
|
writeFileSync18(file, json);
|
|
14491
|
-
writeFileSync18(
|
|
15056
|
+
writeFileSync18(join41(dir, "latest.json"), json);
|
|
14492
15057
|
const total = chosen.reduce((sum, name) => sum + (tables[name]?.length ?? 0), 0);
|
|
14493
15058
|
console.log(paint(`\u2713 backup \u2192 ${file}`, colors.green));
|
|
14494
15059
|
console.log(paint(` ${chosen.length} tables, ${total} rows`, colors.dim));
|
|
@@ -14517,7 +15082,7 @@ var BACKUP_FORMAT_VERSION = 1, RESTORE_CHUNK_ROWS = 500, URL_ENV_KEYS, JSON_DATA
|
|
|
14517
15082
|
const total = order.reduce((sum, name) => sum + (payload.tables[name]?.length ?? 0), 0);
|
|
14518
15083
|
console.log(paint(`\u2713 restored ${order.length} tables, ${total} rows (idempotent upsert by primary key)`, colors.green));
|
|
14519
15084
|
}, runSeed = async (entry) => {
|
|
14520
|
-
const target = entry ?? SEED_CANDIDATES.find((candidate) => existsSync34(
|
|
15085
|
+
const target = entry ?? SEED_CANDIDATES.find((candidate) => existsSync34(join41(process.cwd(), candidate)));
|
|
14521
15086
|
if (target === undefined)
|
|
14522
15087
|
throw new Error(`No seed script found (looked for ${SEED_CANDIDATES.join(", ")}). Pass a path: absolute db seed <file>.`);
|
|
14523
15088
|
console.log(paint(`seeding via ${target}\u2026`, colors.cyan));
|
|
@@ -14552,7 +15117,7 @@ var BACKUP_FORMAT_VERSION = 1, RESTORE_CHUNK_ROWS = 500, URL_ENV_KEYS, JSON_DATA
|
|
|
14552
15117
|
return;
|
|
14553
15118
|
}
|
|
14554
15119
|
if (sub === "restore") {
|
|
14555
|
-
const file = positionalArgs(rest)[0] ??
|
|
15120
|
+
const file = positionalArgs(rest)[0] ?? join41(process.cwd(), "backups", "latest.json");
|
|
14556
15121
|
await runRestore(file, parseOptions(rest));
|
|
14557
15122
|
return;
|
|
14558
15123
|
}
|
|
@@ -14672,7 +15237,7 @@ import {
|
|
|
14672
15237
|
writeFileSync as writeFileSync19
|
|
14673
15238
|
} from "fs";
|
|
14674
15239
|
import { createRequire } from "module";
|
|
14675
|
-
import { dirname as
|
|
15240
|
+
import { dirname as dirname25, join as join42, resolve as resolve33, sep as sep5 } from "path";
|
|
14676
15241
|
var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
|
|
14677
15242
|
try {
|
|
14678
15243
|
const parsed = JSON.parse(readFileSync35(path, "utf-8"));
|
|
@@ -14692,13 +15257,13 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
|
|
|
14692
15257
|
const version2 = Reflect.get(manifest, "version");
|
|
14693
15258
|
return typeof version2 === "string" ? version2 : "unknown";
|
|
14694
15259
|
}, packageJsonFromEntry = (entry, expectedName) => {
|
|
14695
|
-
let directory =
|
|
15260
|
+
let directory = dirname25(entry);
|
|
14696
15261
|
for (;; ) {
|
|
14697
|
-
const candidate =
|
|
15262
|
+
const candidate = join42(directory, "package.json");
|
|
14698
15263
|
const manifest = readManifest(candidate);
|
|
14699
15264
|
if (manifest && manifestName(manifest, "") === expectedName)
|
|
14700
15265
|
return candidate;
|
|
14701
|
-
const parent =
|
|
15266
|
+
const parent = dirname25(directory);
|
|
14702
15267
|
if (parent === directory)
|
|
14703
15268
|
return null;
|
|
14704
15269
|
directory = parent;
|
|
@@ -14714,27 +15279,27 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
|
|
|
14714
15279
|
}
|
|
14715
15280
|
}
|
|
14716
15281
|
}, findInstallRoot = (cwd) => {
|
|
14717
|
-
let directory =
|
|
15282
|
+
let directory = resolve33(cwd);
|
|
14718
15283
|
for (;; ) {
|
|
14719
|
-
if (existsSync36(
|
|
15284
|
+
if (existsSync36(join42(directory, "bun.lock")) || existsSync36(join42(directory, "bun.lockb"))) {
|
|
14720
15285
|
return directory;
|
|
14721
15286
|
}
|
|
14722
|
-
const parent =
|
|
15287
|
+
const parent = dirname25(directory);
|
|
14723
15288
|
if (parent === directory)
|
|
14724
|
-
return
|
|
15289
|
+
return resolve33(cwd);
|
|
14725
15290
|
directory = parent;
|
|
14726
15291
|
}
|
|
14727
15292
|
}, findProjectManifest = (cwd, installRoot) => {
|
|
14728
|
-
let directory =
|
|
15293
|
+
let directory = resolve33(cwd);
|
|
14729
15294
|
for (;; ) {
|
|
14730
|
-
const candidate =
|
|
15295
|
+
const candidate = join42(directory, "package.json");
|
|
14731
15296
|
if (existsSync36(candidate))
|
|
14732
15297
|
return candidate;
|
|
14733
15298
|
if (directory === installRoot)
|
|
14734
|
-
return
|
|
14735
|
-
const parent =
|
|
15299
|
+
return join42(installRoot, "package.json");
|
|
15300
|
+
const parent = dirname25(directory);
|
|
14736
15301
|
if (parent === directory)
|
|
14737
|
-
return
|
|
15302
|
+
return join42(installRoot, "package.json");
|
|
14738
15303
|
directory = parent;
|
|
14739
15304
|
}
|
|
14740
15305
|
}, appendConsumer = (consumers, consumerPaths, path, manifest) => {
|
|
@@ -14772,7 +15337,7 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
|
|
|
14772
15337
|
appendConsumer(consumers, consumerPaths, inspection.consumer.path, inspection.consumer.manifest);
|
|
14773
15338
|
}, inspectTypeGraph = (cwd) => {
|
|
14774
15339
|
const installRoot = findInstallRoot(cwd);
|
|
14775
|
-
const rootManifestPath =
|
|
15340
|
+
const rootManifestPath = join42(installRoot, "package.json");
|
|
14776
15341
|
const rootManifest = readManifest(rootManifestPath) ?? {};
|
|
14777
15342
|
const consumers = [
|
|
14778
15343
|
{ manifest: rootManifest, path: rootManifestPath }
|
|
@@ -14808,7 +15373,7 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
|
|
|
14808
15373
|
const duplicates = duplicateTypeGraphPackages(report);
|
|
14809
15374
|
if (duplicates.length === 0)
|
|
14810
15375
|
return [];
|
|
14811
|
-
const manifestPath =
|
|
15376
|
+
const manifestPath = join42(report.installRoot, "package.json");
|
|
14812
15377
|
const manifest = readManifest(manifestPath);
|
|
14813
15378
|
if (!manifest)
|
|
14814
15379
|
return [];
|
|
@@ -14830,7 +15395,7 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
|
|
|
14830
15395
|
}
|
|
14831
15396
|
return changes;
|
|
14832
15397
|
}, removeDuplicateTypeGraphPackages = (report) => {
|
|
14833
|
-
const manifest = readManifest(
|
|
15398
|
+
const manifest = readManifest(join42(report.installRoot, "package.json")) ?? {};
|
|
14834
15399
|
const rootName = manifestName(manifest, "<workspace>");
|
|
14835
15400
|
const installPrefix = `${realpathSync2(report.installRoot)}${sep5}`;
|
|
14836
15401
|
const nodeModulesSegment = `${sep5}node_modules${sep5}`;
|
|
@@ -14842,7 +15407,7 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
|
|
|
14842
15407
|
for (const stalePath of stalePaths) {
|
|
14843
15408
|
if (!stalePath.startsWith(installPrefix) || !stalePath.includes(nodeModulesSegment))
|
|
14844
15409
|
continue;
|
|
14845
|
-
rmSync6(
|
|
15410
|
+
rmSync6(dirname25(stalePath), { force: true, recursive: true });
|
|
14846
15411
|
removed.push(stalePath);
|
|
14847
15412
|
}
|
|
14848
15413
|
return removed;
|
|
@@ -14872,7 +15437,7 @@ __export(exports_doctor, {
|
|
|
14872
15437
|
import { existsSync as existsSync37, mkdirSync as mkdirSync16, readFileSync as readFileSync36, writeFileSync as writeFileSync20 } from "fs";
|
|
14873
15438
|
import { createRequire as createRequire2 } from "module";
|
|
14874
15439
|
import { arch as arch4, platform as platform5 } from "os";
|
|
14875
|
-
import { join as
|
|
15440
|
+
import { join as join43 } from "path";
|
|
14876
15441
|
var FRAMEWORK_FIELDS2, projectRequire, check = (status2, label, detail) => ({
|
|
14877
15442
|
detail,
|
|
14878
15443
|
label,
|
|
@@ -14907,7 +15472,7 @@ var FRAMEWORK_FIELDS2, projectRequire, check = (status2, label, detail) => ({
|
|
|
14907
15472
|
return [];
|
|
14908
15473
|
const label = `${field.replace("Directory", "")} pages`;
|
|
14909
15474
|
return [
|
|
14910
|
-
existsSync37(
|
|
15475
|
+
existsSync37(join43(process.cwd(), dir)) ? check("ok", label, dir) : check("fail", label, `${dir} (missing)`)
|
|
14911
15476
|
];
|
|
14912
15477
|
}), envCheck = async () => {
|
|
14913
15478
|
const vars = await collectEnvVars();
|
|
@@ -14969,9 +15534,9 @@ ${colors.dim}${checks.length} checks \xB7 ${colors.reset}${summary}${colors.dim}
|
|
|
14969
15534
|
const fixes = [];
|
|
14970
15535
|
for (const field of FRAMEWORK_FIELDS2) {
|
|
14971
15536
|
const dir = readString2(config, field);
|
|
14972
|
-
if (dir === undefined || existsSync37(
|
|
15537
|
+
if (dir === undefined || existsSync37(join43(cwd, dir)))
|
|
14973
15538
|
continue;
|
|
14974
|
-
mkdirSync16(
|
|
15539
|
+
mkdirSync16(join43(cwd, dir, "pages"), { recursive: true });
|
|
14975
15540
|
fixes.push(`created ${dir}/pages`);
|
|
14976
15541
|
}
|
|
14977
15542
|
return fixes;
|
|
@@ -14979,7 +15544,7 @@ ${colors.dim}${checks.length} checks \xB7 ${colors.reset}${summary}${colors.dim}
|
|
|
14979
15544
|
const missing = (await collectEnvVars()).filter((entry) => !entry.set);
|
|
14980
15545
|
if (missing.length === 0)
|
|
14981
15546
|
return null;
|
|
14982
|
-
const envExample =
|
|
15547
|
+
const envExample = join43(cwd, ".env.example");
|
|
14983
15548
|
const existing = existsSync37(envExample) ? readFileSync36(envExample, "utf-8") : "";
|
|
14984
15549
|
const existingKeys = new Set(existing.split(`
|
|
14985
15550
|
`).map((line) => line.split("=")[0]?.trim()));
|
|
@@ -15050,7 +15615,7 @@ var init_doctor = __esm(() => {
|
|
|
15050
15615
|
"htmlDirectory",
|
|
15051
15616
|
"htmxDirectory"
|
|
15052
15617
|
];
|
|
15053
|
-
projectRequire = createRequire2(
|
|
15618
|
+
projectRequire = createRequire2(join43(process.cwd(), "package.json"));
|
|
15054
15619
|
STATUS_MARK = {
|
|
15055
15620
|
fail: `${colors.red}\u2717${colors.reset}`,
|
|
15056
15621
|
ok: `${colors.green}\u2713${colors.reset}`,
|
|
@@ -15440,7 +16005,7 @@ var init_sourceMetadata = __esm(() => {
|
|
|
15440
16005
|
|
|
15441
16006
|
// src/islands/pageMetadata.ts
|
|
15442
16007
|
import { readFileSync as readFileSync37 } from "fs";
|
|
15443
|
-
import { dirname as
|
|
16008
|
+
import { dirname as dirname26, resolve as resolve34 } from "path";
|
|
15444
16009
|
var pagePatterns, getPageDirs = (config) => [
|
|
15445
16010
|
{ dir: config.angularDirectory, framework: "angular" },
|
|
15446
16011
|
{ dir: config.emberDirectory, framework: "ember" },
|
|
@@ -15460,8 +16025,8 @@ var pagePatterns, getPageDirs = (config) => [
|
|
|
15460
16025
|
const source = definition.buildReference?.source;
|
|
15461
16026
|
if (!source)
|
|
15462
16027
|
continue;
|
|
15463
|
-
const resolvedSource = source.startsWith("file://") ? new URL(source).pathname :
|
|
15464
|
-
lookup.set(`${definition.framework}:${definition.component}`,
|
|
16028
|
+
const resolvedSource = source.startsWith("file://") ? new URL(source).pathname : resolve34(dirname26(buildInfo.resolvedRegistryPath), source);
|
|
16029
|
+
lookup.set(`${definition.framework}:${definition.component}`, resolve34(resolvedSource));
|
|
15465
16030
|
}
|
|
15466
16031
|
return lookup;
|
|
15467
16032
|
}, resolveIslandUsages = (islands, islandSourceLookup) => islands.map((usage2) => {
|
|
@@ -15474,13 +16039,13 @@ var pagePatterns, getPageDirs = (config) => [
|
|
|
15474
16039
|
const pattern = pagePatterns[entry.framework];
|
|
15475
16040
|
if (!pattern)
|
|
15476
16041
|
return;
|
|
15477
|
-
const files = await scanEntryPoints(
|
|
16042
|
+
const files = await scanEntryPoints(resolve34(entry.dir), pattern);
|
|
15478
16043
|
for (const filePath of files) {
|
|
15479
16044
|
const source = readFileSync37(filePath, "utf-8");
|
|
15480
16045
|
const islands = extractIslandUsagesFromSource(source);
|
|
15481
|
-
pageMetadata.set(
|
|
16046
|
+
pageMetadata.set(resolve34(filePath), {
|
|
15482
16047
|
islands: resolveIslandUsages(islands, islandSourceLookup),
|
|
15483
|
-
pagePath:
|
|
16048
|
+
pagePath: resolve34(filePath)
|
|
15484
16049
|
});
|
|
15485
16050
|
}
|
|
15486
16051
|
}, loadPageIslandMetadata = async (config) => {
|
|
@@ -15510,13 +16075,13 @@ __export(exports_islands, {
|
|
|
15510
16075
|
runIslands: () => runIslands
|
|
15511
16076
|
});
|
|
15512
16077
|
import { existsSync as existsSync39, readFileSync as readFileSync38, statSync as statSync5 } from "fs";
|
|
15513
|
-
import { join as
|
|
16078
|
+
import { join as join44, relative as relative23, resolve as resolve35 } from "path";
|
|
15514
16079
|
var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.write(`${colors.dim}${message}${colors.reset}
|
|
15515
16080
|
`), hostFrameworkOf = (pagePath, cwd, config) => {
|
|
15516
|
-
const resolved =
|
|
16081
|
+
const resolved = resolve35(cwd, pagePath);
|
|
15517
16082
|
for (const [framework, key] of Object.entries(FRAMEWORK_DIR_KEY)) {
|
|
15518
16083
|
const dir = config[key];
|
|
15519
|
-
if (typeof dir === "string" && resolved.startsWith(
|
|
16084
|
+
if (typeof dir === "string" && resolved.startsWith(resolve35(cwd, dir))) {
|
|
15520
16085
|
return framework;
|
|
15521
16086
|
}
|
|
15522
16087
|
}
|
|
@@ -15528,20 +16093,20 @@ var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.
|
|
|
15528
16093
|
return 0;
|
|
15529
16094
|
}
|
|
15530
16095
|
}, readManifestSizes2 = (manifestDir) => {
|
|
15531
|
-
const manifestPath =
|
|
16096
|
+
const manifestPath = join44(manifestDir, "manifest.json");
|
|
15532
16097
|
if (!existsSync39(manifestPath))
|
|
15533
16098
|
return null;
|
|
15534
16099
|
const manifest = JSON.parse(readFileSync38(manifestPath, "utf-8"));
|
|
15535
16100
|
const sizes = new Map;
|
|
15536
16101
|
for (const [key, value] of Object.entries(manifest)) {
|
|
15537
|
-
sizes.set(key, fileSize3(
|
|
16102
|
+
sizes.set(key, fileSize3(join44(manifestDir, value.replace(/^\//, ""))));
|
|
15538
16103
|
}
|
|
15539
16104
|
return sizes;
|
|
15540
16105
|
}, collectIslands = async (cwd, config, sizes) => {
|
|
15541
16106
|
const registryPath = config.islands?.registry;
|
|
15542
16107
|
if (typeof registryPath !== "string")
|
|
15543
16108
|
return null;
|
|
15544
|
-
const buildInfo = await loadIslandRegistryBuildInfo(
|
|
16109
|
+
const buildInfo = await loadIslandRegistryBuildInfo(resolve35(cwd, registryPath));
|
|
15545
16110
|
const pageMetadata = await loadPageIslandMetadata(config);
|
|
15546
16111
|
const usages = [...pageMetadata.values()].flatMap((meta) => meta.islands.map((island) => ({ ...island, page: meta.pagePath })));
|
|
15547
16112
|
return buildInfo.definitions.map((definition) => {
|
|
@@ -15551,7 +16116,7 @@ var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.
|
|
|
15551
16116
|
crossFramework: hostFramework !== null && hostFramework !== definition.framework,
|
|
15552
16117
|
hostFramework,
|
|
15553
16118
|
hydrate: usage2.hydrate ?? "load",
|
|
15554
|
-
page:
|
|
16119
|
+
page: relative23(cwd, resolve35(cwd, usage2.page))
|
|
15555
16120
|
};
|
|
15556
16121
|
});
|
|
15557
16122
|
const key = getIslandManifestKey(definition.framework, definition.component);
|
|
@@ -15590,7 +16155,7 @@ var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.
|
|
|
15590
16155
|
` ${color}\u2B21${colors.reset} ${colors.bold}${island.component}${colors.reset} ${meta}${sizeText}`
|
|
15591
16156
|
];
|
|
15592
16157
|
if (island.source) {
|
|
15593
|
-
lines.push(` ${colors.dim}${
|
|
16158
|
+
lines.push(` ${colors.dim}${relative23(cwd, island.source)}${colors.reset}`);
|
|
15594
16159
|
}
|
|
15595
16160
|
if (pages.length === 0) {
|
|
15596
16161
|
lines.push(` ${colors.dim}(registered but not mounted on any page)${colors.reset}`);
|
|
@@ -15620,7 +16185,7 @@ var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.
|
|
|
15620
16185
|
}
|
|
15621
16186
|
const outdirIndex = args.indexOf("--outdir");
|
|
15622
16187
|
const outdir = outdirIndex >= 0 ? args[outdirIndex + 1] : config.buildDirectory;
|
|
15623
|
-
const sizes = args.includes("--sizes") ? readManifestSizes2(
|
|
16188
|
+
const sizes = args.includes("--sizes") ? readManifestSizes2(resolve35(cwd, outdir ?? "build")) : null;
|
|
15624
16189
|
const islands = await collectIslands(cwd, config, sizes);
|
|
15625
16190
|
if (islands === null) {
|
|
15626
16191
|
printDim6('No island registry configured. Set `islands: { registry: "..." }` in absolute.config.ts.');
|
|
@@ -15670,12 +16235,12 @@ var init_islands2 = __esm(() => {
|
|
|
15670
16235
|
|
|
15671
16236
|
// src/build/externalAssetPlugin.ts
|
|
15672
16237
|
import { copyFileSync as copyFileSync2, existsSync as existsSync40, mkdirSync as mkdirSync17, statSync as statSync6 } from "fs";
|
|
15673
|
-
import { basename as
|
|
16238
|
+
import { basename as basename12, dirname as dirname27, join as join45, resolve as resolve36 } from "path";
|
|
15674
16239
|
var createExternalAssetPlugin = (outDir, userSourceRoots = []) => ({
|
|
15675
16240
|
name: "absolute-external-asset",
|
|
15676
16241
|
setup(bld) {
|
|
15677
16242
|
const urlPattern = /new\s+URL\(\s*["'](\.\.?\/[^"']+)["']\s*,\s*import\.meta\.url\s*\)/g;
|
|
15678
|
-
const skipRoots = userSourceRoots.map((root) =>
|
|
16243
|
+
const skipRoots = userSourceRoots.map((root) => resolve36(root));
|
|
15679
16244
|
const isUserSource = (path) => skipRoots.some((root) => path.startsWith(`${root}/`));
|
|
15680
16245
|
bld.onLoad({ filter: /\.[mc]?[jt]sx?$/ }, async (args) => {
|
|
15681
16246
|
if (isUserSource(args.path))
|
|
@@ -15685,20 +16250,20 @@ var createExternalAssetPlugin = (outDir, userSourceRoots = []) => ({
|
|
|
15685
16250
|
return;
|
|
15686
16251
|
urlPattern.lastIndex = 0;
|
|
15687
16252
|
let match;
|
|
15688
|
-
const sourceDir =
|
|
16253
|
+
const sourceDir = dirname27(args.path);
|
|
15689
16254
|
while ((match = urlPattern.exec(source)) !== null) {
|
|
15690
16255
|
const relPath = match[1];
|
|
15691
16256
|
if (!relPath)
|
|
15692
16257
|
continue;
|
|
15693
|
-
const assetPath =
|
|
16258
|
+
const assetPath = resolve36(sourceDir, relPath);
|
|
15694
16259
|
if (!existsSync40(assetPath))
|
|
15695
16260
|
continue;
|
|
15696
16261
|
if (!statSync6(assetPath).isFile())
|
|
15697
16262
|
continue;
|
|
15698
|
-
const targetPath =
|
|
16263
|
+
const targetPath = join45(outDir, basename12(assetPath));
|
|
15699
16264
|
if (existsSync40(targetPath))
|
|
15700
16265
|
continue;
|
|
15701
|
-
mkdirSync17(
|
|
16266
|
+
mkdirSync17(dirname27(targetPath), { recursive: true });
|
|
15702
16267
|
copyFileSync2(assetPath, targetPath);
|
|
15703
16268
|
}
|
|
15704
16269
|
return;
|
|
@@ -15727,12 +16292,12 @@ import {
|
|
|
15727
16292
|
} from "fs";
|
|
15728
16293
|
import { createRequire as createRequire3 } from "module";
|
|
15729
16294
|
import {
|
|
15730
|
-
basename as
|
|
15731
|
-
dirname as
|
|
16295
|
+
basename as basename13,
|
|
16296
|
+
dirname as dirname28,
|
|
15732
16297
|
isAbsolute as isAbsolute6,
|
|
15733
|
-
join as
|
|
15734
|
-
relative as
|
|
15735
|
-
resolve as
|
|
16298
|
+
join as join46,
|
|
16299
|
+
relative as relative24,
|
|
16300
|
+
resolve as resolve37
|
|
15736
16301
|
} from "path";
|
|
15737
16302
|
var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`, compileBanner = (version2) => {
|
|
15738
16303
|
const resolvedVersion = version2 || "unknown";
|
|
@@ -15746,7 +16311,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15746
16311
|
const entry = pending.pop();
|
|
15747
16312
|
if (!entry)
|
|
15748
16313
|
continue;
|
|
15749
|
-
const fullPath =
|
|
16314
|
+
const fullPath = join46(entry.parentPath, entry.name);
|
|
15750
16315
|
if (entry.isDirectory())
|
|
15751
16316
|
pending = pending.concat(readdirSync7(fullPath, { withFileTypes: true }));
|
|
15752
16317
|
else
|
|
@@ -15765,7 +16330,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15765
16330
|
if (!Array.isArray(map.sources))
|
|
15766
16331
|
return;
|
|
15767
16332
|
const sourceRoot = typeof map.sourceRoot === "string" ? map.sourceRoot : "";
|
|
15768
|
-
const bundleDirectory =
|
|
16333
|
+
const bundleDirectory = dirname28(filePath);
|
|
15769
16334
|
map.sources = map.sources.map((entry) => {
|
|
15770
16335
|
if (/^[A-Za-z][A-Za-z0-9+.-]*:/.test(entry))
|
|
15771
16336
|
return entry;
|
|
@@ -15774,7 +16339,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15774
16339
|
if (/^[A-Za-z][A-Za-z0-9+.-]*:/.test(sourceRoot)) {
|
|
15775
16340
|
return new URL(entry, sourceRoot).href;
|
|
15776
16341
|
}
|
|
15777
|
-
return
|
|
16342
|
+
return resolve37(bundleDirectory, sourceRoot, entry);
|
|
15778
16343
|
});
|
|
15779
16344
|
delete map.sourceRoot;
|
|
15780
16345
|
const rebased = Buffer.from(JSON.stringify(map)).toString("base64");
|
|
@@ -15792,7 +16357,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15792
16357
|
const entry = pending.pop();
|
|
15793
16358
|
if (!entry)
|
|
15794
16359
|
continue;
|
|
15795
|
-
const fullPath =
|
|
16360
|
+
const fullPath = join46(entry.parentPath, entry.name);
|
|
15796
16361
|
if (entry.isDirectory()) {
|
|
15797
16362
|
if (SERVER_RUNTIME_SCAN_SKIP_DIRS.has(entry.name))
|
|
15798
16363
|
continue;
|
|
@@ -15804,18 +16369,18 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15804
16369
|
return result;
|
|
15805
16370
|
}, copyServerRuntimeAssetReferences = (outdir) => {
|
|
15806
16371
|
const copied = new Set;
|
|
15807
|
-
const normalizedOutdir =
|
|
16372
|
+
const normalizedOutdir = resolve37(outdir);
|
|
15808
16373
|
const copyReference = (filePath, relPath) => {
|
|
15809
|
-
const assetSource =
|
|
16374
|
+
const assetSource = resolve37(dirname28(filePath), relPath);
|
|
15810
16375
|
if (!existsSync41(assetSource) || !statSync7(assetSource).isFile())
|
|
15811
16376
|
return;
|
|
15812
|
-
const assetTarget =
|
|
16377
|
+
const assetTarget = resolve37(normalizedOutdir, relPath.replace(/^\.\//, ""));
|
|
15813
16378
|
if (assetTarget !== normalizedOutdir && !assetTarget.startsWith(`${normalizedOutdir}/`))
|
|
15814
16379
|
return;
|
|
15815
16380
|
if (copied.has(assetTarget))
|
|
15816
16381
|
return;
|
|
15817
16382
|
copied.add(assetTarget);
|
|
15818
|
-
mkdirSync18(
|
|
16383
|
+
mkdirSync18(dirname28(assetTarget), { recursive: true });
|
|
15819
16384
|
cpSync(assetSource, assetTarget, { force: true });
|
|
15820
16385
|
};
|
|
15821
16386
|
for (const filePath of collectProjectSourceFiles(process.cwd())) {
|
|
@@ -15883,18 +16448,18 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15883
16448
|
return resolveBuildModule3(remaining);
|
|
15884
16449
|
}, resolveJsxDevRuntimeCompatPath2 = () => {
|
|
15885
16450
|
const candidates = [
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
|
|
15889
|
-
|
|
15890
|
-
|
|
15891
|
-
|
|
16451
|
+
resolve37(import.meta.dir, "..", "..", "dist", "react", "jsxDevRuntimeCompat.js"),
|
|
16452
|
+
resolve37(import.meta.dir, "..", "..", "react", "jsxDevRuntimeCompat.js"),
|
|
16453
|
+
resolve37(import.meta.dir, "..", "..", "react", "jsxDevRuntimeCompat.ts"),
|
|
16454
|
+
resolve37(import.meta.dir, "..", "..", "..", "dist", "react", "jsxDevRuntimeCompat.js"),
|
|
16455
|
+
resolve37(import.meta.dir, "..", "..", "..", "react", "jsxDevRuntimeCompat.js"),
|
|
16456
|
+
resolve37(import.meta.dir, "..", "..", "..", "src", "react", "jsxDevRuntimeCompat.ts")
|
|
15892
16457
|
];
|
|
15893
16458
|
for (const candidate of candidates) {
|
|
15894
16459
|
if (existsSync41(candidate))
|
|
15895
16460
|
return candidate;
|
|
15896
16461
|
}
|
|
15897
|
-
return
|
|
16462
|
+
return resolve37(import.meta.dir, "..", "..", "react", "jsxDevRuntimeCompat.js");
|
|
15898
16463
|
}, jsxDevRuntimeCompatPath2, shouldEmbedCompiledAsset = (relativePath, skip = new Set) => {
|
|
15899
16464
|
if (skip.has(relativePath))
|
|
15900
16465
|
return false;
|
|
@@ -15919,7 +16484,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15919
16484
|
return true;
|
|
15920
16485
|
}), requireForCompile, resolveNativeAssetForRuntime = (specifier) => {
|
|
15921
16486
|
if (specifier.startsWith("."))
|
|
15922
|
-
return
|
|
16487
|
+
return resolve37(process.cwd(), specifier);
|
|
15923
16488
|
if (specifier.startsWith("/"))
|
|
15924
16489
|
return specifier;
|
|
15925
16490
|
return requireForCompile.resolve(specifier, { paths: [process.cwd()] });
|
|
@@ -15931,11 +16496,11 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15931
16496
|
return nativeAssetEnv;
|
|
15932
16497
|
}, tryReadNodePackageJson = (packageDir) => {
|
|
15933
16498
|
try {
|
|
15934
|
-
return JSON.parse(readFileSync39(
|
|
16499
|
+
return JSON.parse(readFileSync39(join46(packageDir, "package.json"), "utf-8"));
|
|
15935
16500
|
} catch {
|
|
15936
16501
|
return null;
|
|
15937
16502
|
}
|
|
15938
|
-
}, resolveProjectPackageDir = (specifier) =>
|
|
16503
|
+
}, resolveProjectPackageDir = (specifier) => resolve37(process.cwd(), "node_modules", ...specifier.split("/")), copyPackageToBuild = (specifier, outdir, seen) => {
|
|
15939
16504
|
if (seen.has(specifier))
|
|
15940
16505
|
return;
|
|
15941
16506
|
const srcDir = resolveProjectPackageDir(specifier);
|
|
@@ -15943,13 +16508,13 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15943
16508
|
if (!pkg)
|
|
15944
16509
|
return;
|
|
15945
16510
|
seen.add(specifier);
|
|
15946
|
-
const destDir =
|
|
16511
|
+
const destDir = join46(outdir, "node_modules", ...specifier.split("/"));
|
|
15947
16512
|
rmSync7(destDir, { force: true, recursive: true });
|
|
15948
16513
|
cpSync(srcDir, destDir, {
|
|
15949
16514
|
force: true,
|
|
15950
16515
|
recursive: true,
|
|
15951
16516
|
filter(source) {
|
|
15952
|
-
const rel =
|
|
16517
|
+
const rel = relative24(srcDir, source);
|
|
15953
16518
|
const [firstSegment] = rel.split(/[\\/]/);
|
|
15954
16519
|
return firstSegment !== "node_modules" && firstSegment !== ".git";
|
|
15955
16520
|
}
|
|
@@ -15965,7 +16530,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15965
16530
|
}, copyAngularRuntimePackages = (buildConfig, outdir) => {
|
|
15966
16531
|
if (!buildConfig.angularDirectory)
|
|
15967
16532
|
return;
|
|
15968
|
-
const angularScopeDir =
|
|
16533
|
+
const angularScopeDir = resolve37(process.cwd(), "node_modules", "@angular");
|
|
15969
16534
|
const angularPackages = existsSync41(angularScopeDir) ? readdirSync7(angularScopeDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => entry.name !== "compiler-cli").map((entry) => `@angular/${entry.name}`) : [];
|
|
15970
16535
|
const roots = new Set([...angularPackages, "rxjs", "tslib", "typescript"]);
|
|
15971
16536
|
const seen = new Set;
|
|
@@ -15984,7 +16549,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15984
16549
|
copyAngularRuntimePackages(buildConfig, outdir);
|
|
15985
16550
|
copyChunkReferencedPackages(outdir, seen);
|
|
15986
16551
|
}, collectRuntimePackageSpecifiers = (distDir) => {
|
|
15987
|
-
const nodeModulesDir =
|
|
16552
|
+
const nodeModulesDir = join46(distDir, "node_modules");
|
|
15988
16553
|
if (!existsSync41(nodeModulesDir))
|
|
15989
16554
|
return [];
|
|
15990
16555
|
const specifiers = [];
|
|
@@ -15992,7 +16557,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
15992
16557
|
if (!entry.isDirectory())
|
|
15993
16558
|
continue;
|
|
15994
16559
|
if (entry.name.startsWith("@")) {
|
|
15995
|
-
const scopeDir =
|
|
16560
|
+
const scopeDir = join46(nodeModulesDir, entry.name);
|
|
15996
16561
|
for (const scopedEntry of readdirSync7(scopeDir, {
|
|
15997
16562
|
withFileTypes: true
|
|
15998
16563
|
})) {
|
|
@@ -16006,7 +16571,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16006
16571
|
}
|
|
16007
16572
|
return specifiers.sort((firstSpecifier, secondSpecifier) => secondSpecifier.length - firstSpecifier.length);
|
|
16008
16573
|
}, ensureRelativeModuleSpecifier = (fromFile, toFile) => {
|
|
16009
|
-
const rel =
|
|
16574
|
+
const rel = relative24(dirname28(fromFile), toFile).replace(/\\/g, "/");
|
|
16010
16575
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
16011
16576
|
}, pickExportEntry = (value) => {
|
|
16012
16577
|
if (typeof value === "string")
|
|
@@ -16023,18 +16588,18 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16023
16588
|
const packageSpecifier = packageSpecifiers.find((root) => specifier === root || specifier.startsWith(`${root}/`));
|
|
16024
16589
|
if (!packageSpecifier)
|
|
16025
16590
|
return null;
|
|
16026
|
-
const packageDir =
|
|
16591
|
+
const packageDir = join46(distDir, "node_modules", ...packageSpecifier.split("/"));
|
|
16027
16592
|
const subpath = specifier.slice(packageSpecifier.length);
|
|
16028
|
-
const subPackageDir = subpath ?
|
|
16029
|
-
const resolvedPackageDir = subPackageDir && existsSync41(
|
|
16030
|
-
const packageJsonPath =
|
|
16593
|
+
const subPackageDir = subpath ? join46(packageDir, ...subpath.slice(1).split("/")) : null;
|
|
16594
|
+
const resolvedPackageDir = subPackageDir && existsSync41(join46(subPackageDir, "package.json")) ? subPackageDir : packageDir;
|
|
16595
|
+
const packageJsonPath = join46(resolvedPackageDir, "package.json");
|
|
16031
16596
|
if (!existsSync41(packageJsonPath))
|
|
16032
16597
|
return null;
|
|
16033
16598
|
const pkg = JSON.parse(readFileSync39(packageJsonPath, "utf-8"));
|
|
16034
16599
|
const exportKey = resolvedPackageDir !== subPackageDir && subpath ? `.${subpath}` : ".";
|
|
16035
16600
|
const rootExport = pkg.exports?.[exportKey];
|
|
16036
16601
|
const entry = pickExportEntry(rootExport) ?? (resolvedPackageDir === subPackageDir || !subpath ? pkg.module ?? pkg.main ?? "index.js" : `.${subpath}`);
|
|
16037
|
-
return
|
|
16602
|
+
return join46(resolvedPackageDir, entry);
|
|
16038
16603
|
}, RUNTIME_JS_EXTENSIONS, MODULE_SPECIFIER_RE, isRuntimeJsFile = (filePath) => RUNTIME_JS_EXTENSIONS.some((extension) => filePath.endsWith(extension)), isNodeModulesPath = (filePath) => filePath.split(/[\\/]/).includes("node_modules"), isFile = (filePath) => {
|
|
16039
16604
|
try {
|
|
16040
16605
|
return statSync7(filePath).isFile();
|
|
@@ -16047,16 +16612,16 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16047
16612
|
const candidates = [
|
|
16048
16613
|
candidate,
|
|
16049
16614
|
...RUNTIME_JS_EXTENSIONS.map((extension) => `${candidate}${extension}`),
|
|
16050
|
-
...RUNTIME_JS_EXTENSIONS.map((extension) =>
|
|
16615
|
+
...RUNTIME_JS_EXTENSIONS.map((extension) => join46(candidate, `index${extension}`))
|
|
16051
16616
|
];
|
|
16052
16617
|
return candidates.find((filePath) => isRuntimeJsFile(filePath) && isFile(filePath)) ?? null;
|
|
16053
16618
|
}, findContainingRuntimePackageDir = (filePath) => {
|
|
16054
|
-
let dir =
|
|
16055
|
-
while (dir !==
|
|
16056
|
-
if (isNodeModulesPath(dir) && existsSync41(
|
|
16619
|
+
let dir = dirname28(filePath);
|
|
16620
|
+
while (dir !== dirname28(dir)) {
|
|
16621
|
+
if (isNodeModulesPath(dir) && existsSync41(join46(dir, "package.json"))) {
|
|
16057
16622
|
return dir;
|
|
16058
16623
|
}
|
|
16059
|
-
dir =
|
|
16624
|
+
dir = dirname28(dir);
|
|
16060
16625
|
}
|
|
16061
16626
|
return null;
|
|
16062
16627
|
}, resolvePackageImportEntryFile = (fromFile, specifier) => {
|
|
@@ -16069,11 +16634,11 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16069
16634
|
const entry = pickExportEntry(pkg?.imports?.[specifier]);
|
|
16070
16635
|
if (!entry)
|
|
16071
16636
|
return null;
|
|
16072
|
-
return
|
|
16637
|
+
return join46(packageDir, entry);
|
|
16073
16638
|
}, collectRuntimeRewriteRoots = (distDir) => collectFiles2(distDir).filter((filePath) => isRuntimeJsFile(filePath) && !isNodeModulesPath(filePath)), toTopLevelPackage = (specifier) => specifier.split("/").slice(0, specifier.startsWith("@") ? 2 : 1).join("/"), FRAMEWORK_PACKAGE_NAME = "@absolutejs/absolute", copyChunkReferencedPackages = (distDir, seen) => {
|
|
16074
|
-
const distRoot =
|
|
16639
|
+
const distRoot = resolve37(distDir);
|
|
16075
16640
|
for (const filePath of collectRuntimeRewriteRoots(distDir)) {
|
|
16076
|
-
if (
|
|
16641
|
+
if (resolve37(dirname28(filePath)) === distRoot)
|
|
16077
16642
|
continue;
|
|
16078
16643
|
const source = readFileSync39(filePath, "utf-8");
|
|
16079
16644
|
for (const match of source.matchAll(MODULE_SPECIFIER_RE)) {
|
|
@@ -16109,7 +16674,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16109
16674
|
const { masked, restore } = maskLiterals(source);
|
|
16110
16675
|
const rewrittenMasked = masked.replace(MODULE_SPECIFIER_RE, (match, prefix, quote, specifier) => {
|
|
16111
16676
|
if (typeof specifier === "string" && specifier.startsWith(".")) {
|
|
16112
|
-
enqueue(resolveRuntimeJsFile(
|
|
16677
|
+
enqueue(resolveRuntimeJsFile(resolve37(dirname28(filePath), specifier)));
|
|
16113
16678
|
return match;
|
|
16114
16679
|
}
|
|
16115
16680
|
const packageImportTarget = resolveRuntimeJsFile(resolvePackageImportEntryFile(filePath, specifier) ?? "");
|
|
@@ -16130,7 +16695,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16130
16695
|
}
|
|
16131
16696
|
}, generateEntrypoint = (distDir, serverEntry, prerenderMap, version2, buildConfig) => {
|
|
16132
16697
|
const allFiles = collectFiles2(distDir);
|
|
16133
|
-
const serverBundleName = `${
|
|
16698
|
+
const serverBundleName = `${basename13(serverEntry).replace(/\.[^.]+$/, "")}.js`;
|
|
16134
16699
|
const embeddedSkip = new Set(["_compile_entrypoint.ts"]);
|
|
16135
16700
|
const assetSkip = new Set([
|
|
16136
16701
|
serverBundleName,
|
|
@@ -16138,12 +16703,12 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16138
16703
|
"_compile_entrypoint.ts"
|
|
16139
16704
|
]);
|
|
16140
16705
|
const embeddedFiles = allFiles.filter((file) => {
|
|
16141
|
-
const rel =
|
|
16706
|
+
const rel = relative24(distDir, file);
|
|
16142
16707
|
if (embeddedSkip.has(rel))
|
|
16143
16708
|
return false;
|
|
16144
16709
|
return true;
|
|
16145
16710
|
});
|
|
16146
|
-
const clientFiles = embeddedFiles.filter((file) => shouldEmbedCompiledAsset(
|
|
16711
|
+
const clientFiles = embeddedFiles.filter((file) => shouldEmbedCompiledAsset(relative24(distDir, file), assetSkip));
|
|
16147
16712
|
const imports = [];
|
|
16148
16713
|
const nativeImports = [];
|
|
16149
16714
|
const nativeMappings = [];
|
|
@@ -16153,19 +16718,19 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16153
16718
|
const nativeAssets = resolveCompileNativeAssets(buildConfig);
|
|
16154
16719
|
nativeAssets.forEach((asset, idx) => {
|
|
16155
16720
|
const varName = `__native${idx}`;
|
|
16156
|
-
const importSpecifier = asset.import.startsWith(".") ?
|
|
16721
|
+
const importSpecifier = asset.import.startsWith(".") ? resolve37(process.cwd(), asset.import) : asset.import;
|
|
16157
16722
|
nativeImports.push(`import ${varName} from ${JSON.stringify(importSpecifier)} with { type: "file" };`);
|
|
16158
16723
|
nativeMappings.push(` [${JSON.stringify(asset.env)}, resolveNativeAssetPath(${varName})],`);
|
|
16159
16724
|
});
|
|
16160
16725
|
embeddedFiles.forEach((filePath, idx) => {
|
|
16161
|
-
const rel =
|
|
16726
|
+
const rel = relative24(distDir, filePath).replace(/\\/g, "/");
|
|
16162
16727
|
const varName = `__a${idx}`;
|
|
16163
16728
|
embeddedVarMap.set(rel, varName);
|
|
16164
16729
|
imports.push(`import ${varName} from "./${rel}" with { type: "file" };`);
|
|
16165
16730
|
embeddedMappings.push(` ["${rel}", ${varName}],`);
|
|
16166
16731
|
});
|
|
16167
16732
|
clientFiles.forEach((filePath) => {
|
|
16168
|
-
const rel =
|
|
16733
|
+
const rel = relative24(distDir, filePath).replace(/\\/g, "/");
|
|
16169
16734
|
const varName = embeddedVarMap.get(rel);
|
|
16170
16735
|
if (!varName)
|
|
16171
16736
|
return;
|
|
@@ -16179,7 +16744,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
16179
16744
|
const pageVarMap = new Map;
|
|
16180
16745
|
const prerenderEntries = Array.from(prerenderMap.entries());
|
|
16181
16746
|
prerenderEntries.forEach(([route, filePath]) => {
|
|
16182
|
-
const rel =
|
|
16747
|
+
const rel = relative24(distDir, filePath).replace(/\\/g, "/");
|
|
16183
16748
|
const varName = embeddedVarMap.get(rel);
|
|
16184
16749
|
if (varName)
|
|
16185
16750
|
pageVarMap.set(route, varName);
|
|
@@ -16212,7 +16777,7 @@ import { buildGlobalWSHandler } from "elysia/ws";
|
|
|
16212
16777
|
const SERVER_MODULE = (runtimeDir: string) => import(pathToFileURL(join(runtimeDir, ${JSON.stringify(serverBundleName)})).href);
|
|
16213
16778
|
const RUNTIME_BUILD_ID = ${JSON.stringify(runtimeBuildId)};
|
|
16214
16779
|
const RUNTIME_CONFIG_SOURCE = ${JSON.stringify(runtimeConfigSource)};
|
|
16215
|
-
const ORIGINAL_BUILD_DIR = ${JSON.stringify(
|
|
16780
|
+
const ORIGINAL_BUILD_DIR = ${JSON.stringify(resolve37(distDir))};
|
|
16216
16781
|
const ORIGINAL_BUILD_DIR_NORMALIZED = ORIGINAL_BUILD_DIR.replace(/\\\\/g, "/");
|
|
16217
16782
|
const EMBEDDED_NATIVE_AUTH_CLIENTS = ${JSON.stringify(process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV])};
|
|
16218
16783
|
|
|
@@ -16633,17 +17198,17 @@ console.log(\`
|
|
|
16633
17198
|
});
|
|
16634
17199
|
}
|
|
16635
17200
|
}), compile = async (serverEntry, outdir, outfile, configPath2) => {
|
|
16636
|
-
const resolvedOutdir =
|
|
17201
|
+
const resolvedOutdir = resolve37(outdir ?? "dist");
|
|
16637
17202
|
await withBuildDirectoryLock(resolvedOutdir, () => compileUnlocked(serverEntry, resolvedOutdir, outfile, configPath2));
|
|
16638
17203
|
}, compileUnlocked = async (serverEntry, resolvedOutdir, outfile, configPath2) => {
|
|
16639
17204
|
const configuredPrerenderPort = env5.COMPILE_PORT === undefined ? Number(env5.PORT) : Number(env5.COMPILE_PORT);
|
|
16640
17205
|
const prerenderPort = configuredPrerenderPort > 0 ? configuredPrerenderPort : await findFreePort();
|
|
16641
17206
|
killStaleProcesses(prerenderPort);
|
|
16642
|
-
const entryName =
|
|
16643
|
-
const resolvedOutfile =
|
|
17207
|
+
const entryName = basename13(serverEntry).replace(/\.[^.]+$/, "");
|
|
17208
|
+
const resolvedOutfile = resolve37(outfile ?? "compiled-server");
|
|
16644
17209
|
const absoluteVersion = resolvePackageVersion3([
|
|
16645
|
-
|
|
16646
|
-
|
|
17210
|
+
resolve37(import.meta.dir, "..", "..", "..", "package.json"),
|
|
17211
|
+
resolve37(import.meta.dir, "..", "..", "package.json")
|
|
16647
17212
|
]);
|
|
16648
17213
|
compileBanner(absoluteVersion);
|
|
16649
17214
|
const totalStart = performance.now();
|
|
@@ -16656,8 +17221,8 @@ console.log(\`
|
|
|
16656
17221
|
installAbsoluteMobileAuthEnvironment(process.cwd(), normalizeAbsoluteMobileConfig(buildConfig.mobile, process.cwd()));
|
|
16657
17222
|
try {
|
|
16658
17223
|
const build2 = await resolveBuildModule3([
|
|
16659
|
-
|
|
16660
|
-
|
|
17224
|
+
resolve37(import.meta.dir, "..", "..", "core", "build"),
|
|
17225
|
+
resolve37(import.meta.dir, "..", "build")
|
|
16661
17226
|
]);
|
|
16662
17227
|
if (!build2)
|
|
16663
17228
|
throw new Error("Could not locate build module");
|
|
@@ -16679,11 +17244,11 @@ console.log(\`
|
|
|
16679
17244
|
buildConfig.htmxDirectory
|
|
16680
17245
|
].filter((dir) => Boolean(dir));
|
|
16681
17246
|
const islandRegistrySpec = buildConfig.islands?.registry;
|
|
16682
|
-
const islandRegistryPlugin = islandRegistrySpec ? createIslandRegistryDefinitionPlugin(await loadIslandRegistryBuildInfo(
|
|
16683
|
-
const serverBundleEntryDirectory =
|
|
17247
|
+
const islandRegistryPlugin = islandRegistrySpec ? createIslandRegistryDefinitionPlugin(await loadIslandRegistryBuildInfo(resolve37(islandRegistrySpec))) : undefined;
|
|
17248
|
+
const serverBundleEntryDirectory = join46(resolvedOutdir, ".absolutejs-server-entry");
|
|
16684
17249
|
mkdirSync18(serverBundleEntryDirectory, { recursive: true });
|
|
16685
|
-
const typeboxSetupEntry =
|
|
16686
|
-
const serverBundleEntry =
|
|
17250
|
+
const typeboxSetupEntry = join46(serverBundleEntryDirectory, "_typebox_setup.ts");
|
|
17251
|
+
const serverBundleEntry = join46(serverBundleEntryDirectory, basename13(serverEntry));
|
|
16687
17252
|
writeFileSync21(typeboxSetupEntry, `import { setupTypebox } from 'elysia';
|
|
16688
17253
|
import * as compile from 'typebox/compile';
|
|
16689
17254
|
import * as schema from 'typebox/schema';
|
|
@@ -16694,7 +17259,7 @@ import * as value from 'typebox/value';
|
|
|
16694
17259
|
setupTypebox({ typebox: { compile, schema, system, type, value } });
|
|
16695
17260
|
`);
|
|
16696
17261
|
writeFileSync21(serverBundleEntry, `import './_typebox_setup';
|
|
16697
|
-
import * as serverModule from ${JSON.stringify(
|
|
17262
|
+
import * as serverModule from ${JSON.stringify(resolve37(serverEntry))};
|
|
16698
17263
|
|
|
16699
17264
|
export const server = serverModule.server ?? serverModule.app ?? serverModule.default;
|
|
16700
17265
|
export default server;
|
|
@@ -16708,7 +17273,7 @@ export default server;
|
|
|
16708
17273
|
...islandRegistryPlugin ? [islandRegistryPlugin] : [],
|
|
16709
17274
|
...buildConfig.mobile ? [
|
|
16710
17275
|
createAbsoluteMobileRouteMetadataPlugin({
|
|
16711
|
-
entry:
|
|
17276
|
+
entry: resolve37(serverEntry)
|
|
16712
17277
|
})
|
|
16713
17278
|
] : [],
|
|
16714
17279
|
createElysiaOpenApiTypeboxPlugin(),
|
|
@@ -16732,13 +17297,13 @@ export default server;
|
|
|
16732
17297
|
console.error(cliTag4("\x1B[31m", "Server bundle failed."));
|
|
16733
17298
|
process.exit(1);
|
|
16734
17299
|
}
|
|
16735
|
-
const outputPath =
|
|
17300
|
+
const outputPath = resolve37(resolvedOutdir, `${entryName}.js`);
|
|
16736
17301
|
if (!existsSync41(outputPath)) {
|
|
16737
17302
|
console.error(cliTag4("\x1B[31m", `Expected output not found: ${outputPath}`));
|
|
16738
17303
|
process.exit(1);
|
|
16739
17304
|
}
|
|
16740
|
-
if (existsSync41(
|
|
16741
|
-
const vendorDir =
|
|
17305
|
+
if (existsSync41(resolve37(resolvedOutdir, "angular", "vendor", "server"))) {
|
|
17306
|
+
const vendorDir = resolve37(resolvedOutdir, "angular", "vendor", "server");
|
|
16742
17307
|
const vendorEntries = readdirSync7(vendorDir).filter((fileName) => fileName.endsWith(".js"));
|
|
16743
17308
|
const angularServerVendorPaths = {};
|
|
16744
17309
|
for (const file of vendorEntries) {
|
|
@@ -16747,7 +17312,7 @@ export default server;
|
|
|
16747
17312
|
if (scope !== "angular" || rest.length === 0)
|
|
16748
17313
|
continue;
|
|
16749
17314
|
const specifier = `@angular/${rest.join("/")}`;
|
|
16750
|
-
const relPath =
|
|
17315
|
+
const relPath = relative24(dirname28(outputPath), resolve37(vendorDir, file));
|
|
16751
17316
|
angularServerVendorPaths[specifier] = relPath.startsWith(".") ? relPath : `./${relPath}`;
|
|
16752
17317
|
}
|
|
16753
17318
|
if (Object.keys(angularServerVendorPaths).length > 0) {
|
|
@@ -16759,7 +17324,7 @@ export default server;
|
|
|
16759
17324
|
copyServerRuntimeAssetReferences(resolvedOutdir);
|
|
16760
17325
|
const prerenderStart = performance.now();
|
|
16761
17326
|
process.stdout.write(cliTag4("\x1B[36m", "Pre-rendering pages"));
|
|
16762
|
-
rmSync7(
|
|
17327
|
+
rmSync7(join46(resolvedOutdir, "_prerendered"), {
|
|
16763
17328
|
force: true,
|
|
16764
17329
|
recursive: true
|
|
16765
17330
|
});
|
|
@@ -16789,9 +17354,9 @@ export default server;
|
|
|
16789
17354
|
const compileStart = performance.now();
|
|
16790
17355
|
process.stdout.write(cliTag4("\x1B[36m", "Compiling standalone executable"));
|
|
16791
17356
|
const entrypointCode = generateEntrypoint(resolvedOutdir, serverEntry, prerenderMap, absoluteVersion, buildConfig);
|
|
16792
|
-
const entrypointPath =
|
|
17357
|
+
const entrypointPath = join46(resolvedOutdir, "_compile_entrypoint.ts");
|
|
16793
17358
|
await Bun.write(entrypointPath, entrypointCode);
|
|
16794
|
-
mkdirSync18(
|
|
17359
|
+
mkdirSync18(dirname28(resolvedOutfile), { recursive: true });
|
|
16795
17360
|
const result = await Bun.build({
|
|
16796
17361
|
compile: { outfile: resolvedOutfile },
|
|
16797
17362
|
define: { "process.env.NODE_ENV": '"production"' },
|
|
@@ -16820,7 +17385,7 @@ export default server;
|
|
|
16820
17385
|
const size = (Bun.file(resolvedOutfile).size / BYTES_PER_MB).toFixed(0);
|
|
16821
17386
|
const totalDuration = getDurationString(performance.now() - totalStart);
|
|
16822
17387
|
console.log(cliTag4("\x1B[32m", `Compiled to ${resolvedOutfile} (${size}MB) in ${totalDuration}`));
|
|
16823
|
-
console.log(cliTag4("\x1B[2m", `Run with: ./${
|
|
17388
|
+
console.log(cliTag4("\x1B[2m", `Run with: ./${basename13(resolvedOutfile)}`));
|
|
16824
17389
|
sendTelemetryEvent("compile:complete", {
|
|
16825
17390
|
durationMs: Math.round(performance.now() - totalStart),
|
|
16826
17391
|
entry: serverEntry,
|
|
@@ -16874,15 +17439,15 @@ var init_compile = __esm(() => {
|
|
|
16874
17439
|
});
|
|
16875
17440
|
|
|
16876
17441
|
// src/mobile/nativeDeepLinks.ts
|
|
16877
|
-
import { readFile as
|
|
16878
|
-
import { join as
|
|
17442
|
+
import { readFile as readFile13, rename as rename9, writeFile as writeFile10 } from "fs/promises";
|
|
17443
|
+
import { join as join47 } from "path";
|
|
16879
17444
|
var START_MARKER = "<!-- absolutejs:deep-links:start -->", END_MARKER = "<!-- absolutejs:deep-links:end -->", IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements", NOT_FOUND = -1, escapeXml = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">"), writeChangedFile = async (path, source) => {
|
|
16880
|
-
const current = await
|
|
17445
|
+
const current = await readFile13(path, "utf8");
|
|
16881
17446
|
if (current === source)
|
|
16882
17447
|
return false;
|
|
16883
17448
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
16884
|
-
await
|
|
16885
|
-
await
|
|
17449
|
+
await writeFile10(temporary, source, { flag: "wx" });
|
|
17450
|
+
await rename9(temporary, path);
|
|
16886
17451
|
return true;
|
|
16887
17452
|
}, replaceManagedRegion = (source, region, insertAt) => {
|
|
16888
17453
|
const start2 = source.indexOf(START_MARKER);
|
|
@@ -16924,8 +17489,8 @@ ${hosts}
|
|
|
16924
17489
|
${END_MARKER}
|
|
16925
17490
|
`;
|
|
16926
17491
|
}, configureAndroid = async (config) => {
|
|
16927
|
-
const path =
|
|
16928
|
-
const source = await
|
|
17492
|
+
const path = join47(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
17493
|
+
const source = await readFile13(path, "utf8");
|
|
16929
17494
|
const mainActivity = source.indexOf('android:name=".MainActivity"');
|
|
16930
17495
|
if (mainActivity === NOT_FOUND) {
|
|
16931
17496
|
throw new TypeError("Android MainActivity was not found.");
|
|
@@ -16948,8 +17513,8 @@ ${hosts}
|
|
|
16948
17513
|
</array>
|
|
16949
17514
|
${END_MARKER}
|
|
16950
17515
|
`, configureIosInfo = async (config) => {
|
|
16951
|
-
const path =
|
|
16952
|
-
const source = await
|
|
17516
|
+
const path = join47(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
17517
|
+
const source = await readFile13(path, "utf8");
|
|
16953
17518
|
const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
|
|
16954
17519
|
${END_MARKER}
|
|
16955
17520
|
`;
|
|
@@ -16970,10 +17535,10 @@ ${domains}
|
|
|
16970
17535
|
</plist>
|
|
16971
17536
|
`;
|
|
16972
17537
|
}, configureIosEntitlements = async (config) => {
|
|
16973
|
-
const path =
|
|
17538
|
+
const path = join47(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
16974
17539
|
let current = "";
|
|
16975
17540
|
try {
|
|
16976
|
-
current = await
|
|
17541
|
+
current = await readFile13(path, "utf8");
|
|
16977
17542
|
} catch (error) {
|
|
16978
17543
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
16979
17544
|
throw error;
|
|
@@ -16983,12 +17548,12 @@ ${domains}
|
|
|
16983
17548
|
if (current === source)
|
|
16984
17549
|
return false;
|
|
16985
17550
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
16986
|
-
await
|
|
16987
|
-
await
|
|
17551
|
+
await writeFile10(temporary, source, { flag: "wx" });
|
|
17552
|
+
await rename9(temporary, path);
|
|
16988
17553
|
return true;
|
|
16989
17554
|
}, configureIosProject = async (config) => {
|
|
16990
|
-
const path =
|
|
16991
|
-
const source = await
|
|
17555
|
+
const path = join47(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
17556
|
+
const source = await readFile13(path, "utf8");
|
|
16992
17557
|
const declarations = [
|
|
16993
17558
|
...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
|
|
16994
17559
|
].map((match) => match[1]);
|
|
@@ -17026,28 +17591,28 @@ ${domains}
|
|
|
17026
17591
|
var init_nativeDeepLinks = () => {};
|
|
17027
17592
|
|
|
17028
17593
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
17029
|
-
import { readFile as
|
|
17030
|
-
import { join as
|
|
17594
|
+
import { readFile as readFile14, rename as rename10, writeFile as writeFile11 } from "fs/promises";
|
|
17595
|
+
import { join as join48 } from "path";
|
|
17031
17596
|
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->", NOT_FOUND2 = -1, IOS_PRIVACY_FILE_REFERENCE = "A85D0C000000000000000001", IOS_PRIVACY_BUILD_FILE = "A85D0C000000000000000002", PUSH_START_MARKER = "absolutejs:push-notifications:start", PUSH_END_MARKER = "absolutejs:push-notifications:end", escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">"), writeChangedFile2 = async (path, source) => {
|
|
17032
|
-
const current = await
|
|
17597
|
+
const current = await readFile14(path, "utf8");
|
|
17033
17598
|
if (current === source)
|
|
17034
17599
|
return false;
|
|
17035
17600
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
17036
|
-
await
|
|
17037
|
-
await
|
|
17601
|
+
await writeFile11(temporary, source, { flag: "wx" });
|
|
17602
|
+
await rename10(temporary, path);
|
|
17038
17603
|
return true;
|
|
17039
17604
|
}, writeOptionalChangedFile = async (path, source) => {
|
|
17040
17605
|
const current = await optionalSource(path);
|
|
17041
17606
|
if (current === source)
|
|
17042
17607
|
return false;
|
|
17043
17608
|
if (current === null) {
|
|
17044
|
-
await
|
|
17609
|
+
await writeFile11(path, source, { flag: "wx" });
|
|
17045
17610
|
return true;
|
|
17046
17611
|
}
|
|
17047
17612
|
return writeChangedFile2(path, source);
|
|
17048
17613
|
}, optionalSource = async (path) => {
|
|
17049
17614
|
try {
|
|
17050
|
-
return await
|
|
17615
|
+
return await readFile14(path, "utf8");
|
|
17051
17616
|
} catch (error) {
|
|
17052
17617
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
17053
17618
|
return null;
|
|
@@ -17149,13 +17714,13 @@ ${entries}
|
|
|
17149
17714
|
return false;
|
|
17150
17715
|
if (current !== null)
|
|
17151
17716
|
return writeChangedFile2(path, source);
|
|
17152
|
-
await
|
|
17717
|
+
await writeFile11(path, source, { flag: "wx" });
|
|
17153
17718
|
return true;
|
|
17154
17719
|
}, configureIosPrivacyProject = async (config, requirements) => {
|
|
17155
17720
|
if (requirements.iosPrivacyAccessedApis.length === 0)
|
|
17156
17721
|
return false;
|
|
17157
|
-
const projectPath =
|
|
17158
|
-
const project = await
|
|
17722
|
+
const projectPath = join48(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
17723
|
+
const project = await readFile14(projectPath, "utf8");
|
|
17159
17724
|
return writeChangedFile2(projectPath, addIosPrivacyProjectReference(project));
|
|
17160
17725
|
}, addIosPrivacyProjectReference = (source) => {
|
|
17161
17726
|
const fileMatch = source.match(/([A-F0-9]{24}) \/\* PrivacyInfo\.xcprivacy \*\/ = \{isa = PBXFileReference;/u);
|
|
@@ -17205,8 +17770,8 @@ ${next.slice(index)}`;
|
|
|
17205
17770
|
}
|
|
17206
17771
|
return next;
|
|
17207
17772
|
}, configureIos2 = async (config, plan) => {
|
|
17208
|
-
const path =
|
|
17209
|
-
const source = await
|
|
17773
|
+
const path = join48(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
17774
|
+
const source = await readFile14(path, "utf8");
|
|
17210
17775
|
const requirements = absoluteDeviceNativeRequirements(plan);
|
|
17211
17776
|
const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
|
|
17212
17777
|
const ownedStart = source.indexOf(START_MARKER2);
|
|
@@ -17226,7 +17791,7 @@ ${content}
|
|
|
17226
17791
|
${END_MARKER2}
|
|
17227
17792
|
` : "";
|
|
17228
17793
|
const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
|
|
17229
|
-
const privacyPath =
|
|
17794
|
+
const privacyPath = join48(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
|
|
17230
17795
|
const privacyCurrent = await optionalSource(privacyPath);
|
|
17231
17796
|
const privacySource = privacyManifestSource(privacyCurrent, requirements);
|
|
17232
17797
|
const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
|
|
@@ -17236,7 +17801,7 @@ ${content}
|
|
|
17236
17801
|
]);
|
|
17237
17802
|
return infoChanged || privacyChanged || projectChanged || pushChanged;
|
|
17238
17803
|
}, configureIosPushNotifications = async (config, enabled) => {
|
|
17239
|
-
const entitlementsPath =
|
|
17804
|
+
const entitlementsPath = join48(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
17240
17805
|
const entitlements = await optionalSource(entitlementsPath);
|
|
17241
17806
|
if (entitlements === null && !enabled)
|
|
17242
17807
|
return false;
|
|
@@ -17248,7 +17813,7 @@ ${content}
|
|
|
17248
17813
|
<!-- ${PUSH_END_MARKER} -->
|
|
17249
17814
|
` : "";
|
|
17250
17815
|
const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
|
|
17251
|
-
const delegatePath =
|
|
17816
|
+
const delegatePath = join48(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
17252
17817
|
const delegate = await optionalSource(delegatePath);
|
|
17253
17818
|
if (delegate === null && !enabled)
|
|
17254
17819
|
return false;
|
|
@@ -17295,8 +17860,8 @@ ${content}
|
|
|
17295
17860
|
throw new TypeError("Could not find a safe native project location for push notifications.");
|
|
17296
17861
|
return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
|
|
17297
17862
|
}, configureAndroid2 = async (config, plan) => {
|
|
17298
|
-
const path =
|
|
17299
|
-
const source = await
|
|
17863
|
+
const path = join48(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
17864
|
+
const source = await readFile14(path, "utf8");
|
|
17300
17865
|
const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
|
|
17301
17866
|
const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
|
|
17302
17867
|
`);
|
|
@@ -17331,7 +17896,7 @@ ${content}
|
|
|
17331
17896
|
throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
|
|
17332
17897
|
const [manifestChanged, firebaseChanged] = await Promise.all([
|
|
17333
17898
|
writeChangedFile2(path, nextManifest),
|
|
17334
|
-
writeOptionalChangedFile(
|
|
17899
|
+
writeOptionalChangedFile(join48(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
|
|
17335
17900
|
]);
|
|
17336
17901
|
return manifestChanged || firebaseChanged;
|
|
17337
17902
|
}, applyAbsoluteNativeDeviceCapabilities = async (projectRoot, config, platforms = config.platforms, plan = resolveAbsoluteDeviceCapabilityPlan(projectRoot)) => {
|
|
@@ -17355,15 +17920,15 @@ var init_nativeDeviceCapabilities = __esm(() => {
|
|
|
17355
17920
|
});
|
|
17356
17921
|
|
|
17357
17922
|
// src/mobile/nativeBackgroundSync.ts
|
|
17358
|
-
import { readFile as
|
|
17359
|
-
import { join as
|
|
17923
|
+
import { readFile as readFile15, rename as rename11, writeFile as writeFile12 } from "fs/promises";
|
|
17924
|
+
import { join as join49 } from "path";
|
|
17360
17925
|
var writeChanged = async (path, source) => {
|
|
17361
|
-
const current = await
|
|
17926
|
+
const current = await readFile15(path, "utf8");
|
|
17362
17927
|
if (current === source)
|
|
17363
17928
|
return false;
|
|
17364
17929
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
17365
|
-
await
|
|
17366
|
-
await
|
|
17930
|
+
await writeFile12(temporary, source, { flag: "wx" });
|
|
17931
|
+
await rename11(temporary, path);
|
|
17367
17932
|
return true;
|
|
17368
17933
|
}, replaceRegion = (source, start2, end, region, insert) => {
|
|
17369
17934
|
const existingStart = source.indexOf(start2);
|
|
@@ -17439,11 +18004,11 @@ ${makeRegion(values)} </array>
|
|
|
17439
18004
|
if (!platforms.includes("ios") || !projectUsesAbsoluteAuth(projectRoot) || !projectUsesAbsoluteSync(projectRoot))
|
|
17440
18005
|
return { changed: false };
|
|
17441
18006
|
const identifier = `${config.appId}.absolutejs.background-sync`;
|
|
17442
|
-
const infoPath =
|
|
17443
|
-
const info2 = await
|
|
18007
|
+
const infoPath = join49(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
18008
|
+
const info2 = await readFile15(infoPath, "utf8");
|
|
17444
18009
|
const nextInfo = ensurePlistArrayValues(ensurePlistArrayValues(info2, "BGTaskSchedulerPermittedIdentifiers", [identifier], "background-sync-identifiers"), "UIBackgroundModes", ["fetch", "processing"], "background-sync-modes");
|
|
17445
|
-
const delegatePath =
|
|
17446
|
-
let delegate = await
|
|
18010
|
+
const delegatePath = join49(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
18011
|
+
let delegate = await readFile15(delegatePath, "utf8");
|
|
17447
18012
|
if (!delegate.includes("import AbsoluteSyncCapacitor")) {
|
|
17448
18013
|
const importIndex = delegate.lastIndexOf("import Capacitor");
|
|
17449
18014
|
if (importIndex < 0)
|
|
@@ -17475,14 +18040,14 @@ var init_nativeBackgroundSync = __esm(() => {
|
|
|
17475
18040
|
|
|
17476
18041
|
// src/mobile/associationFiles.ts
|
|
17477
18042
|
import {
|
|
17478
|
-
access as
|
|
17479
|
-
mkdir as
|
|
17480
|
-
readFile as
|
|
17481
|
-
rename as
|
|
17482
|
-
rm as
|
|
17483
|
-
writeFile as
|
|
18043
|
+
access as access8,
|
|
18044
|
+
mkdir as mkdir11,
|
|
18045
|
+
readFile as readFile16,
|
|
18046
|
+
rename as rename12,
|
|
18047
|
+
rm as rm8,
|
|
18048
|
+
writeFile as writeFile13
|
|
17484
18049
|
} from "fs/promises";
|
|
17485
|
-
import { resolve as
|
|
18050
|
+
import { resolve as resolve38 } from "path";
|
|
17486
18051
|
import { Elysia } from "elysia";
|
|
17487
18052
|
var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERIFY_TIMEOUT_MS = 1e4, ANDROID_ASSOCIATION_PATH = "/.well-known/assetlinks.json", APPLE_ASSOCIATION_PATH = "/.well-known/apple-app-site-association", missingIdentity = (field, platform6) => new TypeError(`${field} is required to publish ${platform6} deep-link association files.`), createAppleDocument = (config, requireAll) => {
|
|
17488
18053
|
if (!config.platforms.includes("ios"))
|
|
@@ -17535,7 +18100,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
17535
18100
|
}, writeAtomic = async (path, source) => {
|
|
17536
18101
|
let current;
|
|
17537
18102
|
try {
|
|
17538
|
-
current = await
|
|
18103
|
+
current = await readFile16(path, "utf8");
|
|
17539
18104
|
} catch (error) {
|
|
17540
18105
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
17541
18106
|
throw error;
|
|
@@ -17544,21 +18109,21 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
17544
18109
|
if (current === source)
|
|
17545
18110
|
return false;
|
|
17546
18111
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
17547
|
-
await
|
|
17548
|
-
await
|
|
18112
|
+
await writeFile13(temporary, source, { flag: "wx" });
|
|
18113
|
+
await rename12(temporary, path);
|
|
17549
18114
|
return true;
|
|
17550
|
-
},
|
|
18115
|
+
}, exists3 = async (path) => {
|
|
17551
18116
|
try {
|
|
17552
|
-
await
|
|
18117
|
+
await access8(path);
|
|
17553
18118
|
return true;
|
|
17554
18119
|
} catch {
|
|
17555
18120
|
return false;
|
|
17556
18121
|
}
|
|
17557
18122
|
}, assertOwnedOutput = async (root) => {
|
|
17558
|
-
const path =
|
|
18123
|
+
const path = resolve38(root, OWNERSHIP_FILE);
|
|
17559
18124
|
let ownership;
|
|
17560
18125
|
try {
|
|
17561
|
-
ownership = JSON.parse(await
|
|
18126
|
+
ownership = JSON.parse(await readFile16(path, "utf8"));
|
|
17562
18127
|
} catch {
|
|
17563
18128
|
throw new TypeError(`Association output ${root} already exists and is not owned by AbsoluteJS.`);
|
|
17564
18129
|
}
|
|
@@ -17566,26 +18131,26 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
17566
18131
|
throw new TypeError(`Association output ${root} has an unsupported ownership manifest.`);
|
|
17567
18132
|
}
|
|
17568
18133
|
}, publishGeneratedDirectory = async (temporary, root) => {
|
|
17569
|
-
const hasCurrent = await
|
|
18134
|
+
const hasCurrent = await exists3(root);
|
|
17570
18135
|
if (hasCurrent)
|
|
17571
18136
|
await assertOwnedOutput(root);
|
|
17572
18137
|
const backup = `${root}.${crypto.randomUUID()}.previous`;
|
|
17573
18138
|
if (hasCurrent)
|
|
17574
|
-
await
|
|
18139
|
+
await rename12(root, backup);
|
|
17575
18140
|
try {
|
|
17576
|
-
await
|
|
18141
|
+
await rename12(temporary, root);
|
|
17577
18142
|
} catch (error) {
|
|
17578
18143
|
if (hasCurrent)
|
|
17579
|
-
await
|
|
18144
|
+
await rename12(backup, root);
|
|
17580
18145
|
throw error;
|
|
17581
18146
|
}
|
|
17582
18147
|
if (hasCurrent)
|
|
17583
|
-
await
|
|
18148
|
+
await rm8(backup, { force: true, recursive: true });
|
|
17584
18149
|
}, materializeHost = async (root, host2, files) => {
|
|
17585
|
-
const directory =
|
|
17586
|
-
await
|
|
18150
|
+
const directory = resolve38(root, host2, ".well-known");
|
|
18151
|
+
await mkdir11(directory, { recursive: true });
|
|
17587
18152
|
return Promise.all(files.map(async ([name, document]) => {
|
|
17588
|
-
const path =
|
|
18153
|
+
const path = resolve38(directory, name);
|
|
17589
18154
|
await writeAtomic(path, `${JSON.stringify(document, null, 2)}
|
|
17590
18155
|
`);
|
|
17591
18156
|
return path;
|
|
@@ -17608,7 +18173,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
17608
18173
|
});
|
|
17609
18174
|
return endpoints;
|
|
17610
18175
|
}), materializeAbsoluteMobileAssociationFiles = async (config, outputDirectory) => {
|
|
17611
|
-
const root =
|
|
18176
|
+
const root = resolve38(outputDirectory);
|
|
17612
18177
|
const temporary = `${root}.${crypto.randomUUID()}.tmp`;
|
|
17613
18178
|
const documents = createAbsoluteMobileAssociationDocuments(config, {
|
|
17614
18179
|
requireAll: true
|
|
@@ -17619,16 +18184,16 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
17619
18184
|
if (documents.apple) {
|
|
17620
18185
|
files.push(["apple-app-site-association", documents.apple]);
|
|
17621
18186
|
}
|
|
17622
|
-
await
|
|
18187
|
+
await mkdir11(temporary, { recursive: true });
|
|
17623
18188
|
try {
|
|
17624
18189
|
const temporaryPaths = (await Promise.all(config.deepLinkHosts.map((host2) => materializeHost(temporary, host2, files)))).flat();
|
|
17625
|
-
await writeAtomic(
|
|
18190
|
+
await writeAtomic(resolve38(temporary, OWNERSHIP_FILE), `${JSON.stringify({ format: 1, hosts: config.deepLinkHosts }, null, 2)}
|
|
17626
18191
|
`);
|
|
17627
18192
|
await publishGeneratedDirectory(temporary, root);
|
|
17628
|
-
const written = temporaryPaths.map((path) =>
|
|
18193
|
+
const written = temporaryPaths.map((path) => resolve38(root, path.slice(temporary.length + 1)));
|
|
17629
18194
|
return { root, written };
|
|
17630
18195
|
} catch (error) {
|
|
17631
|
-
await
|
|
18196
|
+
await rm8(temporary, { force: true, recursive: true });
|
|
17632
18197
|
throw error;
|
|
17633
18198
|
}
|
|
17634
18199
|
}, verifyAbsoluteMobileAssociationFiles = async (config, request = globalThis.fetch) => {
|
|
@@ -17666,8 +18231,8 @@ var init_associationFiles = __esm(() => {
|
|
|
17666
18231
|
});
|
|
17667
18232
|
|
|
17668
18233
|
// src/mobile/androidWebView.ts
|
|
17669
|
-
import { mkdir as
|
|
17670
|
-
import { dirname as
|
|
18234
|
+
import { mkdir as mkdir12, writeFile as writeFile14 } from "fs/promises";
|
|
18235
|
+
import { dirname as dirname29, resolve as resolve39 } from "path";
|
|
17671
18236
|
|
|
17672
18237
|
class CdpConnection {
|
|
17673
18238
|
diagnostics = [];
|
|
@@ -17938,9 +18503,9 @@ var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POL
|
|
|
17938
18503
|
if (typeof data !== "string") {
|
|
17939
18504
|
throw new Error("Android WebView screenshot returned no image data.");
|
|
17940
18505
|
}
|
|
17941
|
-
const absolutePath =
|
|
17942
|
-
await
|
|
17943
|
-
await
|
|
18506
|
+
const absolutePath = resolve39(path);
|
|
18507
|
+
await mkdir12(dirname29(absolutePath), { recursive: true });
|
|
18508
|
+
await writeFile14(absolutePath, Buffer.from(data, "base64"));
|
|
17944
18509
|
return absolutePath;
|
|
17945
18510
|
},
|
|
17946
18511
|
tap: async (coordinateX, coordinateY) => {
|
|
@@ -18071,21 +18636,21 @@ var DEFAULT_ROUTE_TIMEOUT_MS = 30000, DEFAULT_HMR_TIMEOUT_MS = 30000, routeExpre
|
|
|
18071
18636
|
};
|
|
18072
18637
|
|
|
18073
18638
|
// src/mobile/mobileBundleInspection.ts
|
|
18074
|
-
import { createHash as
|
|
18075
|
-
import { access as
|
|
18076
|
-
import { join as
|
|
18639
|
+
import { createHash as createHash13 } from "crypto";
|
|
18640
|
+
import { access as access9, readFile as readFile17, stat as stat2 } from "fs/promises";
|
|
18641
|
+
import { join as join50, relative as relative25, resolve as resolve40 } from "path";
|
|
18077
18642
|
var MOBILE_FRAMEWORKS, SHA256_PATTERN, isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), portablePath = (projectRoot, path) => {
|
|
18078
|
-
const value =
|
|
18643
|
+
const value = relative25(resolve40(projectRoot), resolve40(path)).replaceAll("\\", "/");
|
|
18079
18644
|
return value || ".";
|
|
18080
18645
|
}, pathExists5 = async (path) => {
|
|
18081
18646
|
try {
|
|
18082
|
-
await
|
|
18647
|
+
await access9(path);
|
|
18083
18648
|
return true;
|
|
18084
18649
|
} catch {
|
|
18085
18650
|
return false;
|
|
18086
18651
|
}
|
|
18087
18652
|
}, readObject = async (path) => {
|
|
18088
|
-
const value = JSON.parse(await
|
|
18653
|
+
const value = JSON.parse(await readFile17(path, "utf8"));
|
|
18089
18654
|
if (!isObject2(value))
|
|
18090
18655
|
throw new TypeError("JSON root must be an object.");
|
|
18091
18656
|
return value;
|
|
@@ -18099,8 +18664,8 @@ var MOBILE_FRAMEWORKS, SHA256_PATTERN, isObject2 = (value) => typeof value === "
|
|
|
18099
18664
|
return value;
|
|
18100
18665
|
}, requireBundleFile = async (root, value, field, expectedHash) => {
|
|
18101
18666
|
const portable = requireString(value, field);
|
|
18102
|
-
const path =
|
|
18103
|
-
const normalizedRoot =
|
|
18667
|
+
const path = resolve40(root, portable);
|
|
18668
|
+
const normalizedRoot = resolve40(root);
|
|
18104
18669
|
if (path === normalizedRoot || !path.startsWith(`${normalizedRoot}/`))
|
|
18105
18670
|
throw new TypeError(`${field} must remain inside the mobile bundle.`);
|
|
18106
18671
|
if (!(await stat2(path).catch(() => {
|
|
@@ -18110,13 +18675,13 @@ var MOBILE_FRAMEWORKS, SHA256_PATTERN, isObject2 = (value) => typeof value === "
|
|
|
18110
18675
|
if (expectedHash !== undefined) {
|
|
18111
18676
|
if (!SHA256_PATTERN.test(expectedHash))
|
|
18112
18677
|
throw new TypeError(`${field} has an invalid SHA-256 digest.`);
|
|
18113
|
-
const actual =
|
|
18678
|
+
const actual = createHash13("sha256").update(await readFile17(path)).digest("hex");
|
|
18114
18679
|
if (actual !== expectedHash)
|
|
18115
18680
|
throw new TypeError(`${field} failed its SHA-256 integrity check.`);
|
|
18116
18681
|
}
|
|
18117
18682
|
return portable;
|
|
18118
18683
|
}, inspectAbsoluteMobileBundle = async (config, projectRoot) => {
|
|
18119
|
-
const manifestPath =
|
|
18684
|
+
const manifestPath = join50(config.bundleDirectory, "absolute-mobile-manifest.json");
|
|
18120
18685
|
const manifest = portablePath(projectRoot, manifestPath);
|
|
18121
18686
|
if (!await pathExists5(manifestPath))
|
|
18122
18687
|
return { manifest, status: "missing" };
|
|
@@ -18216,11 +18781,11 @@ var init_mobileBundleInspection = __esm(() => {
|
|
|
18216
18781
|
});
|
|
18217
18782
|
|
|
18218
18783
|
// src/mobile/releaseDoctor.ts
|
|
18219
|
-
import { access as
|
|
18220
|
-
import { dirname as
|
|
18784
|
+
import { access as access10, readFile as readFile18, readdir as readdir5 } from "fs/promises";
|
|
18785
|
+
import { dirname as dirname30, extname as extname8, join as join51, relative as relative26 } from "path";
|
|
18221
18786
|
var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, EXACT_VERSION_PATTERN, NOT_FOUND3 = -1, LOCK_FILES, MANUAL_REVIEW, pathExists6 = async (path) => {
|
|
18222
18787
|
try {
|
|
18223
|
-
await
|
|
18788
|
+
await access10(path);
|
|
18224
18789
|
return true;
|
|
18225
18790
|
} catch {
|
|
18226
18791
|
return false;
|
|
@@ -18230,13 +18795,13 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18230
18795
|
return findHmrAsset(path);
|
|
18231
18796
|
if (!isFile2 || !RELEASE_ASSET_EXTENSIONS.has(extname8(path)))
|
|
18232
18797
|
return;
|
|
18233
|
-
const source = await
|
|
18798
|
+
const source = await readFile18(path, "utf8");
|
|
18234
18799
|
return HMR_ASSET_PATTERN.test(source) ? path : undefined;
|
|
18235
18800
|
}, findHmrAsset = async (root) => {
|
|
18236
18801
|
if (!await pathExists6(root))
|
|
18237
18802
|
return;
|
|
18238
|
-
const entries = await
|
|
18239
|
-
const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(
|
|
18803
|
+
const entries = await readdir5(root, { withFileTypes: true });
|
|
18804
|
+
const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(join51(root, entry.name), entry.isDirectory(), entry.isFile())));
|
|
18240
18805
|
return matches.find((match) => match !== undefined);
|
|
18241
18806
|
}, pass = (id, detail, path) => ({ detail, id, path, status: "pass" }), fail5 = (id, detail, path, remediation) => ({
|
|
18242
18807
|
detail,
|
|
@@ -18251,7 +18816,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18251
18816
|
remediation,
|
|
18252
18817
|
status: "warn"
|
|
18253
18818
|
}), readJsonObject = async (path) => {
|
|
18254
|
-
const value = JSON.parse(await
|
|
18819
|
+
const value = JSON.parse(await readFile18(path, "utf8"));
|
|
18255
18820
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
18256
18821
|
throw new TypeError("JSON root must be an object.");
|
|
18257
18822
|
return Object.fromEntries(Object.entries(value));
|
|
@@ -18267,7 +18832,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18267
18832
|
}
|
|
18268
18833
|
return declarations;
|
|
18269
18834
|
}, versionCore = (version2) => version2.split("-")[0]?.split(".").slice(0, 2).join("."), capacitorVersionCheck = async (config, projectRoot) => {
|
|
18270
|
-
const manifestPath =
|
|
18835
|
+
const manifestPath = join51(projectRoot, "package.json");
|
|
18271
18836
|
try {
|
|
18272
18837
|
const manifest = await readJsonObject(manifestPath);
|
|
18273
18838
|
const declarations = packageDeclarations(manifest);
|
|
@@ -18280,7 +18845,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18280
18845
|
const declared = declarations.get(name);
|
|
18281
18846
|
if (!declared || !EXACT_VERSION_PATTERN.test(declared))
|
|
18282
18847
|
throw new TypeError(`${name} must be a direct exact dependency.`);
|
|
18283
|
-
const installed = await readJsonObject(
|
|
18848
|
+
const installed = await readJsonObject(join51(projectRoot, "node_modules", name, "package.json"));
|
|
18284
18849
|
if (installed.version !== declared)
|
|
18285
18850
|
throw new TypeError(`${name} does not match its installed version.`);
|
|
18286
18851
|
return declared;
|
|
@@ -18294,10 +18859,10 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18294
18859
|
}
|
|
18295
18860
|
}, dependencyLockCheck = async (projectRoot) => {
|
|
18296
18861
|
const present = (await Promise.all(LOCK_FILES.map(async (name) => ({
|
|
18297
|
-
exists: await pathExists6(
|
|
18862
|
+
exists: await pathExists6(join51(projectRoot, name)),
|
|
18298
18863
|
name
|
|
18299
|
-
})))).find(({ exists:
|
|
18300
|
-
return present ? pass("mobile.dependency-lock", `Dependency graph is locked by ${present.name}.`,
|
|
18864
|
+
})))).find(({ exists: exists4 }) => exists4);
|
|
18865
|
+
return present ? pass("mobile.dependency-lock", `Dependency graph is locked by ${present.name}.`, join51(projectRoot, present.name)) : fail5("mobile.dependency-lock", "No supported dependency lockfile is present.", projectRoot, "Install dependencies with the project package manager and commit its lockfile before release.");
|
|
18301
18866
|
}, productionOriginCheck = (config, projectRoot) => {
|
|
18302
18867
|
const origin = new URL(config.productionOrigin);
|
|
18303
18868
|
return origin.protocol === "https:" ? pass("mobile.production-origin", "Production transport uses an HTTPS origin.") : fail5("mobile.production-origin", "A loopback development origin cannot be used for a signed release.", projectRoot, "Configure mobile.server.productionOrigin with the deployed HTTPS origin.");
|
|
@@ -18332,7 +18897,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18332
18897
|
if (!await pathExists6(nativeConfigPath)) {
|
|
18333
18898
|
return fail5("android.capacitor-config", "The generated Android Capacitor config is missing.", nativeConfigPath, "Run `absolute mobile sync android` before release validation.");
|
|
18334
18899
|
}
|
|
18335
|
-
const unsafe = isUnsafeCapacitorConfig(await
|
|
18900
|
+
const unsafe = isUnsafeCapacitorConfig(await readFile18(nativeConfigPath, "utf8"));
|
|
18336
18901
|
return unsafe ? fail5("android.capacitor-config", "Android Capacitor config contains a development server URL, cleartext transport, navigation allowlist, or invalid JSON.", nativeConfigPath, "Run `absolute mobile sync android`; do not ship development transport overrides.") : pass("android.capacitor-config", "Android Capacitor config contains no development transport overrides.", nativeConfigPath);
|
|
18337
18902
|
}, capacitorIdentityCheck = async (config, platform6, nativeConfigPath) => {
|
|
18338
18903
|
try {
|
|
@@ -18347,12 +18912,12 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18347
18912
|
if (!await pathExists6(manifestPath)) {
|
|
18348
18913
|
return fail5("android.cleartext", "The Android manifest is missing.", manifestPath, "Run `absolute mobile sync android` before release validation.");
|
|
18349
18914
|
}
|
|
18350
|
-
const source = await
|
|
18915
|
+
const source = await readFile18(manifestPath, "utf8");
|
|
18351
18916
|
const cleartext = /android:usesCleartextTraffic=["']true["']/u.test(source);
|
|
18352
18917
|
const networkConfigName = source.match(/android:networkSecurityConfig=["']@xml\/([a-z0-9_]+)["']/u)?.[1];
|
|
18353
|
-
const networkConfigPath = networkConfigName ?
|
|
18918
|
+
const networkConfigPath = networkConfigName ? join51(dirname30(manifestPath), "res", "xml", `${networkConfigName}.xml`) : undefined;
|
|
18354
18919
|
const developmentTrustReference = /android:networkSecurityConfig=["']@xml\/absolutejs_dev_network_security["']/u.test(source);
|
|
18355
|
-
const developmentTrustContents = networkConfigPath ? await
|
|
18920
|
+
const developmentTrustContents = networkConfigPath ? await readFile18(networkConfigPath, "utf8").then((value) => value.includes("@raw/absolutejs_dev_ca")).catch(() => false) : false;
|
|
18356
18921
|
const developmentTrust = developmentTrustReference || developmentTrustContents;
|
|
18357
18922
|
return cleartext || developmentTrust ? fail5("android.cleartext", developmentTrust ? "Android still references the AbsoluteJS development certificate authority." : "Android explicitly permits cleartext traffic.", manifestPath, "Run `absolute mobile sync android`; do not ship development transport or trust overrides.") : pass("android.cleartext", "Android does not explicitly permit cleartext traffic.", manifestPath);
|
|
18358
18923
|
}, hmrAssetsReleaseCheck = async (publicRoot) => {
|
|
@@ -18361,12 +18926,12 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18361
18926
|
}, embeddedBundleReleaseCheck = async (config, projectRoot, platform6, publicRoot) => {
|
|
18362
18927
|
const inspection = await inspectAbsoluteMobileBundle({ ...config, bundleDirectory: publicRoot }, projectRoot);
|
|
18363
18928
|
if (inspection.status === "valid")
|
|
18364
|
-
return pass(`${platform6}.bundle-integrity`, `Packaged mobile manifest, runtime, routes, and ${inspection.pageCount ?? 0} page asset(s) passed structural and SHA-256 validation.`,
|
|
18365
|
-
return fail5(`${platform6}.bundle-integrity`, inspection.status === "missing" ? "The packaged mobile manifest is missing." : `The packaged mobile bundle is invalid: ${inspection.issue ?? "unknown validation error"}`,
|
|
18929
|
+
return pass(`${platform6}.bundle-integrity`, `Packaged mobile manifest, runtime, routes, and ${inspection.pageCount ?? 0} page asset(s) passed structural and SHA-256 validation.`, join51(publicRoot, "absolute-mobile-manifest.json"));
|
|
18930
|
+
return fail5(`${platform6}.bundle-integrity`, inspection.status === "missing" ? "The packaged mobile manifest is missing." : `The packaged mobile bundle is invalid: ${inspection.issue ?? "unknown validation error"}`, join51(publicRoot, "absolute-mobile-manifest.json"), "Rebuild the production mobile bundle and run Capacitor sync for this platform.");
|
|
18366
18931
|
}, contentSecurityPolicyCheck = async (config, platform6, publicRoot) => {
|
|
18367
|
-
const path =
|
|
18932
|
+
const path = join51(publicRoot, "index.html");
|
|
18368
18933
|
try {
|
|
18369
|
-
const source = await
|
|
18934
|
+
const source = await readFile18(path, "utf8");
|
|
18370
18935
|
const requirements = [
|
|
18371
18936
|
"Content-Security-Policy",
|
|
18372
18937
|
"default-src 'self'",
|
|
@@ -18387,18 +18952,18 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18387
18952
|
if (!await pathExists6(root))
|
|
18388
18953
|
return [];
|
|
18389
18954
|
const files = await Array.fromAsync(new Bun.Glob("**/*").scan({ cwd: root, onlyFiles: true }));
|
|
18390
|
-
return files.filter((file) => extensions.has(extname8(file))).map((file) =>
|
|
18955
|
+
return files.filter((file) => extensions.has(extname8(file))).map((file) => join51(root, file));
|
|
18391
18956
|
}, containsPattern = async (paths, pattern) => {
|
|
18392
|
-
const sources = await Promise.all(paths.map((path) =>
|
|
18957
|
+
const sources = await Promise.all(paths.map((path) => readFile18(path, "utf8")));
|
|
18393
18958
|
const index = sources.findIndex((source) => pattern.test(source));
|
|
18394
18959
|
return index === NOT_FOUND3 ? undefined : paths[index];
|
|
18395
18960
|
}, androidNativeSecurityCheck = async (androidRoot) => {
|
|
18396
|
-
const manifestPath =
|
|
18961
|
+
const manifestPath = join51(androidRoot, "app/src/main/AndroidManifest.xml");
|
|
18397
18962
|
try {
|
|
18398
|
-
const manifest = await
|
|
18963
|
+
const manifest = await readFile18(manifestPath, "utf8");
|
|
18399
18964
|
if (/android:debuggable=["']true["']/u.test(manifest))
|
|
18400
18965
|
throw new TypeError("Android release manifest explicitly enables application debugging.");
|
|
18401
|
-
const sources = await sourceFiles(
|
|
18966
|
+
const sources = await sourceFiles(join51(androidRoot, "app/src/main"), new Set([".java", ".kt"]));
|
|
18402
18967
|
const debugSource = await containsPattern(sources, /setWebContentsDebuggingEnabled\s*\(\s*true\s*\)/u);
|
|
18403
18968
|
if (debugSource)
|
|
18404
18969
|
return fail5("android.native-debugging", "Android application source unconditionally enables WebView debugging.", debugSource, "Remove the unconditional WebView debugging call; use the platform debug-build behavior during development.");
|
|
@@ -18407,14 +18972,14 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18407
18972
|
return fail5("android.native-debugging", error instanceof Error ? error.message : "Android native debugging configuration could not be validated.", manifestPath, "Remove explicit release debugging settings and rerun mobile sync.");
|
|
18408
18973
|
}
|
|
18409
18974
|
}, androidExportedComponentsCheck = async (manifestPath) => {
|
|
18410
|
-
const source = await
|
|
18975
|
+
const source = await readFile18(manifestPath, "utf8").catch(() => "");
|
|
18411
18976
|
const exported = [
|
|
18412
18977
|
...source.matchAll(/<(?:activity|activity-alias|provider|receiver|service)\b[^>]*>/giu)
|
|
18413
18978
|
].map(([tag]) => tag).filter((tag) => /android:exported=["']true["']/iu.test(tag)).map((tag) => tag.match(/android:name=["']([^"']+)["']/iu)?.[1]).filter((name) => Boolean(name) && name !== ".MainActivity");
|
|
18414
18979
|
return exported.length === 0 ? pass("android.exported-components", "No non-launcher Android component is explicitly exported.", manifestPath) : warn("android.exported-components", `${exported.length} non-launcher Android component(s) are exported and require manual authorization review.`, manifestPath, "Confirm each exported component is intentional, permission-protected where appropriate, and documented in the mobile threat model review.");
|
|
18415
18980
|
}, androidDeepLinkProjectionCheck = async (config, manifestPath) => {
|
|
18416
18981
|
try {
|
|
18417
|
-
const source = await
|
|
18982
|
+
const source = await readFile18(manifestPath, "utf8");
|
|
18418
18983
|
const required = [
|
|
18419
18984
|
'android:autoVerify="true"',
|
|
18420
18985
|
"android.intent.category.BROWSABLE",
|
|
@@ -18428,24 +18993,24 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18428
18993
|
return fail5("android.deep-links", error instanceof Error ? error.message : "Android deep-link projection could not be validated.", manifestPath, "Run `absolute mobile sync android` and review the AbsoluteJS-owned deep-link region.");
|
|
18429
18994
|
}
|
|
18430
18995
|
}, iosNativeSecurityCheck = async (iosRoot) => {
|
|
18431
|
-
const entitlementsPath =
|
|
18432
|
-
const entitlements = await
|
|
18996
|
+
const entitlementsPath = join51(iosRoot, "App/AbsoluteJS.entitlements");
|
|
18997
|
+
const entitlements = await readFile18(entitlementsPath, "utf8").catch(() => "");
|
|
18433
18998
|
if (/<key>get-task-allow<\/key>\s*<true\s*\/>/u.test(entitlements) || /<key>com\.apple\.security\.get-task-allow<\/key>\s*<true\s*\/>/u.test(entitlements))
|
|
18434
18999
|
return fail5("ios.native-debugging", "iOS source entitlements explicitly permit debugger attachment.", entitlementsPath, "Remove get-task-allow from source entitlements; Xcode supplies development entitlements only to debug builds.");
|
|
18435
|
-
const sources = await sourceFiles(
|
|
19000
|
+
const sources = await sourceFiles(join51(iosRoot, "App"), new Set([".m", ".mm", ".swift"]));
|
|
18436
19001
|
const debugSource = await containsPattern(sources, /\.isInspectable\s*=\s*true|setInspectable\s*\(\s*true\s*\)/u);
|
|
18437
19002
|
if (debugSource)
|
|
18438
19003
|
return fail5("ios.native-debugging", "iOS application source unconditionally enables WebView inspection.", debugSource, "Remove unconditional WebView inspection from release source.");
|
|
18439
19004
|
return pass("ios.native-debugging", "iOS source does not enable release debugger attachment or WebView inspection.", entitlementsPath);
|
|
18440
19005
|
}, iosDeepLinkProjectionCheck = async (config, iosRoot) => {
|
|
18441
|
-
const infoPath =
|
|
18442
|
-
const entitlementsPath =
|
|
18443
|
-
const projectPath =
|
|
19006
|
+
const infoPath = join51(iosRoot, "App/App/Info.plist");
|
|
19007
|
+
const entitlementsPath = join51(iosRoot, "App/AbsoluteJS.entitlements");
|
|
19008
|
+
const projectPath = join51(iosRoot, "App/App.xcodeproj/project.pbxproj");
|
|
18444
19009
|
try {
|
|
18445
19010
|
const [info2, entitlements, project] = await Promise.all([
|
|
18446
|
-
|
|
18447
|
-
|
|
18448
|
-
|
|
19011
|
+
readFile18(infoPath, "utf8"),
|
|
19012
|
+
readFile18(entitlementsPath, "utf8"),
|
|
19013
|
+
readFile18(projectPath, "utf8")
|
|
18449
19014
|
]);
|
|
18450
19015
|
if (config.deepLinkScheme && (!info2.includes("<key>CFBundleURLTypes</key>") || !info2.includes(`<string>${config.deepLinkScheme}</string>`)))
|
|
18451
19016
|
throw new TypeError("iOS custom URL scheme does not match mobile config.");
|
|
@@ -18460,7 +19025,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18460
19025
|
}, syncSchemaReleaseCheck = (projectRoot) => {
|
|
18461
19026
|
if (!projectUsesAbsoluteSync(projectRoot))
|
|
18462
19027
|
return;
|
|
18463
|
-
const manifestPath =
|
|
19028
|
+
const manifestPath = join51(projectRoot, "package.json");
|
|
18464
19029
|
try {
|
|
18465
19030
|
const schema = discoverAbsoluteSyncSchema(projectRoot);
|
|
18466
19031
|
const versions = schema.components.map((component2) => `${component2.id}@${component2.version}`).join(", ");
|
|
@@ -18482,8 +19047,8 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18482
19047
|
}, IOS_USAGE_KEYS, androidDevicePermissionCheck = async (config, permissions) => {
|
|
18483
19048
|
if (!config.platforms.includes("android") || permissions.length === 0)
|
|
18484
19049
|
return;
|
|
18485
|
-
const path =
|
|
18486
|
-
const source = await
|
|
19050
|
+
const path = join51(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
19051
|
+
const source = await readFile18(path, "utf8");
|
|
18487
19052
|
const missing = permissions.filter((permission) => !source.includes(`android:name="${permission}"`) && !source.includes(`android:name='${permission}'`));
|
|
18488
19053
|
if (missing.length === 0)
|
|
18489
19054
|
return;
|
|
@@ -18491,8 +19056,8 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18491
19056
|
}, iosDevicePermissionCheck = async (config, purposes) => {
|
|
18492
19057
|
if (!config.platforms.includes("ios") || purposes.length === 0)
|
|
18493
19058
|
return;
|
|
18494
|
-
const path =
|
|
18495
|
-
const source = await
|
|
19059
|
+
const path = join51(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
19060
|
+
const source = await readFile18(path, "utf8");
|
|
18496
19061
|
const missing = purposes.filter((purpose) => !source.includes(`<key>${IOS_USAGE_KEYS[purpose]}</key>`));
|
|
18497
19062
|
if (missing.length === 0)
|
|
18498
19063
|
return;
|
|
@@ -18500,35 +19065,35 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18500
19065
|
}, iosCapabilityProjectionCheck = async (config, requirements) => {
|
|
18501
19066
|
if (!config.platforms.includes("ios"))
|
|
18502
19067
|
return;
|
|
18503
|
-
const appRoot =
|
|
18504
|
-
const infoPath =
|
|
18505
|
-
const info2 = await
|
|
19068
|
+
const appRoot = join51(config.nativeProjectDirectory, "ios/App/App");
|
|
19069
|
+
const infoPath = join51(appRoot, "Info.plist");
|
|
19070
|
+
const info2 = await readFile18(infoPath, "utf8").catch(() => "");
|
|
18506
19071
|
if (requirements.iosSystemBars && !/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<true\s*\/>/u.test(info2))
|
|
18507
19072
|
return fail5("mobile.device-capabilities", "iOS system-bar capability is missing its required view-controller setting.", infoPath, "Run `absolute mobile sync ios` to regenerate native capability settings.");
|
|
18508
19073
|
if (requirements.iosPrivacyAccessedApis.length > 0) {
|
|
18509
|
-
const privacyPath =
|
|
18510
|
-
const projectPath =
|
|
19074
|
+
const privacyPath = join51(appRoot, "PrivacyInfo.xcprivacy");
|
|
19075
|
+
const projectPath = join51(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
18511
19076
|
const [privacy, project] = await Promise.all([
|
|
18512
|
-
|
|
18513
|
-
|
|
19077
|
+
readFile18(privacyPath, "utf8").catch(() => ""),
|
|
19078
|
+
readFile18(projectPath, "utf8").catch(() => "")
|
|
18514
19079
|
]);
|
|
18515
19080
|
const missing = requirements.iosPrivacyAccessedApis.some(({ api, reasons }) => !privacy.includes(`<string>${api}</string>`) || reasons.some((reason) => !privacy.includes(`<string>${reason}</string>`)));
|
|
18516
19081
|
if (missing || !project.includes("PrivacyInfo.xcprivacy in Resources"))
|
|
18517
19082
|
return fail5("mobile.device-capabilities", "iOS privacy manifest or target membership does not match detected native capabilities.", privacyPath, "Run `absolute mobile sync ios` to regenerate and target PrivacyInfo.xcprivacy.");
|
|
18518
19083
|
}
|
|
18519
19084
|
if (requirements.iosPushNotifications) {
|
|
18520
|
-
const entitlementsPath =
|
|
18521
|
-
const delegatePath =
|
|
19085
|
+
const entitlementsPath = join51(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
19086
|
+
const delegatePath = join51(appRoot, "AppDelegate.swift");
|
|
18522
19087
|
const [entitlements, delegate] = await Promise.all([
|
|
18523
|
-
|
|
18524
|
-
|
|
19088
|
+
readFile18(entitlementsPath, "utf8").catch(() => ""),
|
|
19089
|
+
readFile18(delegatePath, "utf8").catch(() => "")
|
|
18525
19090
|
]);
|
|
18526
19091
|
if (!entitlements.includes("<key>aps-environment</key>") || !delegate.includes("capacitorDidRegisterForRemoteNotifications") || !delegate.includes("capacitorDidFailToRegisterForRemoteNotifications"))
|
|
18527
19092
|
return fail5("mobile.device-capabilities", "iOS push entitlement or AppDelegate forwarding does not match detected capabilities.", entitlementsPath, "Run `absolute mobile sync ios` to regenerate native push integration.");
|
|
18528
19093
|
}
|
|
18529
19094
|
return;
|
|
18530
19095
|
}, deviceCapabilityReleaseCheck = async (config, projectRoot) => {
|
|
18531
|
-
const manifestPath =
|
|
19096
|
+
const manifestPath = join51(projectRoot, "package.json");
|
|
18532
19097
|
try {
|
|
18533
19098
|
const plan = resolveAbsoluteDeviceCapabilityPlan(projectRoot);
|
|
18534
19099
|
assertAbsoluteDeviceCapabilityPackages(projectRoot, plan);
|
|
@@ -18547,11 +19112,11 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18547
19112
|
return fail5("mobile.device-capabilities", error instanceof Error ? error.message : "Native device capability provisioning is invalid.", manifestPath, "Run `absolute mobile sync` and approve the exact capability plugins before releasing.");
|
|
18548
19113
|
}
|
|
18549
19114
|
}, inspectAndroidRelease = async (config, projectRoot) => {
|
|
18550
|
-
const androidRoot =
|
|
18551
|
-
const nativeConfigPath =
|
|
18552
|
-
const manifestPath =
|
|
18553
|
-
const publicRoot =
|
|
18554
|
-
const journalPath =
|
|
19115
|
+
const androidRoot = join51(config.nativeProjectDirectory, "android");
|
|
19116
|
+
const nativeConfigPath = join51(androidRoot, "app", "src", "main", "assets", "capacitor.config.json");
|
|
19117
|
+
const manifestPath = join51(androidRoot, "app", "src", "main", "AndroidManifest.xml");
|
|
19118
|
+
const publicRoot = join51(androidRoot, "app", "src", "main", "assets", "public");
|
|
19119
|
+
const journalPath = join51(projectRoot, ".absolutejs", "mobile", "dev-session", "journal.json");
|
|
18555
19120
|
const checks = await Promise.all([
|
|
18556
19121
|
journalReleaseCheck(journalPath, "android"),
|
|
18557
19122
|
capacitorConfigReleaseCheck(nativeConfigPath),
|
|
@@ -18566,14 +19131,14 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18566
19131
|
]);
|
|
18567
19132
|
return checks.map((check2) => ({
|
|
18568
19133
|
...check2,
|
|
18569
|
-
path: check2.path ?
|
|
19134
|
+
path: check2.path ? relative26(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
|
|
18570
19135
|
}));
|
|
18571
19136
|
}, inspectIosRelease = async (config, projectRoot) => {
|
|
18572
|
-
const iosAppRoot =
|
|
18573
|
-
const nativeConfigPath =
|
|
18574
|
-
const infoPath =
|
|
18575
|
-
const publicRoot =
|
|
18576
|
-
const journalPath =
|
|
19137
|
+
const iosAppRoot = join51(config.nativeProjectDirectory, "ios", "App", "App");
|
|
19138
|
+
const nativeConfigPath = join51(iosAppRoot, "capacitor.config.json");
|
|
19139
|
+
const infoPath = join51(iosAppRoot, "Info.plist");
|
|
19140
|
+
const publicRoot = join51(iosAppRoot, "public");
|
|
19141
|
+
const journalPath = join51(projectRoot, ".absolutejs", "mobile", "ios-dev-session", "journal.json");
|
|
18577
19142
|
const checks = [
|
|
18578
19143
|
await journalReleaseCheck(journalPath, "ios")
|
|
18579
19144
|
];
|
|
@@ -18584,7 +19149,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18584
19149
|
}
|
|
18585
19150
|
if (!await pathExists6(nativeConfigPath)) {
|
|
18586
19151
|
checks.push(fail5("ios.capacitor-config", "The generated iOS Capacitor config is missing.", nativeConfigPath, "Run `absolute mobile sync ios` before release validation."));
|
|
18587
|
-
} else if (isUnsafeCapacitorConfig(await
|
|
19152
|
+
} else if (isUnsafeCapacitorConfig(await readFile18(nativeConfigPath, "utf8"))) {
|
|
18588
19153
|
checks.push(fail5("ios.capacitor-config", "iOS Capacitor config contains a development server URL, cleartext transport, navigation allowlist, or invalid JSON.", nativeConfigPath, "Run `absolute mobile sync ios`; do not ship development transport overrides."));
|
|
18589
19154
|
} else {
|
|
18590
19155
|
checks.push(pass("ios.capacitor-config", "iOS Capacitor config contains no development transport overrides.", nativeConfigPath));
|
|
@@ -18593,15 +19158,15 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18593
19158
|
if (!await pathExists6(infoPath)) {
|
|
18594
19159
|
checks.push(fail5("ios.transport-security", "The iOS Info.plist is missing.", infoPath, "Run `absolute mobile sync ios` before release validation."));
|
|
18595
19160
|
} else {
|
|
18596
|
-
const info2 = await
|
|
19161
|
+
const info2 = await readFile18(infoPath, "utf8");
|
|
18597
19162
|
checks.push(/<key>NSAllowsArbitraryLoads<\/key>\s*<true\s*\/>/u.test(info2) ? fail5("ios.transport-security", "iOS App Transport Security permits arbitrary network loads.", infoPath, "Remove NSAllowsArbitraryLoads from the release Info.plist.") : pass("ios.transport-security", "iOS App Transport Security does not permit arbitrary loads.", infoPath));
|
|
18598
19163
|
}
|
|
18599
19164
|
const hmrAsset = await findHmrAsset(publicRoot);
|
|
18600
19165
|
checks.push(hmrAsset ? fail5("ios.hmr-assets", "A packaged iOS asset contains the development HMR client.", hmrAsset, "Rebuild the production mobile bundle and run Capacitor sync again.") : pass("ios.hmr-assets", "Packaged iOS assets contain no development HMR markers.", publicRoot));
|
|
18601
|
-
checks.push(await embeddedBundleReleaseCheck(config, projectRoot, "ios", publicRoot), await contentSecurityPolicyCheck(config, "ios", publicRoot), await iosNativeSecurityCheck(
|
|
19166
|
+
checks.push(await embeddedBundleReleaseCheck(config, projectRoot, "ios", publicRoot), await contentSecurityPolicyCheck(config, "ios", publicRoot), await iosNativeSecurityCheck(join51(config.nativeProjectDirectory, "ios")), await iosDeepLinkProjectionCheck(config, join51(config.nativeProjectDirectory, "ios")));
|
|
18602
19167
|
return checks.map((check2) => ({
|
|
18603
19168
|
...check2,
|
|
18604
|
-
path: check2.path ?
|
|
19169
|
+
path: check2.path ? relative26(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
|
|
18605
19170
|
}));
|
|
18606
19171
|
}, createAbsoluteMobileComplianceReport = (config, result) => {
|
|
18607
19172
|
const summary = {
|
|
@@ -18631,7 +19196,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18631
19196
|
]);
|
|
18632
19197
|
const checks = globalChecks.map((check2) => ({
|
|
18633
19198
|
...check2,
|
|
18634
|
-
path: check2.path ?
|
|
19199
|
+
path: check2.path ? relative26(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
|
|
18635
19200
|
}));
|
|
18636
19201
|
if (config.platforms.includes("android"))
|
|
18637
19202
|
checks.push(...await inspectAndroidRelease(config, projectRoot));
|
|
@@ -18642,13 +19207,13 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
18642
19207
|
if (syncSchema) {
|
|
18643
19208
|
checks.push({
|
|
18644
19209
|
...syncSchema,
|
|
18645
|
-
path: syncSchema.path ?
|
|
19210
|
+
path: syncSchema.path ? relative26(projectRoot, syncSchema.path).replaceAll("\\", "/") || "." : undefined
|
|
18646
19211
|
});
|
|
18647
19212
|
}
|
|
18648
19213
|
const deviceCapabilities = await deviceCapabilityReleaseCheck(config, projectRoot);
|
|
18649
19214
|
checks.push({
|
|
18650
19215
|
...deviceCapabilities,
|
|
18651
|
-
path: deviceCapabilities.path ?
|
|
19216
|
+
path: deviceCapabilities.path ? relative26(projectRoot, deviceCapabilities.path).replaceAll("\\", "/") || "." : undefined
|
|
18652
19217
|
});
|
|
18653
19218
|
return {
|
|
18654
19219
|
checks,
|
|
@@ -18687,19 +19252,19 @@ var init_releaseDoctor = __esm(() => {
|
|
|
18687
19252
|
});
|
|
18688
19253
|
|
|
18689
19254
|
// src/mobile/androidRelease.ts
|
|
18690
|
-
import { createHash as
|
|
19255
|
+
import { createHash as createHash14 } from "crypto";
|
|
18691
19256
|
import {
|
|
18692
|
-
access as
|
|
19257
|
+
access as access11,
|
|
18693
19258
|
copyFile as copyFile5,
|
|
18694
|
-
mkdir as
|
|
18695
|
-
mkdtemp as
|
|
18696
|
-
readFile as
|
|
18697
|
-
rename as
|
|
18698
|
-
rm as
|
|
19259
|
+
mkdir as mkdir13,
|
|
19260
|
+
mkdtemp as mkdtemp6,
|
|
19261
|
+
readFile as readFile19,
|
|
19262
|
+
rename as rename13,
|
|
19263
|
+
rm as rm9,
|
|
18699
19264
|
stat as stat3,
|
|
18700
|
-
writeFile as
|
|
19265
|
+
writeFile as writeFile15
|
|
18701
19266
|
} from "fs/promises";
|
|
18702
|
-
import { dirname as
|
|
19267
|
+
import { dirname as dirname31, isAbsolute as isAbsolute7, join as join52, relative as relative27, resolve as resolve41, sep as sep6 } from "path";
|
|
18703
19268
|
var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), requireManifest2 = (value) => {
|
|
18704
19269
|
if (!isRecord13(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
|
|
18705
19270
|
throw new TypeError("Invalid embedded AbsoluteJS mobile manifest.");
|
|
@@ -18711,7 +19276,7 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
|
|
|
18711
19276
|
};
|
|
18712
19277
|
}, pathExists7 = async (path) => {
|
|
18713
19278
|
try {
|
|
18714
|
-
await
|
|
19279
|
+
await access11(path);
|
|
18715
19280
|
return true;
|
|
18716
19281
|
} catch {
|
|
18717
19282
|
return false;
|
|
@@ -18763,20 +19328,20 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
|
|
|
18763
19328
|
]);
|
|
18764
19329
|
if (result.exitCode !== 0)
|
|
18765
19330
|
throw new TypeError("jarsigner could not sign the Android App Bundle with the configured CI identity.");
|
|
18766
|
-
}, sha256File2 = async (path) =>
|
|
18767
|
-
const root =
|
|
18768
|
-
const output =
|
|
18769
|
-
const projectRelative =
|
|
19331
|
+
}, sha256File2 = async (path) => createHash14("sha256").update(await readFile19(path)).digest("hex"), safeOutputDirectory2 = (projectRoot, requested) => {
|
|
19332
|
+
const root = resolve41(projectRoot);
|
|
19333
|
+
const output = resolve41(root, requested ?? ".absolutejs/mobile/releases/android");
|
|
19334
|
+
const projectRelative = relative27(root, output);
|
|
18770
19335
|
if (projectRelative === ".." || projectRelative.startsWith(`..${sep6}`) || isAbsolute7(projectRelative)) {
|
|
18771
19336
|
throw new TypeError("mobile build --outdir must remain inside the project.");
|
|
18772
19337
|
}
|
|
18773
19338
|
return output;
|
|
18774
19339
|
}, installRelease2 = async (artifactPath, metadata, outputRoot) => {
|
|
18775
|
-
const releaseRoot =
|
|
19340
|
+
const releaseRoot = join52(outputRoot, metadata.releaseId);
|
|
18776
19341
|
const artifactName = "app-release.aab";
|
|
18777
|
-
const destination =
|
|
19342
|
+
const destination = join52(releaseRoot, artifactName);
|
|
18778
19343
|
if (await pathExists7(releaseRoot)) {
|
|
18779
|
-
const existing = requireManifestIdentity(JSON.parse(await
|
|
19344
|
+
const existing = requireManifestIdentity(JSON.parse(await readFile19(join52(releaseRoot, "release.json"), "utf8")), metadata);
|
|
18780
19345
|
const [installedBytes, installedSha256] = await Promise.all([
|
|
18781
19346
|
stat3(destination).then(({ size }) => size),
|
|
18782
19347
|
sha256File2(destination)
|
|
@@ -18786,20 +19351,20 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
|
|
|
18786
19351
|
}
|
|
18787
19352
|
return { artifactPath: destination, metadata: existing, releaseRoot };
|
|
18788
19353
|
}
|
|
18789
|
-
await
|
|
18790
|
-
const staging = await
|
|
19354
|
+
await mkdir13(dirname31(releaseRoot), { recursive: true });
|
|
19355
|
+
const staging = await mkdtemp6(join52(dirname31(releaseRoot), ".android-stage-"));
|
|
18791
19356
|
try {
|
|
18792
|
-
await copyFile5(artifactPath,
|
|
19357
|
+
await copyFile5(artifactPath, join52(staging, artifactName));
|
|
18793
19358
|
const complete = {
|
|
18794
19359
|
...metadata,
|
|
18795
19360
|
artifact: artifactName
|
|
18796
19361
|
};
|
|
18797
|
-
await
|
|
19362
|
+
await writeFile15(join52(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
|
|
18798
19363
|
`, { flag: "wx" });
|
|
18799
|
-
await
|
|
19364
|
+
await rename13(staging, releaseRoot);
|
|
18800
19365
|
return { artifactPath: destination, metadata: complete, releaseRoot };
|
|
18801
19366
|
} finally {
|
|
18802
|
-
await
|
|
19367
|
+
await rm9(staging, { force: true, recursive: true }).catch(() => {
|
|
18803
19368
|
return;
|
|
18804
19369
|
});
|
|
18805
19370
|
}
|
|
@@ -18819,18 +19384,18 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
|
|
|
18819
19384
|
if (options.versionCode !== undefined && (!Number.isSafeInteger(options.versionCode) || options.versionCode < 1 || options.versionCode > 2100000000)) {
|
|
18820
19385
|
throw new TypeError("Android versionCode must be an integer from 1 through 2100000000.");
|
|
18821
19386
|
}
|
|
18822
|
-
const projectRoot =
|
|
19387
|
+
const projectRoot = resolve41(options.projectRoot);
|
|
18823
19388
|
const host2 = options.host ?? detectAbsoluteMobileHost();
|
|
18824
19389
|
const androidRoot = options.androidRoot ?? process.env.ANDROID_HOME ?? process.env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host2);
|
|
18825
|
-
const nativeDirectory =
|
|
18826
|
-
const manifest = requireManifest2(JSON.parse(await
|
|
19390
|
+
const nativeDirectory = join52(options.config.nativeProjectDirectory, "android");
|
|
19391
|
+
const manifest = requireManifest2(JSON.parse(await readFile19(join52(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
|
|
18827
19392
|
if (manifest.appId !== options.config.appId) {
|
|
18828
19393
|
throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
|
|
18829
19394
|
}
|
|
18830
19395
|
let { versionCode } = options;
|
|
18831
19396
|
if (options.prepareVersionCode) {
|
|
18832
19397
|
const nativeFingerprint = await fingerprintAbsoluteAndroidNativeProject({ nativeDirectory });
|
|
18833
|
-
const buildIdentity =
|
|
19398
|
+
const buildIdentity = createHash14("sha256").update(`${manifest.appBuild}\x00${nativeFingerprint}`).digest("hex");
|
|
18834
19399
|
versionCode = await options.prepareVersionCode(buildIdentity);
|
|
18835
19400
|
}
|
|
18836
19401
|
if (versionCode !== undefined && (!Number.isSafeInteger(versionCode) || versionCode < 1 || versionCode > 2100000000)) {
|
|
@@ -18934,7 +19499,7 @@ var absoluteIosDeviceAcceptanceCommands = (options) => {
|
|
|
18934
19499
|
};
|
|
18935
19500
|
|
|
18936
19501
|
// src/mobile/iosConformance.ts
|
|
18937
|
-
import { readFile as
|
|
19502
|
+
import { readFile as readFile20, stat as stat4 } from "fs/promises";
|
|
18938
19503
|
var HMR_LINE, parseAbsoluteIosHmrLog = (line) => {
|
|
18939
19504
|
const match = HMR_LINE.exec(line);
|
|
18940
19505
|
if (!match)
|
|
@@ -18969,7 +19534,7 @@ var HMR_LINE, parseAbsoluteIosHmrLog = (line) => {
|
|
|
18969
19534
|
if (Date.now() > deadline)
|
|
18970
19535
|
throw new Error(`No iOS native HMR acknowledgement was observed within ${timeoutMs}ms.`);
|
|
18971
19536
|
options.signal?.throwIfAborted();
|
|
18972
|
-
const contents = await
|
|
19537
|
+
const contents = await readFile20(options.logPath).catch(() => Buffer.alloc(0));
|
|
18973
19538
|
if (contents.byteLength < offset) {
|
|
18974
19539
|
offset = 0;
|
|
18975
19540
|
buffered = "";
|
|
@@ -18993,8 +19558,8 @@ var init_iosConformance = __esm(() => {
|
|
|
18993
19558
|
});
|
|
18994
19559
|
|
|
18995
19560
|
// src/mobile/nativeTestReport.ts
|
|
18996
|
-
import { mkdir as
|
|
18997
|
-
import { join as
|
|
19561
|
+
import { mkdir as mkdir14, readFile as readFile21, writeFile as writeFile16 } from "fs/promises";
|
|
19562
|
+
import { join as join53 } from "path";
|
|
18998
19563
|
var secretPattern, bearerPattern, coordinatePattern, nativeCredentialPattern, sanitizeNativeReportText = (value) => value.replace(nativeCredentialPattern, "[REDACTED]").replace(bearerPattern, "Bearer [REDACTED]").replace(secretPattern, "$1$2[REDACTED]").replace(coordinatePattern, "$1$2[REDACTED]").replace(/(https?:\/\/[^\s?#]+)[?#][^\s]*/giu, "$1?[REDACTED]"), markdownCell = (value) => sanitizeNativeReportText(value).replaceAll("|", "\\|").replaceAll(`
|
|
18999
19564
|
`, "<br>"), createAbsoluteNativeAutomatedChecks = (run) => {
|
|
19000
19565
|
const target = `${run.targetKind} ${run.targetId}`;
|
|
@@ -19096,7 +19661,7 @@ var secretPattern, bearerPattern, coordinatePattern, nativeCredentialPattern, sa
|
|
|
19096
19661
|
reportVersion: 1,
|
|
19097
19662
|
run: options.run
|
|
19098
19663
|
}), readPackageVersionForNativeReport = async (packageJsonPath) => {
|
|
19099
|
-
const manifest = JSON.parse(await
|
|
19664
|
+
const manifest = JSON.parse(await readFile21(packageJsonPath, "utf8"));
|
|
19100
19665
|
if (typeof manifest !== "object" || manifest === null)
|
|
19101
19666
|
return "unknown";
|
|
19102
19667
|
const version2 = Reflect.get(manifest, "version");
|
|
@@ -19132,13 +19697,13 @@ Replace each \`NOT_RUN\` with \`PASS\`, \`FAIL\`, or \`SKIPPED\` after completin
|
|
|
19132
19697
|
${table(report.manualChecks)}
|
|
19133
19698
|
`;
|
|
19134
19699
|
}, writeAbsoluteNativeTestReport = async (directory, report) => {
|
|
19135
|
-
await
|
|
19136
|
-
const jsonPath =
|
|
19137
|
-
const markdownPath =
|
|
19700
|
+
await mkdir14(directory, { recursive: true });
|
|
19701
|
+
const jsonPath = join53(directory, "report.json");
|
|
19702
|
+
const markdownPath = join53(directory, "report.md");
|
|
19138
19703
|
await Promise.all([
|
|
19139
|
-
|
|
19704
|
+
writeFile16(jsonPath, `${JSON.stringify(report, null, 2)}
|
|
19140
19705
|
`),
|
|
19141
|
-
|
|
19706
|
+
writeFile16(markdownPath, renderAbsoluteNativeTestReport(report))
|
|
19142
19707
|
]);
|
|
19143
19708
|
return { directory, jsonPath, markdownPath };
|
|
19144
19709
|
};
|
|
@@ -19352,8 +19917,8 @@ var init_androidTestReport = __esm(() => {
|
|
|
19352
19917
|
});
|
|
19353
19918
|
|
|
19354
19919
|
// src/mobile/releasePublisher.ts
|
|
19355
|
-
import { access as
|
|
19356
|
-
import { isAbsolute as isAbsolute8, relative as
|
|
19920
|
+
import { access as access12 } from "fs/promises";
|
|
19921
|
+
import { isAbsolute as isAbsolute8, relative as relative28, resolve as resolve42, sep as sep7 } from "path";
|
|
19357
19922
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
19358
19923
|
var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
19359
19924
|
if (typeof publisher.prepareIosRelease !== "function") {
|
|
@@ -19375,16 +19940,16 @@ var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
|
19375
19940
|
}
|
|
19376
19941
|
return versionCode;
|
|
19377
19942
|
}, isRecord14 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), isPublisher = (value) => isRecord14(value) && typeof value.publish === "function", publisherModulePath = (projectRoot, requested) => {
|
|
19378
|
-
const root =
|
|
19379
|
-
const path =
|
|
19380
|
-
const projectRelative =
|
|
19943
|
+
const root = resolve42(projectRoot);
|
|
19944
|
+
const path = resolve42(root, requested);
|
|
19945
|
+
const projectRelative = relative28(root, path);
|
|
19381
19946
|
if (projectRelative === ".." || projectRelative.startsWith(`..${sep7}`) || isAbsolute8(projectRelative)) {
|
|
19382
19947
|
throw new TypeError("mobile publish --registry must remain inside the project.");
|
|
19383
19948
|
}
|
|
19384
19949
|
return path;
|
|
19385
19950
|
}, loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
|
|
19386
19951
|
const modulePath = publisherModulePath(projectRoot, requestedModulePath);
|
|
19387
|
-
await
|
|
19952
|
+
await access12(modulePath).catch(() => {
|
|
19388
19953
|
throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
|
|
19389
19954
|
});
|
|
19390
19955
|
const loaded = await import(pathToFileURL2(modulePath).href);
|
|
@@ -19445,20 +20010,20 @@ var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
|
19445
20010
|
var init_releasePublisher = () => {};
|
|
19446
20011
|
|
|
19447
20012
|
// src/mobile/mobileInspect.ts
|
|
19448
|
-
import { access as
|
|
19449
|
-
import { join as
|
|
20013
|
+
import { access as access13, readFile as readFile22 } from "fs/promises";
|
|
20014
|
+
import { join as join54, relative as relative29, resolve as resolve43 } from "path";
|
|
19450
20015
|
var ABSOLUTE_MOBILE_INSPECTION_FORMAT = 1, MOBILE_PACKAGE_NAMES, isObject3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), portablePath2 = (projectRoot, path) => {
|
|
19451
|
-
const value =
|
|
20016
|
+
const value = relative29(resolve43(projectRoot), resolve43(path)).replaceAll("\\", "/");
|
|
19452
20017
|
return value || ".";
|
|
19453
20018
|
}, pathExists8 = async (path) => {
|
|
19454
20019
|
try {
|
|
19455
|
-
await
|
|
20020
|
+
await access13(path);
|
|
19456
20021
|
return true;
|
|
19457
20022
|
} catch {
|
|
19458
20023
|
return false;
|
|
19459
20024
|
}
|
|
19460
20025
|
}, readObject2 = async (path) => {
|
|
19461
|
-
const value = JSON.parse(await
|
|
20026
|
+
const value = JSON.parse(await readFile22(path, "utf8"));
|
|
19462
20027
|
if (!isObject3(value))
|
|
19463
20028
|
throw new TypeError("JSON root must be an object.");
|
|
19464
20029
|
return value;
|
|
@@ -19468,13 +20033,13 @@ var ABSOLUTE_MOBILE_INSPECTION_FORMAT = 1, MOBILE_PACKAGE_NAMES, isObject3 = (va
|
|
|
19468
20033
|
for (const [name, declared] of Object.entries(value).filter((entry) => typeof entry[1] === "string"))
|
|
19469
20034
|
declarations.set(name, declared);
|
|
19470
20035
|
}, packageInspections = async (projectRoot, additionalNames) => {
|
|
19471
|
-
const project = await readObject2(
|
|
20036
|
+
const project = await readObject2(join54(projectRoot, "package.json"));
|
|
19472
20037
|
const declarations = new Map;
|
|
19473
20038
|
for (const field of ["dependencies", "devDependencies"])
|
|
19474
20039
|
addPackageDeclarations(declarations, project[field]);
|
|
19475
20040
|
const names = [...new Set([...declarations.keys(), ...additionalNames])].filter((name) => MOBILE_PACKAGE_NAMES.has(name) || name.startsWith("@capacitor/") || additionalNames.includes(name)).sort();
|
|
19476
20041
|
return Promise.all(names.map(async (name) => {
|
|
19477
|
-
const installedManifest = await readObject2(
|
|
20042
|
+
const installedManifest = await readObject2(join54(projectRoot, "node_modules", name, "package.json")).catch(() => {
|
|
19478
20043
|
return;
|
|
19479
20044
|
});
|
|
19480
20045
|
const installed = installedManifest?.version;
|
|
@@ -19523,7 +20088,7 @@ var ABSOLUTE_MOBILE_INSPECTION_FORMAT = 1, MOBILE_PACKAGE_NAMES, isObject3 = (va
|
|
|
19523
20088
|
},
|
|
19524
20089
|
format: ABSOLUTE_MOBILE_INSPECTION_FORMAT,
|
|
19525
20090
|
nativeProjects: await Promise.all(config.platforms.map(async (platform6) => {
|
|
19526
|
-
const path =
|
|
20091
|
+
const path = join54(config.nativeProjectDirectory, platform6);
|
|
19527
20092
|
return {
|
|
19528
20093
|
initialized: await pathExists8(path),
|
|
19529
20094
|
path: portablePath2(projectRoot, path),
|
|
@@ -19594,19 +20159,19 @@ var init_mobileInspect = __esm(() => {
|
|
|
19594
20159
|
|
|
19595
20160
|
// src/mobile/ciWorkflow.ts
|
|
19596
20161
|
import { existsSync as existsSync42 } from "fs";
|
|
19597
|
-
import { access as
|
|
19598
|
-
import { dirname as
|
|
19599
|
-
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1, SECRET_NAME_PATTERN, CI_ENV_INDENTATION = 6, RESERVED_SECRET_NAMES,
|
|
20162
|
+
import { access as access14, mkdir as mkdir15, readFile as readFile23, writeFile as writeFile17 } from "fs/promises";
|
|
20163
|
+
import { dirname as dirname32, extname as extname9, relative as relative30, resolve as resolve44, sep as sep8 } from "path";
|
|
20164
|
+
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1, SECRET_NAME_PATTERN, CI_ENV_INDENTATION = 6, RESERVED_SECRET_NAMES, exists4 = async (path) => {
|
|
19600
20165
|
try {
|
|
19601
|
-
await
|
|
20166
|
+
await access14(path);
|
|
19602
20167
|
return true;
|
|
19603
20168
|
} catch {
|
|
19604
20169
|
return false;
|
|
19605
20170
|
}
|
|
19606
20171
|
}, yamlString = (value) => `'${value.replaceAll("'", "''")}'`, projectPath = (projectRoot, value, field, options = {}) => {
|
|
19607
|
-
const root =
|
|
19608
|
-
const path =
|
|
19609
|
-
const portable =
|
|
20172
|
+
const root = resolve44(projectRoot);
|
|
20173
|
+
const path = resolve44(root, value);
|
|
20174
|
+
const portable = relative30(root, path).replaceAll("\\", "/");
|
|
19610
20175
|
if (portable === ".." || portable.startsWith(`..${sep8}`) || portable.startsWith("../") || portable === "") {
|
|
19611
20176
|
throw new TypeError(`${field} must remain inside the project root.`);
|
|
19612
20177
|
}
|
|
@@ -19616,10 +20181,10 @@ var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1, SECRET_NAME_PATTERN, CI_ENV_INDENTAT
|
|
|
19616
20181
|
throw new TypeError(`${field} does not exist inside the project.`);
|
|
19617
20182
|
return portable;
|
|
19618
20183
|
}, workflowOutputPath = (projectRoot, value) => {
|
|
19619
|
-
const root =
|
|
19620
|
-
const workflows =
|
|
19621
|
-
const path =
|
|
19622
|
-
const portable =
|
|
20184
|
+
const root = resolve44(projectRoot);
|
|
20185
|
+
const workflows = resolve44(root, ".github/workflows");
|
|
20186
|
+
const path = resolve44(root, value ?? ".github/workflows/absolute-mobile.yml");
|
|
20187
|
+
const portable = relative30(workflows, path);
|
|
19623
20188
|
if (portable === ".." || portable.startsWith(`..${sep8}`) || extname9(path) !== ".yml" && extname9(path) !== ".yaml") {
|
|
19624
20189
|
throw new TypeError("mobile ci github --output must be a .yml or .yaml file inside .github/workflows.");
|
|
19625
20190
|
}
|
|
@@ -20008,12 +20573,12 @@ ${bundleAuditSteps}${platforms.includes("android") ? androidJob({ customSecrets,
|
|
|
20008
20573
|
}, writeAbsoluteMobileGithubWorkflow = async (options) => {
|
|
20009
20574
|
const path = workflowOutputPath(options.projectRoot, options.outputPath);
|
|
20010
20575
|
const generated = createAbsoluteMobileGithubWorkflow(options);
|
|
20011
|
-
const previous = await
|
|
20576
|
+
const previous = await exists4(path) ? await readFile23(path, "utf8") : undefined;
|
|
20012
20577
|
if (previous !== undefined && previous !== generated.workflow && !options.force)
|
|
20013
|
-
throw new TypeError(`${
|
|
20578
|
+
throw new TypeError(`${relative30(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
|
|
20014
20579
|
if (previous !== generated.workflow) {
|
|
20015
|
-
await
|
|
20016
|
-
await
|
|
20580
|
+
await mkdir15(dirname32(path), { recursive: true });
|
|
20581
|
+
await writeFile17(path, generated.workflow);
|
|
20017
20582
|
}
|
|
20018
20583
|
return {
|
|
20019
20584
|
changed: previous !== generated.workflow,
|
|
@@ -20075,11 +20640,11 @@ var exports_mobile = {};
|
|
|
20075
20640
|
__export(exports_mobile, {
|
|
20076
20641
|
runMobile: () => runMobile
|
|
20077
20642
|
});
|
|
20078
|
-
import { access as
|
|
20079
|
-
import { join as
|
|
20643
|
+
import { access as access15, mkdir as mkdir16, readFile as readFile24, writeFile as writeFile18 } from "fs/promises";
|
|
20644
|
+
import { join as join55, relative as relative31, resolve as resolve45 } from "path";
|
|
20080
20645
|
import { createInterface } from "readline/promises";
|
|
20081
20646
|
var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), CAPACITOR_PACKAGES, CAPACITOR_PACKAGE_SPECS, CAPACITOR_SYNC_PACKAGE_SPECS, packageNameFromSpec = (spec) => spec.slice(0, spec.lastIndexOf("@")), directProjectPackages = async (projectRoot) => {
|
|
20082
|
-
const manifest = JSON.parse(await
|
|
20647
|
+
const manifest = JSON.parse(await readFile24(join55(projectRoot, "package.json"), "utf8"));
|
|
20083
20648
|
if (!isRecord15(manifest))
|
|
20084
20649
|
throw new TypeError("Application package.json must contain an object.");
|
|
20085
20650
|
const names = new Set;
|
|
@@ -20092,7 +20657,7 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20092
20657
|
return names;
|
|
20093
20658
|
}, resolvedPackageVersion = async (projectRoot, packageName) => {
|
|
20094
20659
|
try {
|
|
20095
|
-
const manifest = JSON.parse(await
|
|
20660
|
+
const manifest = JSON.parse(await readFile24(join55(projectRoot, "node_modules", packageName, "package.json"), "utf8"));
|
|
20096
20661
|
return isRecord15(manifest) && typeof manifest.version === "string" ? manifest.version : undefined;
|
|
20097
20662
|
} catch {
|
|
20098
20663
|
return;
|
|
@@ -20133,9 +20698,9 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20133
20698
|
}
|
|
20134
20699
|
return value;
|
|
20135
20700
|
}, capacitorExecutable = async (projectRoot) => {
|
|
20136
|
-
const executable =
|
|
20701
|
+
const executable = join55(projectRoot, "node_modules", ".bin", "cap");
|
|
20137
20702
|
try {
|
|
20138
|
-
await
|
|
20703
|
+
await access15(executable);
|
|
20139
20704
|
return executable;
|
|
20140
20705
|
} catch {
|
|
20141
20706
|
throw new TypeError(`Capacitor is not installed in this app. Run: bun add ${CAPACITOR_PACKAGES.join(" ")}`);
|
|
@@ -20152,13 +20717,54 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20152
20717
|
if (exitCode !== 0) {
|
|
20153
20718
|
throw new TypeError(`Capacitor exited with status ${exitCode}.`);
|
|
20154
20719
|
}
|
|
20155
|
-
}, runCapacitorForPlatforms = (projectRoot, command, platforms) => platforms.reduce((pending, platform6) => pending.then(() => runCapacitor(projectRoot, [command, platform6])), Promise.resolve()),
|
|
20720
|
+
}, runCapacitorForPlatforms = (projectRoot, command, platforms) => platforms.reduce((pending, platform6) => pending.then(() => runCapacitor(projectRoot, [command, platform6])), Promise.resolve()), expoExecutable = async (project) => {
|
|
20721
|
+
const executable = join55(project, "node_modules", ".bin", "expo");
|
|
20722
|
+
try {
|
|
20723
|
+
await access15(executable);
|
|
20724
|
+
return executable;
|
|
20725
|
+
} catch {
|
|
20726
|
+
throw new TypeError("Expo dependencies are not installed in the generated shell. Run `absolute mobile init --yes`.");
|
|
20727
|
+
}
|
|
20728
|
+
}, runExpo = async (project, args) => {
|
|
20729
|
+
const executable = await expoExecutable(project);
|
|
20730
|
+
const process2 = Bun.spawn([executable, ...args], {
|
|
20731
|
+
cwd: project,
|
|
20732
|
+
stderr: "inherit",
|
|
20733
|
+
stdin: "inherit",
|
|
20734
|
+
stdout: "inherit"
|
|
20735
|
+
});
|
|
20736
|
+
const exitCode = await process2.exited;
|
|
20737
|
+
if (exitCode !== 0)
|
|
20738
|
+
throw new TypeError(`Expo exited with status ${exitCode}.`);
|
|
20739
|
+
}, ensureExpoPackages = async (project, args) => {
|
|
20740
|
+
try {
|
|
20741
|
+
await access15(join55(project, "node_modules", "expo", "package.json"));
|
|
20742
|
+
return;
|
|
20743
|
+
} catch {}
|
|
20744
|
+
const approved = args.includes("--yes") || await confirmInstall("The experimental Expo shell dependencies are missing. Install the pinned Expo SDK 57 toolchain now?");
|
|
20745
|
+
if (!approved)
|
|
20746
|
+
throw new TypeError(`Expo initialization requires running \`bun install\` in ${project}.`);
|
|
20747
|
+
const process2 = Bun.spawn(["bun", "install"], {
|
|
20748
|
+
cwd: project,
|
|
20749
|
+
stderr: "inherit",
|
|
20750
|
+
stdin: "inherit",
|
|
20751
|
+
stdout: "inherit"
|
|
20752
|
+
});
|
|
20753
|
+
const exitCode = await process2.exited;
|
|
20754
|
+
if (exitCode !== 0)
|
|
20755
|
+
throw new TypeError(`Expo dependency installation exited with status ${exitCode}.`);
|
|
20756
|
+
}, loadMobile = async (configPath2) => {
|
|
20156
20757
|
const projectRoot = process.cwd();
|
|
20157
20758
|
const config = await loadConfig(configPath2);
|
|
20158
20759
|
const mobile = normalizeAbsoluteMobileConfig(requireMobileConfig(config.mobile), projectRoot);
|
|
20159
20760
|
return { mobile, projectRoot };
|
|
20761
|
+
}, requireCapacitorEngine = (mobile, command) => {
|
|
20762
|
+
if (mobile.engine === "capacitor")
|
|
20763
|
+
return;
|
|
20764
|
+
throw new TypeError(`${command} is not available for the experimental Expo engine yet. Use mobile init/sync and Expo CLI from the generated shell; Capacitor remains the release-capable engine.`);
|
|
20160
20765
|
}, inspectMobile = async (args) => {
|
|
20161
20766
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
20767
|
+
requireCapacitorEngine(mobile, "mobile inspect");
|
|
20162
20768
|
const report = await inspectAbsoluteMobileProject(mobile, projectRoot, {
|
|
20163
20769
|
absolutejsVersion: await absolutejsVersionForReport()
|
|
20164
20770
|
});
|
|
@@ -20213,6 +20819,24 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20213
20819
|
console.log(removed ? `Removed remote Mac profile ${args[1]}.` : `Remote Mac profile ${args[1]} was not found.`);
|
|
20214
20820
|
}, initialize = async (args) => {
|
|
20215
20821
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
20822
|
+
if (mobile.engine === "expo") {
|
|
20823
|
+
console.warn("Experimental: Expo Auth, Sync, release publishing, and physical-device acceptance are not complete.");
|
|
20824
|
+
const generated2 = await writeAbsoluteExpoProject(mobile, {
|
|
20825
|
+
force: args.includes("--force"),
|
|
20826
|
+
projectRoot
|
|
20827
|
+
});
|
|
20828
|
+
console.log(`${generated2.changed > 0 ? "Generated" : "Verified"} Expo shell ${generated2.path}`);
|
|
20829
|
+
await ensureExpoPackages(generated2.path, args);
|
|
20830
|
+
if (args.includes("--no-native"))
|
|
20831
|
+
return;
|
|
20832
|
+
await runExpo(generated2.path, [
|
|
20833
|
+
"prebuild",
|
|
20834
|
+
"--no-install",
|
|
20835
|
+
"--platform",
|
|
20836
|
+
mobile.platforms.length === 2 ? "all" : mobile.platforms[0] ?? "all"
|
|
20837
|
+
]);
|
|
20838
|
+
return;
|
|
20839
|
+
}
|
|
20216
20840
|
await ensureCapacitorPackages(projectRoot, args);
|
|
20217
20841
|
const generated = await writeAbsoluteCapacitorConfig(mobile, {
|
|
20218
20842
|
force: args.includes("--force"),
|
|
@@ -20227,6 +20851,25 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20227
20851
|
await applyAbsoluteNativeBackgroundSync(projectRoot, mobile);
|
|
20228
20852
|
}, sync = async (args) => {
|
|
20229
20853
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
20854
|
+
if (mobile.engine === "expo") {
|
|
20855
|
+
console.warn("Experimental: syncing the Expo CNG shell and embedded AbsoluteJS bundle.");
|
|
20856
|
+
await writeAbsoluteExpoProject(mobile, {
|
|
20857
|
+
force: args.includes("--force"),
|
|
20858
|
+
projectRoot
|
|
20859
|
+
});
|
|
20860
|
+
await ensureExpoPackages(mobile.nativeProjectDirectory, args);
|
|
20861
|
+
const assets = await syncAbsoluteExpoWebAssets(mobile);
|
|
20862
|
+
console.log(`Synced ${assets.assets} embedded AbsoluteJS assets for ${assets.appBuild}.`);
|
|
20863
|
+
const platform7 = args.find((value) => value === "android" || value === "ios");
|
|
20864
|
+
const platforms2 = platform7 ? [platform7] : mobile.platforms;
|
|
20865
|
+
await runExpo(mobile.nativeProjectDirectory, [
|
|
20866
|
+
"prebuild",
|
|
20867
|
+
"--no-install",
|
|
20868
|
+
"--platform",
|
|
20869
|
+
platforms2.length === 2 ? "all" : platforms2[0] ?? "all"
|
|
20870
|
+
]);
|
|
20871
|
+
return;
|
|
20872
|
+
}
|
|
20230
20873
|
await ensureCapacitorPackages(projectRoot, args);
|
|
20231
20874
|
const platform6 = args.find((value) => value === "android" || value === "ios");
|
|
20232
20875
|
const platforms = platform6 ? [platform6] : mobile.platforms;
|
|
@@ -20240,7 +20883,7 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20240
20883
|
await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, platforms);
|
|
20241
20884
|
}, associations = async (args) => {
|
|
20242
20885
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
20243
|
-
const outputDirectory =
|
|
20886
|
+
const outputDirectory = resolve45(projectRoot, valueAfter(args, "--outdir") ?? ".absolutejs/mobile/associations");
|
|
20244
20887
|
if (args.includes("--verify")) {
|
|
20245
20888
|
const result2 = await verifyAbsoluteMobileAssociationFiles(mobile);
|
|
20246
20889
|
console.log(`Verified ${result2.results.length} hosted association files`);
|
|
@@ -20271,6 +20914,7 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20271
20914
|
throw new TypeError("Usage: absolute mobile ci github [server-entry] [--publish] [--registry module] [--secret-env NAME] [--output path] [--force] [--json] [--config path]");
|
|
20272
20915
|
const configPath2 = valueAfter(args, "--config");
|
|
20273
20916
|
const { mobile, projectRoot } = await loadMobile(configPath2);
|
|
20917
|
+
requireCapacitorEngine(mobile, "mobile ci github");
|
|
20274
20918
|
const result = await writeAbsoluteMobileGithubWorkflow({
|
|
20275
20919
|
config: mobile,
|
|
20276
20920
|
configPath: configPath2,
|
|
@@ -20290,7 +20934,7 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20290
20934
|
const publicResult = {
|
|
20291
20935
|
changed: result.changed,
|
|
20292
20936
|
format: result.format,
|
|
20293
|
-
path:
|
|
20937
|
+
path: relative31(projectRoot, result.path).replaceAll("\\", "/"),
|
|
20294
20938
|
platforms: result.platforms,
|
|
20295
20939
|
publishing: result.publishing,
|
|
20296
20940
|
requiredSecrets: result.requiredSecrets
|
|
@@ -20336,6 +20980,7 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20336
20980
|
}
|
|
20337
20981
|
}, runReleaseDoctor = async (args) => {
|
|
20338
20982
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
20983
|
+
requireCapacitorEngine(mobile, "mobile doctor release");
|
|
20339
20984
|
const platform6 = args.find((value) => value === "android" || value === "ios");
|
|
20340
20985
|
const effectiveMobile = platform6 ? { ...mobile, platforms: [platform6] } : mobile;
|
|
20341
20986
|
const result = await inspectAbsoluteMobileRelease(effectiveMobile, projectRoot);
|
|
@@ -20520,6 +21165,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
20520
21165
|
}, buildAndroid = async (args, prepareVersionCode) => {
|
|
20521
21166
|
const configPath2 = valueAfter(args, "--config");
|
|
20522
21167
|
const { mobile, projectRoot } = await loadMobile(configPath2);
|
|
21168
|
+
requireCapacitorEngine(mobile, "mobile build android");
|
|
20523
21169
|
if (!mobile.platforms.includes("android")) {
|
|
20524
21170
|
throw new TypeError("mobile build android requires android in mobile.platforms.");
|
|
20525
21171
|
}
|
|
@@ -20550,7 +21196,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
20550
21196
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
20551
21197
|
console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} Android App Bundle in ${getDurationString(durationMs)}.`);
|
|
20552
21198
|
console.log(`Artifact: ${release.artifactPath}`);
|
|
20553
|
-
console.log(`Metadata: ${
|
|
21199
|
+
console.log(`Metadata: ${join55(release.releaseRoot, "release.json")}`);
|
|
20554
21200
|
return release;
|
|
20555
21201
|
} finally {
|
|
20556
21202
|
sendTelemetryEvent("mobile:android-release-build", {
|
|
@@ -20573,6 +21219,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
20573
21219
|
const configPath2 = valueAfter(args, "--config");
|
|
20574
21220
|
const googlePlay = googlePlayTarget(args);
|
|
20575
21221
|
const { mobile, projectRoot } = await loadMobile(configPath2);
|
|
21222
|
+
requireCapacitorEngine(mobile, "mobile publish android");
|
|
20576
21223
|
const startedAt = performance.now();
|
|
20577
21224
|
let reused = false;
|
|
20578
21225
|
let success = false;
|
|
@@ -20626,6 +21273,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
20626
21273
|
}, buildIos = async (args, prepareBuildNumber) => {
|
|
20627
21274
|
const configPath2 = valueAfter(args, "--config");
|
|
20628
21275
|
const { mobile, projectRoot } = await loadMobile(configPath2);
|
|
21276
|
+
requireCapacitorEngine(mobile, "mobile build ios");
|
|
20629
21277
|
if (!mobile.platforms.includes("ios")) {
|
|
20630
21278
|
throw new TypeError("mobile build ios requires ios in mobile.platforms.");
|
|
20631
21279
|
}
|
|
@@ -20654,7 +21302,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
20654
21302
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
20655
21303
|
console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} iOS IPA ${release.metadata.marketingVersion}${release.metadata.buildNumber ? ` (${release.metadata.buildNumber})` : ""} in ${getDurationString(durationMs)}.`);
|
|
20656
21304
|
console.log(`Artifact: ${release.artifactPath}`);
|
|
20657
|
-
console.log(`Metadata: ${
|
|
21305
|
+
console.log(`Metadata: ${join55(release.releaseRoot, "release.json")}`);
|
|
20658
21306
|
return release;
|
|
20659
21307
|
} finally {
|
|
20660
21308
|
sendTelemetryEvent("mobile:ios-release-build", {
|
|
@@ -20672,6 +21320,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
20672
21320
|
const configPath2 = valueAfter(args, "--config");
|
|
20673
21321
|
const appStoreConnect = appStoreConnectTarget(args);
|
|
20674
21322
|
const { mobile, projectRoot } = await loadMobile(configPath2);
|
|
21323
|
+
requireCapacitorEngine(mobile, "mobile publish ios");
|
|
20675
21324
|
const startedAt = performance.now();
|
|
20676
21325
|
let reused = false;
|
|
20677
21326
|
let success = false;
|
|
@@ -20761,7 +21410,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
20761
21410
|
checks.push({
|
|
20762
21411
|
id: "sync.storage-schema",
|
|
20763
21412
|
label: `Offline schema ${schema.components.map((component2) => `${component2.id}@${component2.version}`).join(", ")}`,
|
|
20764
|
-
path:
|
|
21413
|
+
path: join55(projectRoot, "package.json"),
|
|
20765
21414
|
platform: "host",
|
|
20766
21415
|
status: "pass"
|
|
20767
21416
|
});
|
|
@@ -20769,7 +21418,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
20769
21418
|
checks.push({
|
|
20770
21419
|
id: "sync.storage-schema",
|
|
20771
21420
|
label: "Offline schema metadata is invalid",
|
|
20772
|
-
path:
|
|
21421
|
+
path: join55(projectRoot, "package.json"),
|
|
20773
21422
|
platform: "host",
|
|
20774
21423
|
remediation: error instanceof Error ? error.message : String(error),
|
|
20775
21424
|
status: "fail"
|
|
@@ -20854,7 +21503,7 @@ Emulator setup verification:`);
|
|
|
20854
21503
|
}
|
|
20855
21504
|
return { https: args.includes("--https"), port };
|
|
20856
21505
|
}
|
|
20857
|
-
const instances = listLiveInstances().filter((instance2) =>
|
|
21506
|
+
const instances = listLiveInstances().filter((instance2) => resolve45(instance2.cwd) === resolve45(projectRoot) && instance2.source === "dev" && instance2.port !== null);
|
|
20858
21507
|
if (instances.length !== 1) {
|
|
20859
21508
|
throw new TypeError(instances.length === 0 ? "No running AbsoluteJS dev server was found for this project. Start `bun dev`, wait for Android to report ready, then run `absolute mobile test android`." : "Multiple dev servers are running for this project. Select one with mobile test android --port <port>.");
|
|
20860
21509
|
}
|
|
@@ -20897,8 +21546,8 @@ Emulator setup verification:`);
|
|
|
20897
21546
|
}
|
|
20898
21547
|
return selected;
|
|
20899
21548
|
}, safeArtifactRoot = (projectRoot, value) => {
|
|
20900
|
-
const root =
|
|
20901
|
-
if (root !== projectRoot && !root.startsWith(`${
|
|
21549
|
+
const root = resolve45(projectRoot, value ?? ".absolutejs/mobile/test-artifacts");
|
|
21550
|
+
if (root !== projectRoot && !root.startsWith(`${resolve45(projectRoot)}/`)) {
|
|
20902
21551
|
throw new TypeError("mobile test --artifacts must remain inside the project.");
|
|
20903
21552
|
}
|
|
20904
21553
|
return root;
|
|
@@ -20922,12 +21571,12 @@ Emulator setup verification:`);
|
|
|
20922
21571
|
timeoutMs
|
|
20923
21572
|
});
|
|
20924
21573
|
}, writeAndroidFailureArtifacts = async (options) => {
|
|
20925
|
-
await
|
|
20926
|
-
const screenshot = options.session ? await options.session.screenshot(
|
|
21574
|
+
await mkdir16(options.artifactRoot, { recursive: true });
|
|
21575
|
+
const screenshot = options.session ? await options.session.screenshot(join55(options.artifactRoot, "android-failure.png")).catch(() => {
|
|
20927
21576
|
return;
|
|
20928
21577
|
}) : undefined;
|
|
20929
|
-
const diagnosticPath =
|
|
20930
|
-
await
|
|
21578
|
+
const diagnosticPath = join55(options.artifactRoot, "android-failure.json");
|
|
21579
|
+
await writeFile18(diagnosticPath, `${JSON.stringify({
|
|
20931
21580
|
diagnostics: options.session?.diagnostics ?? [],
|
|
20932
21581
|
error: options.error instanceof Error ? options.error.message : String(options.error),
|
|
20933
21582
|
platform: "android",
|
|
@@ -20940,6 +21589,7 @@ Emulator setup verification:`);
|
|
|
20940
21589
|
return { diagnosticPath, screenshot };
|
|
20941
21590
|
}, testAndroid = async (args) => {
|
|
20942
21591
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
21592
|
+
requireCapacitorEngine(mobile, "mobile test android");
|
|
20943
21593
|
if (!mobile.platforms.includes("android")) {
|
|
20944
21594
|
throw new TypeError("mobile test android requires android in mobile.platforms.");
|
|
20945
21595
|
}
|
|
@@ -20990,7 +21640,7 @@ Emulator setup verification:`);
|
|
|
20990
21640
|
console.log(JSON.stringify(report, null, 2));
|
|
20991
21641
|
else
|
|
20992
21642
|
printAndroidTestReport(report);
|
|
20993
|
-
const screenshot = reportRoot ? await session.screenshot(
|
|
21643
|
+
const screenshot = reportRoot ? await session.screenshot(join55(artifactRoot, "android-emulator.png")) : undefined;
|
|
20994
21644
|
await writeRequestedAndroidReport({
|
|
20995
21645
|
adb,
|
|
20996
21646
|
args,
|
|
@@ -21058,14 +21708,14 @@ Emulator setup verification:`);
|
|
|
21058
21708
|
const port = Number(explicit);
|
|
21059
21709
|
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
21060
21710
|
throw new TypeError("mobile test --port must be a valid TCP port.");
|
|
21061
|
-
const instance2 = listLiveInstances().find((candidate) =>
|
|
21711
|
+
const instance2 = listLiveInstances().find((candidate) => resolve45(candidate.cwd) === resolve45(projectRoot) && candidate.source === "dev" && candidate.port === port);
|
|
21062
21712
|
return {
|
|
21063
21713
|
https: instance2?.https ?? args.includes("--https"),
|
|
21064
21714
|
instance: instance2,
|
|
21065
21715
|
port
|
|
21066
21716
|
};
|
|
21067
21717
|
}
|
|
21068
|
-
const instances = listLiveInstances().filter((instance2) =>
|
|
21718
|
+
const instances = listLiveInstances().filter((instance2) => resolve45(instance2.cwd) === resolve45(projectRoot) && instance2.source === "dev" && instance2.port !== null);
|
|
21069
21719
|
if (instances.length !== 1)
|
|
21070
21720
|
throw new TypeError(instances.length === 0 ? "No running AbsoluteJS dev server was found for this project. Start `bun dev`, wait for iOS to report ready, then run `absolute mobile test ios`." : "Multiple dev servers are running for this project. Select one with mobile test ios --port <port>.");
|
|
21071
21721
|
const [instance] = instances;
|
|
@@ -21179,8 +21829,8 @@ Emulator setup verification:`);
|
|
|
21179
21829
|
throw new Error(`${label} failed: ${result.stderr.trim() || result.stdout.trim() || `status ${result.exitCode}`}`);
|
|
21180
21830
|
return result;
|
|
21181
21831
|
}, writeIosFailureArtifacts = async (options) => {
|
|
21182
|
-
await
|
|
21183
|
-
const screenshot =
|
|
21832
|
+
await mkdir16(options.artifactRoot, { recursive: true });
|
|
21833
|
+
const screenshot = join55(options.artifactRoot, "ios-failure.png");
|
|
21184
21834
|
const screenshotResult = captureCommand4([
|
|
21185
21835
|
options.xcrun,
|
|
21186
21836
|
"simctl",
|
|
@@ -21189,8 +21839,8 @@ Emulator setup verification:`);
|
|
|
21189
21839
|
"screenshot",
|
|
21190
21840
|
screenshot
|
|
21191
21841
|
]);
|
|
21192
|
-
const diagnosticPath =
|
|
21193
|
-
await
|
|
21842
|
+
const diagnosticPath = join55(options.artifactRoot, "ios-failure.json");
|
|
21843
|
+
await writeFile18(diagnosticPath, `${JSON.stringify({
|
|
21194
21844
|
appId: options.appId,
|
|
21195
21845
|
error: options.error instanceof Error ? options.error.message : String(options.error),
|
|
21196
21846
|
platform: "ios",
|
|
@@ -21215,8 +21865,8 @@ Emulator setup verification:`);
|
|
|
21215
21865
|
}, absolutejsVersionForReport = async () => {
|
|
21216
21866
|
let absolutejsVersion = process.env.ABSOLUTE_VERSION ?? "unknown";
|
|
21217
21867
|
const versions = await Promise.all([
|
|
21218
|
-
|
|
21219
|
-
|
|
21868
|
+
resolve45(import.meta.dir, "..", "..", "package.json"),
|
|
21869
|
+
resolve45(import.meta.dir, "..", "..", "..", "package.json")
|
|
21220
21870
|
].map((candidate) => readPackageVersionForIosReport(candidate).catch(() => "unknown")));
|
|
21221
21871
|
for (const version2 of versions) {
|
|
21222
21872
|
if (version2 === "unknown")
|
|
@@ -21376,6 +22026,7 @@ Emulator setup verification:`);
|
|
|
21376
22026
|
}
|
|
21377
22027
|
}, testIos = async (args) => {
|
|
21378
22028
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
22029
|
+
requireCapacitorEngine(mobile, "mobile test ios");
|
|
21379
22030
|
const { https, instance, port } = requireIosTestContext(args, projectRoot);
|
|
21380
22031
|
if (!mobile.platforms.includes("ios"))
|
|
21381
22032
|
throw new TypeError("mobile test ios requires ios in mobile.platforms.");
|
|
@@ -21434,8 +22085,8 @@ Emulator setup verification:`);
|
|
|
21434
22085
|
mobile.appId
|
|
21435
22086
|
], "iOS app launch");
|
|
21436
22087
|
await waitForIosHmrClient({ https, port, timeoutMs });
|
|
21437
|
-
await
|
|
21438
|
-
const screenshot =
|
|
22088
|
+
await mkdir16(artifactRoot, { recursive: true });
|
|
22089
|
+
const screenshot = join55(artifactRoot, "ios-simulator.png");
|
|
21439
22090
|
requireCapturedCommand([xcrun, "simctl", "io", simulator.udid, "screenshot", screenshot], "iOS simulator screenshot");
|
|
21440
22091
|
const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
|
|
21441
22092
|
const report = {
|
|
@@ -21585,6 +22236,7 @@ Emulator setup verification:`);
|
|
|
21585
22236
|
var init_mobile = __esm(() => {
|
|
21586
22237
|
init_dependencies();
|
|
21587
22238
|
init_capacitorProject();
|
|
22239
|
+
init_expoProject();
|
|
21588
22240
|
init_config();
|
|
21589
22241
|
init_nativeDeepLinks();
|
|
21590
22242
|
init_nativeDeviceCapabilities();
|
|
@@ -21651,10 +22303,10 @@ var exports_typecheck = {};
|
|
|
21651
22303
|
__export(exports_typecheck, {
|
|
21652
22304
|
typecheck: () => typecheck
|
|
21653
22305
|
});
|
|
21654
|
-
import { resolve as
|
|
22306
|
+
import { resolve as resolve46, join as join56 } from "path";
|
|
21655
22307
|
import { existsSync as existsSync43, readFileSync as readFileSync40 } from "fs";
|
|
21656
|
-
import { mkdir as
|
|
21657
|
-
var isCommandService3 = (service) => service.kind === "command" || Array.isArray(service.command), resolveConfigPath = (configPath2) =>
|
|
22308
|
+
import { mkdir as mkdir17, writeFile as writeFile19 } from "fs/promises";
|
|
22309
|
+
var isCommandService3 = (service) => service.kind === "command" || Array.isArray(service.command), resolveConfigPath = (configPath2) => resolve46(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts"), getTypecheckTargets = async (configPath2) => {
|
|
21658
22310
|
if (!existsSync43(resolveConfigPath(configPath2))) {
|
|
21659
22311
|
const defaultService = {};
|
|
21660
22312
|
return [defaultService];
|
|
@@ -21676,7 +22328,7 @@ var isCommandService3 = (service) => service.kind === "command" || Array.isArray
|
|
|
21676
22328
|
const exitCode = await proc.exited;
|
|
21677
22329
|
return { exitCode, name, output: (stdout + stderr).trim() };
|
|
21678
22330
|
}, shellEscape = (value) => `'${value.replaceAll("'", "'\\''")}'`, runShell = async (name, command) => run(name, ["/bin/bash", "-lc", command]), findBin = (name) => {
|
|
21679
|
-
const local =
|
|
22331
|
+
const local = resolve46("node_modules", ".bin", name);
|
|
21680
22332
|
return existsSync43(local) ? local : null;
|
|
21681
22333
|
}, ANSI_COLOR_REGEX, ANSI_PURPLE_REGEX, ANSI_CYAN_REGEX, ANSI_TOKEN_END_REGEX, stripAnsi4 = (str) => str.replace(ANSI_COLOR_REGEX, ""), formatSvelteOutput = (output) => {
|
|
21682
22334
|
const cwd = `${process.cwd()}/`;
|
|
@@ -21724,15 +22376,15 @@ Found ${errorCount} error${suffix}.`;
|
|
|
21724
22376
|
return formatted;
|
|
21725
22377
|
}, ABSOLUTE_INTERNAL_EXCLUDES, resolveAbsoluteTypeFile = (fileName) => {
|
|
21726
22378
|
const candidates = [
|
|
21727
|
-
|
|
21728
|
-
|
|
21729
|
-
|
|
21730
|
-
|
|
22379
|
+
resolve46("node_modules/@absolutejs/absolute/dist/types", fileName),
|
|
22380
|
+
resolve46(import.meta.dir, "../types", fileName),
|
|
22381
|
+
resolve46(import.meta.dir, "../../types", fileName),
|
|
22382
|
+
resolve46(import.meta.dir, "../../../types", fileName)
|
|
21731
22383
|
];
|
|
21732
22384
|
return candidates.find((candidate) => existsSync43(candidate)) ?? candidates[0];
|
|
21733
22385
|
}, ABSOLUTE_TYPECHECK_FILES, readProjectTsconfig = () => {
|
|
21734
22386
|
try {
|
|
21735
|
-
return JSON.parse(readFileSync40(
|
|
22387
|
+
return JSON.parse(readFileSync40(resolve46("tsconfig.json"), "utf-8"));
|
|
21736
22388
|
} catch {
|
|
21737
22389
|
return {};
|
|
21738
22390
|
}
|
|
@@ -21760,27 +22412,27 @@ Found ${errorCount} error${suffix}.`;
|
|
|
21760
22412
|
console.error("\x1B[31m\u2717\x1B[0m vue-tsc is required for Vue type checking. Install it: bun add -d vue-tsc");
|
|
21761
22413
|
process.exit(1);
|
|
21762
22414
|
}
|
|
21763
|
-
const vueTsconfigPath =
|
|
21764
|
-
await
|
|
22415
|
+
const vueTsconfigPath = join56(cacheDir, "tsconfig.vue-check.json");
|
|
22416
|
+
await writeFile19(vueTsconfigPath, JSON.stringify({
|
|
21765
22417
|
compilerOptions: {
|
|
21766
22418
|
rootDir: ".."
|
|
21767
22419
|
},
|
|
21768
22420
|
exclude: getProjectTypecheckExcludes(),
|
|
21769
|
-
extends:
|
|
22421
|
+
extends: resolve46("tsconfig.json"),
|
|
21770
22422
|
include: getProjectTypecheckIncludes()
|
|
21771
22423
|
}, null, "\t"));
|
|
21772
22424
|
const base = [
|
|
21773
22425
|
vueTscBin,
|
|
21774
22426
|
"--noEmit",
|
|
21775
22427
|
"--project",
|
|
21776
|
-
|
|
22428
|
+
resolve46(vueTsconfigPath),
|
|
21777
22429
|
"--pretty"
|
|
21778
22430
|
];
|
|
21779
22431
|
const cached = await run("vue-tsc", [
|
|
21780
22432
|
...base,
|
|
21781
22433
|
"--incremental",
|
|
21782
22434
|
"--tsBuildInfoFile",
|
|
21783
|
-
|
|
22435
|
+
join56(cacheDir, "vue-tsc.tsbuildinfo")
|
|
21784
22436
|
]);
|
|
21785
22437
|
if (cached.exitCode === 0 || cached.output.length > 0)
|
|
21786
22438
|
return cached;
|
|
@@ -21791,8 +22443,8 @@ Found ${errorCount} error${suffix}.`;
|
|
|
21791
22443
|
console.error("\x1B[31m\u2717\x1B[0m @angular/compiler-cli is required for Angular type checking. Install it: bun add -d @angular/compiler-cli");
|
|
21792
22444
|
process.exit(1);
|
|
21793
22445
|
}
|
|
21794
|
-
const angularTsconfigPath =
|
|
21795
|
-
await
|
|
22446
|
+
const angularTsconfigPath = join56(cacheDir, "tsconfig.angular-check.json");
|
|
22447
|
+
await writeFile19(angularTsconfigPath, JSON.stringify({
|
|
21796
22448
|
angularCompilerOptions: {
|
|
21797
22449
|
strictTemplates: true
|
|
21798
22450
|
},
|
|
@@ -21801,32 +22453,32 @@ Found ${errorCount} error${suffix}.`;
|
|
|
21801
22453
|
rootDir: ".."
|
|
21802
22454
|
},
|
|
21803
22455
|
exclude: ABSOLUTE_INTERNAL_EXCLUDES.map(toGeneratedConfigPath),
|
|
21804
|
-
extends:
|
|
22456
|
+
extends: resolve46("tsconfig.json"),
|
|
21805
22457
|
include: [`../${angularDir}/**/*`]
|
|
21806
22458
|
}, null, "\t"));
|
|
21807
|
-
return runShell("ngc", `${shellEscape(ngcBin)} -p ${shellEscape(
|
|
22459
|
+
return runShell("ngc", `${shellEscape(ngcBin)} -p ${shellEscape(resolve46(angularTsconfigPath))}`);
|
|
21808
22460
|
}, buildTscCheck = (cacheDir) => {
|
|
21809
22461
|
const tscBin = findBin("tsc");
|
|
21810
22462
|
if (!tscBin) {
|
|
21811
22463
|
console.error("\x1B[31m\u2717\x1B[0m typescript is required for type checking. Install it: bun add -d typescript");
|
|
21812
22464
|
process.exit(1);
|
|
21813
22465
|
}
|
|
21814
|
-
const tscConfigPath =
|
|
21815
|
-
return
|
|
22466
|
+
const tscConfigPath = join56(cacheDir, "tsconfig.typecheck.json");
|
|
22467
|
+
return writeFile19(tscConfigPath, JSON.stringify({
|
|
21816
22468
|
compilerOptions: {
|
|
21817
22469
|
rootDir: ".."
|
|
21818
22470
|
},
|
|
21819
22471
|
exclude: getProjectTypecheckExcludes(),
|
|
21820
|
-
extends:
|
|
22472
|
+
extends: resolve46("tsconfig.json"),
|
|
21821
22473
|
include: getProjectTypecheckIncludes()
|
|
21822
22474
|
}, null, "\t")).then(() => run("tsc", [
|
|
21823
22475
|
tscBin,
|
|
21824
22476
|
"--noEmit",
|
|
21825
22477
|
"--project",
|
|
21826
|
-
|
|
22478
|
+
resolve46(tscConfigPath),
|
|
21827
22479
|
"--incremental",
|
|
21828
22480
|
"--tsBuildInfoFile",
|
|
21829
|
-
|
|
22481
|
+
join56(cacheDir, "tsc.tsbuildinfo"),
|
|
21830
22482
|
"--pretty"
|
|
21831
22483
|
]));
|
|
21832
22484
|
}, buildSvelteCheck = async (cacheDir, svelteDir) => {
|
|
@@ -21835,16 +22487,16 @@ Found ${errorCount} error${suffix}.`;
|
|
|
21835
22487
|
console.error("\x1B[31m\u2717\x1B[0m svelte-check is required for Svelte type checking. Install it: bun add -d svelte-check");
|
|
21836
22488
|
process.exit(1);
|
|
21837
22489
|
}
|
|
21838
|
-
const svelteTsconfigPath =
|
|
21839
|
-
await
|
|
21840
|
-
extends:
|
|
22490
|
+
const svelteTsconfigPath = join56(cacheDir, "tsconfig.svelte-check.json");
|
|
22491
|
+
await writeFile19(svelteTsconfigPath, JSON.stringify({
|
|
22492
|
+
extends: resolve46("tsconfig.json"),
|
|
21841
22493
|
files: ABSOLUTE_TYPECHECK_FILES,
|
|
21842
22494
|
include: [`../${svelteDir}/**/*`]
|
|
21843
22495
|
}, null, "\t"));
|
|
21844
22496
|
return run("svelte-check", [
|
|
21845
22497
|
svelteBin,
|
|
21846
22498
|
"--tsconfig",
|
|
21847
|
-
|
|
22499
|
+
resolve46(svelteTsconfigPath),
|
|
21848
22500
|
"--threshold",
|
|
21849
22501
|
"error",
|
|
21850
22502
|
"--compiler-warnings",
|
|
@@ -21865,7 +22517,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
21865
22517
|
...new Set(targets.map((config) => config.angularDirectory).filter((dir) => typeof dir === "string" && dir.length > 0))
|
|
21866
22518
|
];
|
|
21867
22519
|
const cacheDir = ".absolutejs";
|
|
21868
|
-
await
|
|
22520
|
+
await mkdir17(cacheDir, { recursive: true });
|
|
21869
22521
|
const checks = [];
|
|
21870
22522
|
checks.push(hasVue ? buildVueTscCheck(cacheDir) : buildTscCheck(cacheDir));
|
|
21871
22523
|
for (const svelteDir of hasSvelte ? svelteDirs : []) {
|
|
@@ -22038,11 +22690,11 @@ var DEFAULT_RELAY_PORT = 8787, DEFAULT_REQUEST_TIMEOUT_MS = 30000, headersToObje
|
|
|
22038
22690
|
url: url.pathname + url.search,
|
|
22039
22691
|
...bodyBytes && bodyBytes.length > 0 ? { bodyBase64: Buffer.from(bodyBytes).toString("base64") } : {}
|
|
22040
22692
|
};
|
|
22041
|
-
const responsePromise = new Promise((
|
|
22042
|
-
pending.set(id,
|
|
22693
|
+
const responsePromise = new Promise((resolve47) => {
|
|
22694
|
+
pending.set(id, resolve47);
|
|
22043
22695
|
});
|
|
22044
22696
|
client.send(encodeTunnelMessage(message));
|
|
22045
|
-
const timeout = new Promise((
|
|
22697
|
+
const timeout = new Promise((resolve47) => setTimeout(() => resolve47({ id, message: "timeout", type: "error" }), requestTimeoutMs));
|
|
22046
22698
|
const result = await Promise.race([responsePromise, timeout]);
|
|
22047
22699
|
pending.delete(id);
|
|
22048
22700
|
if (result.type === "error") {
|
|
@@ -23015,7 +23667,9 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
23015
23667
|
if (mobileConfig && mobileInteractive) {
|
|
23016
23668
|
try {
|
|
23017
23669
|
const normalized = normalizeAbsoluteMobileConfig(mobileConfig, process.cwd());
|
|
23018
|
-
if (normalized.
|
|
23670
|
+
if (normalized.engine === "expo") {
|
|
23671
|
+
console.log(cliTag("\x1B[35m", "Expo hybrid support is experimental. AbsoluteJS web development is running; start Metro from .absolutejs/mobile/expo for the native shell."));
|
|
23672
|
+
} else if (normalized.platforms.includes("android")) {
|
|
23019
23673
|
const androidTarget = options.androidDevice ? "device" : "emulator";
|
|
23020
23674
|
let ready = androidToolchainReady(await inspectAbsoluteMobileToolchain(), androidTarget);
|
|
23021
23675
|
if (!ready) {
|
|
@@ -23042,7 +23696,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
23042
23696
|
}
|
|
23043
23697
|
}
|
|
23044
23698
|
}
|
|
23045
|
-
if (normalized.platforms.includes("ios")) {
|
|
23699
|
+
if (normalized.engine === "capacitor" && normalized.platforms.includes("ios")) {
|
|
23046
23700
|
if (detectAbsoluteMobileHost() !== "macos") {
|
|
23047
23701
|
const remote = selectedRemoteMacProfile ?? await getAbsoluteRemoteMacProfile();
|
|
23048
23702
|
if (!remote) {
|
|
@@ -24406,7 +25060,7 @@ import {
|
|
|
24406
25060
|
writeFileSync as writeFileSync6
|
|
24407
25061
|
} from "fs";
|
|
24408
25062
|
import { createConnection } from "net";
|
|
24409
|
-
import { resolve as
|
|
25063
|
+
import { resolve as resolve23 } from "path";
|
|
24410
25064
|
|
|
24411
25065
|
// src/cli/workspaceTui.ts
|
|
24412
25066
|
init_constants();
|
|
@@ -24968,18 +25622,18 @@ var createWorkspaceTui = ({
|
|
|
24968
25622
|
|
|
24969
25623
|
// src/cli/scripts/workspace.ts
|
|
24970
25624
|
init_utils();
|
|
24971
|
-
var sourceServerBootstrap2 =
|
|
24972
|
-
var serverBootstrap2 = existsSync12(sourceServerBootstrap2) ? sourceServerBootstrap2 :
|
|
25625
|
+
var sourceServerBootstrap2 = resolve23(import.meta.dir, "../../dev/serverBootstrap.ts");
|
|
25626
|
+
var serverBootstrap2 = existsSync12(sourceServerBootstrap2) ? sourceServerBootstrap2 : resolve23(import.meta.dir, "../dev/serverBootstrap.js");
|
|
24973
25627
|
var ANSI_REGEX2 = new RegExp(`${String.fromCharCode(ANSI_ESCAPE_CODE)}\\[[0-?]*[ -/]*[@-~]`, "g");
|
|
24974
25628
|
var sleep = (durationMs) => Bun.sleep(durationMs);
|
|
24975
25629
|
var stripAnsi3 = (value) => value.replace(ANSI_REGEX2, "");
|
|
24976
25630
|
var sanitizeLogFileName = (value) => value.replace(/[^a-zA-Z0-9._-]/g, "_") || "unknown";
|
|
24977
25631
|
var createWorkspaceLogSink = (appendLog) => {
|
|
24978
|
-
const logDirectory =
|
|
25632
|
+
const logDirectory = resolve23(".absolutejs", "workspace", "logs");
|
|
24979
25633
|
mkdirSync7(logDirectory, { recursive: true });
|
|
24980
|
-
readdirSync2(logDirectory).filter((file) => file.endsWith(".log")).forEach((file) => unlinkSync3(
|
|
24981
|
-
writeFileSync6(
|
|
24982
|
-
writeFileSync6(
|
|
25634
|
+
readdirSync2(logDirectory).filter((file) => file.endsWith(".log")).forEach((file) => unlinkSync3(resolve23(logDirectory, file)));
|
|
25635
|
+
writeFileSync6(resolve23(logDirectory, "all.log"), "");
|
|
25636
|
+
writeFileSync6(resolve23(logDirectory, "workspace.log"), "");
|
|
24983
25637
|
const initializedSources = new Set(["workspace"]);
|
|
24984
25638
|
const writeLog = (source, message, level) => {
|
|
24985
25639
|
const cleanMessage = stripAnsi3(message).trimEnd();
|
|
@@ -24989,13 +25643,13 @@ var createWorkspaceLogSink = (appendLog) => {
|
|
|
24989
25643
|
const timestamp = new Date().toISOString();
|
|
24990
25644
|
const line = `[${timestamp}] [${level}] [${source}] ${cleanMessage}
|
|
24991
25645
|
`;
|
|
24992
|
-
const sourceFile =
|
|
25646
|
+
const sourceFile = resolve23(logDirectory, `${sanitizeLogFileName(source)}.log`);
|
|
24993
25647
|
if (!initializedSources.has(source)) {
|
|
24994
25648
|
writeFileSync6(sourceFile, "");
|
|
24995
25649
|
initializedSources.add(source);
|
|
24996
25650
|
}
|
|
24997
25651
|
appendFileSync(sourceFile, line);
|
|
24998
|
-
appendFileSync(
|
|
25652
|
+
appendFileSync(resolve23(logDirectory, "all.log"), line);
|
|
24999
25653
|
};
|
|
25000
25654
|
return {
|
|
25001
25655
|
appendLog: (source, message, level = "info") => {
|
|
@@ -25019,9 +25673,9 @@ var readPackageVersion3 = (candidate) => {
|
|
|
25019
25673
|
};
|
|
25020
25674
|
var resolvePackageVersion2 = () => {
|
|
25021
25675
|
const candidates = [
|
|
25022
|
-
|
|
25023
|
-
|
|
25024
|
-
|
|
25676
|
+
resolve23(import.meta.dir, "..", "..", "package.json"),
|
|
25677
|
+
resolve23(import.meta.dir, "..", "..", "..", "package.json"),
|
|
25678
|
+
resolve23(import.meta.dir, "..", "..", "..", "..", "package.json")
|
|
25025
25679
|
];
|
|
25026
25680
|
for (const candidate of candidates) {
|
|
25027
25681
|
const version2 = readPackageVersion3(candidate);
|
|
@@ -25375,15 +26029,15 @@ var createWorkspaceServiceEnv = (services) => {
|
|
|
25375
26029
|
var getDefinedProcessEnv = () => Object.fromEntries(Object.entries(process.env).filter((entry) => typeof entry[1] === "string"));
|
|
25376
26030
|
var resolveAbsoluteServiceConfigPath = (service, cwd, options) => {
|
|
25377
26031
|
if (service.config)
|
|
25378
|
-
return
|
|
26032
|
+
return resolve23(cwd, service.config);
|
|
25379
26033
|
if (options.configPath)
|
|
25380
|
-
return
|
|
26034
|
+
return resolve23(options.configPath);
|
|
25381
26035
|
if (process.env.ABSOLUTE_CONFIG)
|
|
25382
|
-
return
|
|
26036
|
+
return resolve23(process.env.ABSOLUTE_CONFIG);
|
|
25383
26037
|
return;
|
|
25384
26038
|
};
|
|
25385
26039
|
var resolveService = (name, service, workspaceEnv, options) => {
|
|
25386
|
-
const cwd =
|
|
26040
|
+
const cwd = resolve23(service.cwd ?? ".");
|
|
25387
26041
|
const envVars = Object.assign(getDefinedProcessEnv(), workspaceEnv, service.port ? { PORT: String(service.port) } : {}, service.env, {
|
|
25388
26042
|
ABSOLUTE_INSTANCE_MANAGED: "1",
|
|
25389
26043
|
ABSOLUTE_WORKSPACE_MANAGED: "1",
|
|
@@ -25395,7 +26049,7 @@ var resolveService = (name, service, workspaceEnv, options) => {
|
|
|
25395
26049
|
if (isAbsoluteService(service)) {
|
|
25396
26050
|
const configPath2 = resolveAbsoluteServiceConfigPath(service, cwd, options);
|
|
25397
26051
|
Object.assign(envVars, configPath2 ? { ABSOLUTE_CONFIG: configPath2 } : {}, {
|
|
25398
|
-
ABSOLUTE_SERVER_ENTRY:
|
|
26052
|
+
ABSOLUTE_SERVER_ENTRY: resolve23(cwd, service.entry ?? DEFAULT_SERVER_ENTRY)
|
|
25399
26053
|
});
|
|
25400
26054
|
const command = [
|
|
25401
26055
|
process.execPath,
|
|
@@ -25425,8 +26079,8 @@ var resolveService = (name, service, workspaceEnv, options) => {
|
|
|
25425
26079
|
var resolveServiceBuildDirectory = (service) => {
|
|
25426
26080
|
if (!isAbsoluteService(service))
|
|
25427
26081
|
return null;
|
|
25428
|
-
const cwd =
|
|
25429
|
-
return
|
|
26082
|
+
const cwd = resolve23(service.cwd ?? ".");
|
|
26083
|
+
return resolve23(cwd, service.buildDirectory ?? "build");
|
|
25430
26084
|
};
|
|
25431
26085
|
var findSharedWorkspaceBuildDirectories = (services) => {
|
|
25432
26086
|
const byBuildDirectory = new Map;
|
|
@@ -25644,7 +26298,7 @@ var workspace = async (subcommand, options) => {
|
|
|
25644
26298
|
frameworks: [],
|
|
25645
26299
|
host: getServicePublicHost(resolved.service),
|
|
25646
26300
|
https: getServiceProtocol(resolved.service) === "https",
|
|
25647
|
-
logFile:
|
|
26301
|
+
logFile: resolve23(workspaceLogs.logDirectory, `${sanitizeLogFileName(name)}.log`),
|
|
25648
26302
|
name,
|
|
25649
26303
|
pid: processHandle.pid,
|
|
25650
26304
|
port: resolved.service.port ?? null,
|
|
@@ -25955,7 +26609,7 @@ if (command === "dev") {
|
|
|
25955
26609
|
console.error(" prepare [entry] [--outdir dir] Build production assets and server without launching");
|
|
25956
26610
|
console.error(" start [entry] [--outdir dir] [--prebuilt] Start production server");
|
|
25957
26611
|
console.error(" compile [entry] [--outdir dir] [--outfile path] Compile standalone executable");
|
|
25958
|
-
console.error(" mobile <init|sync|inspect|ci|pair|remotes|doctor|test> Manage Capacitor
|
|
26612
|
+
console.error(" mobile <init|sync|inspect|ci|pair|remotes|doctor|test> Manage Capacitor apps and the experimental Expo hybrid shell");
|
|
25959
26613
|
console.error(" config [--port n] Open the unified config UI (ESLint, tsconfig, Prettier)");
|
|
25960
26614
|
console.error(" db <backup|restore|seed> Backup/restore any Postgres DB (ORM-agnostic, upsert by PK) or run the seed script");
|
|
25961
26615
|
console.error(" doctor [--fix] [--json] Diagnose the project (bun, type graph, config, framework dirs, env, port)");
|