@absolutejs/absolute 0.20.0-beta.121 → 0.20.0-beta.123

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/changelog.json +57 -0
  3. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  4. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  5. package/dist/angular/index.js +14 -2
  6. package/dist/angular/index.js.map +5 -4
  7. package/dist/angular/server.js +14 -2
  8. package/dist/angular/server.js.map +5 -4
  9. package/dist/build.js +120 -43
  10. package/dist/build.js.map +7 -6
  11. package/dist/cli/config/server.js +9 -1
  12. package/dist/cli/{dev-pdefc9ac.js → dev-s7kct3xq.js} +6 -1
  13. package/dist/cli/index-hty8111z.js +410 -0
  14. package/dist/cli/index.js +6 -2
  15. package/dist/cli/patchedBun-zjtrn2s4.js +38 -0
  16. package/dist/client/chunks/index-dk743xs6.js +146 -0
  17. package/dist/client/chunks/index-dk743xs6.js.map +10 -0
  18. package/dist/client/chunks/index-jrcwp722.js +12 -0
  19. package/dist/client/chunks/index-jrcwp722.js.map +10 -0
  20. package/dist/client/chunks/{islands-xj2n8nwf.js → islands-50dg63j9.js} +6 -3
  21. package/dist/client/chunks/{islands-xj2n8nwf.js.map → islands-50dg63j9.js.map} +3 -3
  22. package/dist/client/chunks/{react-pdg4325x.js → react-yq4ss9y4.js} +4 -3
  23. package/dist/client/chunks/{react-pdg4325x.js.map → react-yq4ss9y4.js.map} +2 -2
  24. package/dist/client/index.js +5 -4
  25. package/dist/client/index.js.map +2 -2
  26. package/dist/dev/client/handlers/react.ts +31 -39
  27. package/dist/dev/client/hmrClient.ts +3 -0
  28. package/dist/dev/serverBootstrap.js +11 -0
  29. package/dist/index.js +122 -45
  30. package/dist/index.js.map +7 -6
  31. package/dist/islands/index.js +14 -2
  32. package/dist/islands/index.js.map +5 -4
  33. package/dist/mobile/remoteMacAgentEntry.js +1 -1
  34. package/dist/react/index.js +14 -2
  35. package/dist/react/index.js.map +5 -4
  36. package/dist/react/server.js +14 -2
  37. package/dist/react/server.js.map +5 -4
  38. package/dist/src/cli/patchedBun.d.ts +84 -0
  39. package/dist/src/client/browserTranslation.d.ts +3 -0
  40. package/dist/src/client/browserTranslationAttributes.d.ts +2 -0
  41. package/dist/src/dev/hotRejectionGuard.d.ts +1 -0
  42. package/dist/src/dev/moduleServer.d.ts +10 -3
  43. package/dist/src/mobile/emulatorDoctor.d.ts +1 -1
  44. package/dist/src/vue/components/Image.d.ts +1 -1
  45. package/dist/svelte/index.js +14 -2
  46. package/dist/svelte/index.js.map +5 -4
  47. package/dist/svelte/server.js +14 -2
  48. package/dist/svelte/server.js.map +5 -4
  49. package/dist/types/globals.d.ts +10 -0
  50. package/dist/vue/browser.js +75 -8
  51. package/dist/vue/browser.js.map +5 -4
  52. package/dist/vue/index.js +77 -9
  53. package/dist/vue/index.js.map +6 -5
  54. package/dist/vue/server.js +14 -2
  55. package/dist/vue/server.js.map +5 -4
  56. package/package.json +1 -1
  57. package/dist/client/chunks/index-5py90ctf.js +0 -87
  58. package/dist/client/chunks/index-5py90ctf.js.map +0 -10
  59. package/dist/cli/{mobile-00bqw12c.js → mobile-6kdsrhxy.js} +3 -3
@@ -39210,8 +39210,16 @@ var renderSpaNotFound = async (framework, pageName, request) => {
39210
39210
  });
39211
39211
  };
39212
39212
 
39213
+ // src/client/browserTranslationAttributes.ts
39214
+ var TRANSLATABLE_ATTRIBUTES = [
39215
+ "alt",
39216
+ "title",
39217
+ "placeholder",
39218
+ "aria-label"
39219
+ ];
39220
+
39213
39221
  // src/core/browserTranslation.ts
39214
- var BROWSER_TRANSLATION_BASELINE_SCRIPT = "window.__ABSOLUTE_SSR_TEXT_BASELINES__=new WeakMap();" + "{const r=document.body,b=window.__ABSOLUTE_SSR_TEXT_BASELINES__;" + 'if(r)for(const e of [r,...r.querySelectorAll("*")]){' + "const t=new Map();for(const [i,n]of[...e.childNodes].entries())" + 'if(n.nodeType===3)t.set(i,n.nodeValue??"");if(t.size)b.set(e,t);}}';
39222
+ var BROWSER_TRANSLATION_BASELINE_SCRIPT = "window.__ABSOLUTE_SSR_TEXT_BASELINES__=new WeakMap();" + "window.__ABSOLUTE_SSR_ATTRIBUTE_BASELINES__=new WeakMap();" + "{const r=document.body,b=window.__ABSOLUTE_SSR_TEXT_BASELINES__," + "a=window.__ABSOLUTE_SSR_ATTRIBUTE_BASELINES__;" + 'if(r)for(const e of [r,...r.querySelectorAll("*")]){' + "const t=new Map();for(const [i,n]of[...e.childNodes].entries())" + 'if(n.nodeType===3)t.set(i,n.nodeValue??"");if(t.size)b.set(e,t);' + `const v=new Map();for(const k of ${JSON.stringify(TRANSLATABLE_ATTRIBUTES)}){` + "const s=e.getAttribute(k);if(s!==null)v.set(k,s);}if(v.size)a.set(e,v);}}";
39215
39223
 
39216
39224
  // src/react/pageHandler.ts
39217
39225
  var withRequestUrl = (props, url) => Object.assign(Object.create(null), props, { url });
@@ -12,6 +12,9 @@ import {
12
12
  import {
13
13
  scanListeners
14
14
  } from "./index-fhaf3tdk.js";
15
+ import {
16
+ resolveDevBunExecutable
17
+ } from "./index-hty8111z.js";
15
18
  import {
16
19
  stripStringsAndComments
17
20
  } from "./index-fc9vxw56.js";
@@ -1504,6 +1507,8 @@ var dev = async (serverEntry, configPath, options = {}) => {
1504
1507
  let selectedRemoteMacProfile;
1505
1508
  let expoDevProject;
1506
1509
  markBoot("dev command entered");
1510
+ const bunExecutable = await resolveDevBunExecutable();
1511
+ markBoot("dev bun runtime selected");
1507
1512
  let prescanConfig;
1508
1513
  try {
1509
1514
  const config = await loadConfig(configPath);
@@ -2499,7 +2504,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
2499
2504
  markBoot("dev child spawn requested");
2500
2505
  const prescanForSpawn = prescan;
2501
2506
  prescan = null;
2502
- const proc = nodeSpawn("bun", [
2507
+ const proc = nodeSpawn(bunExecutable, [
2503
2508
  "--hot",
2504
2509
  "--no-clear-screen",
2505
2510
  ...heapSnapshotEnabled ? ["--preload", heapPreloadPath] : [],
@@ -0,0 +1,410 @@
1
+ // @bun
2
+ // src/cli/patchedBun.ts
3
+ import { spawnSync } from "child_process";
4
+ import {
5
+ chmodSync,
6
+ existsSync,
7
+ mkdirSync,
8
+ readFileSync,
9
+ renameSync,
10
+ rmSync,
11
+ writeFileSync
12
+ } from "fs";
13
+ import { homedir } from "os";
14
+ import { dirname, join } from "path";
15
+ import { createInterface } from "readline/promises";
16
+ import { inflateRawSync } from "zlib";
17
+ var PATCHED_BUN_RELEASE = {
18
+ bunVersion: "1.4.0",
19
+ issue: "https://github.com/oven-sh/bun/issues/32919",
20
+ repo: "absolutejs/patched-bun",
21
+ sha256: {
22
+ "bun-darwin-aarch64": "940d8c7eadb9fb4f39f06b0a086bbb6851d1bf3bc164bd3ba3a6966f8229f53c",
23
+ "bun-darwin-x64": "847f215cdd147431d025ffec94063467d1e4e80a5e4c311efff4570e04fa06ed",
24
+ "bun-freebsd-aarch64": "6d1c6c51cb782a1f9d2f4e2481aa7b856eff05be430094fa3b8fb86adf4067a3",
25
+ "bun-freebsd-x64": "c5395cd411bf3df75c3943e6ebb7722b5dd369df9a97c622449d36129cc6277a",
26
+ "bun-linux-aarch64": "fd5931bf59ff2bbaeab5fa37a1b003a3f10ada6b7fee2d3d8f15e606adad61f9",
27
+ "bun-linux-aarch64-android": "ab560ea72357554c93b4b0390b869ec62769c9b5f676ab196ecb3b0e328d7126",
28
+ "bun-linux-aarch64-musl": "b9c3f9936f4c7b6b0b749090f70806a1f73ca48d5a9762709ef9a4e9a5b0fed8",
29
+ "bun-linux-x64": "d36584f9aa71773fada3831ddf01a34c6089988988b900fd968586db099a0567",
30
+ "bun-linux-x64-android": "1a9712c77516fc224ed3307e083a12ea6e4f1a2956e920b9590bf12e4f59304e",
31
+ "bun-linux-x64-musl": "061a8bd6afad866f807d93125508c303f16c2dbf000387c91d22dd777c072951",
32
+ "bun-windows-aarch64": "91ed75e937b191eaf18bb361040acc24cd363b38f7bdaab5228fadd813f2a9ea",
33
+ "bun-windows-x64": "f7a7a22349dc7d4df0347da3f3058fe746763e22950bc77f4ae8021dab75a7b3"
34
+ },
35
+ tag: "bun-v1.4.0-absolute.2"
36
+ };
37
+ var HOURS_PER_DAY = 24;
38
+ var MS_PER_HOUR = 3600000;
39
+ var ASK_LATER_MS = HOURS_PER_DAY * MS_PER_HOUR;
40
+ var PREFERENCE_FILE = "patched-bun.json";
41
+ var EXECUTABLE_MODE = 493;
42
+ var VERSION_PARTS = 3;
43
+ var PROBE_TIMEOUT_MS = 30000;
44
+ var MUSL_LOADERS = ["/lib/ld-musl-x86_64.so.1", "/lib/ld-musl-aarch64.so.1"];
45
+ var DEPENDENCY_FIELDS = [
46
+ "dependencies",
47
+ "devDependencies",
48
+ "peerDependencies"
49
+ ];
50
+ var ZIP = {
51
+ directoryEntry: 33639248,
52
+ endDirectoryOffset: 16,
53
+ endEntryCount: 10,
54
+ endOfDirectory: 101010256,
55
+ endRecordSize: 22,
56
+ entryCommentLength: 32,
57
+ entryCompressedSize: 20,
58
+ entryExtraLength: 30,
59
+ entryHeaderSize: 46,
60
+ entryLocalOffset: 42,
61
+ entryMethod: 10,
62
+ entryNameLength: 28,
63
+ localExtraLength: 28,
64
+ localHeader: 67324752,
65
+ localHeaderSize: 30,
66
+ localNameLength: 26,
67
+ methodDeflate: 8,
68
+ methodStored: 0
69
+ };
70
+ var isAsset = (name) => Object.hasOwn(PATCHED_BUN_RELEASE.sha256, name);
71
+ var detectLibc = () => {
72
+ if (process.platform === "android")
73
+ return "android";
74
+ if (MUSL_LOADERS.some((loader) => existsSync(loader)))
75
+ return "musl";
76
+ return "glibc";
77
+ };
78
+ var absoluteHome = (home) => join(home, ".absolutejs");
79
+ var compareVersions = (left, right) => {
80
+ const parse = (version) => version.split("-")[0]?.split(".").map(Number) ?? [];
81
+ const leftParts = parse(left);
82
+ const rightParts = parse(right);
83
+ const differences = Array.from({ length: VERSION_PARTS }, (_, index) => (leftParts[index] ?? 0) - (rightParts[index] ?? 0));
84
+ return differences.find((difference) => difference !== 0) ?? 0;
85
+ };
86
+ var preferencePath = (home) => join(absoluteHome(home), PREFERENCE_FILE);
87
+ var installedPatchedBun = (home = homedir()) => {
88
+ const asset = patchedBunAsset();
89
+ if (!asset)
90
+ return null;
91
+ const path = patchedBunPath(asset, home);
92
+ return existsSync(path) ? path : null;
93
+ };
94
+ var patchedBunAsset = (platform = process.platform, arch = process.arch, libc = detectLibc()) => {
95
+ const cpu = { arm64: "aarch64", x64: "x64" }[arch];
96
+ const system = {
97
+ android: "linux",
98
+ darwin: "darwin",
99
+ freebsd: "freebsd",
100
+ linux: "linux",
101
+ win32: "windows"
102
+ }[platform];
103
+ if (!cpu || !system)
104
+ return null;
105
+ const abi = system === "linux" && libc !== "glibc" ? `-${libc}` : "";
106
+ const name = `bun-${system}-${cpu}${abi}`;
107
+ return isAsset(name) ? name : null;
108
+ };
109
+ var patchedBunPath = (asset, home = homedir()) => join(absoluteHome(home), "bun", PATCHED_BUN_RELEASE.tag, asset, asset.startsWith("bun-windows") ? "bun.exe" : "bun");
110
+ var runtimeSupportsReactFastRefresh = () => {
111
+ const options = { loader: "tsx", reactFastRefresh: true };
112
+ try {
113
+ return new Bun.Transpiler(options).transformSync("export function Probe(){return null;}").includes("$RefreshReg$");
114
+ } catch {
115
+ return false;
116
+ }
117
+ };
118
+ var parsePreference = (parsed) => {
119
+ if (typeof parsed !== "object" || parsed === null)
120
+ return null;
121
+ if (!("decision" in parsed))
122
+ return null;
123
+ if (parsed.decision === "never") {
124
+ const never = { decision: "never" };
125
+ return never;
126
+ }
127
+ if (parsed.decision !== "later" || !("askAfter" in parsed) || typeof parsed.askAfter !== "string")
128
+ return null;
129
+ const later = { askAfter: parsed.askAfter, decision: "later" };
130
+ return later;
131
+ };
132
+ var patchedBunOfferState = (context) => {
133
+ if (context.supported)
134
+ return "runtime-supports-refresh";
135
+ if (context.installed)
136
+ return "installed";
137
+ if (!context.usesReact)
138
+ return "not-a-react-project";
139
+ if (!context.asset)
140
+ return "unsupported-platform";
141
+ if (compareVersions(context.bunVersion, PATCHED_BUN_RELEASE.bunVersion) > 0)
142
+ return "runtime-newer";
143
+ if (context.preference?.decision === "never")
144
+ return "declined";
145
+ if (context.preference?.decision === "later" && new Date(context.preference.askAfter) > context.now)
146
+ return "asked-recently";
147
+ if (context.ci || !context.interactive)
148
+ return "non-interactive";
149
+ return "offer";
150
+ };
151
+ var readPatchedBunPreference = (home = homedir()) => {
152
+ try {
153
+ return parsePreference(JSON.parse(readFileSync(preferencePath(home), "utf-8")));
154
+ } catch {
155
+ return null;
156
+ }
157
+ };
158
+ var findEndOfDirectory = (view) => {
159
+ for (let offset = view.byteLength - ZIP.endRecordSize;offset >= 0; offset--) {
160
+ if (view.getUint32(offset, true) === ZIP.endOfDirectory)
161
+ return offset;
162
+ }
163
+ throw new Error("Not a zip archive.");
164
+ };
165
+ var inflateEntry = (data, method) => {
166
+ if (method === ZIP.methodStored)
167
+ return data;
168
+ if (method === ZIP.methodDeflate)
169
+ return new Uint8Array(inflateRawSync(data));
170
+ throw new Error(`Unsupported zip compression method ${method}.`);
171
+ };
172
+ var readEntryData = (archive, view, entry) => {
173
+ if (view.getUint32(entry.localOffset, true) !== ZIP.localHeader)
174
+ throw new Error("Corrupt zip entry.");
175
+ const dataStart = entry.localOffset + ZIP.localHeaderSize + view.getUint16(entry.localOffset + ZIP.localNameLength, true) + view.getUint16(entry.localOffset + ZIP.localExtraLength, true);
176
+ return inflateEntry(archive.subarray(dataStart, dataStart + entry.compressedSize), entry.method);
177
+ };
178
+ var readZipEntry = (archive, entryName) => {
179
+ const view = new DataView(archive.buffer, archive.byteOffset, archive.byteLength);
180
+ const end = findEndOfDirectory(view);
181
+ const entries = view.getUint16(end + ZIP.endEntryCount, true);
182
+ const decoder = new TextDecoder;
183
+ let cursor = view.getUint32(end + ZIP.endDirectoryOffset, true);
184
+ for (let index = 0;index < entries; index++) {
185
+ if (view.getUint32(cursor, true) !== ZIP.directoryEntry)
186
+ throw new Error("Corrupt zip directory.");
187
+ const nameLength = view.getUint16(cursor + ZIP.entryNameLength, true);
188
+ const nameStart = cursor + ZIP.entryHeaderSize;
189
+ const name = decoder.decode(archive.subarray(nameStart, nameStart + nameLength));
190
+ const entry = {
191
+ compressedSize: view.getUint32(cursor + ZIP.entryCompressedSize, true),
192
+ localOffset: view.getUint32(cursor + ZIP.entryLocalOffset, true),
193
+ method: view.getUint16(cursor + ZIP.entryMethod, true)
194
+ };
195
+ if (name === entryName)
196
+ return readEntryData(archive, view, entry);
197
+ cursor += ZIP.entryHeaderSize + nameLength + view.getUint16(cursor + ZIP.entryExtraLength, true) + view.getUint16(cursor + ZIP.entryCommentLength, true);
198
+ }
199
+ throw new Error(`${entryName} is not in the archive.`);
200
+ };
201
+ var writePatchedBunPreference = (preference, home = homedir()) => {
202
+ const path = preferencePath(home);
203
+ if (preference === null) {
204
+ rmSync(path, { force: true });
205
+ return;
206
+ }
207
+ mkdirSync(dirname(path), { recursive: true });
208
+ writeFileSync(path, `${JSON.stringify(preference, null, "\t")}
209
+ `);
210
+ };
211
+ var sha256 = (bytes) => new Bun.CryptoHasher("sha256").update(bytes).digest("hex");
212
+ var projectUsesReact = (projectDir) => {
213
+ const hasReact = (deps) => typeof deps === "object" && deps !== null && Object.hasOwn(deps, "react");
214
+ try {
215
+ const manifest = JSON.parse(readFileSync(join(projectDir, "package.json"), "utf-8"));
216
+ if (typeof manifest !== "object" || manifest === null)
217
+ return false;
218
+ return DEPENDENCY_FIELDS.some((field) => hasReact(Reflect.get(manifest, field)));
219
+ } catch {
220
+ return false;
221
+ }
222
+ };
223
+ var PATCHED_BUN_EXPLANATION = [
224
+ "React edits reload the page and lose component state on this Bun.",
225
+ `Stock Bun ignores \`reactFastRefresh\` on Bun.Transpiler (${PATCHED_BUN_RELEASE.issue}),`,
226
+ "so React Fast Refresh cannot keep state across edits. Until Bun ships the fix,",
227
+ `AbsoluteJS publishes Bun ${PATCHED_BUN_RELEASE.bunVersion} with only that fix: https://github.com/${PATCHED_BUN_RELEASE.repo}`,
228
+ "It installs to ~/.absolutejs/bun and only `absolute dev` uses it; your `bun` is unchanged."
229
+ ];
230
+ var installPatchedBun = async (options = {}) => {
231
+ const asset = options.asset ?? patchedBunAsset();
232
+ if (!asset)
233
+ throw new Error(`No patched Bun build for ${process.platform}-${process.arch}.`);
234
+ const home = options.home ?? homedir();
235
+ const log = options.log ?? console.log;
236
+ const url = patchedBunDownloadUrl(asset);
237
+ log(`Downloading ${url}`);
238
+ const response = await (options.fetchImpl ?? fetch)(url);
239
+ if (!response.ok)
240
+ throw new Error(`Download failed: ${url} answered ${response.status}.`);
241
+ const archive = new Uint8Array(await response.arrayBuffer());
242
+ const expected = (options.checksums ?? PATCHED_BUN_RELEASE.sha256)[asset];
243
+ const actual = sha256(archive);
244
+ if (actual !== expected)
245
+ throw new Error(`${asset}.zip does not match its pinned SHA-256 (expected ${expected}, got ${actual}); not installing it.`);
246
+ const target = patchedBunPath(asset, home);
247
+ const binary = readZipEntry(archive, `${asset}/${target.endsWith(".exe") ? "bun.exe" : "bun"}`);
248
+ mkdirSync(dirname(target), { recursive: true });
249
+ const staging = `${target}.${process.pid}.tmp`;
250
+ writeFileSync(staging, binary);
251
+ chmodSync(staging, EXECUTABLE_MODE);
252
+ renameSync(staging, target);
253
+ log(`Installed patched Bun ${PATCHED_BUN_RELEASE.bunVersion} at ${target}`);
254
+ return target;
255
+ };
256
+ var parsePatchedBunChoice = (answer) => {
257
+ const normalized = answer.trim().toLowerCase();
258
+ const choices = [
259
+ {
260
+ choice: "install",
261
+ matches: normalized === "" || normalized === "1" || normalized.startsWith("i")
262
+ },
263
+ {
264
+ choice: "later",
265
+ matches: normalized === "2" || normalized.startsWith("l")
266
+ },
267
+ {
268
+ choice: "never",
269
+ matches: normalized === "3" || normalized.startsWith("d") || normalized.startsWith("n")
270
+ }
271
+ ];
272
+ return choices.find(({ matches }) => matches)?.choice ?? null;
273
+ };
274
+ var patchedBunDownloadUrl = (asset) => `https://github.com/${PATCHED_BUN_RELEASE.repo}/releases/download/${PATCHED_BUN_RELEASE.tag}/${asset}.zip`;
275
+ var verifyPatchedBun = (path) => {
276
+ const probe = spawnSync(path, [
277
+ "-e",
278
+ 'console.log(Bun.version, new Bun.Transpiler({loader:"tsx",reactFastRefresh:true}).transformSync("export function P(){return null}").includes("$RefreshReg$"))'
279
+ ], { encoding: "utf-8", timeout: PROBE_TIMEOUT_MS });
280
+ return probe.status === 0 && probe.stdout.trim() === `${PATCHED_BUN_RELEASE.bunVersion} true`;
281
+ };
282
+ var askUntilAnswered = async (prompt) => {
283
+ const choice = parsePatchedBunChoice(await prompt.question("Choose [1-3] (default 1): "));
284
+ return choice ?? askUntilAnswered(prompt);
285
+ };
286
+ var askForChoice = async () => {
287
+ const prompt = createInterface({
288
+ input: process.stdin,
289
+ output: process.stdout
290
+ });
291
+ try {
292
+ console.log(`
293
+ ${PATCHED_BUN_EXPLANATION.join(`
294
+ `)}
295
+ `);
296
+ console.log(` 1) Install now
297
+ 2) Ask me later
298
+ 3) Don't ask again
299
+ `);
300
+ return await askUntilAnswered(prompt);
301
+ } finally {
302
+ prompt.close();
303
+ }
304
+ };
305
+ var installVerified = async (home) => {
306
+ const path = await installPatchedBun({ home });
307
+ if (!verifyPatchedBun(path)) {
308
+ rmSync(path, { force: true });
309
+ throw new Error("the installed binary did not pass its check; removed it");
310
+ }
311
+ writePatchedBunPreference(null, home);
312
+ return path;
313
+ };
314
+ var recordDecline = (choice, home) => {
315
+ if (choice === "never") {
316
+ writePatchedBunPreference({ decision: "never" }, home);
317
+ console.log("OK, not asking again. `absolute bun-patch install` installs it any time; `absolute bun-patch reset` asks again.");
318
+ return;
319
+ }
320
+ writePatchedBunPreference({
321
+ askAfter: new Date(Date.now() + ASK_LATER_MS).toISOString(),
322
+ decision: "later"
323
+ }, home);
324
+ console.log("OK, asking again tomorrow. `absolute bun-patch install` installs it any time.");
325
+ };
326
+ var resolveDevBunExecutable = async (projectDir = process.cwd(), home = homedir()) => {
327
+ if (process.env.ABSOLUTE_PATCHED_BUN === "0")
328
+ return "bun";
329
+ const installed = installedPatchedBun(home);
330
+ if (installed) {
331
+ console.log(`Using AbsoluteJS patched Bun ${PATCHED_BUN_RELEASE.bunVersion} for React Fast Refresh (${installed}).`);
332
+ return installed;
333
+ }
334
+ const state = patchedBunOfferState({
335
+ asset: patchedBunAsset(),
336
+ bunVersion: Bun.version,
337
+ ci: Boolean(process.env.CI),
338
+ installed: false,
339
+ interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY),
340
+ now: new Date,
341
+ preference: readPatchedBunPreference(home),
342
+ supported: runtimeSupportsReactFastRefresh(),
343
+ usesReact: projectUsesReact(projectDir)
344
+ });
345
+ if (state === "non-interactive")
346
+ console.log(`React edits will reload the page: stock Bun lacks the reactFastRefresh fix (${PATCHED_BUN_RELEASE.issue}). Run \`absolute bun-patch install\` to use AbsoluteJS's patched Bun.`);
347
+ if (state !== "offer")
348
+ return "bun";
349
+ const choice = await askForChoice();
350
+ if (choice !== "install") {
351
+ recordDecline(choice, home);
352
+ return "bun";
353
+ }
354
+ try {
355
+ return await installVerified(home);
356
+ } catch (error) {
357
+ console.error(`Could not install the patched Bun (${error instanceof Error ? error.message : String(error)}). Continuing with your bun; React edits will reload the page.`);
358
+ return "bun";
359
+ }
360
+ };
361
+ var describePreference = (preference) => {
362
+ if (preference === null)
363
+ return "will ask";
364
+ if (preference.decision === "never")
365
+ return "won't ask again";
366
+ return `asking again after ${preference.askAfter}`;
367
+ };
368
+ var describeInstalled = (installed) => {
369
+ if (!installed)
370
+ return "no";
371
+ if (verifyPatchedBun(installed))
372
+ return installed;
373
+ return `${installed} (FAILED its check; run \`absolute bun-patch install\`)`;
374
+ };
375
+ var printStatus = (home) => {
376
+ const supported = runtimeSupportsReactFastRefresh();
377
+ console.log(`Release: ${PATCHED_BUN_RELEASE.tag} (${PATCHED_BUN_RELEASE.issue})`);
378
+ console.log(`Platform build: ${patchedBunAsset() ?? "none for this platform"}`);
379
+ console.log(`Your bun: ${Bun.version} (${supported ? "already has the fix" : "stock, no fix"})`);
380
+ console.log(`Installed: ${describeInstalled(installedPatchedBun(home))}`);
381
+ console.log(`Prompt: ${describePreference(readPatchedBunPreference(home))}`);
382
+ };
383
+ var bunPatch = async (args, home = homedir()) => {
384
+ const [action = "status"] = args;
385
+ if (action === "status") {
386
+ printStatus(home);
387
+ return;
388
+ }
389
+ if (action === "install") {
390
+ await installVerified(home);
391
+ console.log("`absolute dev` will use it from now on.");
392
+ return;
393
+ }
394
+ if (action === "remove") {
395
+ rmSync(join(absoluteHome(home), "bun"), {
396
+ force: true,
397
+ recursive: true
398
+ });
399
+ console.log("Removed the patched Bun. `absolute dev` uses your bun again.");
400
+ return;
401
+ }
402
+ if (action === "reset") {
403
+ writePatchedBunPreference(null, home);
404
+ console.log("`absolute dev` will offer the patched Bun again.");
405
+ return;
406
+ }
407
+ throw new Error(`Unknown bun-patch action "${action}". Use status, install, remove or reset.`);
408
+ };
409
+
410
+ export { PATCHED_BUN_RELEASE, installedPatchedBun, patchedBunAsset, patchedBunPath, runtimeSupportsReactFastRefresh, patchedBunOfferState, readPatchedBunPreference, readZipEntry, writePatchedBunPreference, PATCHED_BUN_EXPLANATION, installPatchedBun, parsePatchedBunChoice, patchedBunDownloadUrl, verifyPatchedBun, resolveDevBunExecutable, bunPatch };
package/dist/cli/index.js CHANGED
@@ -58,13 +58,16 @@ if (command === "dev") {
58
58
  }
59
59
  const positionalArgs = stripNamedArgs("--config", "--android-device", "--ios-device").filter((arg) => arg !== "--no-mobile" && arg !== "--eager");
60
60
  const serverEntry = positionalArgs[0] ?? DEFAULT_SERVER_ENTRY;
61
- const { dev } = await import("./dev-pdefc9ac.js");
61
+ const { dev } = await import("./dev-s7kct3xq.js");
62
62
  await dev(serverEntry, configPath, {
63
63
  androidDevice,
64
64
  eager: args.includes("--eager"),
65
65
  iosDevice,
66
66
  mobile: !args.includes("--no-mobile")
67
67
  });
68
+ } else if (command === "bun-patch") {
69
+ const { bunPatch } = await import("./patchedBun-zjtrn2s4.js");
70
+ await bunPatch(args);
68
71
  } else if (command === "start") {
69
72
  sendTelemetryEvent("cli:command", { command });
70
73
  const outdir = parseNamedArg("--outdir");
@@ -208,7 +211,7 @@ if (command === "dev") {
208
211
  sendTelemetryEvent("cli:command", {
209
212
  command: `mobile:${workspaceCommand ?? "unknown"}`
210
213
  });
211
- const { runMobile } = await import("./mobile-00bqw12c.js");
214
+ const { runMobile } = await import("./mobile-6kdsrhxy.js");
212
215
  try {
213
216
  await runMobile(args);
214
217
  } catch (error) {
@@ -267,6 +270,7 @@ if (command === "dev") {
267
270
  console.error(" routes [--json] List every route (pages + API) of a running dev server");
268
271
  console.error(" typecheck Run type checkers for all frameworks");
269
272
  console.error(" migrate Report what moving this project to AbsoluteJS involves");
273
+ console.error(" bun-patch [status|install|remove|reset] Bun with the React Fast Refresh fix (oven-sh/bun#32919)");
270
274
  console.error(" telemetry Manage anonymous telemetry");
271
275
  console.error(" tunnel-relay Run the public reverse-tunnel relay (for webhook dev)");
272
276
  process.exit(1);
@@ -0,0 +1,38 @@
1
+ // @bun
2
+ import {
3
+ PATCHED_BUN_EXPLANATION,
4
+ PATCHED_BUN_RELEASE,
5
+ bunPatch,
6
+ installPatchedBun,
7
+ installedPatchedBun,
8
+ parsePatchedBunChoice,
9
+ patchedBunAsset,
10
+ patchedBunDownloadUrl,
11
+ patchedBunOfferState,
12
+ patchedBunPath,
13
+ readPatchedBunPreference,
14
+ readZipEntry,
15
+ resolveDevBunExecutable,
16
+ runtimeSupportsReactFastRefresh,
17
+ verifyPatchedBun,
18
+ writePatchedBunPreference
19
+ } from "./index-hty8111z.js";
20
+ import"./index-mywsk201.js";
21
+ export {
22
+ PATCHED_BUN_EXPLANATION,
23
+ PATCHED_BUN_RELEASE,
24
+ bunPatch,
25
+ installPatchedBun,
26
+ installedPatchedBun,
27
+ parsePatchedBunChoice,
28
+ patchedBunAsset,
29
+ patchedBunDownloadUrl,
30
+ patchedBunOfferState,
31
+ patchedBunPath,
32
+ readPatchedBunPreference,
33
+ readZipEntry,
34
+ resolveDevBunExecutable,
35
+ runtimeSupportsReactFastRefresh,
36
+ verifyPatchedBun,
37
+ writePatchedBunPreference
38
+ };
@@ -0,0 +1,146 @@
1
+ import {
2
+ TRANSLATABLE_ATTRIBUTES
3
+ } from "./index-jrcwp722.js";
4
+
5
+ // src/client/browserTranslation.ts
6
+ var translatedFontText = (node, baselines) => {
7
+ if (!(node instanceof Element) || node.tagName !== "FONT")
8
+ return;
9
+ const elements = [node, ...node.querySelectorAll("*")];
10
+ if (elements.some((element) => element.tagName !== "FONT" || baselines.has(element)))
11
+ return;
12
+ return node.textContent ?? "";
13
+ };
14
+ var translationRestorer = (restore, hasTranslation) => Object.assign(restore, { hasTranslation });
15
+ var emptyTranslationRestorer = () => translationRestorer(() => {
16
+ return;
17
+ }, false);
18
+ var textNodeAt = (parent, index) => {
19
+ const node = parent.childNodes[index];
20
+ return node instanceof Text ? node : undefined;
21
+ };
22
+ var prepareTextTranslation = (element, index, baseline, path, baselines) => {
23
+ const original = element.childNodes[index];
24
+ const wrappedText = translatedFontText(original, baselines);
25
+ if (wrappedText !== undefined) {
26
+ original?.replaceWith(document.createTextNode(baseline));
27
+ return { baseline, index, path, translated: wrappedText };
28
+ }
29
+ const node = textNodeAt(element, index);
30
+ if (node === undefined || node.data === baseline)
31
+ return;
32
+ const snapshot = {
33
+ baseline,
34
+ index,
35
+ path,
36
+ translated: node.data
37
+ };
38
+ node.data = baseline;
39
+ return snapshot;
40
+ };
41
+ var visitElements = (root, visit) => {
42
+ visit(root);
43
+ for (const element of root.querySelectorAll("*"))
44
+ visit(element);
45
+ };
46
+ var elementPath = (root, element) => {
47
+ const path = [];
48
+ let current = element;
49
+ while (current !== root) {
50
+ const parent = current.parentElement;
51
+ if (parent === null)
52
+ return null;
53
+ path.unshift([...parent.children].indexOf(current));
54
+ current = parent;
55
+ }
56
+ return path;
57
+ };
58
+ var elementAtPath = (root, path) => {
59
+ let current = root;
60
+ for (const index of path) {
61
+ const child = current.children[index];
62
+ if (!(child instanceof Element))
63
+ return null;
64
+ current = child;
65
+ }
66
+ return current;
67
+ };
68
+ var captureSsrTextBaselines = (root) => {
69
+ if (root === null || typeof window === "undefined")
70
+ return;
71
+ const baselines = window.__ABSOLUTE_SSR_TEXT_BASELINES__ ?? new WeakMap;
72
+ const attributes = window.__ABSOLUTE_SSR_ATTRIBUTE_BASELINES__ ?? new WeakMap;
73
+ visitElements(root, (element) => {
74
+ const text = new Map;
75
+ for (const [index, node] of [...element.childNodes].entries()) {
76
+ if (node.nodeType === Node.TEXT_NODE)
77
+ text.set(index, node.nodeValue ?? "");
78
+ }
79
+ if (text.size > 0)
80
+ baselines.set(element, text);
81
+ const values = new Map;
82
+ for (const name of TRANSLATABLE_ATTRIBUTES) {
83
+ const value = element.getAttribute(name);
84
+ if (value !== null)
85
+ values.set(name, value);
86
+ }
87
+ if (values.size > 0)
88
+ attributes.set(element, values);
89
+ });
90
+ window.__ABSOLUTE_SSR_TEXT_BASELINES__ = baselines;
91
+ window.__ABSOLUTE_SSR_ATTRIBUTE_BASELINES__ = attributes;
92
+ };
93
+ var prepareBrowserTranslationHydration = (root) => {
94
+ if (root === null || typeof window === "undefined")
95
+ return emptyTranslationRestorer();
96
+ const baselines = window.__ABSOLUTE_SSR_TEXT_BASELINES__;
97
+ if (baselines === undefined)
98
+ return emptyTranslationRestorer();
99
+ const translated = [];
100
+ const translatedAttributes = [];
101
+ const attributes = window.__ABSOLUTE_SSR_ATTRIBUTE_BASELINES__;
102
+ visitElements(root, (element) => {
103
+ const text = baselines.get(element);
104
+ const path = elementPath(root, element);
105
+ if (path === null)
106
+ return;
107
+ for (const [index, baseline] of text ?? []) {
108
+ const snapshot = prepareTextTranslation(element, index, baseline, path, baselines);
109
+ if (snapshot === undefined)
110
+ continue;
111
+ translated.push(snapshot);
112
+ }
113
+ for (const [name, baseline] of attributes?.get(element) ?? []) {
114
+ const value = element.getAttribute(name);
115
+ if (value === null || value === baseline)
116
+ continue;
117
+ translatedAttributes.push({
118
+ baseline,
119
+ name,
120
+ path,
121
+ translated: value
122
+ });
123
+ element.setAttribute(name, baseline);
124
+ }
125
+ });
126
+ return translationRestorer(() => {
127
+ for (const snapshot of translated) {
128
+ const parent = elementAtPath(root, snapshot.path);
129
+ if (parent === null)
130
+ continue;
131
+ const node = textNodeAt(parent, snapshot.index);
132
+ if (node !== undefined && node.data === snapshot.baseline)
133
+ node.data = snapshot.translated;
134
+ }
135
+ for (const snapshot of translatedAttributes) {
136
+ const element = elementAtPath(root, snapshot.path);
137
+ if (element?.getAttribute(snapshot.name) === snapshot.baseline)
138
+ element.setAttribute(snapshot.name, snapshot.translated);
139
+ }
140
+ }, translated.length > 0 || translatedAttributes.length > 0);
141
+ };
142
+
143
+ export { captureSsrTextBaselines, prepareBrowserTranslationHydration };
144
+
145
+ //# debugId=2B49FE79D0C510E564756E2164756E21
146
+ //# sourceMappingURL=index-dk743xs6.js.map