@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
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  createClientPluginManager,
3
3
  installChunkErrorRecovery
4
- } from "../chunk-W2O6SKJU.mjs";
4
+ } from "../chunk-3P63LWDM.mjs";
5
5
  import {
6
6
  searchParamsToObject
7
7
  } from "../chunk-4DCGM2BW.mjs";
8
8
  import "../chunk-FXG2PS27.mjs";
9
- import "../chunk-LGCIIMFR.mjs";
9
+ import "../chunk-NKIHYEWC.mjs";
10
10
  import {
11
11
  __name
12
12
  } from "../chunk-CGILA3WO.mjs";
package/dist/plugin.cjs CHANGED
@@ -15620,6 +15620,57 @@ __name(safeGlobFiles, "safeGlobFiles");
15620
15620
  // src/server/renderer.ts
15621
15621
  var fs3 = __toESM(require("fs"));
15622
15622
  var path11 = __toESM(require("path"));
15623
+
15624
+ // src/server/full-document.ts
15625
+ function stripContentsWrappers(markup) {
15626
+ let out = markup.replace(/^\s+/, "");
15627
+ const opener = /^<div\b[^>]*style="display\s*:\s*contents"[^>]*>/i;
15628
+ let match;
15629
+ while (match = opener.exec(out)) {
15630
+ out = out.slice(match[0].length).replace(/^\s+/, "");
15631
+ }
15632
+ return out;
15633
+ }
15634
+ __name(stripContentsWrappers, "stripContentsWrappers");
15635
+ function extractFarmFullDocument(markup) {
15636
+ const inner = stripContentsWrappers(markup);
15637
+ if (!/^<!doctype/i.test(inner) && !/^<html[\s>]/i.test(inner)) return null;
15638
+ const start = markup.search(/<!doctype|<html[\s>]/i);
15639
+ const closeIndex = markup.toLowerCase().lastIndexOf("</html>");
15640
+ if (start < 0 || closeIndex < 0) return null;
15641
+ return markup.slice(start, closeIndex + "</html>".length);
15642
+ }
15643
+ __name(extractFarmFullDocument, "extractFarmFullDocument");
15644
+ function opensFarmFullDocument(markup) {
15645
+ const inner = stripContentsWrappers(markup);
15646
+ return /^<!doctype/i.test(inner) || /^<html[\s>]/i.test(inner);
15647
+ }
15648
+ __name(opensFarmFullDocument, "opensFarmFullDocument");
15649
+ function composeFarmFullDocument(documentHtml, assets) {
15650
+ let html = documentHtml;
15651
+ if (assets.htmlAttributes) {
15652
+ html = html.replace(
15653
+ /<html\b([^>]*)>/i,
15654
+ (_match, attrs) => `<html${attrs}${assets.htmlAttributes}>`
15655
+ );
15656
+ }
15657
+ if (!/\sid=["']root["']/i.test(html)) {
15658
+ html = html.replace(/<body\b([^>]*)>/i, '<body$1><div id="root">').replace(/<\/body>/i, "</div></body>");
15659
+ }
15660
+ if (assets.headAssets) {
15661
+ html = html.replace(/<\/head>/i, () => ` ${assets.headAssets}
15662
+ </head>`);
15663
+ }
15664
+ if (assets.bodyFooter) {
15665
+ html = html.replace(/<\/body>/i, () => ` ${assets.bodyFooter}
15666
+ </body>`);
15667
+ }
15668
+ return /^\s*<!doctype/i.test(html) ? html : `<!DOCTYPE html>
15669
+ ${html}`;
15670
+ }
15671
+ __name(composeFarmFullDocument, "composeFarmFullDocument");
15672
+
15673
+ // src/server/renderer.ts
15623
15674
  var import_stream = require("stream");
15624
15675
 
15625
15676
  // src/middleware/server.ts
@@ -18970,7 +19021,7 @@ _setFarmThemeServerSnapshotResolver(() => {
18970
19021
  });
18971
19022
 
18972
19023
  // package.json
18973
- var version = "0.1.0-beta.46";
19024
+ var version = "0.1.0-beta.48";
18974
19025
 
18975
19026
  // src/version.ts
18976
19027
  var FARM_VERSION = version;
@@ -19079,6 +19130,16 @@ function warnSuppressedAsyncHydrationOnce(modulePath) {
19079
19130
  );
19080
19131
  }
19081
19132
  __name(warnSuppressedAsyncHydrationOnce, "warnSuppressedAsyncHydrationOnce");
19133
+ var fullDocumentRoutes = /* @__PURE__ */ new Set();
19134
+ var warnedFullDocumentLayout = false;
19135
+ function warnFarmFullDocumentLayout() {
19136
+ if (warnedFullDocumentLayout) return;
19137
+ warnedFullDocumentLayout = true;
19138
+ logger.warn(
19139
+ `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.`
19140
+ );
19141
+ }
19142
+ __name(warnFarmFullDocumentLayout, "warnFarmFullDocumentLayout");
19082
19143
  function hasRequestHeader(req, name2) {
19083
19144
  const value = req.headers[name2.toLowerCase()];
19084
19145
  return Array.isArray(value) ? value.length > 0 : Boolean(value);
@@ -20532,7 +20593,27 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
20532
20593
  this.config.basePath,
20533
20594
  getTheme()
20534
20595
  );
20535
- const html = `<!DOCTYPE html>
20596
+ const fullDocument = extractFarmFullDocument(content);
20597
+ let html;
20598
+ if (fullDocument) {
20599
+ warnFarmFullDocumentLayout();
20600
+ html = composeFarmFullDocument(fullDocument, {
20601
+ htmlAttributes: `${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}`,
20602
+ headAssets: [
20603
+ themeDocument.head,
20604
+ `<meta name="farm-deployment-id" content="${escapeHtmlAttribute2(deploymentId)}">`,
20605
+ metaTags,
20606
+ alternateTags,
20607
+ renderFarmFontDevHead(this.config.root || process.cwd()),
20608
+ `<link rel="stylesheet" href="/src/app/globals.css">`,
20609
+ `<script type="module" src="/@vite/client"></script>`,
20610
+ rendererHydrationScript,
20611
+ bootstrapScript
20612
+ ].filter(Boolean).join("\n "),
20613
+ bodyFooter: [deferredScript, `<script type="module" src="/@farm/client.js"></script>`].filter(Boolean).join("\n ")
20614
+ });
20615
+ } else {
20616
+ html = `<!DOCTYPE html>
20536
20617
  <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
20537
20618
  <head>
20538
20619
  ${themeDocument.head}
@@ -20553,6 +20634,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
20553
20634
  <script type="module" src="/@farm/client.js"></script>
20554
20635
  </body>
20555
20636
  </html>`;
20637
+ }
20556
20638
  emitFarmEvent({
20557
20639
  type: "render.stream.shellReady",
20558
20640
  route,
@@ -20575,7 +20657,8 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
20575
20657
  }
20576
20658
  async renderWithSSR(element, req, res, clearMiddlewareData, options = {}) {
20577
20659
  const renderToPipeableStream2 = this.rendererRuntime.renderToPipeableStream;
20578
- if (!renderToPipeableStream2) {
20660
+ const fullDocumentRouteKey = options.observabilityRoute || req.__FARM_ROUTE__ || req.url || "/";
20661
+ if (!renderToPipeableStream2 || fullDocumentRoutes.has(fullDocumentRouteKey)) {
20579
20662
  return this.renderBufferedSSR(element, req, res, clearMiddlewareData, options);
20580
20663
  }
20581
20664
  return new Promise((resolve8, reject) => {
@@ -20722,6 +20805,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
20722
20805
  htmlParts.push(shell);
20723
20806
  staticShellParts?.push(shell);
20724
20807
  let firstChunk = true;
20808
+ let checkedFullDocument = false;
20725
20809
  const writableStream = new import_stream.Writable({
20726
20810
  write(chunk, encoding, callback) {
20727
20811
  if (firstChunk && process.env.FARM_VERBOSE) {
@@ -20729,6 +20813,13 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
20729
20813
  firstChunk = false;
20730
20814
  }
20731
20815
  const chunkText = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);
20816
+ if (!checkedFullDocument) {
20817
+ checkedFullDocument = true;
20818
+ if (opensFarmFullDocument(chunkText)) {
20819
+ fullDocumentRoutes.add(fullDocumentRouteKey);
20820
+ warnFarmFullDocumentLayout();
20821
+ }
20822
+ }
20732
20823
  htmlParts.push(chunkText);
20733
20824
  if (staticShellParts && !staticShellClosed) {
20734
20825
  const dynamicIndex = findPPRDynamicChunkIndex(chunkText);
@@ -20927,6 +21018,24 @@ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue2(i18nSnapshot)};
20927
21018
  getTheme()
20928
21019
  );
20929
21020
  const rendererHydrationScript = this.rendererRuntime.generateHydrationScript?.() || "";
21021
+ const fullDocument = extractFarmFullDocument(content);
21022
+ if (fullDocument) {
21023
+ warnFarmFullDocumentLayout();
21024
+ return composeFarmFullDocument(fullDocument, {
21025
+ htmlAttributes: `${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}`,
21026
+ headAssets: [
21027
+ themeDocument.head,
21028
+ `<meta name="farm-deployment-id" content="${escapeHtmlAttribute2(this.getDeploymentId())}">`,
21029
+ alternateLinks,
21030
+ fontHead,
21031
+ `<link rel="stylesheet" href="/src/app/globals.css" />`,
21032
+ `<script type="module" src="/@vite/client"></script>`,
21033
+ rendererHydrationScript,
21034
+ integrationManifestScript
21035
+ ].filter(Boolean).join("\n "),
21036
+ bodyFooter: clientScript.trim()
21037
+ });
21038
+ }
20930
21039
  return `<!DOCTYPE html>
20931
21040
  <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
20932
21041
  <head>