@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.
@@ -17366,7 +17366,14 @@ function buildRepeatablePagesInputForApply(schema, sectionState) {
17366
17366
  const minEntries = page.minEntries != null ? Math.max(0, page.minEntries) : 1;
17367
17367
  let entryCount;
17368
17368
  if (Array.isArray(entries)) {
17369
- entryCount = minEntries === 0 ? entries.length : Math.max(1, entries.length);
17369
+ const realEntries = entries.filter((entry) => {
17370
+ if (!isRecord(entry)) return false;
17371
+ return Object.keys(entry).some(
17372
+ (k) => k !== ENTRY_ID_KEY && k !== ENTRY_NAME_KEY
17373
+ );
17374
+ });
17375
+ const count = minEntries === 0 ? realEntries.length : Math.max(1, realEntries.length);
17376
+ entryCount = count;
17370
17377
  } else {
17371
17378
  entryCount = minEntries === 0 ? 0 : minEntries;
17372
17379
  }
@@ -17377,6 +17384,25 @@ function buildRepeatablePagesInputForApply(schema, sectionState) {
17377
17384
  };
17378
17385
  });
17379
17386
  }
17387
+ function sanitizeSectionStateAgainstSchema(state, schema) {
17388
+ if (!state) return {};
17389
+ if (!schema) return { ...state };
17390
+ const known = /* @__PURE__ */ new Set();
17391
+ for (const s of schema.sections ?? []) known.add(s.id);
17392
+ for (const p of schema.repeatablePages ?? []) known.add(p.id);
17393
+ const out = {};
17394
+ for (const [key, value] of Object.entries(state)) {
17395
+ if (known.has(key)) {
17396
+ out[key] = value;
17397
+ continue;
17398
+ }
17399
+ const compositeMatch = /^(.+?)_(\d+)_(.+)$/.exec(key);
17400
+ if (compositeMatch && known.has(compositeMatch[1]) && known.has(compositeMatch[3])) {
17401
+ out[key] = value;
17402
+ }
17403
+ }
17404
+ return out;
17405
+ }
17380
17406
  async function fetchRow(supabaseUrl, anonKey, table, id) {
17381
17407
  const url = `${supabaseUrl}/rest/v1/${table}?id=eq.${id}&select=*`;
17382
17408
  const res = await fetch(url, {
@@ -17609,7 +17635,8 @@ async function resolveFromForm(options) {
17609
17635
  let mergedSectionState = { ...sectionState };
17610
17636
  const templateDefaultData = templateRow.default_data;
17611
17637
  if (templateDefaultData && isDefaultDataV2(templateDefaultData)) {
17612
- const defaults = templateDefaultData.sectionState;
17638
+ const rawDefaults = templateDefaultData.sectionState;
17639
+ const defaults = sanitizeSectionStateAgainstSchema(rawDefaults, formSchema);
17613
17640
  for (const key of Object.keys(defaults)) {
17614
17641
  if (!(key in mergedSectionState)) {
17615
17642
  mergedSectionState[key] = defaults[key];
@@ -17618,6 +17645,7 @@ async function resolveFromForm(options) {
17618
17645
  }
17619
17646
  mergedSectionState = mergeRepeatableEntryMeta(mergedSectionState, templateDefaultMetaSectionState, inferredSections);
17620
17647
  mergedSectionState = mergeRepeatableEntryMeta(mergedSectionState, defaultFormMetaSectionState, inferredSections);
17648
+ mergedSectionState = sanitizeSectionStateAgainstSchema(mergedSectionState, formSchema);
17621
17649
  const flatFormData = flattenSectionStateToFormData(mergedSectionState, inferredSections);
17622
17650
  const dynamicFields = templateConfig.dynamicFields || [];
17623
17651
  const mappings = [];
@@ -19057,9 +19085,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
19057
19085
  }
19058
19086
  return svgString;
19059
19087
  }
19060
- const resolvedPackageVersion = "0.5.218";
19088
+ const resolvedPackageVersion = "0.5.219";
19061
19089
  const PACKAGE_VERSION = resolvedPackageVersion;
19062
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.218";
19090
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.219";
19063
19091
  const roundParityValue = (value) => {
19064
19092
  if (typeof value !== "number") return value;
19065
19093
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -19620,6 +19648,58 @@ class PixldocsRenderer {
19620
19648
  compressionQuality
19621
19649
  });
19622
19650
  }
19651
+ /**
19652
+ * Render the template AND deliver the resulting PDF to the user — currently
19653
+ * via email (SendGrid). The PDF is rendered server-side on EC2, uploaded to
19654
+ * S3 (returned as `pdfUrl` for download fallback), and emailed with the PDF
19655
+ * attached.
19656
+ *
19657
+ * Every delivery is logged in the `delivery_log` table for audit + admin
19658
+ * resend. The same `pdfUrl` is returned to the caller so the host app can
19659
+ * also offer a "Download" button on the success screen.
19660
+ *
19661
+ * ```ts
19662
+ * const result = await renderer.renderAndDeliver({
19663
+ * templateId, formSchemaId, sectionState,
19664
+ * project: 'biomaker',
19665
+ * recipient: { email: 'user@example.com', name: 'Anya' },
19666
+ * });
19667
+ * // → { jobId, pdfUrl, deliveries: [{ channel: 'email', status: 'sent' }] }
19668
+ * ```
19669
+ *
19670
+ * Requires `RendererConfig.deliveryServerUrl` to be set.
19671
+ */
19672
+ async renderAndDeliver(options) {
19673
+ var _a;
19674
+ const base = (_a = this.config.deliveryServerUrl) == null ? void 0 : _a.replace(/\/+$/, "");
19675
+ if (!base) {
19676
+ throw new Error("renderAndDeliver: RendererConfig.deliveryServerUrl is required");
19677
+ }
19678
+ const { templateId, formSchemaId, sectionState, themeId, watermark, project, recipient, channels, scale } = options;
19679
+ if (!project) throw new Error('renderAndDeliver: project is required (e.g. "biomaker", "pixldocs")');
19680
+ if (!(recipient == null ? void 0 : recipient.email)) throw new Error("renderAndDeliver: recipient.email is required");
19681
+ const body = {
19682
+ template_id: templateId,
19683
+ form_schema_id: formSchemaId,
19684
+ data: { version: 2, sectionState },
19685
+ project,
19686
+ recipient,
19687
+ channels: channels || ["email"]
19688
+ };
19689
+ if (themeId) body.theme = themeId;
19690
+ if (typeof watermark === "boolean") body.watermark = watermark;
19691
+ if (typeof scale === "number") body.scale = scale;
19692
+ const res = await fetch(`${base}/v1/render-and-deliver`, {
19693
+ method: "POST",
19694
+ headers: { "Content-Type": "application/json" },
19695
+ body: JSON.stringify(body)
19696
+ });
19697
+ if (!res.ok) {
19698
+ const errText = await res.text().catch(() => "");
19699
+ throw new Error(`renderAndDeliver failed: ${res.status} ${errText.slice(0, 300)}`);
19700
+ }
19701
+ return await res.json();
19702
+ }
19623
19703
  async renderById(templateId, formData, options) {
19624
19704
  const resolved = await resolveTemplateData({
19625
19705
  templateId,
@@ -19751,7 +19831,7 @@ class PixldocsRenderer {
19751
19831
  await this.waitForCanvasScene(container, cloned, i);
19752
19832
  }
19753
19833
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
19754
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-CoZ-RUqL.cjs"));
19834
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-CwyiHDGD.cjs"));
19755
19835
  const prepared = preparePagesForExport(
19756
19836
  cloned.pages,
19757
19837
  canvasWidth,
@@ -21941,7 +22021,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
21941
22021
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
21942
22022
  sanitizeSvgTreeForPdf(svgToDraw);
21943
22023
  try {
21944
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-CoZ-RUqL.cjs"));
22024
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-CwyiHDGD.cjs"));
21945
22025
  try {
21946
22026
  await logTextMeasurementDiagnostic(svgToDraw);
21947
22027
  } catch {
@@ -22338,4 +22418,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
22338
22418
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
22339
22419
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
22340
22420
  exports.warmTemplateFromForm = warmTemplateFromForm;
22341
- //# sourceMappingURL=index-D3NJNdX_.cjs.map
22421
+ //# sourceMappingURL=index-CBB2UdwF.cjs.map