@absolutejs/absolute 0.19.0-beta.4 → 0.19.0-beta.41
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/.absolutejs/tsconfig.tsbuildinfo +1 -1
- package/.claude/settings.local.json +23 -1
- package/dist/build.js +633 -59
- package/dist/build.js.map +13 -10
- package/dist/cli/index.js +29 -1
- package/dist/dev/client/frameworkDetect.ts +1 -2
- package/dist/dev/client/handlers/react.ts +96 -4
- package/dist/index.js +897 -209
- package/dist/index.js.map +17 -13
- package/dist/react/index.js +86 -1
- package/dist/react/index.js.map +5 -4
- package/dist/src/build/buildDepVendor.d.ts +2 -0
- package/dist/src/dev/clientManager.d.ts +2 -0
- package/dist/src/dev/moduleServer.d.ts +11 -0
- package/dist/src/dev/ssrRenderer.d.ts +7 -0
- package/dist/src/dev/ssrWorker.d.ts +0 -0
- package/dist/src/dev/transformCache.d.ts +4 -0
- package/dist/src/plugins/hmr.d.ts +1 -1
- package/dist/ssrWorker.ts +55 -0
- package/dist/types/messages.d.ts +5 -1
- package/native/packages/darwin-arm64/fast_ops.dylib +0 -0
- package/native/packages/darwin-arm64/package.json +1 -1
- package/native/packages/darwin-x64/fast_ops.dylib +0 -0
- package/native/packages/darwin-x64/package.json +1 -1
- package/native/packages/linux-arm64/package.json +1 -1
- package/native/packages/linux-x64/fast_ops.so +0 -0
- package/native/packages/linux-x64/package.json +1 -1
- package/package.json +6 -6
- package/types/globals.d.ts +1 -0
- package/types/messages.ts +7 -1
- package/types/typeGuards.ts +2 -0
package/dist/cli/index.js
CHANGED
|
@@ -598,7 +598,7 @@ var dev = async (serverEntry, configPath2) => {
|
|
|
598
598
|
interactive?.showPrompt();
|
|
599
599
|
};
|
|
600
600
|
const spawnServer = () => {
|
|
601
|
-
const proc = Bun.spawn(["bun", "--
|
|
601
|
+
const proc = Bun.spawn(["bun", "--no-clear-screen", serverEntry], {
|
|
602
602
|
cwd: process.cwd(),
|
|
603
603
|
env: {
|
|
604
604
|
...process.env,
|
|
@@ -633,6 +633,7 @@ var dev = async (serverEntry, configPath2) => {
|
|
|
633
633
|
let serverProcess = spawnServer();
|
|
634
634
|
const sessionStart = Date.now();
|
|
635
635
|
let frameworks = [];
|
|
636
|
+
let frameworkDirs = [];
|
|
636
637
|
try {
|
|
637
638
|
const cfg = await loadConfig(configPath2);
|
|
638
639
|
frameworks = [
|
|
@@ -643,7 +644,34 @@ var dev = async (serverEntry, configPath2) => {
|
|
|
643
644
|
cfg.vueDirectory && "vue",
|
|
644
645
|
cfg.angularDirectory && "angular"
|
|
645
646
|
].filter((val) => Boolean(val));
|
|
647
|
+
frameworkDirs = [
|
|
648
|
+
cfg.reactDirectory,
|
|
649
|
+
cfg.htmlDirectory,
|
|
650
|
+
cfg.htmxDirectory,
|
|
651
|
+
cfg.svelteDirectory,
|
|
652
|
+
cfg.vueDirectory,
|
|
653
|
+
cfg.angularDirectory
|
|
654
|
+
].filter((val) => Boolean(val)).map((dir) => resolve3(dir));
|
|
646
655
|
} catch {}
|
|
656
|
+
const { watch } = await import("fs");
|
|
657
|
+
const serverDir = resolve3(serverEntry, "..");
|
|
658
|
+
const isFrameworkFile = (filePath) => frameworkDirs.some((dir) => resolve3(filePath).startsWith(dir));
|
|
659
|
+
let restartTimeout = null;
|
|
660
|
+
watch(serverDir, { recursive: true }, (_event, filename) => {
|
|
661
|
+
if (!filename)
|
|
662
|
+
return;
|
|
663
|
+
const fullPath = resolve3(serverDir, filename);
|
|
664
|
+
if (isFrameworkFile(fullPath))
|
|
665
|
+
return;
|
|
666
|
+
if (!filename.endsWith(".ts") && !filename.endsWith(".tsx"))
|
|
667
|
+
return;
|
|
668
|
+
if (restartTimeout)
|
|
669
|
+
clearTimeout(restartTimeout);
|
|
670
|
+
restartTimeout = setTimeout(() => {
|
|
671
|
+
console.log(`\x1B[2m${formatTimestamp()}\x1B[0m \x1B[36m[cli]\x1B[0m \x1B[36mServer file changed, restarting...\x1B[0m`);
|
|
672
|
+
restartServer();
|
|
673
|
+
}, 100);
|
|
674
|
+
});
|
|
647
675
|
sendTelemetryEvent("dev:start", { entry: serverEntry, frameworks });
|
|
648
676
|
const cleanup = async (exitCode = 0) => {
|
|
649
677
|
if (cleaning)
|
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
export const detectCurrentFramework = () => {
|
|
4
4
|
if (window.__HMR_FRAMEWORK__) return window.__HMR_FRAMEWORK__;
|
|
5
|
+
if (window.__REACT_ROOT__) return 'react';
|
|
5
6
|
const path = window.location.pathname;
|
|
6
7
|
if (path === '/vue' || path.startsWith('/vue/')) return 'vue';
|
|
7
8
|
if (path === '/svelte' || path.startsWith('/svelte/')) return 'svelte';
|
|
8
9
|
if (path === '/angular' || path.startsWith('/angular/')) return 'angular';
|
|
9
10
|
if (path === '/htmx' || path.startsWith('/htmx/')) return 'htmx';
|
|
10
11
|
if (path === '/html' || path.startsWith('/html/')) return 'html';
|
|
11
|
-
if (path === '/') return 'html';
|
|
12
12
|
if (path === '/react' || path.startsWith('/react/')) return 'react';
|
|
13
|
-
if (window.__REACT_ROOT__) return 'react';
|
|
14
13
|
|
|
15
14
|
return null;
|
|
16
15
|
};
|
|
@@ -8,11 +8,13 @@ import { detectCurrentFramework } from '../frameworkDetect';
|
|
|
8
8
|
|
|
9
9
|
export const handleReactUpdate = (message: {
|
|
10
10
|
data: {
|
|
11
|
+
code?: string;
|
|
11
12
|
hasCSSChanges?: boolean;
|
|
12
13
|
hasComponentChanges?: boolean;
|
|
13
14
|
manifest?: Record<string, string>;
|
|
14
15
|
pageModuleUrl?: string;
|
|
15
16
|
primarySource?: string;
|
|
17
|
+
serverDuration?: number;
|
|
16
18
|
};
|
|
17
19
|
}) => {
|
|
18
20
|
const currentFramework = detectCurrentFramework();
|
|
@@ -31,12 +33,21 @@ export const handleReactUpdate = (message: {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
const refreshRuntime = window.$RefreshRuntime$;
|
|
36
|
+
const serverDuration = message.data.serverDuration;
|
|
34
37
|
|
|
35
|
-
//
|
|
38
|
+
// Inline code path: transpiled code sent via WebSocket.
|
|
39
|
+
// Import from blob URL — no HTTP fetch, immune to bun --hot restarts.
|
|
40
|
+
if (message.data.code && refreshRuntime) {
|
|
41
|
+
applyInlineCode(message.data.code, refreshRuntime, serverDuration);
|
|
42
|
+
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ESM fast path: import the page module directly
|
|
36
47
|
const pageModuleUrl = message.data.pageModuleUrl;
|
|
37
48
|
|
|
38
49
|
if (pageModuleUrl && refreshRuntime) {
|
|
39
|
-
applyRefreshImport(pageModuleUrl, refreshRuntime);
|
|
50
|
+
applyRefreshImport(pageModuleUrl, refreshRuntime, serverDuration);
|
|
40
51
|
|
|
41
52
|
return;
|
|
42
53
|
}
|
|
@@ -46,7 +57,7 @@ export const handleReactUpdate = (message: {
|
|
|
46
57
|
const newUrl = componentKey && message.data.manifest?.[componentKey];
|
|
47
58
|
|
|
48
59
|
if (newUrl && refreshRuntime) {
|
|
49
|
-
applyRefreshImport(newUrl, refreshRuntime);
|
|
60
|
+
applyRefreshImport(newUrl, refreshRuntime, serverDuration);
|
|
50
61
|
|
|
51
62
|
return;
|
|
52
63
|
}
|
|
@@ -55,13 +66,94 @@ export const handleReactUpdate = (message: {
|
|
|
55
66
|
window.location.reload();
|
|
56
67
|
};
|
|
57
68
|
|
|
69
|
+
// Import transpiled code from a blob URL — no HTTP fetch needed.
|
|
70
|
+
// Blob URLs resolve absolute imports (like /react/vendor/react.js)
|
|
71
|
+
// against the page's origin, so vendor imports work correctly.
|
|
72
|
+
const applyInlineCode = (
|
|
73
|
+
code: string,
|
|
74
|
+
refreshRuntime: { performReactRefresh: () => void },
|
|
75
|
+
serverDuration?: number
|
|
76
|
+
) => {
|
|
77
|
+
const clientStart = performance.now();
|
|
78
|
+
|
|
79
|
+
// Convert absolute paths to full URLs so blob can resolve them
|
|
80
|
+
const origin = window.location.origin;
|
|
81
|
+
const fullCode = code.replace(
|
|
82
|
+
/(from\s*["'])(\/[^"']+)(["'])/g,
|
|
83
|
+
`$1${origin}$2$3`
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const blob = new Blob([fullCode], { type: 'text/javascript' });
|
|
87
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
88
|
+
|
|
89
|
+
import(blobUrl)
|
|
90
|
+
.then(() => {
|
|
91
|
+
URL.revokeObjectURL(blobUrl);
|
|
92
|
+
refreshRuntime.performReactRefresh();
|
|
93
|
+
|
|
94
|
+
if (window.__HMR_WS__) {
|
|
95
|
+
const fetchMs = Math.round(performance.now() - clientStart);
|
|
96
|
+
const total = (serverDuration ?? 0) + fetchMs;
|
|
97
|
+
window.__HMR_WS__.send(
|
|
98
|
+
JSON.stringify({
|
|
99
|
+
duration: total,
|
|
100
|
+
fetchMs,
|
|
101
|
+
refreshMs: 0,
|
|
102
|
+
serverMs: serverDuration ?? 0,
|
|
103
|
+
type: 'hmr-timing'
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (window.__ERROR_BOUNDARY__) {
|
|
109
|
+
window.__ERROR_BOUNDARY__.reset();
|
|
110
|
+
} else {
|
|
111
|
+
hideErrorOverlay();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return undefined;
|
|
115
|
+
})
|
|
116
|
+
.catch((err) => {
|
|
117
|
+
URL.revokeObjectURL(blobUrl);
|
|
118
|
+
console.warn(
|
|
119
|
+
'[HMR] Inline code failed, falling back to fetch:',
|
|
120
|
+
err
|
|
121
|
+
);
|
|
122
|
+
applyRefreshImport(
|
|
123
|
+
'',
|
|
124
|
+
refreshRuntime,
|
|
125
|
+
serverDuration
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
58
130
|
const applyRefreshImport = (
|
|
59
131
|
moduleUrl: string,
|
|
60
|
-
refreshRuntime: { performReactRefresh: () => void }
|
|
132
|
+
refreshRuntime: { performReactRefresh: () => void },
|
|
133
|
+
serverDuration?: number
|
|
61
134
|
) => {
|
|
135
|
+
const clientStart = performance.now();
|
|
62
136
|
import(`${moduleUrl}?t=${Date.now()}`)
|
|
63
137
|
.then(() => {
|
|
138
|
+
const fetchDone = performance.now();
|
|
64
139
|
refreshRuntime.performReactRefresh();
|
|
140
|
+
const refreshDone = performance.now();
|
|
141
|
+
|
|
142
|
+
if (window.__HMR_WS__) {
|
|
143
|
+
const fetchMs = Math.round(fetchDone - clientStart);
|
|
144
|
+
const refreshMs = Math.round(refreshDone - fetchDone);
|
|
145
|
+
const total = (serverDuration ?? 0) + fetchMs + refreshMs;
|
|
146
|
+
window.__HMR_WS__.send(
|
|
147
|
+
JSON.stringify({
|
|
148
|
+
duration: total,
|
|
149
|
+
fetchMs,
|
|
150
|
+
refreshMs,
|
|
151
|
+
serverMs: serverDuration ?? 0,
|
|
152
|
+
type: 'hmr-timing'
|
|
153
|
+
})
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
65
157
|
if (window.__ERROR_BOUNDARY__) {
|
|
66
158
|
window.__ERROR_BOUNDARY__.reset();
|
|
67
159
|
} else {
|