xanix 1.0.14 → 1.0.16

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 (87) hide show
  1. package/dist/bin/bundler/buildServer.js +4 -10
  2. package/dist/bin/bundler/cacheNpmModules.js +13 -24
  3. package/dist/bin/bundler/config/defines.d.ts +20 -0
  4. package/dist/bin/bundler/config/defines.js +21 -0
  5. package/dist/bin/bundler/config/external.d.ts +1 -0
  6. package/dist/bin/bundler/config/external.js +12 -0
  7. package/dist/bin/bundler/config/output.js +0 -1
  8. package/dist/bin/bundler/dep-generateClientEntries.d.ts +5 -0
  9. package/dist/bin/bundler/dep-generateClientEntries.js +25 -0
  10. package/dist/bin/bundler/generateClientEntries.js +4 -12
  11. package/dist/bin/bundler/plugins/XanixDocument/index.js +15 -5
  12. package/dist/bin/bundler/plugins/XanixEntryFinder/finder.js +4 -6
  13. package/dist/bin/bundler/plugins/XanixEntryFinder/index.js +12 -11
  14. package/dist/bin/bundler/plugins/XanixEnv.js +5 -14
  15. package/dist/bin/bundler/plugins/XanixPageTransform/index.js +28 -0
  16. package/dist/bin/bundler/plugins/XanixPageTransform/transformer.d.ts +8 -6
  17. package/dist/bin/bundler/plugins/XanixPageTransform/transformer.js +111 -198
  18. package/dist/bin/bundler/plugins/XanixReactRefresh.d.ts +1 -1
  19. package/dist/bin/bundler/plugins/XanixReactRefresh.js +31 -31
  20. package/dist/bin/bundler/plugins/XanixTsconfigAlias.d.ts +17 -0
  21. package/dist/bin/bundler/plugins/XanixTsconfigAlias.js +176 -29
  22. package/dist/bin/bundler/plugins/XanixUseServer.d.ts +7 -0
  23. package/dist/bin/bundler/plugins/XanixUseServer.js +382 -0
  24. package/dist/bin/bundler/plugins/plugins.d.ts +7 -2
  25. package/dist/bin/bundler/plugins/plugins.js +116 -18
  26. package/dist/bin/bundler/watchClient.d.ts +4 -2
  27. package/dist/bin/bundler/watchClient.js +33 -5
  28. package/dist/bin/bundler/watchServer.d.ts +4 -4
  29. package/dist/bin/bundler/watchServer.js +27 -25
  30. package/dist/bin/cli/dev.js +68 -46
  31. package/dist/bin/include/entry.d.ts +0 -1
  32. package/dist/bin/include/entry.js +0 -7
  33. package/dist/bin/include/manifest.d.ts +2 -1
  34. package/dist/bin/include/manifest.js +26 -7
  35. package/dist/bin/include/utils.d.ts +2 -0
  36. package/dist/bin/include/utils.js +6 -0
  37. package/dist/bin/index.js +0 -0
  38. package/dist/bin/types.d.ts +0 -1
  39. package/dist/classes/XanixRedirect.d.ts +6 -0
  40. package/dist/classes/XanixRedirect.js +8 -0
  41. package/dist/client-runtime.d.ts +0 -1
  42. package/dist/client-runtime.js +17 -25
  43. package/dist/components/BaseDocument.d.ts +2 -2
  44. package/dist/components/DocumentContext.d.ts +5 -7
  45. package/dist/components/Head.js +6 -19
  46. package/dist/db/index.d.ts +2 -0
  47. package/dist/db/index.js +1 -0
  48. package/dist/db/test.d.ts +2 -0
  49. package/dist/db/test.js +1 -0
  50. package/dist/hooks/useCookies.d.ts +16 -1
  51. package/dist/hooks/useCookies.js +114 -6
  52. package/dist/hooks/useData.js +10 -11
  53. package/dist/hooks/useLocation.js +52 -13
  54. package/dist/hooks/useMetadata.d.ts +2 -0
  55. package/dist/hooks/useMetadata.js +6 -0
  56. package/dist/hooks/usePathname.js +4 -2
  57. package/dist/hooks/useRequest.js +1 -1
  58. package/dist/hooks/useResponse.d.ts +2 -0
  59. package/dist/hooks/useResponse.js +8 -0
  60. package/dist/hooks/useSearchParams.d.ts +40 -1
  61. package/dist/hooks/useSearchParams.js +154 -22
  62. package/dist/hooks/useServer/context.d.ts +7 -0
  63. package/dist/hooks/useServer/context.js +19 -0
  64. package/dist/hooks/useServer/core.d.ts +20 -0
  65. package/dist/hooks/useServer/core.js +72 -0
  66. package/dist/hooks/useServer/index.d.ts +20 -0
  67. package/dist/hooks/useServer/index.js +76 -0
  68. package/dist/hooks/useServer/registerUseServer.d.ts +3 -0
  69. package/dist/hooks/useServer/registerUseServer.js +5 -0
  70. package/dist/hooks/useServer/registry.d.ts +7 -0
  71. package/dist/hooks/useServer/registry.js +12 -0
  72. package/dist/hooks/useServer/state.d.ts +9 -0
  73. package/dist/hooks/useServer/state.js +33 -0
  74. package/dist/index.d.ts +15 -4
  75. package/dist/index.js +5 -6
  76. package/dist/navigate.d.ts +4 -1
  77. package/dist/navigate.js +10 -4
  78. package/dist/server/runtime/createServer.js +34 -22
  79. package/dist/server/runtime/xanixPage.d.ts +4 -2
  80. package/dist/server/runtime/xanixPage.js +47 -33
  81. package/dist/types/assets.d.ts +34 -34
  82. package/dist/types/express.d.ts +7 -12
  83. package/dist/types/globals.d.ts +26 -25
  84. package/dist/types/xanix-virtual.d.ts +41 -26
  85. package/package.json +72 -73
  86. package/dist/server/index.d.ts +0 -0
  87. package/dist/server/index.js +0 -1
@@ -60,7 +60,7 @@ export function getJSXComponentName(node) {
60
60
  }
61
61
  return null;
62
62
  }
63
- export function findComponentImport(ast, componentName) {
63
+ function findComponentImport(ast, componentName) {
64
64
  for (const node of ast.program.body) {
65
65
  if (!t.isImportDeclaration(node)) {
66
66
  continue;
@@ -89,69 +89,19 @@ export function findComponentImport(ast, componentName) {
89
89
  }
90
90
  return null;
91
91
  }
92
- /**
93
- * Remove a specific component from:
94
- *
95
- * import Home from "./Home";
96
- *
97
- * or:
98
- *
99
- * import Home, { foo } from "./Home";
100
- *
101
- * or:
102
- *
103
- * import { Home, foo } from "./Home";
104
- */
105
- function removeComponentImport(componentImport) {
92
+ function removeComponentImport(ast, componentImport) {
106
93
  const { declaration, specifier } = componentImport;
107
94
  const index = declaration.specifiers.indexOf(specifier);
108
95
  if (index !== -1) {
109
96
  declaration.specifiers.splice(index, 1);
110
97
  }
111
- }
112
- function removeEmptyImportDeclarations(ast) {
113
- ast.program.body = ast.program.body.filter((statement) => {
114
- if (!t.isImportDeclaration(statement)) {
115
- return true;
98
+ if (declaration.specifiers.length === 0) {
99
+ const bodyIndex = ast.program.body.indexOf(declaration);
100
+ if (bodyIndex !== -1) {
101
+ ast.program.body.splice(bodyIndex, 1);
116
102
  }
117
- return statement.specifiers.length > 0;
118
- });
119
- }
120
- /**
121
- * Create:
122
- *
123
- * const Home =
124
- * (await import("./Home")).default;
125
- *
126
- * or:
127
- *
128
- * const Home =
129
- * (await import("./Home")).Home;
130
- */
131
- function createDynamicComponentImport(componentName, importPath, exportName) {
132
- const importCall = t.callExpression(t.import(), [
133
- t.stringLiteral(importPath),
134
- ]);
135
- const awaitedImport = t.awaitExpression(importCall);
136
- const property = exportName === "default"
137
- ? t.identifier("default")
138
- : t.identifier(exportName);
139
- const value = t.memberExpression(awaitedImport, property);
140
- return t.variableDeclaration("const", [
141
- t.variableDeclarator(t.identifier(componentName), value),
142
- ]);
103
+ }
143
104
  }
144
- /**
145
- * Convert a JSX name into an expression.
146
- *
147
- * Example:
148
- *
149
- * <Home />
150
- *
151
- * becomes:
152
- *
153
- * Home
154
- */
155
105
  function jsxNameToExpression(name) {
156
106
  if (t.isJSXIdentifier(name)) {
157
107
  return t.identifier(name.name);
@@ -180,46 +130,13 @@ function jsxNameToExpressionFromJSXName(name) {
180
130
  }
181
131
  return null;
182
132
  }
183
- /**
184
- * Convert JSX attributes into an object expression.
185
- *
186
- * Example:
187
- *
188
- * <Home
189
- * name="Naxrul"
190
- * age={30}
191
- * active
192
- * {...user}
193
- * />
194
- *
195
- * becomes:
196
- *
197
- * {
198
- * name: "Naxrul",
199
- * age: 30,
200
- * active: true,
201
- * ...user
202
- * }
203
- */
204
133
  function jsxAttributesToProps(jsx) {
205
134
  const properties = [];
206
135
  for (const attribute of jsx.openingElement.attributes) {
207
- /**
208
- * Handle:
209
- *
210
- * {...props}
211
- */
212
136
  if (t.isJSXSpreadAttribute(attribute)) {
213
137
  properties.push(t.spreadElement(attribute.argument));
214
138
  continue;
215
139
  }
216
- /**
217
- * Normal JSX attribute:
218
- *
219
- * name="value"
220
- * name={value}
221
- * active
222
- */
223
140
  if (!t.isJSXAttribute(attribute)) {
224
141
  continue;
225
142
  }
@@ -230,39 +147,14 @@ function jsxAttributesToProps(jsx) {
230
147
  return t.stringLiteral(`${name.namespace.name}:${name.name.name}`);
231
148
  }
232
149
  const key = jsxAttributeNameToExpression(attribute.name);
233
- /**
234
- * Boolean JSX prop:
235
- *
236
- * <Home active />
237
- *
238
- * becomes:
239
- *
240
- * active: true
241
- */
242
150
  if (!attribute.value) {
243
151
  properties.push(t.objectProperty(key, t.booleanLiteral(true)));
244
152
  continue;
245
153
  }
246
- /**
247
- * String prop:
248
- *
249
- * name="Naxrul"
250
- *
251
- * becomes:
252
- *
253
- * name: "Naxrul"
254
- */
255
154
  if (t.isStringLiteral(attribute.value)) {
256
155
  properties.push(t.objectProperty(key, t.stringLiteral(attribute.value.value)));
257
156
  continue;
258
157
  }
259
- /**
260
- * Expression prop:
261
- *
262
- * age={30}
263
- * user={user}
264
- * items={items.map(...)}
265
- */
266
158
  if (t.isJSXExpressionContainer(attribute.value)) {
267
159
  const expression = attribute.value.expression;
268
160
  if (t.isJSXEmptyExpression(expression)) {
@@ -271,33 +163,12 @@ function jsxAttributesToProps(jsx) {
271
163
  properties.push(t.objectProperty(key, expression));
272
164
  continue;
273
165
  }
274
- /**
275
- * JSX element as a prop:
276
- *
277
- * content={<div>Hello</div>}
278
- */
279
166
  if (t.isJSXElement(attribute.value)) {
280
167
  properties.push(t.objectProperty(key, attribute.value));
281
- continue;
282
168
  }
283
169
  }
284
170
  return t.objectExpression(properties);
285
171
  }
286
- /**
287
- * Convert:
288
- *
289
- * <Home name="Naxrul" age={30} />
290
- *
291
- * into:
292
- *
293
- * {
294
- * component: Home,
295
- * props: {
296
- * name: "Naxrul",
297
- * age: 30
298
- * }
299
- * }
300
- */
301
172
  function jsxToComponentAndProps(jsx) {
302
173
  const component = jsxNameToExpression(jsx.openingElement.name);
303
174
  if (!component) {
@@ -309,6 +180,15 @@ function jsxToComponentAndProps(jsx) {
309
180
  props,
310
181
  };
311
182
  }
183
+ function createDynamicComponentProperty(importPath) {
184
+ const importCall = t.callExpression(t.import(), [
185
+ t.stringLiteral(importPath),
186
+ ]);
187
+ const awaitedImport = t.awaitExpression(importCall);
188
+ const arrowFunction = t.arrowFunctionExpression([], awaitedImport);
189
+ arrowFunction.async = true;
190
+ return t.objectProperty(t.identifier("component"), arrowFunction);
191
+ }
312
192
  function hasRuntimeImport(ast, name) {
313
193
  for (const statement of ast.program.body) {
314
194
  if (!t.isImportDeclaration(statement)) {
@@ -331,8 +211,6 @@ function injectRuntimeImport(ast, name) {
331
211
  if (hasRuntimeImport(ast, name)) {
332
212
  return;
333
213
  }
334
- // Find existing:
335
- // import { ... } from "xanix/runtime";
336
214
  for (const statement of ast.program.body) {
337
215
  if (!t.isImportDeclaration(statement)) {
338
216
  continue;
@@ -343,7 +221,6 @@ function injectRuntimeImport(ast, name) {
343
221
  statement.specifiers.push(t.importSpecifier(t.identifier(name), t.identifier(name)));
344
222
  return;
345
223
  }
346
- // No runtime import exists yet
347
224
  ast.program.body.unshift(t.importDeclaration([t.importSpecifier(t.identifier(name), t.identifier(name))], t.stringLiteral(RUNTIME_IMPORT)));
348
225
  }
349
226
  export function transformer(code, id) {
@@ -352,13 +229,14 @@ export function transformer(code, id) {
352
229
  plugins: ["typescript", "jsx"],
353
230
  });
354
231
  let changed = false;
232
+ const entries = [];
355
233
  traverse(ast, {
356
234
  CallExpression(callPath) {
357
235
  const call = callPath.node;
358
- /**
236
+ /*
359
237
  * Find:
360
238
  *
361
- * res.send(<Home />);
239
+ * res.send(...)
362
240
  */
363
241
  if (!t.isMemberExpression(call.callee)) {
364
242
  return;
@@ -369,9 +247,19 @@ export function transformer(code, id) {
369
247
  return;
370
248
  }
371
249
  const argument = call.arguments[0];
250
+ /*
251
+ * Only transform:
252
+ *
253
+ * res.send(<HomePage />)
254
+ */
372
255
  if (!argument || !t.isJSXElement(argument)) {
373
256
  return;
374
257
  }
258
+ /*
259
+ * Find:
260
+ *
261
+ * (req, res) => {}
262
+ */
375
263
  const functionPath = callPath.getFunctionParent();
376
264
  if (!functionPath) {
377
265
  return;
@@ -385,97 +273,119 @@ export function transformer(code, id) {
385
273
  if (!t.isIdentifier(requestParam) || !t.isIdentifier(responseParam)) {
386
274
  return;
387
275
  }
276
+ /*
277
+ * Find component name:
278
+ *
279
+ * <HomePage />
280
+ */
388
281
  const componentName = getJSXComponentName(argument);
389
282
  if (!componentName) {
390
283
  return;
391
284
  }
285
+ /*
286
+ * Find:
287
+ *
288
+ * import HomePage from "../pages/Home";
289
+ */
392
290
  const componentImport = findComponentImport(ast, componentName);
393
291
  if (!componentImport) {
394
292
  return;
395
293
  }
396
294
  const componentImportPath = componentImport.file;
295
+ /*
296
+ * Resolve:
297
+ *
298
+ * ../pages/Home
299
+ *
300
+ * ->
301
+ *
302
+ * C:/xampp/htdocs/xanix/app/pages/Home/index.tsx
303
+ */
397
304
  const componentFile = resolveComponentFile(id, componentImportPath);
398
305
  if (!path.isAbsolute(componentFile)) {
399
306
  return;
400
307
  }
308
+ /*
309
+ * Normalize absolute file path.
310
+ */
401
311
  const normalizedFile = normalizeFilePath(componentFile);
312
+ /*
313
+ * Stable page ID.
314
+ */
402
315
  const pageId = createPageId(normalizedFile);
403
- /**
404
- * Convert:
405
- *
406
- * <Home name="Naxrul" age={30} />
316
+ /*
317
+ * JSX:
407
318
  *
408
- * into:
319
+ * <HomePage title="Hello" />
409
320
  *
410
- * component: Home
321
+ * ->
411
322
  *
412
- * props: {
413
- * name: "Naxrul",
414
- * age: 30
323
+ * {
324
+ * title: "Hello"
415
325
  * }
416
326
  */
417
327
  const componentAndProps = jsxToComponentAndProps(argument);
418
328
  if (!componentAndProps) {
419
329
  return;
420
330
  }
421
- /**
422
- * Remove:
423
- *
424
- * import Home from "./Home";
331
+ /*
332
+ * Create manifest entry.
425
333
  */
426
- removeComponentImport(componentImport);
427
- /**
428
- * Add:
429
- *
430
- * const Home =
431
- * (await import("./Home")).default;
334
+ entries.push({
335
+ id: pageId,
336
+ name: componentName,
337
+ file: normalizedFile,
338
+ path: componentImportPath,
339
+ export: componentImport.export,
340
+ });
341
+ /*
342
+ * Remove static component import.
432
343
  */
433
- const dynamicImport = createDynamicComponentImport(componentName, componentImportPath, componentImport.export);
434
- /**
435
- * Insert immediately before:
344
+ removeComponentImport(ast, componentImport);
345
+ /*
346
+ * Create:
436
347
  *
437
- * res.send(<Home />);
348
+ * component: async () =>
349
+ * await import("../pages/Home")
438
350
  */
439
- const statementPath = callPath.getStatementParent();
440
- if (statementPath) {
441
- statementPath.insertBefore(dynamicImport);
442
- }
443
- /**
444
- * Route becomes:
445
- *
446
- * async (req, res) => {}
351
+ const componentProperty = createDynamicComponentProperty(componentImportPath);
352
+ /*
353
+ * Make route handler async.
447
354
  */
448
355
  if (t.isFunction(functionPath.node)) {
449
356
  functionPath.node.async = true;
450
357
  }
451
- /**
358
+ /*
359
+ * Create:
360
+ *
361
+ * await xanixPage({
362
+ * component: async () =>
363
+ * await import("../pages/Home"),
364
+ * pageId: "...",
365
+ * req,
366
+ * res,
367
+ * props: {}
368
+ * })
369
+ */
370
+ const pageOptions = t.objectExpression([
371
+ componentProperty,
372
+ t.objectProperty(t.identifier("pageId"), t.stringLiteral(pageId)),
373
+ t.objectProperty(t.identifier("req"), t.identifier(requestParam.name)),
374
+ t.objectProperty(t.identifier("res"), t.identifier(responseParam.name)),
375
+ t.objectProperty(t.identifier("props"), componentAndProps.props),
376
+ ]);
377
+ const pageCall = t.awaitExpression(t.callExpression(t.identifier("xanixPage"), [pageOptions]));
378
+ /*
452
379
  * Replace:
453
380
  *
454
- * res.send(<Home />);
381
+ * res.send(<HomePage />);
455
382
  *
456
383
  * with:
457
384
  *
458
385
  * res.send(
459
- * await xanixPage({
460
- * clientId,
461
- * req,
462
- * res,
463
- * component: Home,
464
- * props: {
465
- * ...
466
- * }
467
- * })
386
+ * await xanixPage({...})
468
387
  * );
469
388
  */
470
- const pageCall = t.awaitExpression(t.callExpression(t.identifier("xanixPage"), [
471
- t.objectExpression([
472
- t.objectProperty(t.identifier("pageId"), t.stringLiteral(pageId)),
473
- t.objectProperty(t.identifier("req"), t.identifier(requestParam.name)),
474
- t.objectProperty(t.identifier("res"), t.identifier(responseParam.name)),
475
- t.objectProperty(t.identifier("Component"), componentAndProps.component),
476
- t.objectProperty(t.identifier("props"), componentAndProps.props),
477
- ]),
478
- ]));
479
389
  call.arguments[0] = pageCall;
480
390
  changed = true;
481
391
  },
@@ -483,19 +393,22 @@ export function transformer(code, id) {
483
393
  if (!changed) {
484
394
  return null;
485
395
  }
486
- /**
396
+ /*
487
397
  * Add:
488
398
  *
489
- * import xanixPage from "xanix/page";
399
+ * import { xanixPage } from "xanix/runtime";
490
400
  */
491
401
  injectRuntimeImport(ast, "xanixPage");
492
- /**
493
- * Remove empty imports.
402
+ /*
403
+ * Generate final code + source map.
494
404
  */
495
- removeEmptyImportDeclarations(ast);
496
- const output = generate(ast, {}, code);
405
+ const output = generate(ast, {
406
+ sourceMaps: true,
407
+ sourceFileName: id,
408
+ }, code);
497
409
  return {
498
410
  code: output.code,
499
411
  map: output.map,
412
+ entries,
500
413
  };
501
414
  }
@@ -1,2 +1,2 @@
1
1
  import type { Plugin } from "rollup";
2
- export default function xanixReactRefresh(): Plugin;
2
+ export default function xanixReactRefresh(WebSocketPort: number): Plugin;
@@ -6,7 +6,7 @@ import generate from "@babel/generator";
6
6
  import * as t from "@babel/types";
7
7
  import { getClientRuntimeFile } from "../../include/utils.js";
8
8
  const root = process.cwd();
9
- export default function xanixReactRefresh() {
9
+ export default function xanixReactRefresh(WebSocketPort) {
10
10
  return {
11
11
  name: "xanix-react-refresh",
12
12
  load(id) {
@@ -14,36 +14,36 @@ export default function xanixReactRefresh() {
14
14
  return null;
15
15
  }
16
16
  const code = fs.readFileSync(id, "utf8");
17
- const refreshCode = `
18
- import * as RefreshRuntime from "react-refresh/runtime";
19
-
20
- ${code}
21
-
22
- RefreshRuntime.injectIntoGlobalHook(window);
23
- window.$RefreshReg$ = RefreshRuntime.register;
24
- window.$RefreshSig$ = () => (type) => type;
25
- const ws = new WebSocket("ws://localhost:8080");
26
-
27
-
28
- ws.onmessage = async (event) => {
29
- const files = JSON.parse(event.data);
30
-
31
- for (const file of files) {
32
- if (!file.endsWith(".js")) {
33
- continue;
34
- }
35
-
36
- const url =
37
- getImportUrl(file.replace(/\\.js$/, "")) +
38
- "?t=" +
39
- Date.now();
40
-
41
- await import(url);
42
- }
43
-
44
- RefreshRuntime.performReactRefresh();
45
- ws.send("reload")
46
- };
17
+ const refreshCode = `
18
+ import * as RefreshRuntime from "react-refresh/runtime";
19
+
20
+ ${code}
21
+
22
+ RefreshRuntime.injectIntoGlobalHook(window);
23
+ window.$RefreshReg$ = RefreshRuntime.register;
24
+ window.$RefreshSig$ = () => (type) => type;
25
+ const ws = new WebSocket("ws://localhost:" + ${WebSocketPort});
26
+
27
+
28
+ ws.onmessage = async (event) => {
29
+ const files = JSON.parse(event.data);
30
+
31
+ for (const file of files) {
32
+ if (!file.endsWith(".js")) {
33
+ continue;
34
+ }
35
+
36
+ const url =
37
+ getImportUrl(file.replace(/\\.js$/, "")) +
38
+ "?t=" +
39
+ Date.now();
40
+
41
+ await import(url);
42
+ }
43
+
44
+ RefreshRuntime.performReactRefresh();
45
+ ws.send("reload")
46
+ };
47
47
  `;
48
48
  return {
49
49
  code: refreshCode,
@@ -1,2 +1,19 @@
1
1
  import type { Plugin } from "rollup";
2
+ /**
3
+ * Check whether an import matches a tsconfig path alias.
4
+ *
5
+ * Examples:
6
+ *
7
+ * @db
8
+ * @db/index
9
+ * @db/user
10
+ *
11
+ * with:
12
+ *
13
+ * "@db/*": ["./src/db/*"]
14
+ */
15
+ export declare function tsconfigPathsMatcher(id: string): boolean;
16
+ /**
17
+ * Rollup plugin.
18
+ */
2
19
  export default function xanixTsconfigAlias(): Plugin;