xanix 0.0.0 → 1.0.0
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/BaseDocument.d.ts +3 -0
- package/dist/BaseDocument.js +8 -0
- package/dist/Document.d.ts +7 -0
- package/dist/Document.js +7 -0
- package/dist/bin/bundler/buildCache.d.ts +11 -0
- package/dist/bin/bundler/buildCache.js +129 -0
- package/dist/bin/bundler/buildClient.d.ts +3 -0
- package/dist/bin/bundler/buildClient.js +41 -0
- package/dist/bin/bundler/buildServer.d.ts +7 -0
- package/dist/bin/bundler/buildServer.js +55 -0
- package/dist/bin/bundler/cacheNpmModules.d.ts +11 -0
- package/dist/bin/bundler/cacheNpmModules.js +157 -0
- package/dist/bin/bundler/config/output.d.ts +14 -0
- package/dist/bin/bundler/config/output.js +48 -0
- package/dist/bin/bundler/generateClientEntries.d.ts +3 -0
- package/dist/bin/bundler/generateClientEntries.js +59 -0
- package/dist/bin/bundler/plugins/XanixAssets/index.d.ts +4 -0
- package/dist/bin/bundler/plugins/XanixAssets/index.js +22 -0
- package/dist/bin/bundler/plugins/XanixBrowserCodeRemover.d.ts +6 -0
- package/dist/bin/bundler/plugins/XanixBrowserCodeRemover.js +350 -0
- package/dist/bin/bundler/plugins/XanixEntryFinder/finder.d.ts +11 -0
- package/dist/bin/bundler/plugins/XanixEntryFinder/finder.js +156 -0
- package/dist/bin/bundler/plugins/XanixEntryFinder/index.d.ts +6 -0
- package/dist/bin/bundler/plugins/XanixEntryFinder/index.js +36 -0
- package/dist/bin/bundler/plugins/XanixEnv.d.ts +15 -0
- package/dist/bin/bundler/plugins/XanixEnv.js +46 -0
- package/dist/bin/bundler/plugins/XanixHydrate.d.ts +3 -0
- package/dist/bin/bundler/plugins/XanixHydrate.js +34 -0
- package/dist/bin/bundler/plugins/XanixReactRefresh.d.ts +2 -0
- package/dist/bin/bundler/plugins/XanixReactRefresh.js +126 -0
- package/dist/bin/bundler/plugins/XanixResolveCacheDeps/index.d.ts +5 -0
- package/dist/bin/bundler/plugins/XanixResolveCacheDeps/index.js +22 -0
- package/dist/bin/bundler/plugins/XanixTransform/index.d.ts +5 -0
- package/dist/bin/bundler/plugins/XanixTransform/index.js +19 -0
- package/dist/bin/bundler/plugins/XanixTransform/transformer.d.ts +16 -0
- package/dist/bin/bundler/plugins/XanixTransform/transformer.js +631 -0
- package/dist/bin/bundler/plugins/XanixWatchChange copy.d.ts +10 -0
- package/dist/bin/bundler/plugins/XanixWatchChange copy.js +30 -0
- package/dist/bin/bundler/plugins/XanixWatchChange.d.ts +9 -0
- package/dist/bin/bundler/plugins/XanixWatchChange.js +27 -0
- package/dist/bin/bundler/plugins/XanixWatchChangeClient.d.ts +7 -0
- package/dist/bin/bundler/plugins/XanixWatchChangeClient.js +15 -0
- package/dist/bin/bundler/plugins/commonjs.d.ts +3 -0
- package/dist/bin/bundler/plugins/commonjs.js +10 -0
- package/dist/bin/bundler/plugins/dep-XanixWatchChange.d.ts +9 -0
- package/dist/bin/bundler/plugins/dep-XanixWatchChange.js +27 -0
- package/dist/bin/bundler/plugins/nodeResolve.d.ts +3 -0
- package/dist/bin/bundler/plugins/nodeResolve.js +10 -0
- package/dist/bin/bundler/plugins/pathResolver.d.ts +5 -0
- package/dist/bin/bundler/plugins/pathResolver.js +57 -0
- package/dist/bin/bundler/plugins/plugins.d.ts +8 -0
- package/dist/bin/bundler/plugins/plugins.js +75 -0
- package/dist/bin/bundler/plugins/rollupEsbuild.d.ts +3 -0
- package/dist/bin/bundler/plugins/rollupEsbuild.js +14 -0
- package/dist/bin/bundler/plugins/xanixServerData.d.ts +6 -0
- package/dist/bin/bundler/plugins/xanixServerData.js +224 -0
- package/dist/bin/bundler/plugins/xanixTsconfigAlias.d.ts +6 -0
- package/dist/bin/bundler/plugins/xanixTsconfigAlias.js +51 -0
- package/dist/bin/bundler/plugins/xanixUseDataId.d.ts +4 -0
- package/dist/bin/bundler/plugins/xanixUseDataId.js +93 -0
- package/dist/bin/bundler/watchClient.d.ts +8 -0
- package/dist/bin/bundler/watchClient.js +54 -0
- package/dist/bin/bundler/watchServer.d.ts +10 -0
- package/dist/bin/bundler/watchServer.js +84 -0
- package/dist/bin/cli/build.d.ts +2 -0
- package/dist/bin/cli/build.js +18 -0
- package/dist/bin/cli/dev.d.ts +2 -0
- package/dist/bin/cli/dev.js +103 -0
- package/dist/bin/cli/start.d.ts +2 -0
- package/dist/bin/cli/start.js +19 -0
- package/dist/bin/include/entry.d.ts +3 -0
- package/dist/bin/include/entry.js +28 -0
- package/dist/bin/include/logger.d.ts +10 -0
- package/dist/bin/include/logger.js +11 -0
- package/dist/bin/include/manifest.d.ts +3 -0
- package/dist/bin/include/manifest.js +13 -0
- package/dist/bin/include/utils.d.ts +2 -0
- package/dist/bin/include/utils.js +14 -0
- package/dist/bin/index.d.ts +2 -0
- package/dist/bin/index.js +26 -0
- package/dist/bin/types.d.ts +12 -0
- package/dist/bin/types.js +1 -0
- package/dist/client/components/Body.d.ts +5 -0
- package/dist/client/components/Body.js +10 -0
- package/dist/client/components/Document/context.d.ts +3 -0
- package/dist/client/components/Document/context.js +14 -0
- package/dist/client/components/Document/index.d.ts +8 -0
- package/dist/client/components/Document/index.js +6 -0
- package/dist/client/components/Head copy.d.ts +5 -0
- package/dist/client/components/Head copy.js +8 -0
- package/dist/client/components/Head.d.ts +5 -0
- package/dist/client/components/Head.js +10 -0
- package/dist/client/components/Link.d.ts +6 -0
- package/dist/client/components/Link.js +10 -0
- package/dist/client/context/RouteContext.d.ts +8 -0
- package/dist/client/context/RouteContext.js +16 -0
- package/dist/client/hooks/usePageProps.d.ts +1 -0
- package/dist/client/hooks/usePageProps.js +2 -0
- package/dist/client/hooks/useRoute.d.ts +1 -0
- package/dist/client/hooks/useRoute.js +2 -0
- package/dist/client/hooks/useSearchParams.d.ts +1 -0
- package/dist/client/hooks/useSearchParams.js +2 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +2 -0
- package/dist/client/navigation.d.ts +4 -0
- package/dist/client/navigation.js +14 -0
- package/dist/client/refresh.d.ts +7 -0
- package/dist/client/refresh.js +15 -0
- package/dist/client/runtime.d.ts +10 -0
- package/dist/client/runtime.js +98 -0
- package/dist/client-runtime.d.ts +10 -0
- package/dist/client-runtime.js +113 -0
- package/dist/components/BaseDocument.d.ts +3 -0
- package/dist/components/BaseDocument.js +8 -0
- package/dist/components/Body.d.ts +5 -0
- package/dist/components/Body.js +8 -0
- package/dist/components/Document/Document.d.ts +16 -0
- package/dist/components/Document/Document.js +15 -0
- package/dist/components/Document/context.d.ts +17 -0
- package/dist/components/Document/context.js +13 -0
- package/dist/components/Document/index.d.ts +7 -0
- package/dist/components/Document/index.js +10 -0
- package/dist/components/Document.d.ts +7 -0
- package/dist/components/Document.js +9 -0
- package/dist/components/DocumentContext/DocumentContext.d.ts +15 -0
- package/dist/components/DocumentContext/DocumentContext.js +18 -0
- package/dist/components/DocumentContext/context.d.ts +11 -0
- package/dist/components/DocumentContext/context.js +14 -0
- package/dist/components/DocumentContext/index.d.ts +15 -0
- package/dist/components/DocumentContext/index.js +18 -0
- package/dist/components/DocumentContext.d.ts +19 -0
- package/dist/components/DocumentContext.js +6 -0
- package/dist/components/DocumentProvider.d.ts +13 -0
- package/dist/components/DocumentProvider.js +7 -0
- package/dist/components/Head.d.ts +5 -0
- package/dist/components/Head.js +42 -0
- package/dist/components/Link.d.ts +7 -0
- package/dist/components/Link.js +28 -0
- package/dist/components/Script.d.ts +3 -0
- package/dist/components/Script.js +5 -0
- package/dist/dataLoader.d.ts +11 -0
- package/dist/dataLoader.js +46 -0
- package/dist/document/BaseDocument.d.ts +3 -0
- package/dist/document/BaseDocument.js +8 -0
- package/dist/document/Body.d.ts +5 -0
- package/dist/document/Body.js +9 -0
- package/dist/document/Document/Document.d.ts +7 -0
- package/dist/document/Document/Document.js +10 -0
- package/dist/document/Document/context.d.ts +17 -0
- package/dist/document/Document/context.js +13 -0
- package/dist/document/Document/index.d.ts +7 -0
- package/dist/document/Document/index.js +10 -0
- package/dist/document/Document.d.ts +7 -0
- package/dist/document/Document.js +10 -0
- package/dist/document/DocumentContext.d.ts +17 -0
- package/dist/document/DocumentContext.js +6 -0
- package/dist/document/Head.d.ts +5 -0
- package/dist/document/Head.js +40 -0
- package/dist/document/Link.d.ts +7 -0
- package/dist/document/Link.js +28 -0
- package/dist/document/Script.d.ts +3 -0
- package/dist/document/Script.js +5 -0
- package/dist/document/context.d.ts +17 -0
- package/dist/document/context.js +13 -0
- package/dist/document/index.d.ts +8 -0
- package/dist/document/index.js +7 -0
- package/dist/document/useDocument.d.ts +2 -0
- package/dist/document/useDocument.js +10 -0
- package/dist/hooks/useCookies.d.ts +2 -0
- package/dist/hooks/useCookies.js +11 -0
- package/dist/hooks/useData.d.ts +18 -0
- package/dist/hooks/useData.js +69 -0
- package/dist/hooks/useDocument.d.ts +2 -0
- package/dist/hooks/useDocument.js +10 -0
- package/dist/hooks/useHeaders.d.ts +2 -0
- package/dist/hooks/useHeaders.js +9 -0
- package/dist/hooks/useLocation.d.ts +2 -0
- package/dist/hooks/useLocation.js +25 -0
- package/dist/hooks/usePage.d.ts +5 -0
- package/dist/hooks/usePage.js +9 -0
- package/dist/hooks/useParams.d.ts +2 -0
- package/dist/hooks/useParams.js +6 -0
- package/dist/hooks/usePathname.d.ts +2 -0
- package/dist/hooks/usePathname.js +9 -0
- package/dist/hooks/useRequest.d.ts +2 -0
- package/dist/hooks/useRequest.js +8 -0
- package/dist/hooks/useSearchParams.d.ts +12 -0
- package/dist/hooks/useSearchParams.js +66 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +27 -0
- package/dist/loader.d.ts +11 -0
- package/dist/loader.js +16 -0
- package/dist/navigate.d.ts +7 -0
- package/dist/navigate.js +31 -0
- package/dist/navigation/index.d.ts +2 -0
- package/dist/navigation/index.js +2 -0
- package/dist/navigation/navigate.d.ts +7 -0
- package/dist/navigation/navigate.js +31 -0
- package/dist/navigation/useLocation.d.ts +1 -0
- package/dist/navigation/useLocation.js +22 -0
- package/dist/router/index.d.ts +1 -0
- package/dist/router/index.js +1 -0
- package/dist/router/useParams.d.ts +9 -0
- package/dist/router/useParams.js +50 -0
- package/dist/router/useSearchParams .d.ts +9 -0
- package/dist/router/useSearchParams .js +50 -0
- package/dist/router/useSearchParams.d.ts +11 -0
- package/dist/router/useSearchParams.js +80 -0
- package/dist/server/index.d.ts +0 -0
- package/dist/server/index.js +1 -0
- package/dist/server/page.d.ts +9 -0
- package/dist/server/page.js +60 -0
- package/dist/server/readManifest.d.ts +14 -0
- package/dist/server/readManifest.js +8 -0
- package/dist/server/runtime/createServer.d.ts +12 -0
- package/dist/server/runtime/createServer.js +48 -0
- package/dist/server/runtime/index.d.ts +3 -0
- package/dist/server/runtime/index.js +3 -0
- package/dist/server/runtime/readManifest.d.ts +14 -0
- package/dist/server/runtime/readManifest.js +8 -0
- package/dist/server/runtime/xanixPage.d.ts +9 -0
- package/dist/server/runtime/xanixPage.js +87 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.js +7 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.js +27 -0
- package/dist/xanix.d.ts +3 -0
- package/dist/xanix.js +40 -0
- package/package.json +73 -13
- package/src/xanix-env.d.ts +79 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { parse } from "@babel/parser";
|
|
2
|
+
import traverse from "@babel/traverse";
|
|
3
|
+
import generate from "@babel/generator";
|
|
4
|
+
import * as t from "@babel/types";
|
|
5
|
+
const DEFAULT_BROWSER_GLOBALS = [
|
|
6
|
+
"window",
|
|
7
|
+
"document",
|
|
8
|
+
"localStorage",
|
|
9
|
+
"sessionStorage",
|
|
10
|
+
"navigator",
|
|
11
|
+
"location",
|
|
12
|
+
"history",
|
|
13
|
+
"screen",
|
|
14
|
+
"indexedDB",
|
|
15
|
+
"caches",
|
|
16
|
+
"WebSocket",
|
|
17
|
+
"File",
|
|
18
|
+
"FileReader",
|
|
19
|
+
"Blob",
|
|
20
|
+
"FormData",
|
|
21
|
+
"EventSource",
|
|
22
|
+
"Worker",
|
|
23
|
+
"SharedWorker",
|
|
24
|
+
"IntersectionObserver",
|
|
25
|
+
"ResizeObserver",
|
|
26
|
+
"MutationObserver",
|
|
27
|
+
"PerformanceObserver",
|
|
28
|
+
"Notification",
|
|
29
|
+
"BroadcastChannel",
|
|
30
|
+
"MessageChannel",
|
|
31
|
+
"MessageEvent",
|
|
32
|
+
"URL",
|
|
33
|
+
"URLSearchParams",
|
|
34
|
+
"MediaSource",
|
|
35
|
+
"MediaRecorder",
|
|
36
|
+
"Audio",
|
|
37
|
+
"Image",
|
|
38
|
+
"HTMLImageElement",
|
|
39
|
+
];
|
|
40
|
+
export default function xanixBrowserCodeRemover(options = {}) {
|
|
41
|
+
const { target = "server", globals = DEFAULT_BROWSER_GLOBALS } = options;
|
|
42
|
+
const browserGlobals = new Set(globals);
|
|
43
|
+
return {
|
|
44
|
+
name: "xanix-browser-code-remover",
|
|
45
|
+
transform(code, id) {
|
|
46
|
+
if (target !== "server") {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
if (id.includes("/node_modules/") || id.includes("\\node_modules\\")) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
if (!/\.(?:[cm]?[jt]sx?)$/.test(id)) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const ast = parse(code, {
|
|
56
|
+
sourceType: "module",
|
|
57
|
+
plugins: [
|
|
58
|
+
"jsx",
|
|
59
|
+
"typescript",
|
|
60
|
+
// "decorators-legacy",
|
|
61
|
+
// "classProperties",
|
|
62
|
+
// "classPrivateProperties",
|
|
63
|
+
// "classPrivateMethods",
|
|
64
|
+
// "optionalChaining",
|
|
65
|
+
// "nullishCoalescingOperator",
|
|
66
|
+
// "dynamicImport",
|
|
67
|
+
// "topLevelAwait",
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
const removePaths = new Set();
|
|
71
|
+
const replacePaths = new Set();
|
|
72
|
+
function isBrowserGlobal(path) {
|
|
73
|
+
const name = path.node.name;
|
|
74
|
+
if (!browserGlobals.has(name)) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (!path.isReferencedIdentifier()) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
// Don't transform locally declared variables.
|
|
81
|
+
if (path.scope.getBinding(name)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
function containsBrowserGlobal(path) {
|
|
87
|
+
let found = false;
|
|
88
|
+
path.traverse({
|
|
89
|
+
Identifier(innerPath) {
|
|
90
|
+
if (found) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (isBrowserGlobal(innerPath)) {
|
|
94
|
+
found = true;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
return found;
|
|
99
|
+
}
|
|
100
|
+
function getBrowserExpression(path) {
|
|
101
|
+
let current = path;
|
|
102
|
+
while (current.parentPath) {
|
|
103
|
+
const parent = current.parentPath;
|
|
104
|
+
/*
|
|
105
|
+
* window.foo
|
|
106
|
+
* window.foo.bar
|
|
107
|
+
* window["foo"]
|
|
108
|
+
*/
|
|
109
|
+
if (parent.isMemberExpression() ||
|
|
110
|
+
parent.isOptionalMemberExpression()) {
|
|
111
|
+
current = parent;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
/*
|
|
115
|
+
* window.foo()
|
|
116
|
+
* window.foo.bar()
|
|
117
|
+
*/
|
|
118
|
+
if (parent.isCallExpression() || parent.isOptionalCallExpression()) {
|
|
119
|
+
const callee = parent.get("callee");
|
|
120
|
+
if (!Array.isArray(callee) && callee.node === current.node) {
|
|
121
|
+
current = parent;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
/*
|
|
127
|
+
* window.foo!
|
|
128
|
+
*/
|
|
129
|
+
if (parent.isTSNonNullExpression()) {
|
|
130
|
+
current = parent;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
/*
|
|
134
|
+
* window.foo as Something
|
|
135
|
+
*/
|
|
136
|
+
if (parent.isTSAsExpression()) {
|
|
137
|
+
current = parent;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
return current;
|
|
143
|
+
}
|
|
144
|
+
function findContainingStatement(path) {
|
|
145
|
+
let current = path;
|
|
146
|
+
while (current.parentPath) {
|
|
147
|
+
const parent = current.parentPath;
|
|
148
|
+
if (parent.isExpressionStatement()) {
|
|
149
|
+
return parent;
|
|
150
|
+
}
|
|
151
|
+
if (parent.isFunctionDeclaration() ||
|
|
152
|
+
parent.isFunctionExpression() ||
|
|
153
|
+
parent.isArrowFunctionExpression()) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
current = parent;
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
function markRemove(path) {
|
|
161
|
+
if (!path.removed) {
|
|
162
|
+
removePaths.add(path);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function markReplace(path) {
|
|
166
|
+
if (!path.removed) {
|
|
167
|
+
replacePaths.add(path);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
traverse(ast, {
|
|
171
|
+
/*
|
|
172
|
+
* ---------------------------------------------------------
|
|
173
|
+
* JSX
|
|
174
|
+
*
|
|
175
|
+
* <div>{window.innerWidth}</div>
|
|
176
|
+
*
|
|
177
|
+
* ->
|
|
178
|
+
*
|
|
179
|
+
* <div>{undefined}</div>
|
|
180
|
+
* ---------------------------------------------------------
|
|
181
|
+
*/
|
|
182
|
+
JSXExpressionContainer(path) {
|
|
183
|
+
const expression = path.get("expression");
|
|
184
|
+
if (!expression || Array.isArray(expression)) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (expression.isJSXEmptyExpression()) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (!expression.isExpression()) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (!containsBrowserGlobal(expression)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
markReplace(expression);
|
|
197
|
+
},
|
|
198
|
+
/*
|
|
199
|
+
* ---------------------------------------------------------
|
|
200
|
+
* Standalone browser statements
|
|
201
|
+
*
|
|
202
|
+
* window.addEventListener(...)
|
|
203
|
+
* document.title = "Xanix"
|
|
204
|
+
* localStorage.setItem(...)
|
|
205
|
+
*
|
|
206
|
+
* ->
|
|
207
|
+
*
|
|
208
|
+
* removed
|
|
209
|
+
* ---------------------------------------------------------
|
|
210
|
+
*/
|
|
211
|
+
ExpressionStatement(path) {
|
|
212
|
+
if (!containsBrowserGlobal(path)) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
markRemove(path);
|
|
216
|
+
},
|
|
217
|
+
/*
|
|
218
|
+
* ---------------------------------------------------------
|
|
219
|
+
* Variable declarations
|
|
220
|
+
*
|
|
221
|
+
* const width = window.innerWidth;
|
|
222
|
+
*
|
|
223
|
+
* ->
|
|
224
|
+
*
|
|
225
|
+
* const width = undefined;
|
|
226
|
+
* ---------------------------------------------------------
|
|
227
|
+
*/
|
|
228
|
+
VariableDeclarator(path) {
|
|
229
|
+
const init = path.get("init");
|
|
230
|
+
if (!init || Array.isArray(init)) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (!init.isExpression()) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (!containsBrowserGlobal(init)) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
markReplace(init);
|
|
240
|
+
},
|
|
241
|
+
/*
|
|
242
|
+
* ---------------------------------------------------------
|
|
243
|
+
* Return
|
|
244
|
+
*
|
|
245
|
+
* return window.innerWidth;
|
|
246
|
+
*
|
|
247
|
+
* ->
|
|
248
|
+
*
|
|
249
|
+
* return undefined;
|
|
250
|
+
* ---------------------------------------------------------
|
|
251
|
+
*/
|
|
252
|
+
ReturnStatement(path) {
|
|
253
|
+
const argument = path.get("argument");
|
|
254
|
+
if (!argument || Array.isArray(argument)) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (!argument.isExpression()) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (!containsBrowserGlobal(argument)) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
markReplace(argument);
|
|
264
|
+
},
|
|
265
|
+
/*
|
|
266
|
+
* ---------------------------------------------------------
|
|
267
|
+
* Identifier
|
|
268
|
+
* ---------------------------------------------------------
|
|
269
|
+
*/
|
|
270
|
+
Identifier(path) {
|
|
271
|
+
if (!isBrowserGlobal(path)) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const browserExpression = getBrowserExpression(path);
|
|
275
|
+
/*
|
|
276
|
+
* JSXExpressionContainer is handled above.
|
|
277
|
+
*/
|
|
278
|
+
if (browserExpression.parentPath?.isJSXExpressionContainer()) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
/*
|
|
282
|
+
* Example:
|
|
283
|
+
*
|
|
284
|
+
* window.addEventListener(...)
|
|
285
|
+
*
|
|
286
|
+
* Remove the complete statement.
|
|
287
|
+
*/
|
|
288
|
+
const statement = findContainingStatement(browserExpression);
|
|
289
|
+
if (statement) {
|
|
290
|
+
markRemove(statement);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const parent = browserExpression.parentPath;
|
|
294
|
+
/*
|
|
295
|
+
* Variable initializer:
|
|
296
|
+
*
|
|
297
|
+
* const x = window.foo;
|
|
298
|
+
*/
|
|
299
|
+
if (parent?.isVariableDeclarator()) {
|
|
300
|
+
markReplace(browserExpression);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
/*
|
|
304
|
+
* Return:
|
|
305
|
+
*
|
|
306
|
+
* return window.foo;
|
|
307
|
+
*/
|
|
308
|
+
if (parent?.isReturnStatement()) {
|
|
309
|
+
markReplace(browserExpression);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
/*
|
|
313
|
+
* General expression:
|
|
314
|
+
*
|
|
315
|
+
* console.log(window.innerWidth)
|
|
316
|
+
*
|
|
317
|
+
* ->
|
|
318
|
+
*
|
|
319
|
+
* console.log(undefined)
|
|
320
|
+
*/
|
|
321
|
+
markReplace(browserExpression);
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
/*
|
|
325
|
+
* Remove first.
|
|
326
|
+
*/
|
|
327
|
+
for (const path of removePaths) {
|
|
328
|
+
if (!path.removed) {
|
|
329
|
+
path.remove();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/*
|
|
333
|
+
* Replace second.
|
|
334
|
+
*/
|
|
335
|
+
for (const path of replacePaths) {
|
|
336
|
+
if (!path.removed) {
|
|
337
|
+
path.replaceWith(t.identifier("undefined"));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const output = generate(ast, {
|
|
341
|
+
sourceMaps: true,
|
|
342
|
+
sourceFileName: id,
|
|
343
|
+
}, code);
|
|
344
|
+
return {
|
|
345
|
+
code: output.code,
|
|
346
|
+
map: output.map,
|
|
347
|
+
};
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import { XanixClientEntry } from "../../../types";
|
|
3
|
+
export declare function resolveFile(file: string): string;
|
|
4
|
+
export declare function resolveComponentFile(importer: string, importPath: string): string;
|
|
5
|
+
export declare function createClientId(file: string): string;
|
|
6
|
+
export declare function getJSXComponentName(node: t.JSXElement): string | null;
|
|
7
|
+
export declare function findComponentImport(ast: t.File, componentName: string): {
|
|
8
|
+
file: string;
|
|
9
|
+
export: string;
|
|
10
|
+
} | null;
|
|
11
|
+
export declare function entryFinder(code: string, id: string): XanixClientEntry[];
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
import { parse } from "@babel/parser";
|
|
5
|
+
import traverse from "@babel/traverse";
|
|
6
|
+
import * as t from "@babel/types";
|
|
7
|
+
const SOURCE_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".mjs", ".cjs"];
|
|
8
|
+
function normalizeFilePath(file) {
|
|
9
|
+
return path.resolve(file).split(path.sep).join("/");
|
|
10
|
+
}
|
|
11
|
+
export function resolveFile(file) {
|
|
12
|
+
const absolute = path.resolve(file);
|
|
13
|
+
if (fs.existsSync(absolute)) {
|
|
14
|
+
const stat = fs.statSync(absolute);
|
|
15
|
+
if (stat.isFile()) {
|
|
16
|
+
return absolute;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
for (const ext of SOURCE_EXTENSIONS) {
|
|
20
|
+
const candidate = `${absolute}${ext}`;
|
|
21
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
22
|
+
return path.resolve(candidate);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (fs.existsSync(absolute) && fs.statSync(absolute).isDirectory()) {
|
|
26
|
+
for (const ext of SOURCE_EXTENSIONS) {
|
|
27
|
+
const candidate = path.join(absolute, `index${ext}`);
|
|
28
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
29
|
+
return path.resolve(candidate);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return absolute;
|
|
34
|
+
}
|
|
35
|
+
export function resolveComponentFile(importer, importPath) {
|
|
36
|
+
if (!importPath.startsWith(".")) {
|
|
37
|
+
return importPath;
|
|
38
|
+
}
|
|
39
|
+
const base = path.resolve(path.dirname(importer), importPath);
|
|
40
|
+
return resolveFile(base);
|
|
41
|
+
}
|
|
42
|
+
export function createClientId(file) {
|
|
43
|
+
return `c_${crypto
|
|
44
|
+
.createHash("sha256")
|
|
45
|
+
.update(path.normalize(file))
|
|
46
|
+
.digest("hex")
|
|
47
|
+
.slice(0, 12)}`;
|
|
48
|
+
}
|
|
49
|
+
export function getJSXComponentName(node) {
|
|
50
|
+
const name = node.openingElement.name;
|
|
51
|
+
if (t.isJSXIdentifier(name)) {
|
|
52
|
+
return name.name;
|
|
53
|
+
}
|
|
54
|
+
if (t.isJSXMemberExpression(name)) {
|
|
55
|
+
if (t.isJSXIdentifier(name.object) && t.isJSXIdentifier(name.property)) {
|
|
56
|
+
return `${name.object.name}.${name.property.name}`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
export function findComponentImport(ast, componentName) {
|
|
62
|
+
for (const node of ast.program.body) {
|
|
63
|
+
if (!t.isImportDeclaration(node)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
for (const specifier of node.specifiers) {
|
|
67
|
+
if (t.isImportDefaultSpecifier(specifier) &&
|
|
68
|
+
specifier.local.name === componentName) {
|
|
69
|
+
return {
|
|
70
|
+
file: node.source.value,
|
|
71
|
+
export: "default",
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (t.isImportSpecifier(specifier) &&
|
|
75
|
+
specifier.local.name === componentName) {
|
|
76
|
+
const imported = specifier.imported;
|
|
77
|
+
return {
|
|
78
|
+
file: node.source.value,
|
|
79
|
+
export: t.isIdentifier(imported) ? imported.name : imported.value,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
export function entryFinder(code, id) {
|
|
87
|
+
const ast = parse(code, {
|
|
88
|
+
sourceType: "module",
|
|
89
|
+
plugins: ["typescript", "jsx"],
|
|
90
|
+
});
|
|
91
|
+
const entries = new Map();
|
|
92
|
+
traverse(ast, {
|
|
93
|
+
CallExpression(callPath) {
|
|
94
|
+
const call = callPath.node;
|
|
95
|
+
/*
|
|
96
|
+
* Find:
|
|
97
|
+
*
|
|
98
|
+
* res.send(<Home />);
|
|
99
|
+
*/
|
|
100
|
+
if (!t.isMemberExpression(call.callee)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!t.isIdentifier(call.callee.property, {
|
|
104
|
+
name: "send",
|
|
105
|
+
})) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const argument = call.arguments[0];
|
|
109
|
+
if (!argument || !t.isJSXElement(argument)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const functionPath = callPath.getFunctionParent();
|
|
113
|
+
if (!functionPath) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const params = functionPath.node.params;
|
|
117
|
+
if (params.length < 2) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const requestParam = params[0];
|
|
121
|
+
const responseParam = params[1];
|
|
122
|
+
if (!t.isIdentifier(requestParam) || !t.isIdentifier(responseParam)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const componentName = getJSXComponentName(argument);
|
|
126
|
+
if (!componentName) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const componentImport = findComponentImport(ast, componentName);
|
|
130
|
+
if (!componentImport) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const componentImportPath = componentImport.file;
|
|
134
|
+
const componentFile = resolveComponentFile(id, componentImportPath);
|
|
135
|
+
if (!path.isAbsolute(componentFile)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const normalizedFile = normalizeFilePath(componentFile);
|
|
139
|
+
const clientId = createClientId(normalizedFile);
|
|
140
|
+
const root = process.cwd();
|
|
141
|
+
const relativeSource = path.relative(root, componentFile);
|
|
142
|
+
const parsed = path.parse(relativeSource);
|
|
143
|
+
const buildPath = normalizeFilePath(path.resolve(root, ".xanix", parsed.dir, `${parsed.name}.js`));
|
|
144
|
+
const entry = {
|
|
145
|
+
id: clientId,
|
|
146
|
+
name: componentName,
|
|
147
|
+
file: normalizedFile,
|
|
148
|
+
path: componentImportPath,
|
|
149
|
+
build: buildPath,
|
|
150
|
+
export: componentImport.export,
|
|
151
|
+
};
|
|
152
|
+
entries.set(clientId, entry);
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
return Array.from(entries.values());
|
|
156
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { entryFinder } from "./finder.js";
|
|
2
|
+
export function XanixEntryFinder({ entries }) {
|
|
3
|
+
return {
|
|
4
|
+
name: "xanix-entry-finder",
|
|
5
|
+
async transform(code, id) {
|
|
6
|
+
if (id.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(id)) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
const clientEntries = entryFinder(code, id);
|
|
10
|
+
if (!clientEntries) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
for (const entry of clientEntries) {
|
|
14
|
+
const resolved = await this.resolve(entry.file, id, {
|
|
15
|
+
skipSelf: true,
|
|
16
|
+
});
|
|
17
|
+
if (!resolved) {
|
|
18
|
+
this.error(`Could not resolve client component "${entry.file}" imported by "${id}"`);
|
|
19
|
+
}
|
|
20
|
+
entries.set(entry.id, entry);
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
},
|
|
24
|
+
generateBundle() {
|
|
25
|
+
const manifest = {
|
|
26
|
+
version: 1,
|
|
27
|
+
entries: [...entries.values()],
|
|
28
|
+
};
|
|
29
|
+
this.emitFile({
|
|
30
|
+
type: "asset",
|
|
31
|
+
fileName: "client-manifest.json",
|
|
32
|
+
source: JSON.stringify(manifest, null, 2),
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Plugin } from "rollup";
|
|
2
|
+
export interface XanixEnvPluginOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Build environment.
|
|
5
|
+
*
|
|
6
|
+
* development → .env + .env.dev
|
|
7
|
+
* production → .env + .env.prod
|
|
8
|
+
*/
|
|
9
|
+
mode?: "development" | "production";
|
|
10
|
+
/**
|
|
11
|
+
* Whether this is a client build.
|
|
12
|
+
*/
|
|
13
|
+
isClient?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export default function XanixEnvPlugin(options?: XanixEnvPluginOptions): Plugin;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import dotenv from "dotenv";
|
|
4
|
+
import replace from "@rollup/plugin-replace";
|
|
5
|
+
export default function XanixEnvPlugin(options = {}) {
|
|
6
|
+
const root = process.cwd();
|
|
7
|
+
const mode = options.mode ?? "development";
|
|
8
|
+
const isClient = options.isClient ?? false;
|
|
9
|
+
const publicPrefix = "PUBLIC_";
|
|
10
|
+
const envFiles = [
|
|
11
|
+
path.resolve(root, ".env"),
|
|
12
|
+
path.resolve(root, mode === "development" ? ".env.dev" : ".env.prod"),
|
|
13
|
+
];
|
|
14
|
+
const env = {};
|
|
15
|
+
for (const file of envFiles) {
|
|
16
|
+
if (!fs.existsSync(file)) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const result = dotenv.parse(fs.readFileSync(file));
|
|
20
|
+
Object.assign(env, result);
|
|
21
|
+
}
|
|
22
|
+
const clientEnv = {};
|
|
23
|
+
const serverEnv = {};
|
|
24
|
+
for (const [key, value] of Object.entries(env)) {
|
|
25
|
+
if (key.startsWith(publicPrefix)) {
|
|
26
|
+
clientEnv[`process.env.${key}`] = JSON.stringify(value);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
serverEnv[`process.env.${key}`] = JSON.stringify(value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const envs = {
|
|
33
|
+
"process.env.NODE_ENV": JSON.stringify(mode),
|
|
34
|
+
// "typeof window": isClient ? '"object"' : '"undefined"',
|
|
35
|
+
// "typeof document": isClient ? '"object"' : '"undefined"',
|
|
36
|
+
__XANIX_CLIENT__: JSON.stringify(isClient),
|
|
37
|
+
__XANIX_SERVER__: JSON.stringify(!isClient),
|
|
38
|
+
__XANIX_DEV__: JSON.stringify(mode === "development"),
|
|
39
|
+
__XANIX_PROD__: JSON.stringify(mode === "production"),
|
|
40
|
+
...(isClient ? clientEnv : serverEnv),
|
|
41
|
+
};
|
|
42
|
+
return replace({
|
|
43
|
+
preventAssignment: true,
|
|
44
|
+
values: envs,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export default function xanixHydrate(entries) {
|
|
2
|
+
const entryNames = new Set(entries.map((entry) => entry.name));
|
|
3
|
+
return {
|
|
4
|
+
name: "xanix-hydrate",
|
|
5
|
+
renderChunk(code, chunk) {
|
|
6
|
+
// Only process the entries we explicitly provided.
|
|
7
|
+
if (!chunk.isEntry || !entryNames.has(chunk.name)) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
// Must have a default export.
|
|
11
|
+
if (!chunk.exports.includes("default")) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
// Find Rollup's generated default export variable.
|
|
15
|
+
const match = code.match(/export\s*\{\s*([^,\s]+)\s+as\s+default\s*\}/);
|
|
16
|
+
if (!match) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const component = match[1];
|
|
20
|
+
const hydration = `\nwindow.xanix.hydrate(` +
|
|
21
|
+
`${component}, ` +
|
|
22
|
+
`window.PAGE_PROPS` +
|
|
23
|
+
`);\n`;
|
|
24
|
+
const exportIndex = code.lastIndexOf("export {");
|
|
25
|
+
if (exportIndex === -1) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
code: code.slice(0, exportIndex) + hydration + code.slice(exportIndex),
|
|
30
|
+
map: null,
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|