@pajecawav/yamf 0.0.6 → 0.0.8

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 (55) hide show
  1. package/README.md +32 -1
  2. package/dist/components/Head.d.ts +2 -3
  3. package/dist/components/Head.d.ts.map +1 -1
  4. package/dist/context/ssr.d.ts +1 -2
  5. package/dist/context/ssr.d.ts.map +1 -1
  6. package/dist/hooks/useEvent.d.ts +1 -2
  7. package/dist/hooks/useEvent.d.ts.map +1 -1
  8. package/dist/hooks/useHead.d.ts +2 -3
  9. package/dist/hooks/useHead.d.ts.map +1 -1
  10. package/dist/hooks/useHead.js.map +1 -1
  11. package/dist/island/types.d.ts +2 -3
  12. package/dist/island/types.d.ts.map +1 -1
  13. package/dist/page.d.ts +3 -4
  14. package/dist/page.d.ts.map +1 -1
  15. package/dist/server/entry.d.mts +3 -4
  16. package/dist/server/entry.d.mts.map +1 -1
  17. package/dist/server/entry.mjs +11 -1
  18. package/dist/server/entry.mjs.map +1 -1
  19. package/dist/server/island/server.d.mts +2 -3
  20. package/dist/server/island/server.d.mts.map +1 -1
  21. package/dist/server/island/server.mjs +2 -2
  22. package/dist/server/island/server.mjs.map +1 -1
  23. package/dist/server/island/types.d.mts +1 -2
  24. package/dist/server/island/types.d.mts.map +1 -1
  25. package/dist/server/shared/assets.d.mts +1 -2
  26. package/dist/server/shared/assets.d.mts.map +1 -1
  27. package/dist/server/shared/head.d.mts +1 -2
  28. package/dist/server/shared/head.d.mts.map +1 -1
  29. package/dist/shared/assets.d.ts +2 -3
  30. package/dist/shared/assets.d.ts.map +1 -1
  31. package/dist/shared/head.d.ts +1 -2
  32. package/dist/shared/head.d.ts.map +1 -1
  33. package/dist/vite/index.d.mts +2 -2
  34. package/dist/vite/index.d.mts.map +1 -1
  35. package/dist/vite/index.mjs +3 -1
  36. package/dist/vite/index.mjs.map +1 -1
  37. package/dist/vite/islands.mjs +38 -59
  38. package/dist/vite/islands.mjs.map +1 -1
  39. package/dist/vite/virtual-assets.mjs +1 -1
  40. package/dist/vite/virtual-assets.mjs.map +1 -1
  41. package/dist/vite/virtual-error-handler.mjs +23 -0
  42. package/dist/vite/virtual-error-handler.mjs.map +1 -0
  43. package/dist/vite/virtual-pages.mjs +1 -1
  44. package/dist/vite/virtual-pages.mjs.map +1 -1
  45. package/dist/vite/virtual-root.mjs +1 -1
  46. package/dist/vite/virtual-root.mjs.map +1 -1
  47. package/dist/vite/virtual-template.mjs +1 -1
  48. package/dist/vite/virtual-template.mjs.map +1 -1
  49. package/package.json +22 -31
  50. package/src/island/server.tsx +7 -5
  51. package/src/server/entry.tsx +25 -3
  52. package/src/virtual.d.ts +8 -0
  53. package/src/vite/index.ts +2 -0
  54. package/src/vite/islands.ts +76 -175
  55. package/src/vite/virtual-error-handler.ts +40 -0
@@ -1,227 +1,128 @@
1
1
  // reference https://github.com/hi-ogawa/vite-plugin-fullstack/blob/28e9540a68529c58842e9a3bf17d2193a065d524/examples/island/src/framework/island/plugin.ts
2
- import { generate } from "@babel/generator";
3
- import { parse } from "@babel/parser";
4
- import _traverse from "@babel/traverse";
5
- import {
6
- callExpression,
7
- exportDefaultDeclaration,
8
- exportNamedDeclaration,
9
- functionDeclaration,
10
- functionExpression,
11
- identifier,
12
- importDeclaration,
13
- importDefaultSpecifier,
14
- importNamespaceSpecifier,
15
- memberExpression,
16
- stringLiteral,
17
- variableDeclaration,
18
- variableDeclarator,
19
- } from "@babel/types";
20
- import type { Plugin } from "vite";
21
-
22
- // @ts-ignore
23
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion
24
- const traverse = (_traverse.default as typeof _traverse) ?? _traverse;
2
+ import { withMagicString } from "rolldown-string";
3
+ import type { ParserOptions, Plugin } from "vite";
4
+ import { Visitor } from "vite";
25
5
 
26
6
  const ISLAND_REGEX = /\.island\.(j|t)sx?$/;
27
7
 
8
+ type Lang = NonNullable<ParserOptions["lang"]>;
9
+
10
+ function langFromId(id: string): Lang {
11
+ if (id.endsWith(".tsx")) {
12
+ return "tsx";
13
+ }
14
+ if (id.endsWith(".ts")) {
15
+ return "ts";
16
+ }
17
+ if (id.endsWith(".jsx")) {
18
+ return "jsx";
19
+ }
20
+ return "js";
21
+ }
22
+
28
23
  export const islands = (): Plugin[] => {
29
24
  return [
30
25
  {
31
26
  name: "yamf:islands",
32
27
  transform: {
33
28
  filter: { id: ISLAND_REGEX },
34
- handler(code, id) {
29
+ handler: withMagicString(function (this, s, id) {
35
30
  if (this.environment.name !== "ssr") {
36
31
  return;
37
32
  }
38
33
 
39
- const seenExports = new Set<string>();
40
-
41
- const ast = parse(code, {
42
- sourceType: "module",
43
- plugins: ["typescript", "jsx"],
34
+ const program = this.parse(s.original, {
35
+ lang: langFromId(id),
44
36
  });
45
37
 
46
- traverse(ast, {
47
- Program(path) {
48
- // prepends server island runtime
49
- // import * as __runtime from "yamf/server";
50
- path.unshiftContainer(
51
- "body",
52
- importDeclaration(
53
- [importNamespaceSpecifier(identifier("__runtime"))],
54
- stringLiteral("@pajecawav/yamf/server"),
55
- ),
56
- );
38
+ // prepend server island runtime + asset imports:
39
+ // import * as __runtime from "@pajecawav/yamf/server";
40
+ // import __assets from "<id>?assets=client";
41
+ s.prepend(`import * as __runtime from "@pajecawav/yamf/server";\n`);
42
+ s.prepend(`import __assets from "${id}?assets=client";\n`);
57
43
 
58
- // prepends asset imports for the island:
59
- // import __assets from "MODULE_ID?assets=client";
60
- path.unshiftContainer(
61
- "body",
62
- importDeclaration(
63
- [importDefaultSpecifier(identifier("__assets"))],
64
- stringLiteral(`${id}?assets=client`),
65
- ),
66
- );
67
- },
68
- ExportDefaultDeclaration(path) {
69
- const declarationType = path.node.declaration.type;
44
+ const seenExports = new Set<string>();
70
45
 
46
+ new Visitor({
47
+ ExportDefaultDeclaration(node) {
48
+ const declaration = node.declaration;
71
49
  if (
72
- !(
73
- declarationType === "FunctionDeclaration" ||
74
- declarationType === "FunctionExpression" ||
75
- declarationType === "ArrowFunctionExpression"
76
- )
50
+ declaration.type !== "FunctionDeclaration" &&
51
+ declaration.type !== "FunctionExpression" &&
52
+ declaration.type !== "ArrowFunctionExpression"
77
53
  ) {
78
54
  return;
79
55
  }
80
56
 
81
- const originalFunction =
82
- path.node.declaration.type === "FunctionExpression" ||
83
- path.node.declaration.type === "ArrowFunctionExpression"
84
- ? path.node.declaration
85
- : functionExpression(
86
- null,
87
- path.node.declaration.params,
88
- path.node.declaration.body,
89
- undefined,
90
- path.node.declaration.async,
91
- );
92
-
93
- const islandIdentifier = identifier("__ISLAND__");
94
-
95
- path.insertBefore(
96
- variableDeclaration("const", [
97
- variableDeclarator(islandIdentifier, originalFunction),
98
- ]),
99
- );
100
-
101
- path.replaceWith(
102
- exportDefaultDeclaration(
103
- callExpression(
104
- memberExpression(
105
- identifier("__runtime"),
106
- identifier("createIsland"),
107
- ),
108
- [
109
- islandIdentifier,
110
- stringLiteral("default"),
111
- identifier("__assets"),
112
- ],
113
- ),
114
- ),
57
+ // export default <fn> ->
58
+ // const __ISLAND__ = <fn>; export default __runtime.createIsland(__ISLAND__, "default", __assets)
59
+ s.overwrite(node.start, declaration.start, "const __ISLAND__ = ");
60
+ s.appendRight(
61
+ declaration.end,
62
+ `; export default __runtime.createIsland(__ISLAND__, "default", __assets)`,
115
63
  );
116
64
  },
117
- ExportNamedDeclaration(path) {
118
- if (path.node.declaration?.type === "VariableDeclaration") {
119
- const declaration = path.node.declaration.declarations.at(0);
120
-
65
+ ExportNamedDeclaration(node) {
66
+ const declaration = node.declaration;
67
+ if (declaration?.type === "VariableDeclaration") {
68
+ const declarator = declaration.declarations[0];
121
69
  if (
122
- !declaration ||
123
- declaration.id.type !== "Identifier" ||
124
- seenExports.has(declaration.id.name)
70
+ !declarator ||
71
+ declarator.id.type !== "Identifier" ||
72
+ !declarator.init ||
73
+ seenExports.has(declarator.id.name)
125
74
  ) {
126
75
  return;
127
76
  }
128
- const exportName = declaration.id.name;
77
+ const exportName = declarator.id.name;
129
78
  seenExports.add(exportName);
130
79
 
131
- const islandIdentifier = identifier(`__wrap_${exportName}`);
132
-
133
- path.insertBefore(
134
- variableDeclaration("const", [
135
- variableDeclarator(islandIdentifier, declaration.init),
136
- ]),
80
+ // export const <name> = <init> ->
81
+ // const __wrap_<name> = <init>; export const <name> = __runtime.createIsland(__wrap_<name>, "<name>", __assets)
82
+ s.overwrite(
83
+ node.start,
84
+ declarator.init.start,
85
+ `const __wrap_${exportName} = `,
137
86
  );
138
-
139
- path.replaceWith(
140
- exportNamedDeclaration(
141
- variableDeclaration("const", [
142
- variableDeclarator(
143
- identifier(exportName),
144
- callExpression(
145
- memberExpression(
146
- identifier("__runtime"),
147
- identifier("createIsland"),
148
- ),
149
- [
150
- islandIdentifier,
151
- stringLiteral(exportName),
152
- identifier("__assets"),
153
- ],
154
- ),
155
- ),
156
- ]),
157
- ),
87
+ s.appendRight(
88
+ declarator.init.end,
89
+ `; export const ${exportName} = __runtime.createIsland(__wrap_${exportName}, "${exportName}", __assets)`,
158
90
  );
159
- } else if (path.node.declaration?.type === "FunctionDeclaration") {
160
- const declaration = path.node.declaration;
161
-
91
+ } else if (declaration?.type === "FunctionDeclaration") {
92
+ const fnId = declaration.id;
162
93
  if (
163
- !declaration ||
164
- declaration.id?.type !== "Identifier" ||
165
- seenExports.has(declaration.id.name)
94
+ !fnId ||
95
+ fnId.type !== "Identifier" ||
96
+ seenExports.has(fnId.name)
166
97
  ) {
167
98
  return;
168
99
  }
169
- const exportName = declaration.id.name;
100
+ const exportName = fnId.name;
170
101
  seenExports.add(exportName);
171
102
 
172
- const islandIdentifier = identifier(`__wrap_${exportName}`);
173
-
174
- path.insertBefore(
175
- functionDeclaration(
176
- islandIdentifier,
177
- declaration.params,
178
- declaration.body,
179
- declaration.generator,
180
- declaration.async,
181
- ),
182
- );
183
-
184
- path.replaceWith(
185
- exportNamedDeclaration(
186
- variableDeclaration("const", [
187
- variableDeclarator(
188
- identifier(exportName),
189
- callExpression(
190
- memberExpression(
191
- identifier("__runtime"),
192
- identifier("createIsland"),
193
- ),
194
- [
195
- islandIdentifier,
196
- stringLiteral(exportName),
197
- identifier("__assets"),
198
- ],
199
- ),
200
- ),
201
- ]),
202
- ),
103
+ // export function <name>() {} ->
104
+ // function __wrap_<name>() {}; export const <name> = __runtime.createIsland(__wrap_<name>, "<name>", __assets)
105
+ s.remove(node.start, declaration.start);
106
+ s.overwrite(fnId.start, fnId.end, `__wrap_${exportName}`);
107
+ s.appendRight(
108
+ declaration.end,
109
+ `; export const ${exportName} = __runtime.createIsland(__wrap_${exportName}, "${exportName}", __assets)`,
203
110
  );
204
111
  }
205
112
  },
206
- });
207
-
208
- const result = generate(ast);
209
-
210
- return { code: result.code, map: result.map };
211
- },
113
+ }).visit(program);
114
+ }),
212
115
  },
213
116
  },
214
117
  {
215
118
  name: "yamf:islands:raw-import",
216
119
  transform: {
217
120
  order: "post",
218
- handler(code) {
219
- if (code.includes("__island_raw_import__")) {
220
- return code.replaceAll("__island_raw_import__", "import");
121
+ handler: withMagicString(function (s) {
122
+ if (s.original.includes("__island_raw_import__")) {
123
+ s.replaceAll("__island_raw_import__", "import");
221
124
  }
222
-
223
- return undefined;
224
- },
125
+ }),
225
126
  },
226
127
  },
227
128
  ];
@@ -0,0 +1,40 @@
1
+ import type { NitroPluginConfig } from "nitro/vite";
2
+ import type { Plugin } from "vite";
3
+ import { js } from "../shared/utils";
4
+
5
+ export interface VirtualErrorHandlerOptions {
6
+ nitro?: NitroPluginConfig;
7
+ }
8
+
9
+ export const virtualErrorHandler = (options?: VirtualErrorHandlerOptions): Plugin => {
10
+ const virtualModuleId = "virtual:yamf:error-handler";
11
+ const resolvedVirtualModuleId = "\0" + virtualModuleId;
12
+
13
+ return {
14
+ name: "yamf:virtual-error-handler",
15
+ resolveId(id) {
16
+ if (id === virtualModuleId) {
17
+ return resolvedVirtualModuleId;
18
+ }
19
+
20
+ return undefined;
21
+ },
22
+ load(id) {
23
+ if (id !== resolvedVirtualModuleId) {
24
+ return;
25
+ }
26
+
27
+ const errorHandler = options?.nitro?.errorHandler;
28
+
29
+ if (!errorHandler) {
30
+ return js`export const errorHandler = null;`;
31
+ }
32
+
33
+ if (Array.isArray(errorHandler)) {
34
+ throw new Error("Multiple error handlers are not supported");
35
+ }
36
+
37
+ return js`export { default as errorHandler } from "${errorHandler}";`;
38
+ },
39
+ };
40
+ };