@pixldocs/canvas-renderer 0.5.218 → 0.5.219

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.
@@ -17348,7 +17348,14 @@ function buildRepeatablePagesInputForApply(schema, sectionState) {
17348
17348
  const minEntries = page.minEntries != null ? Math.max(0, page.minEntries) : 1;
17349
17349
  let entryCount;
17350
17350
  if (Array.isArray(entries)) {
17351
- entryCount = minEntries === 0 ? entries.length : Math.max(1, entries.length);
17351
+ const realEntries = entries.filter((entry) => {
17352
+ if (!isRecord(entry)) return false;
17353
+ return Object.keys(entry).some(
17354
+ (k) => k !== ENTRY_ID_KEY && k !== ENTRY_NAME_KEY
17355
+ );
17356
+ });
17357
+ const count = minEntries === 0 ? realEntries.length : Math.max(1, realEntries.length);
17358
+ entryCount = count;
17352
17359
  } else {
17353
17360
  entryCount = minEntries === 0 ? 0 : minEntries;
17354
17361
  }
@@ -17359,6 +17366,25 @@ function buildRepeatablePagesInputForApply(schema, sectionState) {
17359
17366
  };
17360
17367
  });
17361
17368
  }
17369
+ function sanitizeSectionStateAgainstSchema(state, schema) {
17370
+ if (!state) return {};
17371
+ if (!schema) return { ...state };
17372
+ const known = /* @__PURE__ */ new Set();
17373
+ for (const s of schema.sections ?? []) known.add(s.id);
17374
+ for (const p of schema.repeatablePages ?? []) known.add(p.id);
17375
+ const out = {};
17376
+ for (const [key, value] of Object.entries(state)) {
17377
+ if (known.has(key)) {
17378
+ out[key] = value;
17379
+ continue;
17380
+ }
17381
+ const compositeMatch = /^(.+?)_(\d+)_(.+)$/.exec(key);
17382
+ if (compositeMatch && known.has(compositeMatch[1]) && known.has(compositeMatch[3])) {
17383
+ out[key] = value;
17384
+ }
17385
+ }
17386
+ return out;
17387
+ }
17362
17388
  async function fetchRow(supabaseUrl, anonKey, table, id) {
17363
17389
  const url = `${supabaseUrl}/rest/v1/${table}?id=eq.${id}&select=*`;
17364
17390
  const res = await fetch(url, {
@@ -17591,7 +17617,8 @@ async function resolveFromForm(options) {
17591
17617
  let mergedSectionState = { ...sectionState };
17592
17618
  const templateDefaultData = templateRow.default_data;
17593
17619
  if (templateDefaultData && isDefaultDataV2(templateDefaultData)) {
17594
- const defaults = templateDefaultData.sectionState;
17620
+ const rawDefaults = templateDefaultData.sectionState;
17621
+ const defaults = sanitizeSectionStateAgainstSchema(rawDefaults, formSchema);
17595
17622
  for (const key of Object.keys(defaults)) {
17596
17623
  if (!(key in mergedSectionState)) {
17597
17624
  mergedSectionState[key] = defaults[key];
@@ -17600,6 +17627,7 @@ async function resolveFromForm(options) {
17600
17627
  }
17601
17628
  mergedSectionState = mergeRepeatableEntryMeta(mergedSectionState, templateDefaultMetaSectionState, inferredSections);
17602
17629
  mergedSectionState = mergeRepeatableEntryMeta(mergedSectionState, defaultFormMetaSectionState, inferredSections);
17630
+ mergedSectionState = sanitizeSectionStateAgainstSchema(mergedSectionState, formSchema);
17603
17631
  const flatFormData = flattenSectionStateToFormData(mergedSectionState, inferredSections);
17604
17632
  const dynamicFields = templateConfig.dynamicFields || [];
17605
17633
  const mappings = [];
@@ -19039,9 +19067,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
19039
19067
  }
19040
19068
  return svgString;
19041
19069
  }
19042
- const resolvedPackageVersion = "0.5.218";
19070
+ const resolvedPackageVersion = "0.5.219";
19043
19071
  const PACKAGE_VERSION = resolvedPackageVersion;
19044
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.218";
19072
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.219";
19045
19073
  const roundParityValue = (value) => {
19046
19074
  if (typeof value !== "number") return value;
19047
19075
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -19602,6 +19630,58 @@ class PixldocsRenderer {
19602
19630
  compressionQuality
19603
19631
  });
19604
19632
  }
19633
+ /**
19634
+ * Render the template AND deliver the resulting PDF to the user — currently
19635
+ * via email (SendGrid). The PDF is rendered server-side on EC2, uploaded to
19636
+ * S3 (returned as `pdfUrl` for download fallback), and emailed with the PDF
19637
+ * attached.
19638
+ *
19639
+ * Every delivery is logged in the `delivery_log` table for audit + admin
19640
+ * resend. The same `pdfUrl` is returned to the caller so the host app can
19641
+ * also offer a "Download" button on the success screen.
19642
+ *
19643
+ * ```ts
19644
+ * const result = await renderer.renderAndDeliver({
19645
+ * templateId, formSchemaId, sectionState,
19646
+ * project: 'biomaker',
19647
+ * recipient: { email: 'user@example.com', name: 'Anya' },
19648
+ * });
19649
+ * // → { jobId, pdfUrl, deliveries: [{ channel: 'email', status: 'sent' }] }
19650
+ * ```
19651
+ *
19652
+ * Requires `RendererConfig.deliveryServerUrl` to be set.
19653
+ */
19654
+ async renderAndDeliver(options) {
19655
+ var _a;
19656
+ const base = (_a = this.config.deliveryServerUrl) == null ? void 0 : _a.replace(/\/+$/, "");
19657
+ if (!base) {
19658
+ throw new Error("renderAndDeliver: RendererConfig.deliveryServerUrl is required");
19659
+ }
19660
+ const { templateId, formSchemaId, sectionState, themeId, watermark, project, recipient, channels, scale } = options;
19661
+ if (!project) throw new Error('renderAndDeliver: project is required (e.g. "biomaker", "pixldocs")');
19662
+ if (!(recipient == null ? void 0 : recipient.email)) throw new Error("renderAndDeliver: recipient.email is required");
19663
+ const body = {
19664
+ template_id: templateId,
19665
+ form_schema_id: formSchemaId,
19666
+ data: { version: 2, sectionState },
19667
+ project,
19668
+ recipient,
19669
+ channels: channels || ["email"]
19670
+ };
19671
+ if (themeId) body.theme = themeId;
19672
+ if (typeof watermark === "boolean") body.watermark = watermark;
19673
+ if (typeof scale === "number") body.scale = scale;
19674
+ const res = await fetch(`${base}/v1/render-and-deliver`, {
19675
+ method: "POST",
19676
+ headers: { "Content-Type": "application/json" },
19677
+ body: JSON.stringify(body)
19678
+ });
19679
+ if (!res.ok) {
19680
+ const errText = await res.text().catch(() => "");
19681
+ throw new Error(`renderAndDeliver failed: ${res.status} ${errText.slice(0, 300)}`);
19682
+ }
19683
+ return await res.json();
19684
+ }
19605
19685
  async renderById(templateId, formData, options) {
19606
19686
  const resolved = await resolveTemplateData({
19607
19687
  templateId,
@@ -19733,7 +19813,7 @@ class PixldocsRenderer {
19733
19813
  await this.waitForCanvasScene(container, cloned, i);
19734
19814
  }
19735
19815
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
19736
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-som_tmDY.js");
19816
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-Dejgf_PM.js");
19737
19817
  const prepared = preparePagesForExport(
19738
19818
  cloned.pages,
19739
19819
  canvasWidth,
@@ -21923,7 +22003,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
21923
22003
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
21924
22004
  sanitizeSvgTreeForPdf(svgToDraw);
21925
22005
  try {
21926
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-som_tmDY.js");
22006
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-Dejgf_PM.js");
21927
22007
  try {
21928
22008
  await logTextMeasurementDiagnostic(svgToDraw);
21929
22009
  } catch {
@@ -22323,4 +22403,4 @@ export {
22323
22403
  buildTeaserBlurFlatKeys as y,
22324
22404
  collectFontDescriptorsFromConfig as z
22325
22405
  };
22326
- //# sourceMappingURL=index-CZk_GpIL.js.map
22406
+ //# sourceMappingURL=index-DbUPI6zs.js.map