@growth-labs/cms 0.8.18 → 0.8.20

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 (33) hide show
  1. package/dist/engine/content-insights.d.ts +27 -11
  2. package/dist/engine/content-insights.d.ts.map +1 -1
  3. package/dist/engine/content-insights.js +102 -53
  4. package/dist/engine/content-insights.js.map +1 -1
  5. package/dist/lib/publish-timezone.d.ts +38 -0
  6. package/dist/lib/publish-timezone.d.ts.map +1 -0
  7. package/dist/lib/publish-timezone.js +135 -0
  8. package/dist/lib/publish-timezone.js.map +1 -0
  9. package/dist/routes/content-insights.d.ts.map +1 -1
  10. package/dist/routes/content-insights.js +5 -2
  11. package/dist/routes/content-insights.js.map +1 -1
  12. package/dist/routes/content.d.ts.map +1 -1
  13. package/dist/routes/content.js +2 -102
  14. package/dist/routes/content.js.map +1 -1
  15. package/dist/schema/migrations.d.ts.map +1 -1
  16. package/dist/schema/migrations.js +7 -0
  17. package/dist/schema/migrations.js.map +1 -1
  18. package/dist/schema/types.d.ts +4 -1
  19. package/dist/schema/types.d.ts.map +1 -1
  20. package/dist/schema/types.js.map +1 -1
  21. package/dist/ui/inspector/PublishTab.d.ts +7 -1
  22. package/dist/ui/inspector/PublishTab.d.ts.map +1 -1
  23. package/dist/ui/inspector/PublishTab.js +24 -26
  24. package/dist/ui/inspector/PublishTab.js.map +1 -1
  25. package/migrations/0032_content_insight_publication_identity.sql +3 -0
  26. package/package.json +1 -1
  27. package/src/engine/content-insights.ts +142 -63
  28. package/src/lib/publish-timezone.ts +154 -0
  29. package/src/routes/content-insights.ts +6 -1
  30. package/src/routes/content.ts +5 -116
  31. package/src/schema/migrations.ts +7 -0
  32. package/src/schema/types.ts +4 -1
  33. package/src/ui/inspector/PublishTab.tsx +33 -25
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,iFAAiF;AACjF,iFAAiF;AACjF,sEAAsE;AACtE,gFAAgF;AAChF,yBAAyB;AACzB,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;AAEhF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA2qBvB,wDAAwD;AACxD,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,IAAI,CAAC;IACtD,WAAW;IACX,iBAAiB;IACjB,UAAU;IACV,cAAc;IACd,SAAS;IACT,OAAO;CACP,CAAC,CAAA;AA8EF;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAanC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAqB;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,kBAAkB,CAAA;IACnD,MAAM,SAAS,GAAG;QACjB,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;QAC7C,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;QAC/B,KAAK,CAAC,UAAU;QAChB,MAAM,CAAC,OAAO,CAAC;KACf,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACV,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;IACzF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAA;AACX,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,iFAAiF;AACjF,iFAAiF;AACjF,sEAAsE;AACtE,gFAAgF;AAChF,yBAAyB;AACzB,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;AAEhF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA8qBvB,wDAAwD;AACxD,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,IAAI,CAAC;IACtD,WAAW;IACX,iBAAiB;IACjB,UAAU;IACV,cAAc;IACd,SAAS;IACT,OAAO;CACP,CAAC,CAAA;AA8EF;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAanC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAqB;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,kBAAkB,CAAA;IACnD,MAAM,SAAS,GAAG;QACjB,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;QAC7C,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;QAC/B,KAAK,CAAC,UAAU;QAChB,MAAM,CAAC,OAAO,CAAC;KACf,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACV,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;IACzF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAA;AACX,CAAC"}
@@ -11,8 +11,14 @@ export interface PublishTabProps {
11
11
  authorId: string | null;
12
12
  /** Current scheduled publish time (ISO string, null if not scheduled). */
13
13
  publishAt: string | null;
14
+ /**
15
+ * Timezone the editor schedules in. The same zone is used to DISPLAY the
16
+ * stored instant and to SAVE what is typed, so a resave of untouched fields
17
+ * is a true no-op. Defaults to the publication timezone.
18
+ */
19
+ publishTimezone?: string;
14
20
  /** Called after a status/field change so the parent can refresh. */
15
21
  onChanged?: () => void;
16
22
  }
17
- export declare function PublishTab({ docId, status, slug, visibility, authorId, publishAt, onChanged, }: PublishTabProps): React.ReactElement;
23
+ export declare function PublishTab({ docId, status, slug, visibility, authorId, publishAt, publishTimezone, onChanged, }: PublishTabProps): React.ReactElement;
18
24
  //# sourceMappingURL=PublishTab.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PublishTab.d.ts","sourceRoot":"","sources":["../../../src/ui/inspector/PublishTab.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAiB1D,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,MAAM,EAAE,aAAa,CAAA;IACrB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAoCD,wBAAgB,UAAU,CAAC,EAC1B,KAAK,EACL,MAAM,EACN,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,SAAS,EACT,SAAS,GACT,EAAE,eAAe,GAAG,KAAK,CAAC,YAAY,CAwXtC"}
1
+ {"version":3,"file":"PublishTab.d.ts","sourceRoot":"","sources":["../../../src/ui/inspector/PublishTab.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAiB1D,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,MAAM,EAAE,aAAa,CAAA;IACrB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAoCD,wBAAgB,UAAU,CAAC,EAC1B,KAAK,EACL,MAAM,EACN,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,SAAS,EACT,eAA2C,EAC3C,SAAS,GACT,EAAE,eAAe,GAAG,KAAK,CAAC,YAAY,CAwXtC"}
@@ -10,7 +10,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  //
11
11
  // Compile-gated (tsc, jsx: react-jsx). No vitest — pure shapers are in
12
12
  // inspector-data.ts and tested there.
13
- import { useCallback, useEffect, useState } from 'react';
13
+ import { useCallback, useEffect, useMemo, useState } from 'react';
14
+ import { formatInstantInZone, PUBLISH_TIMEZONE_FALLBACK } from '../../lib/publish-timezone.js';
14
15
  import { apiErrorMessage } from '../api-error.js';
15
16
  import { Icon } from '../icons.js';
16
17
  import { Field } from './Field.js';
@@ -28,23 +29,24 @@ const STATUS_OPTS = [
28
29
  // ---------------------------------------------------------------------------
29
30
  // PublishTab
30
31
  // ---------------------------------------------------------------------------
31
- export function PublishTab({ docId, status, slug, visibility, authorId, publishAt, onChanged, }) {
32
+ export function PublishTab({ docId, status, slug, visibility, authorId, publishAt, publishTimezone = PUBLISH_TIMEZONE_FALLBACK, onChanged, }) {
32
33
  const [saving, setSaving] = useState(false);
33
34
  const [selectedStatus, setSelectedStatus] = useState(null);
34
35
  const [actionError, setActionError] = useState(null);
35
36
  // Local schedule date/time inputs.
36
- const [schedDate, setSchedDate] = useState(() => {
37
+ // The editor thinks in publication-local wall clock, so that is what these
38
+ // inputs show. Falling back to the raw UTC slice keeps an unusable zone
39
+ // readable rather than blank.
40
+ const scheduled = useMemo(() => {
37
41
  if (!publishAt)
38
- return '';
39
- // publishAt is an ISO string; extract the date part.
40
- return publishAt.slice(0, 10);
41
- });
42
- const [schedTime, setSchedTime] = useState(() => {
43
- if (!publishAt)
44
- return '12:00';
45
- // Extract HH:MM from ISO.
46
- return publishAt.slice(11, 16) || '12:00';
47
- });
42
+ return null;
43
+ const ms = Date.parse(publishAt);
44
+ if (!Number.isFinite(ms))
45
+ return null;
46
+ return formatInstantInZone(ms, publishTimezone);
47
+ }, [publishAt, publishTimezone]);
48
+ const [schedDate, setSchedDate] = useState(() => scheduled?.date ?? publishAt?.slice(0, 10) ?? '');
49
+ const [schedTime, setSchedTime] = useState(() => scheduled?.time ?? publishAt?.slice(11, 16) ?? '12:00');
48
50
  // Author list (fetched once on mount).
49
51
  const [authors, setAuthors] = useState([]);
50
52
  const [authorError, setAuthorError] = useState(null);
@@ -112,18 +114,14 @@ export function PublishTab({ docId, status, slug, visibility, authorId, publishA
112
114
  setSaving(true);
113
115
  setActionError(null);
114
116
  try {
115
- // schedDate/schedTime are sliced directly from the UTC ISO publishAt
116
- // (no zone conversion happens anywhere in this component -- see their
117
- // initializers above), so the digits shown here already ARE UTC. Tag
118
- // them 'UTC' on save, not a hardcoded zone: sending literal UTC digits
119
- // under a non-UTC zone label (this used 'Europe/Paris' unconditionally
120
- // until the Falklands P0, 2026-09-08) made the server reinterpret them
121
- // in that zone's offset, silently shifting publish_at by that zone's
122
- // current UTC offset on every resave -- including an incidental
123
- // resave that never touched these fields. 'UTC' makes display and
124
- // save agree, so a resave of untouched fields is a true no-op.
117
+ // These digits are publication-local wall clock (see the initializers),
118
+ // so they are saved under that SAME zone. Display and save must agree:
119
+ // sending digits under a zone they were not rendered in made the server
120
+ // reinterpret them and shift publish_at by that zone's offset on every
121
+ // resave, including an incidental one that never touched these fields
122
+ // (the 2026-09-08 P0). Agreement is what keeps a resave a no-op.
125
123
  const localDateTime = `${schedDate}T${schedTime}`;
126
- const body = buildScheduleBody(localDateTime, 'UTC');
124
+ const body = buildScheduleBody(localDateTime, publishTimezone);
127
125
  await runAction(docId, 'schedule', body);
128
126
  setSelectedStatus('scheduled');
129
127
  onChanged?.();
@@ -134,7 +132,7 @@ export function PublishTab({ docId, status, slug, visibility, authorId, publishA
134
132
  finally {
135
133
  setSaving(false);
136
134
  }
137
- }, [docId, schedDate, schedTime, saving, onChanged]);
135
+ }, [docId, schedDate, schedTime, saving, onChanged, publishTimezone]);
138
136
  const handleVisibilityChange = useCallback(async (newVis) => {
139
137
  try {
140
138
  await patchContent(docId, { visibility: newVis });
@@ -212,7 +210,7 @@ export function PublishTab({ docId, status, slug, visibility, authorId, publishA
212
210
  // -------------------------------------------------------------------------
213
211
  const displayStatus = selectedStatus ?? status;
214
212
  const showScheduleControls = shouldShowScheduleControls(status, selectedStatus);
215
- return (_jsxs("div", { children: [_jsxs(Section, { title: "Status & visibility", icon: "target", children: [_jsx("div", { style: statusList, children: STATUS_OPTS.map((opt) => (_jsxs("button", { type: "button", onClick: () => void handleStatusChange(opt.id), disabled: saving && opt.id === displayStatus, style: statusBtn(displayStatus === opt.id), "aria-pressed": displayStatus === opt.id, children: [_jsx("span", { style: radioCircle(displayStatus === opt.id), children: displayStatus === opt.id && _jsx("span", { style: radioDot }) }), _jsxs("span", { style: { flex: 1 }, children: [_jsx("span", { style: statusLabel, children: opt.label }), _jsx("span", { style: statusDesc, children: statusDescription(opt, displayStatus) })] })] }, opt.id))) }), actionError && (_jsx("div", { role: "alert", style: publishErrorText, children: actionError })), showScheduleControls && (_jsxs("div", { style: schedGrid, className: "fade-only", children: [_jsx(Field, { label: "Date (UTC)", children: _jsx("input", { className: "input", type: "date", value: schedDate, onChange: (e) => setSchedDate(e.target.value) }) }), _jsx(Field, { label: "Time (UTC)", children: _jsx("input", { className: "input", type: "time", value: schedTime, onChange: (e) => setSchedTime(e.target.value) }) }), _jsx("div", { style: { gridColumn: '1 / -1' }, children: _jsx("button", { type: "button", className: "btn primary sm", style: { width: '100%' }, onClick: () => void handleSchedule(), disabled: !schedDate || !schedTime, children: "Save schedule" }) })] })), _jsx(Field, { label: "Access", children: _jsxs("div", { className: "seg", style: { width: '100%' }, children: [_jsxs("button", { type: "button", className: visibility === 'free' ? 'on' : '', style: { flex: 1, justifyContent: 'center' }, onClick: () => void handleVisibilityChange('free'), "aria-pressed": visibility === 'free', children: [_jsx(Icon, { name: "globe", size: 14 }), "Free"] }), _jsxs("button", { type: "button", className: visibility === 'premium' ? 'on' : '', style: { flex: 1, justifyContent: 'center' }, onClick: () => void handleVisibilityChange('premium'), "aria-pressed": visibility === 'premium', children: [_jsx(Icon, { name: "star", size: 14 }), "Premium"] })] }) })] }), _jsx(Section, { title: "Address", icon: "link", children: _jsx(Field, { label: "URL slug", help: "The permanent address for this content.", children: _jsx(SlugInput, { defaultValue: slug, onCommit: handleSlugChange }) }) }), _jsx(Section, { title: "Ownership", icon: "users", children: _jsxs(Field, { label: "Author", help: "Choose or add the primary byline for this article.", children: [_jsxs("select", { value: authorId ?? '', onChange: handleAuthorChange, className: "selectbox", "aria-label": "Author", children: [_jsx("option", { value: "", children: "\u2014 unassigned \u2014" }), authors.map((a) => (_jsx("option", { value: a.id, children: a.name }, a.id)))] }), currentAuthor && (_jsxs("div", { style: authorHint, children: [_jsx(Icon, { name: "checkCircle", size: 13, style: { color: 'var(--green)' } }), currentAuthor.name] })), _jsxs("div", { style: authorActions, children: [_jsxs("button", { type: "button", className: "btn sm", onClick: () => setAddAuthorOpen((open) => !open), "aria-expanded": addAuthorOpen, children: [_jsx(Icon, { name: "plus", size: 14 }), "Add author"] }), _jsxs("button", { type: "button", className: "btn ghost sm", onClick: () => void loadAuthors(), children: [_jsx(Icon, { name: "refresh", size: 14 }), "Refresh"] })] }), addAuthorOpen && (_jsxs("div", { style: addAuthorBox, children: [_jsx("input", { className: "input", type: "text", value: newAuthorName, onChange: (e) => setNewAuthorName(e.currentTarget.value), onKeyDown: (e) => {
213
+ return (_jsxs("div", { children: [_jsxs(Section, { title: "Status & visibility", icon: "target", children: [_jsx("div", { style: statusList, children: STATUS_OPTS.map((opt) => (_jsxs("button", { type: "button", onClick: () => void handleStatusChange(opt.id), disabled: saving && opt.id === displayStatus, style: statusBtn(displayStatus === opt.id), "aria-pressed": displayStatus === opt.id, children: [_jsx("span", { style: radioCircle(displayStatus === opt.id), children: displayStatus === opt.id && _jsx("span", { style: radioDot }) }), _jsxs("span", { style: { flex: 1 }, children: [_jsx("span", { style: statusLabel, children: opt.label }), _jsx("span", { style: statusDesc, children: statusDescription(opt, displayStatus) })] })] }, opt.id))) }), actionError && (_jsx("div", { role: "alert", style: publishErrorText, children: actionError })), showScheduleControls && (_jsxs("div", { style: schedGrid, className: "fade-only", children: [_jsx(Field, { label: `Date (${publishTimezone})`, children: _jsx("input", { className: "input", type: "date", value: schedDate, onChange: (e) => setSchedDate(e.target.value) }) }), _jsx(Field, { label: `Time (${publishTimezone})`, children: _jsx("input", { className: "input", type: "time", value: schedTime, onChange: (e) => setSchedTime(e.target.value) }) }), _jsx("div", { style: { gridColumn: '1 / -1' }, children: _jsx("button", { type: "button", className: "btn primary sm", style: { width: '100%' }, onClick: () => void handleSchedule(), disabled: !schedDate || !schedTime, children: "Save schedule" }) })] })), _jsx(Field, { label: "Access", children: _jsxs("div", { className: "seg", style: { width: '100%' }, children: [_jsxs("button", { type: "button", className: visibility === 'free' ? 'on' : '', style: { flex: 1, justifyContent: 'center' }, onClick: () => void handleVisibilityChange('free'), "aria-pressed": visibility === 'free', children: [_jsx(Icon, { name: "globe", size: 14 }), "Free"] }), _jsxs("button", { type: "button", className: visibility === 'premium' ? 'on' : '', style: { flex: 1, justifyContent: 'center' }, onClick: () => void handleVisibilityChange('premium'), "aria-pressed": visibility === 'premium', children: [_jsx(Icon, { name: "star", size: 14 }), "Premium"] })] }) })] }), _jsx(Section, { title: "Address", icon: "link", children: _jsx(Field, { label: "URL slug", help: "The permanent address for this content.", children: _jsx(SlugInput, { defaultValue: slug, onCommit: handleSlugChange }) }) }), _jsx(Section, { title: "Ownership", icon: "users", children: _jsxs(Field, { label: "Author", help: "Choose or add the primary byline for this article.", children: [_jsxs("select", { value: authorId ?? '', onChange: handleAuthorChange, className: "selectbox", "aria-label": "Author", children: [_jsx("option", { value: "", children: "\u2014 unassigned \u2014" }), authors.map((a) => (_jsx("option", { value: a.id, children: a.name }, a.id)))] }), currentAuthor && (_jsxs("div", { style: authorHint, children: [_jsx(Icon, { name: "checkCircle", size: 13, style: { color: 'var(--green)' } }), currentAuthor.name] })), _jsxs("div", { style: authorActions, children: [_jsxs("button", { type: "button", className: "btn sm", onClick: () => setAddAuthorOpen((open) => !open), "aria-expanded": addAuthorOpen, children: [_jsx(Icon, { name: "plus", size: 14 }), "Add author"] }), _jsxs("button", { type: "button", className: "btn ghost sm", onClick: () => void loadAuthors(), children: [_jsx(Icon, { name: "refresh", size: 14 }), "Refresh"] })] }), addAuthorOpen && (_jsxs("div", { style: addAuthorBox, children: [_jsx("input", { className: "input", type: "text", value: newAuthorName, onChange: (e) => setNewAuthorName(e.currentTarget.value), onKeyDown: (e) => {
216
214
  if (e.key === 'Enter') {
217
215
  e.preventDefault();
218
216
  void handleAddAuthor();
@@ -1 +1 @@
1
- {"version":3,"file":"PublishTab.js","sourceRoot":"","sources":["../../../src/ui/inspector/PublishTab.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PublishTab.js","sourceRoot":"","sources":["../../../src/ui/inspector/PublishTab.tsx"],"names":[],"mappings":";AAAA,2DAA2D;AAC3D,EAAE;AACF,YAAY;AACZ,8EAA8E;AAC9E,6DAA6D;AAC7D,oEAAoE;AACpE,4DAA4D;AAC5D,iEAAiE;AACjE,EAAE;AACF,uEAAuE;AACvE,sCAAsC;AAEtC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAA;AAE9F,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EACN,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,SAAS,EACT,0BAA0B,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AA4BtC,8EAA8E;AAC9E,4CAA4C;AAC5C,8EAA8E;AAE9E,MAAM,WAAW,GAA8D;IAC9E,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,yBAAyB,EAAE;IAChE,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,6BAA6B,EAAE;IACzE,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,8BAA8B,EAAE;IAC7E,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,kBAAkB,EAAE;CACjE,CAAA;AAqBD,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,UAAU,UAAU,CAAC,EAC1B,KAAK,EACL,MAAM,EACN,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,SAAS,EACT,eAAe,GAAG,yBAAyB,EAC3C,SAAS,GACQ;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAuB,IAAI,CAAC,CAAA;IAChF,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IAEnE,mCAAmC;IACnC,2EAA2E;IAC3E,wEAAwE;IACxE,8BAA8B;IAC9B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE;QAC9B,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAA;QACrC,OAAO,mBAAmB,CAAC,EAAE,EAAE,eAAe,CAAC,CAAA;IAChD,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAA;IAEhC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,IAAI,IAAI,SAAS,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;IAClG,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CACzC,GAAG,EAAE,CAAC,SAAS,EAAE,IAAI,IAAI,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,OAAO,CAC5D,CAAA;IAED,uCAAuC;IACvC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAiB,EAAE,CAAC,CAAA;IAC1D,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IACnE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACzD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IACtD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACvD,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,6BAA6B,CAAC,CAAA;YACtD,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;YACtD,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAA;YACnD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;YACzF,UAAU,CAAC,IAAI,CAAC,CAAA;YAChB,cAAc,CAAC,IAAI,CAAC,CAAA;QACrB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,cAAc,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAA;QAC9E,CAAC;IACF,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,SAAS,CAAC,GAAG,EAAE;QACd,KAAK,WAAW,EAAE,CAAA;IACnB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEjB,SAAS,CAAC,GAAG,EAAE;QACd,iBAAiB,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IACtE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,qCAAqC;IACrC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAA;IAE5D,4EAA4E;IAC5E,WAAW;IACX,4EAA4E;IAE5E,MAAM,kBAAkB,GAAG,WAAW,CACrC,KAAK,EAAE,SAAwB,EAAE,EAAE;QAClC,IAAI,MAAM;YAAE,OAAM;QAClB,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;YAC/B,iBAAiB,CAAC,WAAW,CAAC,CAAA;YAC9B,OAAM;QACP,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,CAAA;QACf,cAAc,CAAC,IAAI,CAAC,CAAA;QACpB,IAAI,CAAC;YACJ,IAAI,SAAS,KAAK,OAAO,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;gBACrD,MAAM,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,CAAA;gBACzC,iBAAiB,CAAC,OAAO,CAAC,CAAA;gBAC1B,SAAS,EAAE,EAAE,CAAA;gBACb,OAAM;YACP,CAAC;YACD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAA;YACxD,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;YACpC,iBAAiB,CAAC,SAAS,CAAC,CAAA;YAC5B,SAAS,EAAE,EAAE,CAAA;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,cAAc,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAA;QAC5E,CAAC;gBAAS,CAAC;YACV,SAAS,CAAC,KAAK,CAAC,CAAA;QACjB,CAAC;IACF,CAAC,EACD,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAClC,CAAA;IAED,MAAM,cAAc,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC7C,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS;YAAE,OAAM;QACpC,IAAI,MAAM;YAAE,OAAM;QAClB,SAAS,CAAC,IAAI,CAAC,CAAA;QACf,cAAc,CAAC,IAAI,CAAC,CAAA;QACpB,IAAI,CAAC;YACJ,wEAAwE;YACxE,uEAAuE;YACvE,wEAAwE;YACxE,uEAAuE;YACvE,sEAAsE;YACtE,iEAAiE;YACjE,MAAM,aAAa,GAAG,GAAG,SAAS,IAAI,SAAS,EAAE,CAAA;YACjD,MAAM,IAAI,GAAG,iBAAiB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAA;YAC9D,MAAM,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,IAA0C,CAAC,CAAA;YAC9E,iBAAiB,CAAC,WAAW,CAAC,CAAA;YAC9B,SAAS,EAAE,EAAE,CAAA;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,cAAc,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAA;QAC9E,CAAC;gBAAS,CAAC;YACV,SAAS,CAAC,KAAK,CAAC,CAAA;QACjB,CAAC;IACF,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC,CAAA;IAErE,MAAM,sBAAsB,GAAG,WAAW,CACzC,KAAK,EAAE,MAA0B,EAAE,EAAE;QACpC,IAAI,CAAC;YACJ,MAAM,YAAY,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;YACjD,SAAS,EAAE,EAAE,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACR,YAAY;QACb,CAAC;IACF,CAAC,EACD,CAAC,KAAK,EAAE,SAAS,CAAC,CAClB,CAAA;IAED,MAAM,gBAAgB,GAAG,WAAW,CACnC,KAAK,EAAE,OAAe,EAAE,EAAE;QACzB,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAM;QAC1C,IAAI,CAAC;YACJ,MAAM,YAAY,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;YAC5C,SAAS,EAAE,EAAE,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACR,YAAY;QACb,CAAC;IACF,CAAC,EACD,CAAC,KAAK,EAAE,SAAS,CAAC,CAClB,CAAA;IAED,MAAM,kBAAkB,GAAG,WAAW,CACrC,KAAK,EAAE,CAAuC,EAAE,EAAE;QACjD,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAA;QAC1C,IAAI,CAAC;YACJ,MAAM,YAAY,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAA;YACpD,SAAS,EAAE,EAAE,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACR,YAAY;QACb,CAAC;IACF,CAAC,EACD,CAAC,KAAK,EAAE,SAAS,CAAC,CAClB,CAAA;IAED,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC9C,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,CAAA;QACjC,IAAI,CAAC,IAAI,IAAI,YAAY;YAAE,OAAM;QACjC,eAAe,CAAC,IAAI,CAAC,CAAA;QACrB,cAAc,CAAC,IAAI,CAAC,CAAA;QACpB,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oBAAoB,EAAE;gBAC7C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;aAC9B,CAAC,CAAA;YACF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAErE,CAAA;gBACD,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC,CAAA;YAC9D,CAAC;YACD,MAAM,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA0B,CAAA;YAC3D,MAAM,UAAU,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,CAAA;YAC3C,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CACnB,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACtE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAC5B,CACD,CAAA;YACD,MAAM,YAAY,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;YACnD,gBAAgB,CAAC,EAAE,CAAC,CAAA;YACpB,gBAAgB,CAAC,KAAK,CAAC,CAAA;YACvB,SAAS,EAAE,EAAE,CAAA;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,cAAc,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAA;QAC5E,CAAC;gBAAS,CAAC;YACV,eAAe,CAAC,KAAK,CAAC,CAAA;QACvB,CAAC;IACF,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC,CAAA;IAEnD,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC;YAAE,OAAM;QACvD,IAAI,CAAC;YACJ,MAAM,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;YACrC,SAAS,EAAE,EAAE,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACR,YAAY;QACb,CAAC;IACF,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAA;IAEtB,4EAA4E;IAC5E,SAAS;IACT,4EAA4E;IAC5E,MAAM,aAAa,GAAG,cAAc,IAAI,MAAM,CAAA;IAC9C,MAAM,oBAAoB,GAAG,0BAA0B,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAE/E,OAAO,CACN,0BAEC,MAAC,OAAO,IAAC,KAAK,EAAC,qBAAqB,EAAC,IAAI,EAAC,QAAQ,aAEjD,cAAK,KAAK,EAAE,UAAU,YACpB,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACzB,kBAEC,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,EAC9C,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,EAAE,KAAK,aAAa,EAC5C,KAAK,EAAE,SAAS,CAAC,aAAa,KAAK,GAAG,CAAC,EAAE,CAAC,kBAC5B,aAAa,KAAK,GAAG,CAAC,EAAE,aAEtC,eAAM,KAAK,EAAE,WAAW,CAAC,aAAa,KAAK,GAAG,CAAC,EAAE,CAAC,YAChD,aAAa,KAAK,GAAG,CAAC,EAAE,IAAI,eAAM,KAAK,EAAE,QAAQ,GAAI,GAChD,EACP,gBAAM,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,aACvB,eAAM,KAAK,EAAE,WAAW,YAAG,GAAG,CAAC,KAAK,GAAQ,EAC5C,eAAM,KAAK,EAAE,UAAU,YAAG,iBAAiB,CAAC,GAAG,EAAE,aAAa,CAAC,GAAQ,IACjE,KAbF,GAAG,CAAC,EAAE,CAcH,CACT,CAAC,GACG,EACL,WAAW,IAAI,CACf,cAAK,IAAI,EAAC,OAAO,EAAC,KAAK,EAAE,gBAAgB,YACvC,WAAW,GACP,CACN,EAGA,oBAAoB,IAAI,CACxB,eAAK,KAAK,EAAE,SAAS,EAAE,SAAS,EAAC,WAAW,aAC3C,KAAC,KAAK,IAAC,KAAK,EAAE,SAAS,eAAe,GAAG,YACxC,gBACC,SAAS,EAAC,OAAO,EACjB,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAC5C,GACK,EACR,KAAC,KAAK,IAAC,KAAK,EAAE,SAAS,eAAe,GAAG,YACxC,gBACC,SAAS,EAAC,OAAO,EACjB,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAC5C,GACK,EACR,cAAK,KAAK,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,YACnC,iBACC,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,gBAAgB,EAC1B,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,cAAc,EAAE,EACpC,QAAQ,EAAE,CAAC,SAAS,IAAI,CAAC,SAAS,8BAG1B,GACJ,IACD,CACN,EAGD,KAAC,KAAK,IAAC,KAAK,EAAC,QAAQ,YACpB,eAAK,SAAS,EAAC,KAAK,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,aAC5C,kBACC,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAC5C,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAE,EAC5C,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,sBAAsB,CAAC,MAAM,CAAC,kBACpC,UAAU,KAAK,MAAM,aAEnC,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAE,EAAE,GAAI,YAEvB,EACT,kBACC,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAC/C,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAE,EAC5C,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,sBAAsB,CAAC,SAAS,CAAC,kBACvC,UAAU,KAAK,SAAS,aAEtC,KAAC,IAAI,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAE,EAAE,GAAI,eAEtB,IACJ,GACC,IACC,EAGV,KAAC,OAAO,IAAC,KAAK,EAAC,SAAS,EAAC,IAAI,EAAC,MAAM,YACnC,KAAC,KAAK,IAAC,KAAK,EAAC,UAAU,EAAC,IAAI,EAAC,yCAAyC,YACrE,KAAC,SAAS,IAAC,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,GAAI,GACtD,GACC,EAGV,KAAC,OAAO,IAAC,KAAK,EAAC,WAAW,EAAC,IAAI,EAAC,OAAO,YACtC,MAAC,KAAK,IAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,EAAC,oDAAoD,aAC9E,kBACC,KAAK,EAAE,QAAQ,IAAI,EAAE,EACrB,QAAQ,EAAE,kBAAkB,EAC5B,SAAS,EAAC,WAAW,gBACV,QAAQ,aAEnB,iBAAQ,KAAK,EAAC,EAAE,yCAAwB,EACvC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACnB,iBAAmB,KAAK,EAAE,CAAC,CAAC,EAAE,YAC5B,CAAC,CAAC,IAAI,IADK,CAAC,CAAC,EAAE,CAER,CACT,CAAC,IACM,EACR,aAAa,IAAI,CACjB,eAAK,KAAK,EAAE,UAAU,aACrB,KAAC,IAAI,IAAC,IAAI,EAAC,aAAa,EAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,GAAI,EACtE,aAAa,CAAC,IAAI,IACd,CACN,EACD,eAAK,KAAK,EAAE,aAAa,aACxB,kBACC,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,QAAQ,EAClB,OAAO,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,mBACjC,aAAa,aAE5B,KAAC,IAAI,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAE,EAAE,GAAI,kBAEtB,EACT,kBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,cAAc,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,WAAW,EAAE,aAC/E,KAAC,IAAI,IAAC,IAAI,EAAC,SAAS,EAAC,IAAI,EAAE,EAAE,GAAI,eAEzB,IACJ,EACL,aAAa,IAAI,CACjB,eAAK,KAAK,EAAE,YAAY,aACvB,gBACC,SAAS,EAAC,OAAO,EACjB,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,EACxD,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;wCAChB,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;4CACvB,CAAC,CAAC,cAAc,EAAE,CAAA;4CAClB,KAAK,eAAe,EAAE,CAAA;wCACvB,CAAC;oCACF,CAAC,EACD,WAAW,EAAC,aAAa,gBACd,aAAa,GACvB,EACF,iBACC,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,gBAAgB,EAC1B,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,eAAe,EAAE,EACrC,QAAQ,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,YAAY,YAE9C,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,GAChC,IACJ,CACN,EACA,WAAW,IAAI,cAAK,KAAK,EAAE,eAAe,YAAG,WAAW,GAAO,IACzD,GACC,EAGV,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,YAC1B,kBACC,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,eAAe,EACzB,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,WAAW,EAAE,aAEjC,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAE,EAAE,GAAI,qBAEvB,GACJ,IACD,CACN,CAAA;AACF,CAAC;AAED,SAAS,iBAAiB,CACzB,MAA2C,EAC3C,aAA4B;IAE5B,IAAI,MAAM,CAAC,EAAE,KAAK,OAAO,IAAI,aAAa,KAAK,WAAW,EAAE,CAAC;QAC5D,OAAO,+BAA+B,CAAA;IACvC,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAA;AACnB,CAAC;AAED,8EAA8E;AAC9E,iEAAiE;AACjE,8EAA8E;AAE9E,SAAS,SAAS,CAAC,EAClB,YAAY,EACZ,QAAQ,GAIR;IACA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAA;IAEhD,6CAA6C;IAC7C,SAAS,CAAC,GAAG,EAAE;QACd,QAAQ,CAAC,YAAY,CAAC,CAAA;IACvB,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAA;IAElB,OAAO,CACN,eAAK,KAAK,EAAE,OAAO,aAClB,eAAM,SAAS,EAAC,MAAM,EAAC,KAAK,EAAE,UAAU,kBAEjC,EACP,gBACC,SAAS,EAAC,OAAO,EACjB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAC7B,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;oBAChB,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;wBACvB,CAAC,CAAC,cAAc,EAAE,CAAA;wBAClB,QAAQ,CAAC,KAAK,CAAC,CAAA;oBAChB,CAAC;gBACF,CAAC,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,gBAC1B,UAAU,GACpB,IACG,CACN,CAAA;AACF,CAAC;AAED,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAM,UAAU,GAAwB;IACvC,OAAO,EAAE,MAAM;IACf,aAAa,EAAE,QAAQ;IACvB,GAAG,EAAE,CAAC;IACN,YAAY,EAAE,EAAE;CAChB,CAAA;AAED,SAAS,SAAS,CAAC,MAAe;IACjC,OAAO;QACN,SAAS,EAAE,MAAM;QACjB,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,GAAG,EAAE,EAAE;QACP,OAAO,EAAE,WAAW;QACpB,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,aAAa,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,EAAE;QACjE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,cAAc;QAC1D,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,MAAM;KACb,CAAA;AACF,CAAC;AAED,SAAS,WAAW,CAAC,MAAe;IACnC,OAAO;QACN,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE;QACV,YAAY,EAAE,KAAK;QACnB,MAAM,EAAE,aAAa,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,qBAAqB,EAAE;QACvE,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,UAAU,EAAE,CAAC;KACb,CAAA;AACF,CAAC;AAED,MAAM,QAAQ,GAAwB;IACrC,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,YAAY,EAAE,KAAK;IACnB,UAAU,EAAE,eAAe;CAC3B,CAAA;AAED,MAAM,WAAW,GAAwB;IACxC,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,GAAG;IACf,KAAK,EAAE,YAAY;CACnB,CAAA;AAED,MAAM,UAAU,GAAwB;IACvC,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,IAAI;IACd,KAAK,EAAE,kBAAkB;CACzB,CAAA;AAED,MAAM,gBAAgB,GAAwB;IAC7C,MAAM,EAAE,UAAU;IAClB,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,2DAA2D;IACnE,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,gDAAgD;IAC5D,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE,IAAI;CAChB,CAAA;AAED,MAAM,SAAS,GAAwB;IACtC,OAAO,EAAE,MAAM;IACf,mBAAmB,EAAE,SAAS;IAC9B,GAAG,EAAE,CAAC;IACN,YAAY,EAAE,CAAC;CACf,CAAA;AAED,MAAM,OAAO,GAAwB;IACpC,OAAO,EAAE,MAAM;IACf,UAAU,EAAE,QAAQ;IACpB,MAAM,EAAE,+BAA+B;IACvC,YAAY,EAAE,CAAC;IACf,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,cAAc;CAC1B,CAAA;AAED,MAAM,UAAU,GAAwB;IACvC,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,kBAAkB;IACzB,OAAO,EAAE,cAAc;IACvB,UAAU,EAAE,QAAQ;CACpB,CAAA;AAED,MAAM,UAAU,GAAwB;IACvC,OAAO,EAAE,MAAM;IACf,UAAU,EAAE,QAAQ;IACpB,GAAG,EAAE,CAAC;IACN,QAAQ,EAAE,IAAI;IACd,KAAK,EAAE,kBAAkB;IACzB,SAAS,EAAE,CAAC;CACZ,CAAA;AAED,MAAM,aAAa,GAAwB;IAC1C,OAAO,EAAE,MAAM;IACf,GAAG,EAAE,CAAC;IACN,SAAS,EAAE,EAAE;CACb,CAAA;AAED,MAAM,YAAY,GAAwB;IACzC,OAAO,EAAE,MAAM;IACf,mBAAmB,EAAE,UAAU;IAC/B,GAAG,EAAE,CAAC;IACN,SAAS,EAAE,CAAC;CACZ,CAAA;AAED,MAAM,eAAe,GAAwB;IAC5C,SAAS,EAAE,CAAC;IACZ,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE,GAAG;IACf,KAAK,EAAE,YAAY;CACnB,CAAA"}
@@ -0,0 +1,3 @@
1
+ -- Existing rows remain unverified; never synthesize a historical payload digest.
2
+ ALTER TABLE content_insight_runs ADD COLUMN publication_run_id TEXT;
3
+ ALTER TABLE content_insight_runs ADD COLUMN payload_sha256 TEXT;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-labs/cms",
3
- "version": "0.8.18",
3
+ "version": "0.8.20",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "growth-labs-cms-migrations": "./dist/cli/migrations.js"
@@ -6,6 +6,7 @@ import type {
6
6
  InsightEvidence,
7
7
  } from '../schema/types.js'
8
8
  import type { D1Database } from './d1.js'
9
+ import { canonicalJsonSha256, type JsonValue } from './publication-receipt/canonical-json.js'
9
10
 
10
11
  /** True when an Insights read/write depends on a table missing from an older schema. */
11
12
  export function isMissingInsightsTable(error: unknown): boolean {
@@ -99,69 +100,100 @@ export async function undismissInsight(
99
100
  }
100
101
 
101
102
  export type ReplaceOutcome = 'applied' | 'duplicate' | 'stale'
103
+
104
+ /** Identity read from the committed run row, never echoed from the incoming request. */
105
+ export interface InsightPublicationIdentity {
106
+ eventId: string
107
+ siteId: string
108
+ runDate: string
109
+ runAttempt: number
110
+ runId: string | null
111
+ contentHash: string
112
+ /** RFC 8785 SHA-256 of the full validated {meta, rows}, including actual row content. */
113
+ payloadSha256: string | null
114
+ /** Legacy rows have no digest/run identity and cannot confirm a duplicate. */
115
+ verified: boolean
116
+ }
117
+
102
118
  export interface ReplaceResult {
103
119
  outcome: ReplaceOutcome
104
120
  landedRunAttempt: number
121
+ publication: InsightPublicationIdentity
105
122
  }
106
123
 
124
+ export class InsightPublicationError extends Error {
125
+ constructor(readonly code: 'publication_identity_conflict' | 'publication_identity_unverified') {
126
+ super(code)
127
+ this.name = 'InsightPublicationError'
128
+ }
129
+ }
130
+
131
+ /** Only ingest references these columns; do not mask unrelated missing-column failures. */
132
+ export function isMissingInsightPublicationSchema(error: unknown): boolean {
133
+ return (
134
+ isMissingInsightsTable(error) ||
135
+ (error instanceof Error &&
136
+ /(?:no such table: content_insight_runs\b|no such column:\s*(?:publication_run_id|payload_sha256)\b|table\s+content_insight_runs\s+has no column named\s+(?:publication_run_id|payload_sha256)\b)/i.test(
137
+ error.message,
138
+ ))
139
+ )
140
+ }
141
+
142
+ interface PublicationRow {
143
+ event_id: string
144
+ site_id: string
145
+ run_date: string
146
+ run_attempt: number
147
+ publication_run_id: string | null
148
+ content_hash: string
149
+ payload_sha256: string | null
150
+ }
151
+
152
+ const publicationColumns = `event_id, site_id, run_date, run_attempt,
153
+ publication_run_id, content_hash, payload_sha256`
154
+
107
155
  /**
108
- * Replay-safe replace of the board for (meta.site_id, meta.run_date).
109
- * - 'duplicate': meta.event_id already present in content_insight_runs.event_id → no-op.
110
- * - 'stale': an equal-or-higher run_attempt already landed for (site_id, run_date) → no-op
111
- * (HMAC authenticates the sender; run_attempt is the monotonic replay guard).
112
- * - 'applied': DELETE the existing board scoped by (site_id, run_date), bulk-insert rows
113
- * (mint id, run_id = meta.run_id, beat from payload, created_at = unixepoch()),
114
- * upsert the run row.
115
- * Dismissals are untouched — they live in their own table keyed (site_id, intent_key).
156
+ * Every eligibility read, guarded write and identity read executes in ONE D1 batch.
157
+ * The run table stays unchanged until the final mutation, so every DELETE/INSERT
158
+ * evaluates the same predicate against the same transaction state. D1 rolls back
159
+ * the entire batch on any failure. Dismissals are never touched.
116
160
  *
117
- * The INSERT carries 16 columns (id, site_id, run_id, run_date, desk, suggestion_type,
118
- * signal_type, is_best_bet, best_bet_rank, desk_rank, headline, evidence, brief,
119
- * intent_key, beat, created_at) matching migration 0016 column order.
161
+ * Current event IDs are immutable: exact replay is a no-op; divergent or legacy
162
+ * unverified reuse fails without writes. Once superseded, an old event has no
163
+ * historical dedupe promise; its original attempt remains stale.
120
164
  */
121
165
  export async function replaceInsightsBoard(
122
166
  db: D1Database,
123
167
  payload: InsightsIngestPayload,
124
168
  ): Promise<ReplaceResult> {
125
169
  const { meta, rows } = payload
126
-
127
- // 1) event_id dedupe (mirrors foundry_callback_events).
128
- const dupEvent = await db
129
- .prepare('SELECT id FROM content_insight_runs WHERE event_id = ? LIMIT 1')
130
- .bind(meta.event_id)
131
- .first<{ id: string }>()
132
- if (dupEvent) return { outcome: 'duplicate', landedRunAttempt: meta.run_attempt }
133
-
134
- // 2) stale-replay guard: reject equal-or-lower run_attempt for (site_id, run_date).
135
- const existing = await db
136
- .prepare(
137
- 'SELECT id, run_attempt FROM content_insight_runs WHERE site_id = ? AND run_date = ? LIMIT 1',
138
- )
139
- .bind(meta.site_id, meta.run_date)
140
- .first<{ id: string; run_attempt: number }>()
141
- if (existing && meta.run_attempt <= existing.run_attempt) {
142
- return { outcome: 'stale', landedRunAttempt: existing.run_attempt }
143
- }
144
-
170
+ const payloadSha256 = await canonicalJsonSha256(payload as unknown as JsonValue)
145
171
  const now = Math.floor(Date.now() / 1000)
146
172
 
147
- // 3) Scoped replace + bulk insert + run upsert in one D1 batch.
173
+ const eligible = `NOT EXISTS (SELECT 1 FROM content_insight_runs WHERE event_id = ?)
174
+ AND NOT EXISTS (SELECT 1 FROM content_insight_runs
175
+ WHERE site_id = ? AND run_date = ? AND run_attempt >= ?)`
176
+ const eligibilityBindings = [meta.event_id, meta.site_id, meta.run_date, meta.run_attempt]
177
+ const currentPublication = db
178
+ .prepare(`SELECT ${publicationColumns} FROM content_insight_runs
179
+ WHERE site_id = ? AND run_date = ?`)
180
+ .bind(meta.site_id, meta.run_date)
148
181
  const statements = [
149
182
  db
150
- .prepare('DELETE FROM content_insights WHERE site_id = ? AND run_date = ?')
151
- .bind(meta.site_id, meta.run_date),
183
+ .prepare(`SELECT ${publicationColumns} FROM content_insight_runs WHERE event_id = ? LIMIT 2`)
184
+ .bind(meta.event_id),
185
+ currentPublication,
186
+ db
187
+ .prepare(`DELETE FROM content_insights WHERE site_id = ? AND run_date = ? AND ${eligible}`)
188
+ .bind(meta.site_id, meta.run_date, ...eligibilityBindings),
152
189
  ]
153
190
  for (const row of rows) {
154
- // 16 columns: id, site_id, run_id, run_date, desk, suggestion_type, signal_type,
155
- // is_best_bet, best_bet_rank, desk_rank, headline, evidence, brief,
156
- // intent_key, beat, created_at
157
191
  statements.push(
158
192
  db
159
- .prepare(
160
- `INSERT INTO content_insights
161
- (id, site_id, run_id, run_date, desk, suggestion_type, signal_type, is_best_bet,
162
- best_bet_rank, desk_rank, headline, evidence, brief, intent_key, beat, created_at)
163
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
164
- )
193
+ .prepare(`INSERT INTO content_insights
194
+ (id, site_id, run_id, run_date, desk, suggestion_type, signal_type, is_best_bet,
195
+ best_bet_rank, desk_rank, headline, evidence, brief, intent_key, beat, created_at)
196
+ SELECT ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,? WHERE ${eligible}`)
165
197
  .bind(
166
198
  crypto.randomUUID(),
167
199
  row.site_id,
@@ -179,30 +211,32 @@ export async function replaceInsightsBoard(
179
211
  row.intent_key,
180
212
  row.beat,
181
213
  now,
214
+ ...eligibilityBindings,
182
215
  ),
183
216
  )
184
217
  }
185
- // Upsert the run row keyed on UNIQUE (site_id, run_date).
218
+ // This MUST be the final mutation: preceding row writes share its eligibility.
186
219
  statements.push(
187
220
  db
188
- .prepare(
189
- `INSERT INTO content_insight_runs
190
- (id, site_id, run_date, status, event_id, run_attempt, generated_at, content_hash,
191
- demand_count, opportunity_count, started_at, completed_at, error)
192
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
193
- ON CONFLICT(site_id, run_date) DO UPDATE SET
194
- status = excluded.status,
195
- event_id = excluded.event_id,
196
- run_attempt = excluded.run_attempt,
197
- generated_at = excluded.generated_at,
198
- content_hash = excluded.content_hash,
199
- demand_count = excluded.demand_count,
200
- opportunity_count = excluded.opportunity_count,
201
- completed_at = excluded.completed_at,
202
- error = excluded.error`,
203
- )
221
+ .prepare(`INSERT INTO content_insight_runs
222
+ (id, site_id, run_date, status, event_id, run_attempt, generated_at, content_hash,
223
+ demand_count, opportunity_count, started_at, completed_at, error,
224
+ publication_run_id, payload_sha256)
225
+ SELECT ?,?,?,?,?,?,?,?,?,?,?,?,?,?,? WHERE ${eligible}
226
+ ON CONFLICT(site_id, run_date) DO UPDATE SET
227
+ status = excluded.status,
228
+ event_id = excluded.event_id,
229
+ run_attempt = excluded.run_attempt,
230
+ generated_at = excluded.generated_at,
231
+ content_hash = excluded.content_hash,
232
+ demand_count = excluded.demand_count,
233
+ opportunity_count = excluded.opportunity_count,
234
+ completed_at = excluded.completed_at,
235
+ error = excluded.error,
236
+ publication_run_id = excluded.publication_run_id,
237
+ payload_sha256 = excluded.payload_sha256`)
204
238
  .bind(
205
- existing?.id ?? crypto.randomUUID(),
239
+ crypto.randomUUID(),
206
240
  meta.site_id,
207
241
  meta.run_date,
208
242
  meta.status,
@@ -215,9 +249,54 @@ export async function replaceInsightsBoard(
215
249
  now,
216
250
  meta.status === 'completed' || meta.status === 'partial' ? now : null,
217
251
  meta.error ?? null,
252
+ meta.run_id,
253
+ payloadSha256,
254
+ ...eligibilityBindings,
218
255
  ),
256
+ currentPublication,
219
257
  )
220
-
221
- await db.batch(statements)
222
- return { outcome: 'applied', landedRunAttempt: meta.run_attempt }
258
+ const results = await db.batch(statements)
259
+ const events = (results[0].results ?? []) as unknown as PublicationRow[]
260
+ const previous = results[1].results?.[0] as unknown as PublicationRow | undefined
261
+ if (events.length > 0) {
262
+ const event = events[0]
263
+ if (
264
+ events.length !== 1 ||
265
+ event.site_id !== meta.site_id ||
266
+ event.run_date !== meta.run_date ||
267
+ event.run_attempt !== meta.run_attempt ||
268
+ event.content_hash !== meta.content_hash ||
269
+ (event.publication_run_id !== null && event.publication_run_id !== meta.run_id)
270
+ ) {
271
+ throw new InsightPublicationError('publication_identity_conflict')
272
+ }
273
+ if (event.payload_sha256 === null || event.publication_run_id === null) {
274
+ throw new InsightPublicationError('publication_identity_unverified')
275
+ }
276
+ if (event.payload_sha256 !== payloadSha256) {
277
+ throw new InsightPublicationError('publication_identity_conflict')
278
+ }
279
+ }
280
+ const committed = results[results.length - 1].results?.[0] as unknown as
281
+ | PublicationRow
282
+ | undefined
283
+ if (!committed) throw new Error('Missing committed insight publication')
284
+ return {
285
+ outcome: events.length
286
+ ? 'duplicate'
287
+ : previous && previous.run_attempt >= meta.run_attempt
288
+ ? 'stale'
289
+ : 'applied',
290
+ landedRunAttempt: committed.run_attempt,
291
+ publication: {
292
+ eventId: committed.event_id,
293
+ siteId: committed.site_id,
294
+ runDate: committed.run_date,
295
+ runAttempt: committed.run_attempt,
296
+ runId: committed.publication_run_id,
297
+ contentHash: committed.content_hash,
298
+ payloadSha256: committed.payload_sha256,
299
+ verified: committed.payload_sha256 !== null && committed.publication_run_id !== null,
300
+ },
301
+ }
223
302
  }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Publication-timezone helpers — ONE implementation, shared by the schedule
3
+ * route and the Publish tab.
4
+ *
5
+ * Why this module exists: the editor types a wall-clock time and expects the
6
+ * post to go out at that time in the publication's timezone. That only holds
7
+ * if the digits the UI DISPLAYS and the zone it SAVES agree. When they
8
+ * disagreed, every resave shifted `publish_at` by the zone offset — including
9
+ * an incidental resave that never touched the field (the 2026-09-08 P0). So
10
+ * display and entry must use the same converter as the server, not a second
11
+ * copy of the arithmetic.
12
+ */
13
+
14
+ /** Fronts default; the server falls back to this when no zone is configured. */
15
+ export const PUBLISH_TIMEZONE_FALLBACK = 'Europe/Paris'
16
+
17
+ /** `YYYY-MM-DDTHH:MM` exactly — the shape the date and time inputs produce. */
18
+ const LOCAL_DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})$/
19
+
20
+ type LocalDateTimeParts = { year: number; month: number; day: number; hour: number; minute: number }
21
+
22
+ export function parseLocalDateTime(value: string): LocalDateTimeParts | null {
23
+ const match = LOCAL_DATE_TIME_RE.exec(value)
24
+ if (!match) return null
25
+ const [, y, m, d, h, min] = match
26
+ const parts: LocalDateTimeParts = {
27
+ year: Number.parseInt(y, 10),
28
+ month: Number.parseInt(m, 10),
29
+ day: Number.parseInt(d, 10),
30
+ hour: Number.parseInt(h, 10),
31
+ minute: Number.parseInt(min, 10),
32
+ }
33
+ if (
34
+ !Number.isInteger(parts.year) ||
35
+ parts.month < 1 ||
36
+ parts.month > 12 ||
37
+ parts.day < 1 ||
38
+ parts.day > 31 ||
39
+ parts.hour < 0 ||
40
+ parts.hour > 23 ||
41
+ parts.minute < 0 ||
42
+ parts.minute > 59
43
+ ) {
44
+ return null
45
+ }
46
+ const dateCheck = new Date(Date.UTC(parts.year, parts.month - 1, parts.day))
47
+ if (
48
+ dateCheck.getUTCFullYear() !== parts.year ||
49
+ dateCheck.getUTCMonth() + 1 !== parts.month ||
50
+ dateCheck.getUTCDate() !== parts.day
51
+ ) {
52
+ return null
53
+ }
54
+ return parts
55
+ }
56
+
57
+ export function getZonedParts(instantMs: number, timeZone: string): LocalDateTimeParts | null {
58
+ if (!isValidTimeZone(timeZone)) return null
59
+ const formatter = new Intl.DateTimeFormat('en-US', {
60
+ timeZone,
61
+ hour12: false,
62
+ year: 'numeric',
63
+ month: '2-digit',
64
+ day: '2-digit',
65
+ hour: '2-digit',
66
+ minute: '2-digit',
67
+ second: '2-digit',
68
+ })
69
+ const values = { year: '', month: '', day: '', hour: '', minute: '', second: '' }
70
+ for (const part of formatter.formatToParts(new Date(instantMs))) {
71
+ if (part.type in values) values[part.type as keyof typeof values] = part.value
72
+ }
73
+ const year = Number.parseInt(values.year, 10)
74
+ const month = Number.parseInt(values.month, 10)
75
+ const day = Number.parseInt(values.day, 10)
76
+ const hour = Number.parseInt(values.hour, 10)
77
+ const minute = Number.parseInt(values.minute, 10)
78
+ if (![year, month, day, hour, minute].every(Number.isFinite)) return null
79
+ return { year, month, day, hour, minute }
80
+ }
81
+
82
+ export function isValidTimeZone(timeZone: string): boolean {
83
+ try {
84
+ new Intl.DateTimeFormat('en-US', { timeZone }).format(new Date())
85
+ return true
86
+ } catch {
87
+ return false
88
+ }
89
+ }
90
+
91
+ export function getTimeZoneOffsetMs(instantMs: number, timeZone: string): number | null {
92
+ const zoned = getZonedParts(instantMs, timeZone)
93
+ if (!zoned) return null
94
+ const asUtc = Date.UTC(zoned.year, zoned.month - 1, zoned.day, zoned.hour, zoned.minute, 0)
95
+ return asUtc - instantMs
96
+ }
97
+
98
+ export function parseLocalDateTimeInZoneToUnixSeconds(
99
+ value: string,
100
+ timeZone: string,
101
+ ): number | null {
102
+ const target = parseLocalDateTime(value)
103
+ if (!target) return null
104
+ const targetUtcMs = Date.UTC(
105
+ target.year,
106
+ target.month - 1,
107
+ target.day,
108
+ target.hour,
109
+ target.minute,
110
+ 0,
111
+ )
112
+ let candidateMs = targetUtcMs
113
+ for (let i = 0; i < 5; i += 1) {
114
+ const offsetMs = getTimeZoneOffsetMs(candidateMs, timeZone)
115
+ if (offsetMs === null) return null
116
+ const next = targetUtcMs - offsetMs
117
+ if (Math.abs(next - candidateMs) < 1000) {
118
+ candidateMs = next
119
+ break
120
+ }
121
+ candidateMs = next
122
+ }
123
+ const resolved = getZonedParts(candidateMs, timeZone)
124
+ if (
125
+ !resolved ||
126
+ resolved.year !== target.year ||
127
+ resolved.month !== target.month ||
128
+ resolved.day !== target.day ||
129
+ resolved.hour !== target.hour ||
130
+ resolved.minute !== target.minute
131
+ ) {
132
+ return null
133
+ }
134
+ return Math.floor(candidateMs / 1000)
135
+ }
136
+
137
+ /**
138
+ * Inverse of `parseLocalDateTimeInZoneToUnixSeconds`: render an instant as the
139
+ * wall-clock digits an editor in `timeZone` would read, split for the date and
140
+ * time inputs. Returns null when the zone is unusable, so callers can fall back
141
+ * rather than silently display a wrong hour.
142
+ */
143
+ export function formatInstantInZone(
144
+ instantMs: number,
145
+ timeZone: string,
146
+ ): { date: string; time: string } | null {
147
+ const parts = getZonedParts(instantMs, timeZone)
148
+ if (!parts) return null
149
+ const pad = (n: number, width = 2) => String(n).padStart(width, '0')
150
+ return {
151
+ date: `${pad(parts.year, 4)}-${pad(parts.month)}-${pad(parts.day)}`,
152
+ time: `${pad(parts.hour)}:${pad(parts.minute)}`,
153
+ }
154
+ }