@farm.js/plugin 0.1.0-beta.1 → 0.1.0-beta.100

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 (54) hide show
  1. package/dist/api/index.d.ts +2 -0
  2. package/dist/api/index.d.ts.map +1 -1
  3. package/dist/api/index.js +25 -95
  4. package/dist/dev-static.d.ts +8 -0
  5. package/dist/dev-static.d.ts.map +1 -0
  6. package/dist/dev-static.js +37 -0
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1 -1
  10. package/dist/middleware/index.d.ts.map +1 -1
  11. package/dist/middleware/index.js +28 -53
  12. package/dist/middleware/matching.d.ts +29 -0
  13. package/dist/middleware/matching.d.ts.map +1 -0
  14. package/dist/middleware/matching.js +79 -0
  15. package/dist/rsc/automatic-optimized-boundary.d.ts +11 -0
  16. package/dist/rsc/automatic-optimized-boundary.d.ts.map +1 -0
  17. package/dist/rsc/automatic-optimized-boundary.js +162 -0
  18. package/dist/rsc/compatibility.d.ts +8 -0
  19. package/dist/rsc/compatibility.d.ts.map +1 -0
  20. package/dist/rsc/compatibility.js +46 -0
  21. package/dist/rsc/dev-response.d.ts +3 -0
  22. package/dist/rsc/dev-response.d.ts.map +1 -0
  23. package/dist/rsc/dev-response.js +10 -0
  24. package/dist/rsc/entries/client.d.ts +1 -0
  25. package/dist/rsc/entries/client.d.ts.map +1 -1
  26. package/dist/rsc/entries/client.js +42 -5
  27. package/dist/rsc/entries/error-fallback.d.ts +3 -0
  28. package/dist/rsc/entries/error-fallback.d.ts.map +1 -0
  29. package/dist/rsc/entries/error-fallback.js +12 -0
  30. package/dist/rsc/entries/rsc.d.ts.map +1 -1
  31. package/dist/rsc/entries/rsc.js +187 -189
  32. package/dist/rsc/entries/ssr.d.ts.map +1 -1
  33. package/dist/rsc/entries/ssr.js +44 -74
  34. package/dist/rsc/index.d.ts +15 -2
  35. package/dist/rsc/index.d.ts.map +1 -1
  36. package/dist/rsc/index.js +167 -69
  37. package/dist/rsc/nitro-build.d.ts.map +1 -1
  38. package/dist/rsc/nitro-build.js +28 -8
  39. package/dist/rsc/optimized-boundary.d.ts +10 -1
  40. package/dist/rsc/optimized-boundary.d.ts.map +1 -1
  41. package/dist/rsc/optimized-boundary.js +229 -1
  42. package/dist/rsc/route-action-transform.d.ts +11 -0
  43. package/dist/rsc/route-action-transform.d.ts.map +1 -0
  44. package/dist/rsc/route-action-transform.js +369 -0
  45. package/dist/rsc/server-fn-transform.js +1 -1
  46. package/dist/rsc/test-fixture-dependencies.d.ts +2 -0
  47. package/dist/rsc/test-fixture-dependencies.d.ts.map +1 -0
  48. package/dist/rsc/test-fixture-dependencies.js +23 -0
  49. package/dist/rsc/types.d.ts +9 -0
  50. package/dist/rsc/types.d.ts.map +1 -1
  51. package/dist/rsc/vite-plugin-nitro.d.ts +20 -7
  52. package/dist/rsc/vite-plugin-nitro.d.ts.map +1 -1
  53. package/dist/rsc/vite-plugin-nitro.js +51 -66
  54. package/package.json +15 -8
@@ -219,9 +219,20 @@ function createRscRequest(event) {
219
219
  return new Request(event.req, { signal: controller.signal });
220
220
  }
221
221
 
222
- export default defineEventHandler((event) => handler(createRscRequest(event), {
223
- waitUntil: (promise) => event.waitUntil(promise),
224
- }));
222
+ export default defineEventHandler(async (event) => {
223
+ const response = await handler(createRscRequest(event), {
224
+ waitUntil: (promise) => event.waitUntil(promise),
225
+ });
226
+ // H3's prepared headers override Response headers. Keep both the runtime's
227
+ // fields (e.g. Accept-Encoding from static middleware) and the app's fields.
228
+ const vary = [event.res.headers.get('vary'), response.headers.get('vary')]
229
+ .filter(Boolean).join(',').split(',').map(value => value.trim()).filter(Boolean);
230
+ if (vary.length) {
231
+ const fields = new Map(vary.map(value => [value.toLowerCase(), value]));
232
+ event.res.headers.set('vary', fields.has('*') ? '*' : [...fields.values()].join(', '));
233
+ }
234
+ return response;
235
+ });
225
236
  `.trim();
226
237
  const entryPath = path.join(buildDir, "rsc-entry.mjs");
227
238
  mkdirSync(buildDir, { recursive: true });
@@ -271,7 +282,15 @@ export async function buildRscNitro(options) {
271
282
  },
272
283
  // Externalize rsc/ssr so we don't bundle (they reference Vite-generated manifest). We copy dist into server output after build.
273
284
  rollupConfig: {
274
- external: (id) => id.includes("../dist/") || id.includes("dist/rsc") || id.includes("dist/ssr"),
285
+ external: (id) => {
286
+ // Ids reach this predicate in both separator forms on Windows, and matching
287
+ // only the POSIX one makes the same module external in one pass and not in
288
+ // the next, which Rollup rejects.
289
+ const normalized = id.split("\\").join("/");
290
+ return (normalized.includes("../dist/") ||
291
+ normalized.includes("dist/rsc") ||
292
+ normalized.includes("dist/ssr"));
293
+ },
275
294
  },
276
295
  compatibilityDate: "2024-12-01",
277
296
  minify: true,
@@ -366,13 +385,14 @@ export async function buildRscNitro(options) {
366
385
  }
367
386
  }
368
387
  if (existsSync(ssrIndexPath)) {
369
- const assetsDir = path.join(publicDir, "assets");
388
+ const assetsDirName = assetsDir ?? "assets";
389
+ const assetsRoot = path.join(publicDir, assetsDirName);
370
390
  let clientCssHref = "";
371
- if (existsSync(assetsDir)) {
372
- const files = readdirSync(assetsDir);
391
+ if (existsSync(assetsRoot)) {
392
+ const files = readdirSync(assetsRoot);
373
393
  const cssFile = files.find((f) => f.endsWith(".css"));
374
394
  if (cssFile)
375
- clientCssHref = "/assets/" + cssFile;
395
+ clientCssHref = `/${assetsDirName}/${cssFile}`;
376
396
  }
377
397
  try {
378
398
  let ssrCode = readFileSync(ssrIndexPath, "utf-8");
@@ -1,5 +1,6 @@
1
1
  import { type RenderOptions, type StrataDocument } from "@farming-labs/strata";
2
2
  import { type StaticFragmentBoundary, type StaticFragmentProps } from "@farming-labs/strata/react-server";
3
+ import { type ReactElement } from "react";
3
4
  export type { RenderOptions, StrataDocument, StrataElement, StrataNode, StrataTag, StrataText, } from "@farming-labs/strata";
4
5
  export interface OptimizedBoundaryProps extends Omit<StaticFragmentProps, "content"> {
5
6
  /**
@@ -9,12 +10,20 @@ export interface OptimizedBoundaryProps extends Omit<StaticFragmentProps, "conte
9
10
  document: StrataDocument;
10
11
  renderOptions?: RenderOptions;
11
12
  }
13
+ /**
14
+ * Internal compiler target for automatic optimized boundaries. This helper is
15
+ * deliberately fail-open: any unsupported or unsafe tree returns the original
16
+ * React element unchanged.
17
+ *
18
+ * @internal
19
+ */
20
+ export declare function _optimizeBoundary(element: ReactElement): ReactElement;
12
21
  /**
13
22
  * Render a typed host-only document with the optimized native runtime and
14
23
  * place it inside an opaque React-owned boundary.
15
24
  *
16
25
  * Enable `experimental.optimizedBoundary` before importing this component.
17
26
  */
18
- export declare function OptimizedBoundary({ document, renderOptions, ...props }: OptimizedBoundaryProps): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
27
+ export declare function OptimizedBoundary({ document, renderOptions, ...props }: OptimizedBoundaryProps): ReactElement;
19
28
  export type OptimizedBoundaryTag = StaticFragmentBoundary;
20
29
  //# sourceMappingURL=optimized-boundary.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"optimized-boundary.d.ts","sourceRoot":"","sources":["../../src/rsc/optimized-boundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACzB,MAAM,mCAAmC,CAAC;AAE3C,YAAY,EACV,aAAa,EACb,cAAc,EACd,aAAa,EACb,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,mBAAmB,EAAE,SAAS,CAAC;IAClF;;;OAGG;IACH,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,KAAK,EAAE,EAAE,sBAAsB,0FAM9F;AAED,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAC"}
1
+ {"version":3,"file":"optimized-boundary.d.ts","sourceRoot":"","sources":["../../src/rsc/optimized-boundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EAIpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAA2C,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAEnF,YAAY,EACV,aAAa,EACb,cAAc,EACd,aAAa,EACb,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,mBAAmB,EAAE,SAAS,CAAC;IAClF;;;OAGG;IACH,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAiND;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,YAAY,CAsBrE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,aAAa,EACb,GAAG,KAAK,EACT,EAAE,sBAAsB,GAAG,YAAY,CAMvC;AAED,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAC"}
@@ -1,5 +1,233 @@
1
- import { render } from "@farming-labs/strata";
1
+ import { render, } from "@farming-labs/strata";
2
2
  import { StaticFragment, } from "@farming-labs/strata/react-server";
3
+ import { createElement, Fragment, isValidElement } from "react";
4
+ const AUTOMATIC_MIN_NODES = 8;
5
+ const AUTOMATIC_MIN_BYTES = 256;
6
+ const AUTOMATIC_BOUNDARIES = new Set([
7
+ "article",
8
+ "aside",
9
+ "div",
10
+ "footer",
11
+ "header",
12
+ "main",
13
+ "nav",
14
+ "section",
15
+ "span",
16
+ ]);
17
+ const STRATA_TAGS = new Set([
18
+ "a",
19
+ "abbr",
20
+ "address",
21
+ "article",
22
+ "aside",
23
+ "b",
24
+ "blockquote",
25
+ "br",
26
+ "caption",
27
+ "cite",
28
+ "code",
29
+ "col",
30
+ "colgroup",
31
+ "dd",
32
+ "del",
33
+ "details",
34
+ "dfn",
35
+ "div",
36
+ "dl",
37
+ "dt",
38
+ "em",
39
+ "figcaption",
40
+ "figure",
41
+ "footer",
42
+ "h1",
43
+ "h2",
44
+ "h3",
45
+ "h4",
46
+ "h5",
47
+ "h6",
48
+ "header",
49
+ "hr",
50
+ "i",
51
+ "img",
52
+ "ins",
53
+ "kbd",
54
+ "li",
55
+ "main",
56
+ "mark",
57
+ "nav",
58
+ "ol",
59
+ "p",
60
+ "pre",
61
+ "q",
62
+ "s",
63
+ "samp",
64
+ "section",
65
+ "small",
66
+ "span",
67
+ "strong",
68
+ "sub",
69
+ "summary",
70
+ "sup",
71
+ "table",
72
+ "tbody",
73
+ "td",
74
+ "tfoot",
75
+ "th",
76
+ "thead",
77
+ "time",
78
+ "tr",
79
+ "u",
80
+ "ul",
81
+ "var",
82
+ "wbr",
83
+ ]);
84
+ const BOOLEAN_ATTRIBUTES = new Set(["hidden", "reversed"]);
85
+ const ATTRIBUTE_NAMES = {
86
+ className: "class",
87
+ colSpan: "colspan",
88
+ dateTime: "datetime",
89
+ rowSpan: "rowspan",
90
+ };
91
+ function AutomaticOptimizedBoundary({ document, fallback, ...props }) {
92
+ let content;
93
+ try {
94
+ content = render(document);
95
+ }
96
+ catch {
97
+ return fallback;
98
+ }
99
+ if (content.nodeCount < AUTOMATIC_MIN_NODES && content.bytes < AUTOMATIC_MIN_BYTES) {
100
+ return fallback;
101
+ }
102
+ return StaticFragment({ ...props, content });
103
+ }
104
+ function attributeValue(name, value) {
105
+ if (value === null || value === undefined)
106
+ return undefined;
107
+ if (typeof value === "string" || typeof value === "number" || typeof value === "bigint") {
108
+ return String(value);
109
+ }
110
+ if (typeof value !== "boolean")
111
+ return null;
112
+ if (name.startsWith("aria-") || name.startsWith("data-"))
113
+ return String(value);
114
+ if (BOOLEAN_ATTRIBUTES.has(name))
115
+ return value ? "" : undefined;
116
+ return null;
117
+ }
118
+ function convertAttributes(tag, props) {
119
+ const attributes = {};
120
+ for (const [reactName, rawValue] of Object.entries(props)) {
121
+ if (reactName === "children")
122
+ continue;
123
+ if (reactName === "dangerouslySetInnerHTML" ||
124
+ reactName === "ref" ||
125
+ reactName === "style" ||
126
+ reactName === "suppressHydrationWarning" ||
127
+ /^on[A-Z]/.test(reactName)) {
128
+ return null;
129
+ }
130
+ const name = ATTRIBUTE_NAMES[reactName] || reactName;
131
+ const value = attributeValue(name, rawValue);
132
+ if (value === null)
133
+ return null;
134
+ if (value !== undefined)
135
+ attributes[name] = value;
136
+ }
137
+ return Object.keys(attributes).length > 0 ? attributes : {};
138
+ }
139
+ function automaticDocumentFromElement(element) {
140
+ const rootProps = element.props;
141
+ const children = [];
142
+ if (!appendStrataNodes(rootProps.children, children))
143
+ return null;
144
+ return { type: "document", ...(children.length > 0 ? { children } : {}) };
145
+ }
146
+ function appendStrataNodes(value, output) {
147
+ if (value === null || value === undefined || typeof value === "boolean")
148
+ return true;
149
+ if (typeof value === "string" || typeof value === "number" || typeof value === "bigint") {
150
+ output.push({ type: "text", value: String(value) });
151
+ return true;
152
+ }
153
+ if (Array.isArray(value)) {
154
+ for (const child of value) {
155
+ if (!appendStrataNodes(child, output))
156
+ return false;
157
+ }
158
+ return true;
159
+ }
160
+ if (!isValidElement(value))
161
+ return false;
162
+ const element = value;
163
+ const props = element.props;
164
+ if (element.type === Fragment)
165
+ return appendStrataNodes(props.children, output);
166
+ if (element.type === OptimizedBoundary || element.type === AutomaticOptimizedBoundary) {
167
+ const boundary = props.as ?? "div";
168
+ if (typeof boundary !== "string" || !STRATA_TAGS.has(boundary))
169
+ return false;
170
+ const { as: _as, document: _document, fallback: _fallback, ...boundaryProps } = props;
171
+ const attributes = convertAttributes(boundary, boundaryProps);
172
+ if (!attributes)
173
+ return false;
174
+ const document = props.document;
175
+ if (!document || document.type !== "document")
176
+ return false;
177
+ output.push({
178
+ type: "element",
179
+ tag: boundary,
180
+ ...(Object.keys(attributes).length > 0 ? { attributes } : {}),
181
+ ...(document.children?.length ? { children: document.children } : {}),
182
+ });
183
+ return true;
184
+ }
185
+ if (typeof element.type !== "string" || !STRATA_TAGS.has(element.type)) {
186
+ return false;
187
+ }
188
+ const tag = element.type;
189
+ const attributes = convertAttributes(tag, props);
190
+ if (!attributes)
191
+ return false;
192
+ const children = [];
193
+ if (!appendStrataNodes(props.children, children))
194
+ return false;
195
+ output.push({
196
+ type: "element",
197
+ tag,
198
+ ...(Object.keys(attributes).length > 0 ? { attributes } : {}),
199
+ ...(children.length > 0 ? { children } : {}),
200
+ });
201
+ return true;
202
+ }
203
+ /**
204
+ * Internal compiler target for automatic optimized boundaries. This helper is
205
+ * deliberately fail-open: any unsupported or unsafe tree returns the original
206
+ * React element unchanged.
207
+ *
208
+ * @internal
209
+ */
210
+ export function _optimizeBoundary(element) {
211
+ if (!isValidElement(element) ||
212
+ typeof element.type !== "string" ||
213
+ !AUTOMATIC_BOUNDARIES.has(element.type)) {
214
+ return element;
215
+ }
216
+ const props = element.props;
217
+ if (props.dangerouslySetInnerHTML !== undefined || props.ref !== undefined)
218
+ return element;
219
+ const document = automaticDocumentFromElement(element);
220
+ if (!document)
221
+ return element;
222
+ const { children: _children, ...boundaryProps } = props;
223
+ return createElement(AutomaticOptimizedBoundary, {
224
+ ...boundaryProps,
225
+ ...(element.key !== null ? { key: element.key } : {}),
226
+ as: element.type,
227
+ document,
228
+ fallback: element,
229
+ });
230
+ }
3
231
  /**
4
232
  * Render a typed host-only document with the optimized native runtime and
5
233
  * place it inside an opaque React-owned boundary.
@@ -0,0 +1,11 @@
1
+ export type FarmRouteActionClientTransformResult = {
2
+ code: string;
3
+ routes: string[];
4
+ };
5
+ /**
6
+ * Replace a programmatic route imported by the browser with a small action-only
7
+ * proxy. Route loaders, components, database imports, and other server code do
8
+ * not enter the client graph.
9
+ */
10
+ export declare function transformFarmRouteActionClients(code: string, id: string): FarmRouteActionClientTransformResult | null;
11
+ //# sourceMappingURL=route-action-transform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-action-transform.d.ts","sourceRoot":"","sources":["../../src/rsc/route-action-transform.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,oCAAoC,GAAG;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAcF;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,oCAAoC,GAAG,IAAI,CAqC7C"}