@farm.js/core 0.1.0-beta.46 → 0.1.0-beta.48

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 (38) hide show
  1. package/dist/{chunk-W2O6SKJU.mjs → chunk-3P63LWDM.mjs} +2 -2
  2. package/dist/{chunk-V7VDW7IY.mjs → chunk-HEZHCCMF.mjs} +2 -2
  3. package/dist/{chunk-LGCIIMFR.mjs → chunk-NKIHYEWC.mjs} +2 -2
  4. package/dist/{chunk-LGCIIMFR.mjs.map → chunk-NKIHYEWC.mjs.map} +1 -1
  5. package/dist/{chunk-TQJMU5BP.mjs → chunk-VZKOMD6C.mjs} +113 -4
  6. package/dist/chunk-VZKOMD6C.mjs.map +1 -0
  7. package/dist/client/lifecycle.mjs +2 -2
  8. package/dist/client-plugins.cjs +1 -1
  9. package/dist/client-plugins.cjs.map +1 -1
  10. package/dist/client-plugins.mjs +2 -2
  11. package/dist/client.cjs +1 -1
  12. package/dist/client.cjs.map +1 -1
  13. package/dist/client.mjs +2 -2
  14. package/dist/index.cjs +117 -4
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.mjs +4 -4
  17. package/dist/internal/build-runtime.cjs +117 -4
  18. package/dist/internal/build-runtime.cjs.map +1 -1
  19. package/dist/internal/build-runtime.mjs +3 -3
  20. package/dist/internal/client-runtime.cjs +1 -1
  21. package/dist/internal/client-runtime.cjs.map +1 -1
  22. package/dist/internal/client-runtime.mjs +2 -2
  23. package/dist/plugin.cjs +112 -3
  24. package/dist/plugin.cjs.map +1 -1
  25. package/dist/plugin.mjs +2 -2
  26. package/dist/server.cjs +112 -3
  27. package/dist/server.cjs.map +1 -1
  28. package/dist/server.mjs +2 -2
  29. package/dist/version.cjs +1 -1
  30. package/dist/version.cjs.map +1 -1
  31. package/dist/version.mjs +1 -1
  32. package/dist/vite.cjs +112 -3
  33. package/dist/vite.cjs.map +1 -1
  34. package/dist/vite.mjs +2 -2
  35. package/package.json +1 -1
  36. package/dist/chunk-TQJMU5BP.mjs.map +0 -1
  37. /package/dist/{chunk-W2O6SKJU.mjs.map → chunk-3P63LWDM.mjs.map} +0 -0
  38. /package/dist/{chunk-V7VDW7IY.mjs.map → chunk-HEZHCCMF.mjs.map} +0 -0
package/dist/plugin.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  import "./chunk-RQ633A5I.mjs";
7
7
  import {
8
8
  farmPlugin
9
- } from "./chunk-TQJMU5BP.mjs";
9
+ } from "./chunk-VZKOMD6C.mjs";
10
10
  import "./chunk-XJTDE4L4.mjs";
11
11
  import "./chunk-CAUVJN4X.mjs";
12
12
  import "./chunk-AMZZCRQ7.mjs";
@@ -63,7 +63,7 @@ import "./chunk-RBRLLZL5.mjs";
63
63
  import "./chunk-WZ5QFROO.mjs";
64
64
  import "./chunk-7ZMKVETU.mjs";
65
65
  import "./chunk-FXG2PS27.mjs";
66
- import "./chunk-LGCIIMFR.mjs";
66
+ import "./chunk-NKIHYEWC.mjs";
67
67
  import "./chunk-CGILA3WO.mjs";
68
68
  export {
69
69
  FarmRuntimeShutdownError,
package/dist/server.cjs CHANGED
@@ -17829,6 +17829,57 @@ __name(safeGlobFiles, "safeGlobFiles");
17829
17829
  // src/server/renderer.ts
17830
17830
  var fs3 = __toESM(require("fs"));
17831
17831
  var path11 = __toESM(require("path"));
17832
+
17833
+ // src/server/full-document.ts
17834
+ function stripContentsWrappers(markup) {
17835
+ let out = markup.replace(/^\s+/, "");
17836
+ const opener = /^<div\b[^>]*style="display\s*:\s*contents"[^>]*>/i;
17837
+ let match;
17838
+ while (match = opener.exec(out)) {
17839
+ out = out.slice(match[0].length).replace(/^\s+/, "");
17840
+ }
17841
+ return out;
17842
+ }
17843
+ __name(stripContentsWrappers, "stripContentsWrappers");
17844
+ function extractFarmFullDocument(markup) {
17845
+ const inner = stripContentsWrappers(markup);
17846
+ if (!/^<!doctype/i.test(inner) && !/^<html[\s>]/i.test(inner)) return null;
17847
+ const start = markup.search(/<!doctype|<html[\s>]/i);
17848
+ const closeIndex = markup.toLowerCase().lastIndexOf("</html>");
17849
+ if (start < 0 || closeIndex < 0) return null;
17850
+ return markup.slice(start, closeIndex + "</html>".length);
17851
+ }
17852
+ __name(extractFarmFullDocument, "extractFarmFullDocument");
17853
+ function opensFarmFullDocument(markup) {
17854
+ const inner = stripContentsWrappers(markup);
17855
+ return /^<!doctype/i.test(inner) || /^<html[\s>]/i.test(inner);
17856
+ }
17857
+ __name(opensFarmFullDocument, "opensFarmFullDocument");
17858
+ function composeFarmFullDocument(documentHtml, assets) {
17859
+ let html = documentHtml;
17860
+ if (assets.htmlAttributes) {
17861
+ html = html.replace(
17862
+ /<html\b([^>]*)>/i,
17863
+ (_match, attrs) => `<html${attrs}${assets.htmlAttributes}>`
17864
+ );
17865
+ }
17866
+ if (!/\sid=["']root["']/i.test(html)) {
17867
+ html = html.replace(/<body\b([^>]*)>/i, '<body$1><div id="root">').replace(/<\/body>/i, "</div></body>");
17868
+ }
17869
+ if (assets.headAssets) {
17870
+ html = html.replace(/<\/head>/i, () => ` ${assets.headAssets}
17871
+ </head>`);
17872
+ }
17873
+ if (assets.bodyFooter) {
17874
+ html = html.replace(/<\/body>/i, () => ` ${assets.bodyFooter}
17875
+ </body>`);
17876
+ }
17877
+ return /^\s*<!doctype/i.test(html) ? html : `<!DOCTYPE html>
17878
+ ${html}`;
17879
+ }
17880
+ __name(composeFarmFullDocument, "composeFarmFullDocument");
17881
+
17882
+ // src/server/renderer.ts
17832
17883
  var import_stream = require("stream");
17833
17884
 
17834
17885
  // src/middleware/server.ts
@@ -21183,7 +21234,7 @@ _setFarmThemeServerSnapshotResolver(() => {
21183
21234
  });
21184
21235
 
21185
21236
  // package.json
21186
- var version = "0.1.0-beta.46";
21237
+ var version = "0.1.0-beta.48";
21187
21238
 
21188
21239
  // src/version.ts
21189
21240
  var FARM_VERSION = version;
@@ -21292,6 +21343,16 @@ function warnSuppressedAsyncHydrationOnce(modulePath) {
21292
21343
  );
21293
21344
  }
21294
21345
  __name(warnSuppressedAsyncHydrationOnce, "warnSuppressedAsyncHydrationOnce");
21346
+ var fullDocumentRoutes = /* @__PURE__ */ new Set();
21347
+ var warnedFullDocumentLayout = false;
21348
+ function warnFarmFullDocumentLayout() {
21349
+ if (warnedFullDocumentLayout) return;
21350
+ warnedFullDocumentLayout = true;
21351
+ logger.warn(
21352
+ `A root layout returned a full <html> document. Farm.js owns the document shell, so a layout should return a fragment (its children) \u2014 like the docs example \u2014 and let the framework provide <html>/<head>/<body>. The document has been composed into the response, but returning a fragment avoids the ambiguity and keeps dev and production identical.`
21353
+ );
21354
+ }
21355
+ __name(warnFarmFullDocumentLayout, "warnFarmFullDocumentLayout");
21295
21356
  function hasRequestHeader(req, name2) {
21296
21357
  const value = req.headers[name2.toLowerCase()];
21297
21358
  return Array.isArray(value) ? value.length > 0 : Boolean(value);
@@ -22745,7 +22806,27 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
22745
22806
  this.config.basePath,
22746
22807
  getTheme()
22747
22808
  );
22748
- const html = `<!DOCTYPE html>
22809
+ const fullDocument = extractFarmFullDocument(content);
22810
+ let html;
22811
+ if (fullDocument) {
22812
+ warnFarmFullDocumentLayout();
22813
+ html = composeFarmFullDocument(fullDocument, {
22814
+ htmlAttributes: `${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}`,
22815
+ headAssets: [
22816
+ themeDocument.head,
22817
+ `<meta name="farm-deployment-id" content="${escapeHtmlAttribute2(deploymentId)}">`,
22818
+ metaTags,
22819
+ alternateTags,
22820
+ renderFarmFontDevHead(this.config.root || process.cwd()),
22821
+ `<link rel="stylesheet" href="/src/app/globals.css">`,
22822
+ `<script type="module" src="/@vite/client"></script>`,
22823
+ rendererHydrationScript,
22824
+ bootstrapScript
22825
+ ].filter(Boolean).join("\n "),
22826
+ bodyFooter: [deferredScript, `<script type="module" src="/@farm/client.js"></script>`].filter(Boolean).join("\n ")
22827
+ });
22828
+ } else {
22829
+ html = `<!DOCTYPE html>
22749
22830
  <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
22750
22831
  <head>
22751
22832
  ${themeDocument.head}
@@ -22766,6 +22847,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
22766
22847
  <script type="module" src="/@farm/client.js"></script>
22767
22848
  </body>
22768
22849
  </html>`;
22850
+ }
22769
22851
  emitFarmEvent({
22770
22852
  type: "render.stream.shellReady",
22771
22853
  route,
@@ -22788,7 +22870,8 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
22788
22870
  }
22789
22871
  async renderWithSSR(element, req, res, clearMiddlewareData, options = {}) {
22790
22872
  const renderToPipeableStream2 = this.rendererRuntime.renderToPipeableStream;
22791
- if (!renderToPipeableStream2) {
22873
+ const fullDocumentRouteKey = options.observabilityRoute || req.__FARM_ROUTE__ || req.url || "/";
22874
+ if (!renderToPipeableStream2 || fullDocumentRoutes.has(fullDocumentRouteKey)) {
22792
22875
  return this.renderBufferedSSR(element, req, res, clearMiddlewareData, options);
22793
22876
  }
22794
22877
  return new Promise((resolve8, reject) => {
@@ -22935,6 +23018,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
22935
23018
  htmlParts.push(shell);
22936
23019
  staticShellParts?.push(shell);
22937
23020
  let firstChunk = true;
23021
+ let checkedFullDocument = false;
22938
23022
  const writableStream = new import_stream.Writable({
22939
23023
  write(chunk, encoding, callback) {
22940
23024
  if (firstChunk && process.env.FARM_VERBOSE) {
@@ -22942,6 +23026,13 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
22942
23026
  firstChunk = false;
22943
23027
  }
22944
23028
  const chunkText = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);
23029
+ if (!checkedFullDocument) {
23030
+ checkedFullDocument = true;
23031
+ if (opensFarmFullDocument(chunkText)) {
23032
+ fullDocumentRoutes.add(fullDocumentRouteKey);
23033
+ warnFarmFullDocumentLayout();
23034
+ }
23035
+ }
22945
23036
  htmlParts.push(chunkText);
22946
23037
  if (staticShellParts && !staticShellClosed) {
22947
23038
  const dynamicIndex = findPPRDynamicChunkIndex(chunkText);
@@ -23140,6 +23231,24 @@ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue2(i18nSnapshot)};
23140
23231
  getTheme()
23141
23232
  );
23142
23233
  const rendererHydrationScript = this.rendererRuntime.generateHydrationScript?.() || "";
23234
+ const fullDocument = extractFarmFullDocument(content);
23235
+ if (fullDocument) {
23236
+ warnFarmFullDocumentLayout();
23237
+ return composeFarmFullDocument(fullDocument, {
23238
+ htmlAttributes: `${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}`,
23239
+ headAssets: [
23240
+ themeDocument.head,
23241
+ `<meta name="farm-deployment-id" content="${escapeHtmlAttribute2(this.getDeploymentId())}">`,
23242
+ alternateLinks,
23243
+ fontHead,
23244
+ `<link rel="stylesheet" href="/src/app/globals.css" />`,
23245
+ `<script type="module" src="/@vite/client"></script>`,
23246
+ rendererHydrationScript,
23247
+ integrationManifestScript
23248
+ ].filter(Boolean).join("\n "),
23249
+ bodyFooter: clientScript.trim()
23250
+ });
23251
+ }
23143
23252
  return `<!DOCTYPE html>
23144
23253
  <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
23145
23254
  <head>