@absolutejs/absolute 0.20.0-beta.27 → 0.20.0-beta.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -17460,6 +17460,19 @@ var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POL
17460
17460
  await mkdir11(dirname28(absolutePath), { recursive: true });
17461
17461
  await writeFile13(absolutePath, Buffer.from(data, "base64"));
17462
17462
  return absolutePath;
17463
+ },
17464
+ tap: async (coordinateX, coordinateY) => {
17465
+ if (!Number.isFinite(coordinateX) || !Number.isFinite(coordinateY) || coordinateX < 0 || coordinateY < 0) {
17466
+ throw new TypeError("Android WebView tap coordinates must be finite non-negative numbers.");
17467
+ }
17468
+ await connection.command("Input.dispatchTouchEvent", {
17469
+ touchPoints: [{ x: coordinateX, y: coordinateY }],
17470
+ type: "touchStart"
17471
+ });
17472
+ await connection.command("Input.dispatchTouchEvent", {
17473
+ touchPoints: [],
17474
+ type: "touchEnd"
17475
+ });
17463
17476
  }
17464
17477
  };
17465
17478
  }, failForward = (error, options, capture, hostPort) => {
@@ -18242,7 +18255,32 @@ var init_androidTestReport = __esm(() => {
18242
18255
  ["CAP-01", "Complete automatic device-capability provisioning checks."],
18243
18256
  [
18244
18257
  "SYSUI-01",
18245
- "Complete keyboard and modern edge-to-edge system-bars checks."
18258
+ "Confirm Keyboard and System Bars are provisioned automatically."
18259
+ ],
18260
+ [
18261
+ "SYSUI-02",
18262
+ "Confirm the web fallback reports provider-neutral capabilities."
18263
+ ],
18264
+ ["SYSUI-03", "Confirm the real WebView selects the native adapters."],
18265
+ [
18266
+ "SYSUI-04",
18267
+ "Open and dismiss the native keyboard five times without stale state."
18268
+ ],
18269
+ [
18270
+ "SYSUI-05",
18271
+ "Confirm light and dark foreground choices reach both Android system bars."
18272
+ ],
18273
+ [
18274
+ "SYSUI-06",
18275
+ "Hide and restore system bars and confirm restored content remains inside the safe area."
18276
+ ],
18277
+ [
18278
+ "SYSUI-07",
18279
+ "Rotate and relaunch while preserving the route and native adapters."
18280
+ ],
18281
+ [
18282
+ "SYSUI-08",
18283
+ "Apply a System UI component edit through native HMR and record its timing."
18246
18284
  ],
18247
18285
  [
18248
18286
  "FILES-01",
@@ -46,6 +46,29 @@ const isStringRecord = (value: unknown): value is Record<string, string> =>
46
46
  Object.values(value).every((entry) => typeof entry === 'string');
47
47
 
48
48
  restoreAbsoluteHmrApply();
49
+ const nativeDeviceAdapterPath = '/__absolute/native-device-adapter.js';
50
+ const nativeDeviceAdapterReady =
51
+ absoluteHmrClientTarget() === 'web'
52
+ ? Promise.resolve()
53
+ : import(nativeDeviceAdapterPath).then(() => undefined);
54
+ Reflect.set(
55
+ globalThis,
56
+ '__ABS_NATIVE_DEVICES_READY__',
57
+ nativeDeviceAdapterReady
58
+ );
59
+ Reflect.set(globalThis, '__ABS_NATIVE_DEVICES_READY_STATE__', 'loading');
60
+ void nativeDeviceAdapterReady.then(
61
+ () => {
62
+ Reflect.set(globalThis, '__ABS_NATIVE_DEVICES_READY_STATE__', 'ready');
63
+ },
64
+ (error) => {
65
+ Reflect.set(globalThis, '__ABS_NATIVE_DEVICES_READY_STATE__', 'failed');
66
+ console.error(
67
+ '[Absolute Mobile] Native device adapter failed to load:',
68
+ error
69
+ );
70
+ }
71
+ );
49
72
  const removeNativeSyncDevtools =
50
73
  absoluteHmrClientTarget() === 'web'
51
74
  ? () => undefined
package/dist/index.js CHANGED
@@ -29893,6 +29893,7 @@ var init_buildDepVendor = __esm(() => {
29893
29893
  var exports_devBuild = {};
29894
29894
  __export(exports_devBuild, {
29895
29895
  devBuild: () => devBuild,
29896
+ collectDepVendorSourceDirs: () => collectDepVendorSourceDirs,
29896
29897
  applyConfigChanges: () => applyConfigChanges
29897
29898
  });
29898
29899
  import { readdir as readdir6 } from "fs/promises";
@@ -29905,7 +29906,8 @@ var FRAMEWORK_DIR_KEYS, collectDepVendorSourceDirs = (config) => {
29905
29906
  config.vueDirectory,
29906
29907
  config.angularDirectory,
29907
29908
  config.htmlDirectory,
29908
- config.htmxDirectory
29909
+ config.htmxDirectory,
29910
+ resolve47(import.meta.dir, "../dev/client")
29909
29911
  ].filter((dir) => Boolean(dir));
29910
29912
  return Array.from(new Set(configuredDirs));
29911
29913
  }, parseDirectoryConfig = (source) => {
@@ -30905,6 +30907,53 @@ var init_requestInspector = __esm(() => {
30905
30907
  }).as("global");
30906
30908
  });
30907
30909
 
30910
+ // src/mobile/devDeviceAdapter.ts
30911
+ var exports_devDeviceAdapter = {};
30912
+ __export(exports_devDeviceAdapter, {
30913
+ buildAbsoluteNativeDevAdapter: () => buildAbsoluteNativeDevAdapter,
30914
+ absoluteNativeDevAdapterSource: () => absoluteNativeDevAdapterSource
30915
+ });
30916
+ import { mkdtemp as mkdtemp3, rm as rm15, writeFile as writeFile9 } from "fs/promises";
30917
+ import { join as join52 } from "path";
30918
+ import { tmpdir } from "os";
30919
+ var absoluteNativeDevAdapterSource = (projectRoot, mobile, resolveModule = (specifier) => specifier) => {
30920
+ const plan = resolveAbsoluteDeviceCapabilityPlan(projectRoot);
30921
+ const imports = plan.capabilities.map((name, index) => {
30922
+ const provider = plan.providers[name];
30923
+ if (!provider)
30924
+ throw new TypeError(`Missing device capability provider ${name}.`);
30925
+ return `import { ${provider.factory} as absoluteDeviceCapability${index} } from ${JSON.stringify(resolveModule(provider.module))};`;
30926
+ });
30927
+ const capabilities = plan.capabilities.map((name, index) => `${JSON.stringify(name)}: absoluteDeviceCapability${index}()`).join(", ");
30928
+ return [
30929
+ `import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(resolveModule("@absolutejs/devices-capacitor"))};`,
30930
+ ...imports,
30931
+ `installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(`absolutejs.${mobile.appId}.`)}${capabilities ? `, ${capabilities}` : ""} });`
30932
+ ].join(`
30933
+ `);
30934
+ }, buildAbsoluteNativeDevAdapter = async (projectRoot, mobile) => {
30935
+ const temporaryDirectory = await mkdtemp3(join52(tmpdir(), "absolutejs-native-dev-adapter-"));
30936
+ const entry = join52(temporaryDirectory, "entry.ts");
30937
+ try {
30938
+ await writeFile9(entry, absoluteNativeDevAdapterSource(projectRoot, mobile, (specifier) => Bun.resolveSync(specifier, projectRoot)));
30939
+ const result = await Bun.build({
30940
+ entrypoints: [entry],
30941
+ format: "esm",
30942
+ minify: true,
30943
+ target: "browser"
30944
+ });
30945
+ if (!result.success || result.outputs.length !== 1) {
30946
+ throw new AggregateError(result.logs, "Failed to build the AbsoluteJS native development device adapter.");
30947
+ }
30948
+ return result.outputs[0]?.text() ?? "";
30949
+ } finally {
30950
+ await rm15(temporaryDirectory, { force: true, recursive: true });
30951
+ }
30952
+ };
30953
+ var init_devDeviceAdapter = __esm(() => {
30954
+ init_deviceCapabilities();
30955
+ });
30956
+
30908
30957
  // src/core/prerender.ts
30909
30958
  var exports_prerender = {};
30910
30959
  __export(exports_prerender, {
@@ -30916,7 +30965,7 @@ __export(exports_prerender, {
30916
30965
  PRERENDER_BYPASS_HEADER: () => PRERENDER_BYPASS_HEADER
30917
30966
  });
30918
30967
  import { mkdirSync as mkdirSync16, readFileSync as readFileSync34 } from "fs";
30919
- import { join as join52 } from "path";
30968
+ import { join as join53 } from "path";
30920
30969
  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) => {
30921
30970
  const metaPath = htmlPath.replace(/\.html$/, ".meta");
30922
30971
  await Bun.write(metaPath, String(Date.now()));
@@ -30986,7 +31035,7 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
30986
31035
  if (!isCompleteHtml(html))
30987
31036
  return false;
30988
31037
  const fileName = routeToFilename(route);
30989
- const filePath = join52(prerenderDir, fileName);
31038
+ const filePath = join53(prerenderDir, fileName);
30990
31039
  await Bun.write(filePath, html);
30991
31040
  await writeTimestamp(filePath);
30992
31041
  return true;
@@ -31016,13 +31065,13 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
31016
31065
  return;
31017
31066
  }
31018
31067
  const fileName = routeToFilename(route);
31019
- const filePath = join52(prerenderDir, fileName);
31068
+ const filePath = join53(prerenderDir, fileName);
31020
31069
  await Bun.write(filePath, html);
31021
31070
  await writeTimestamp(filePath);
31022
31071
  result.routes.set(route, filePath);
31023
31072
  log2?.(` Pre-rendered ${route} \u2192 ${fileName} (${html.length} bytes)`);
31024
31073
  }, prerender = async (port, outDir, staticConfig, log2) => {
31025
- const prerenderDir = join52(outDir, "_prerendered");
31074
+ const prerenderDir = join53(outDir, "_prerendered");
31026
31075
  mkdirSync16(prerenderDir, { recursive: true });
31027
31076
  const baseUrl = `http://localhost:${port}`;
31028
31077
  let routes;
@@ -31148,7 +31197,7 @@ import {
31148
31197
  watch as watch2
31149
31198
  } from "fs";
31150
31199
  import { createHash as createHash9 } from "crypto";
31151
- import { dirname as dirname33, join as join56, resolve as resolve50 } from "path";
31200
+ import { dirname as dirname33, join as join57, resolve as resolve50 } from "path";
31152
31201
  var ATOMIC_RECOVERY_WINDOW_MS = 1000, RELOAD_DEBOUNCE_MS = 80, ENTRY_IMPORT_RETRY_DELAY_MS = 250, MAX_ENTRY_IMPORT_ATTEMPTS = 3, WATCH_FALLBACK_INTERVAL_MS = 250, ATOMIC_WRITE_TEMP_PATTERNS2, isAtomicWriteTemp = (filename) => filename.endsWith(".tmp") || filename.includes(".tmp.") || filename.endsWith("~") || filename.startsWith(".#") || filename.startsWith(".absolutejs-hmr-") || ATOMIC_WRITE_TEMP_PATTERNS2.some((pattern) => pattern.test(filename)), fileHash = (path) => {
31153
31202
  try {
31154
31203
  return createHash9("sha256").update(readFileSync38(path)).digest("hex");
@@ -31190,7 +31239,7 @@ var ATOMIC_RECOVERY_WINDOW_MS = 1000, RELOAD_DEBOUNCE_MS = 80, ENTRY_IMPORT_RETR
31190
31239
  let pendingEntryCause = null;
31191
31240
  let siblingSequence = 0;
31192
31241
  const importFreshEntry = async (attempt = 1) => {
31193
- const siblingPath = join56(entryDir, `.absolutejs-hmr-${process.pid}-${siblingSequence++}.ts`);
31242
+ const siblingPath = join57(entryDir, `.absolutejs-hmr-${process.pid}-${siblingSequence++}.ts`);
31194
31243
  let failure;
31195
31244
  try {
31196
31245
  copyFileSync4(entryPath, siblingPath);
@@ -31303,7 +31352,7 @@ var ATOMIC_RECOVERY_WINDOW_MS = 1000, RELOAD_DEBOUNCE_MS = 80, ENTRY_IMPORT_RETR
31303
31352
  continue;
31304
31353
  let st2;
31305
31354
  try {
31306
- st2 = statSync8(join56(dir, entry.name));
31355
+ st2 = statSync8(join57(dir, entry.name));
31307
31356
  } catch {
31308
31357
  continue;
31309
31358
  }
@@ -32172,7 +32221,7 @@ var handleHTMXPageRequest = async (pagePath, options = {}) => {
32172
32221
  // src/core/prepare.ts
32173
32222
  import { createHash as createHash8 } from "crypto";
32174
32223
  import { existsSync as existsSync39, readdirSync as readdirSync10, readFileSync as readFileSync35 } from "fs";
32175
- import { basename as basename18, join as join53, relative as relative20, resolve as resolvePath4 } from "path";
32224
+ import { basename as basename18, join as join54, relative as relative20, resolve as resolvePath4 } from "path";
32176
32225
  import { Elysia as Elysia9, NotFound } from "elysia";
32177
32226
 
32178
32227
  // src/plugins/openApiPlugin.ts
@@ -33574,7 +33623,7 @@ var registerIconVersioning = (buildDir) => {
33574
33623
  if (cached !== undefined)
33575
33624
  return cached;
33576
33625
  const path = href.split("?")[0] ?? href;
33577
- const filePath = join53(buildDir, path);
33626
+ const filePath = join54(buildDir, path);
33578
33627
  let versioned = href;
33579
33628
  if (existsSync39(filePath)) {
33580
33629
  const hash = createHash8("sha256").update(readFileSync35(filePath)).digest("hex").slice(0, ICON_HASH_LENGTH);
@@ -33667,12 +33716,20 @@ var prepareDev = async (config, buildDir) => {
33667
33716
  const { requestInspector: requestInspector2 } = await Promise.resolve().then(() => (init_requestInspector(), exports_requestInspector));
33668
33717
  const { serverTiming } = await import("@elysia/server-timing");
33669
33718
  const mobileAssociationPlugin = createAbsoluteMobileAssociationPlugin(config.mobile, process.cwd());
33719
+ const nativeMobileConfig = config.mobile;
33720
+ let nativeDevAdapterBundle;
33721
+ const getNativeDevAdapterBundle = () => nativeDevAdapterBundle ??= nativeMobileConfig ? Promise.resolve().then(() => (init_devDeviceAdapter(), exports_devDeviceAdapter)).then(({ buildAbsoluteNativeDevAdapter: buildAbsoluteNativeDevAdapter2 }) => buildAbsoluteNativeDevAdapter2(process.cwd(), nativeMobileConfig)) : Promise.resolve("export {};");
33670
33722
  const absolutejs = new Elysia9({ name: "absolutejs-runtime" }).use(requestInspector2).use(absoluteRequestContext).use(serverTiming()).use(devtoolsJson2(buildDir, {
33671
33723
  normalizeForWindowsContainer: config.dev?.devtools?.normalizeForWindowsContainer,
33672
33724
  projectRoot: config.dev?.devtools?.projectRoot,
33673
33725
  uuid: config.dev?.devtools?.uuid,
33674
33726
  uuidCachePath: config.dev?.devtools?.uuidCachePath
33675
- })).use(imageOptimizer2(config.images, buildDir)).use(mobileAssociationPlugin).use(await mountStaticPlugin(staticPlugin, {
33727
+ })).use(imageOptimizer2(config.images, buildDir)).use(mobileAssociationPlugin).get("/__absolute/native-device-adapter.js", async () => new Response(await getNativeDevAdapterBundle(), {
33728
+ headers: {
33729
+ "Cache-Control": "no-store",
33730
+ "Content-Type": "text/javascript; charset=utf-8"
33731
+ }
33732
+ })).use(await mountStaticPlugin(staticPlugin, {
33676
33733
  alwaysStatic: true,
33677
33734
  assets: buildDir,
33678
33735
  directive: "no-cache",
@@ -33704,13 +33761,13 @@ var loadPrerenderMap = (prerenderDir) => {
33704
33761
  continue;
33705
33762
  const name = basename18(entry, ".html");
33706
33763
  const route = name === "index" ? "/" : `/${name}`;
33707
- map.set(route, join53(prerenderDir, entry));
33764
+ map.set(route, join54(prerenderDir, entry));
33708
33765
  }
33709
33766
  return map;
33710
33767
  };
33711
33768
  var loadMobileCompatibilityPlugin = async (buildDir) => {
33712
- const root = join53(buildDir, ".absolutejs", "mobile-compatibility");
33713
- if (!existsSync39(join53(root, "current.json"))) {
33769
+ const root = join54(buildDir, ".absolutejs", "mobile-compatibility");
33770
+ if (!existsSync39(join54(root, "current.json"))) {
33714
33771
  return new Elysia9({ name: "absolutejs-mobile-compatibility-empty" });
33715
33772
  }
33716
33773
  const options = await loadAbsoluteMobileMaterializedBundle(root);
@@ -33771,12 +33828,12 @@ var prepare = async (configOrPath) => {
33771
33828
  setCurrentPageIslandMetadata(await loadPageIslandMetadata(config));
33772
33829
  recordStep("load production manifest and island metadata", stepStartedAt);
33773
33830
  stepStartedAt = performance.now();
33774
- const conventionsPath = join53(buildDir, "conventions.json");
33831
+ const conventionsPath = join54(buildDir, "conventions.json");
33775
33832
  if (existsSync39(conventionsPath)) {
33776
33833
  const conventions2 = JSON.parse(readFileSync35(conventionsPath, "utf-8"));
33777
33834
  setConventions(conventions2);
33778
33835
  }
33779
- const spaRoutesPath = join53(buildDir, "spa-routes.json");
33836
+ const spaRoutesPath = join54(buildDir, "spa-routes.json");
33780
33837
  if (existsSync39(spaRoutesPath)) {
33781
33838
  setSpaRouteManifest(JSON.parse(readFileSync35(spaRoutesPath, "utf-8")));
33782
33839
  }
@@ -33789,7 +33846,7 @@ var prepare = async (configOrPath) => {
33789
33846
  prefix: "",
33790
33847
  staticLimit: MAX_STATIC_ROUTE_COUNT
33791
33848
  });
33792
- const generatedAssetsRoot = join53(buildDir, ".absolutejs");
33849
+ const generatedAssetsRoot = join54(buildDir, ".absolutejs");
33793
33850
  const generatedAssetsPlugin = new Elysia9({
33794
33851
  name: "absolutejs-generated-assets"
33795
33852
  }).get("/.absolutejs/*", async ({ params, set }) => {
@@ -33827,7 +33884,7 @@ var prepare = async (configOrPath) => {
33827
33884
  responseValue.headers.set("cache-control", isFingerprintedAsset(pathname) ? "public, max-age=31536000, immutable" : "public, max-age=0, must-revalidate");
33828
33885
  });
33829
33886
  stepStartedAt = performance.now();
33830
- const prerenderDir = join53(buildDir, "_prerendered");
33887
+ const prerenderDir = join54(buildDir, "_prerendered");
33831
33888
  const prerenderMap = loadPrerenderMap(prerenderDir);
33832
33889
  const mobileCompatibilityPlugin = await loadMobileCompatibilityPlugin(buildDir);
33833
33890
  const mobileAssociationPlugin = createAbsoluteMobileAssociationPlugin(config.mobile, process.cwd(), { requireAll: true });
@@ -33900,10 +33957,10 @@ import {
33900
33957
  readFileSync as readFileSync36,
33901
33958
  rmSync as rmSync4
33902
33959
  } from "fs";
33903
- import { join as join54 } from "path";
33904
- var CERT_DIR = join54(process.cwd(), ".absolutejs");
33905
- var CERT_PATH = join54(CERT_DIR, "cert.pem");
33906
- var KEY_PATH = join54(CERT_DIR, "key.pem");
33960
+ import { join as join55 } from "path";
33961
+ var CERT_DIR = join55(process.cwd(), ".absolutejs");
33962
+ var CERT_PATH = join55(CERT_DIR, "cert.pem");
33963
+ var KEY_PATH = join55(CERT_DIR, "key.pem");
33907
33964
  var CERT_VALIDITY_DAYS = 365;
33908
33965
  var devLog = (msg) => console.log(`\x1B[2m${new Date().toLocaleTimeString()}\x1B[0m \x1B[36m[dev]\x1B[0m ${msg}`);
33909
33966
  var devWarn = (msg) => console.log(`\x1B[2m${new Date().toLocaleTimeString()}\x1B[0m \x1B[33m[dev]\x1B[0m \x1B[33m${msg}\x1B[0m`);
@@ -34023,12 +34080,12 @@ import {
34023
34080
  writeFileSync as writeFileSync11
34024
34081
  } from "fs";
34025
34082
  import { homedir as homedir2 } from "os";
34026
- import { basename as basename19, join as join55 } from "path";
34083
+ import { basename as basename19, join as join56 } from "path";
34027
34084
  var registeredPids = new Set;
34028
34085
  var exitHandlerRegistered = false;
34029
- var instanceFilePath = (pid) => join55(instanceRegistryDir(), `${pid}.json`);
34030
- var instanceLogPath = (pid) => join55(instanceRegistryDir(), `${pid}.log`);
34031
- var instanceRegistryDir = () => join55(homedir2(), ".absolutejs", "instances");
34086
+ var instanceFilePath = (pid) => join56(instanceRegistryDir(), `${pid}.json`);
34087
+ var instanceLogPath = (pid) => join56(instanceRegistryDir(), `${pid}.log`);
34088
+ var instanceRegistryDir = () => join56(homedir2(), ".absolutejs", "instances");
34032
34089
  var removeInstanceFilesSync = (pid) => {
34033
34090
  try {
34034
34091
  unlinkSync2(instanceFilePath(pid));
@@ -34063,7 +34120,7 @@ var registerInstance = (record) => {
34063
34120
  return record;
34064
34121
  };
34065
34122
  var resolveProjectName = (cwd2) => {
34066
- const parsed = readJsonFile(join55(cwd2, "package.json"));
34123
+ const parsed = readJsonFile(join56(cwd2, "package.json"));
34067
34124
  if (parsed !== null && typeof parsed === "object" && typeof parsed.name === "string" && parsed.name.trim().length > 0) {
34068
34125
  return parsed.name;
34069
34126
  }
@@ -40721,5 +40778,5 @@ export {
40721
40778
  ANGULAR_INIT_TIMEOUT_MS
40722
40779
  };
40723
40780
 
40724
- //# debugId=C9BAE4208249D80364756E2164756E21
40781
+ //# debugId=AA3EE02769A805B764756E2164756E21
40725
40782
  //# sourceMappingURL=index.js.map