@growth-labs/cms 0.8.2 → 0.8.3

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 (77) hide show
  1. package/dist/engine/ai-dek-notifications.d.ts +2 -0
  2. package/dist/engine/ai-dek-notifications.d.ts.map +1 -1
  3. package/dist/engine/ai-dek-notifications.js +11 -2
  4. package/dist/engine/ai-dek-notifications.js.map +1 -1
  5. package/dist/engine/ai-dek.d.ts +23 -0
  6. package/dist/engine/ai-dek.d.ts.map +1 -1
  7. package/dist/engine/ai-dek.js +94 -31
  8. package/dist/engine/ai-dek.js.map +1 -1
  9. package/dist/engine/foundry-dispatch.d.ts +13 -3
  10. package/dist/engine/foundry-dispatch.d.ts.map +1 -1
  11. package/dist/engine/foundry-dispatch.js +80 -25
  12. package/dist/engine/foundry-dispatch.js.map +1 -1
  13. package/dist/engine/fronts-publish-intent.d.ts +55 -0
  14. package/dist/engine/fronts-publish-intent.d.ts.map +1 -1
  15. package/dist/engine/fronts-publish-intent.js +181 -55
  16. package/dist/engine/fronts-publish-intent.js.map +1 -1
  17. package/dist/engine/fronts-publish.d.ts +11 -0
  18. package/dist/engine/fronts-publish.d.ts.map +1 -1
  19. package/dist/engine/fronts-publish.js +106 -4
  20. package/dist/engine/fronts-publish.js.map +1 -1
  21. package/dist/engine/index.d.ts +1 -1
  22. package/dist/engine/index.d.ts.map +1 -1
  23. package/dist/engine/index.js +1 -1
  24. package/dist/engine/index.js.map +1 -1
  25. package/dist/engine/podcast-source.d.ts +3 -2
  26. package/dist/engine/podcast-source.d.ts.map +1 -1
  27. package/dist/engine/podcast-source.js +6 -4
  28. package/dist/engine/podcast-source.js.map +1 -1
  29. package/dist/engine/publisher.d.ts.map +1 -1
  30. package/dist/engine/publisher.js +16 -8
  31. package/dist/engine/publisher.js.map +1 -1
  32. package/dist/engine/soft-delete.d.ts +3 -1
  33. package/dist/engine/soft-delete.d.ts.map +1 -1
  34. package/dist/engine/soft-delete.js +21 -5
  35. package/dist/engine/soft-delete.js.map +1 -1
  36. package/dist/engine/video-source.d.ts +4 -2
  37. package/dist/engine/video-source.d.ts.map +1 -1
  38. package/dist/engine/video-source.js +7 -4
  39. package/dist/engine/video-source.js.map +1 -1
  40. package/dist/routes/content.d.ts +14 -0
  41. package/dist/routes/content.d.ts.map +1 -1
  42. package/dist/routes/content.js +37 -24
  43. package/dist/routes/content.js.map +1 -1
  44. package/dist/routes/context.d.ts +6 -0
  45. package/dist/routes/context.d.ts.map +1 -1
  46. package/dist/routes/context.js.map +1 -1
  47. package/dist/routes/fronts-publish.d.ts +2 -0
  48. package/dist/routes/fronts-publish.d.ts.map +1 -1
  49. package/dist/routes/fronts-publish.js +178 -2
  50. package/dist/routes/fronts-publish.js.map +1 -1
  51. package/dist/ui/api/_content-config.d.ts.map +1 -1
  52. package/dist/ui/api/_content-config.js +7 -0
  53. package/dist/ui/api/_content-config.js.map +1 -1
  54. package/dist/ui/api/fronts/schedule.d.ts +2 -0
  55. package/dist/ui/api/fronts/schedule.d.ts.map +1 -1
  56. package/dist/ui/api/fronts/schedule.js +2 -0
  57. package/dist/ui/api/fronts/schedule.js.map +1 -1
  58. package/dist/ui/editor/ContentForm.d.ts.map +1 -1
  59. package/dist/ui/editor/ContentForm.js +2 -2
  60. package/dist/ui/editor/ContentForm.js.map +1 -1
  61. package/package.json +1 -1
  62. package/src/engine/ai-dek-notifications.ts +19 -2
  63. package/src/engine/ai-dek.ts +131 -40
  64. package/src/engine/foundry-dispatch.ts +110 -24
  65. package/src/engine/fronts-publish-intent.ts +289 -65
  66. package/src/engine/fronts-publish.ts +121 -4
  67. package/src/engine/index.ts +1 -0
  68. package/src/engine/podcast-source.ts +6 -4
  69. package/src/engine/publisher.ts +20 -8
  70. package/src/engine/soft-delete.ts +28 -8
  71. package/src/engine/video-source.ts +7 -4
  72. package/src/routes/content.ts +56 -31
  73. package/src/routes/context.ts +6 -0
  74. package/src/routes/fronts-publish.ts +213 -2
  75. package/src/ui/api/_content-config.ts +15 -0
  76. package/src/ui/api/fronts/schedule.ts +4 -0
  77. package/src/ui/editor/ContentForm.tsx +4 -5
@@ -8,6 +8,7 @@ import type {
8
8
  DispatchFaqHook,
9
9
  DispatchTakeawaysHook,
10
10
  DispatchWebhookHook,
11
+ FrontsScheduleMaintenanceHook,
11
12
  PublishReadinessHook,
12
13
  } from '../../routes/content.js'
13
14
  import type { R2BucketLike, RouteContext } from '../../routes/context.js'
@@ -20,6 +21,8 @@ import { buildSiteAuthz } from './_authz.js'
20
21
  * ContentRouteConfig so adapters can surface them without a separate locals key.
21
22
  */
22
23
  type CmsHooksLocals = ContentRouteConfig['hooks'] & {
24
+ frontsDefaultChannelTargets?: ContentRouteConfig['frontsDefaultChannelTargets']
25
+ frontsScheduleMaintenance?: FrontsScheduleMaintenanceHook
23
26
  activeWorkspaceId?: string
24
27
  dispatchTakeaways?: DispatchTakeawaysHook
25
28
  dispatchFaq?: DispatchFaqHook
@@ -40,12 +43,22 @@ type CmsHooksLocals = ContentRouteConfig['hooks'] & {
40
43
  */
41
44
  export function toContentCtx(c: APIContext, params?: Record<string, string>): RouteContext {
42
45
  const env = (c.locals as { cmsEnv?: Record<string, unknown> }).cmsEnv ?? {}
46
+ const cfContext = (
47
+ c.locals as {
48
+ cfContext?: { waitUntil?: (promise: Promise<unknown>) => void }
49
+ }
50
+ ).cfContext
51
+ const waitUntil =
52
+ cfContext && typeof cfContext.waitUntil === 'function'
53
+ ? cfContext.waitUntil.bind(cfContext)
54
+ : undefined
43
55
  const userId =
44
56
  (c.locals as { user?: { subject?: string } }).user?.subject ??
45
57
  (env.__identitySubject as string | undefined) ??
46
58
  null
47
59
  return {
48
60
  request: c.request,
61
+ ...(waitUntil ? { waitUntil } : {}),
49
62
  params: params ?? (c.params as Record<string, string>),
50
63
  db: env.SITE_DB as RouteContext['db'],
51
64
  bucket: (env.PUBLIC_MEDIA ?? env.MEDIA) as R2BucketLike | undefined,
@@ -75,6 +88,8 @@ export function toContentConfig(c: APIContext): ContentRouteConfig {
75
88
  : undefined,
76
89
  requiredPrimaryTopicContentTypes: config.primaryTopic?.contentTypes,
77
90
  activeWorkspaceId: hooks.activeWorkspaceId,
91
+ frontsDefaultChannelTargets: hooks.frontsDefaultChannelTargets,
92
+ frontsScheduleMaintenance: hooks.frontsScheduleMaintenance,
78
93
  hooks: {
79
94
  llm: hooks.llm,
80
95
  foundryVideo: hooks.foundryVideo,
@@ -10,3 +10,7 @@ import { toContentConfig, toContentCtx } from '../_content-config.js'
10
10
 
11
11
  export const GET = (c: APIContext) =>
12
12
  createFrontsPublishRoutes(toContentConfig(c)).schedule(toContentCtx(c, {}))
13
+
14
+ /** Go requests one bounded maintenance operation; the GET projection never mutates. */
15
+ export const POST = (c: APIContext) =>
16
+ createFrontsPublishRoutes(toContentConfig(c)).maintainSchedule(toContentCtx(c, {}))
@@ -32,7 +32,6 @@ import {
32
32
  applyMediaSourceReadiness,
33
33
  buildContentCreatePayload,
34
34
  buildContentUpdatePayload,
35
- type ContentDraftFields,
36
35
  canCreateContentDraft,
37
36
  foundryDispatchSourceForDraft,
38
37
  initialContentMetadata,
@@ -356,7 +355,7 @@ export function ContentForm({
356
355
  // -- Autosave logic -------------------------------------------------------
357
356
 
358
357
  const queueFoundryProcessing = useCallback(
359
- async (id: string, draft: ContentDraftFields) => {
358
+ async (id: string, draft: FormState) => {
360
359
  const source = foundryDispatchSourceForDraft(contentType, draft)
361
360
  if (!source) return
362
361
  const durationSeconds = normalizeMediaDurationSeconds(draft.durationSeconds)
@@ -369,7 +368,7 @@ export function ContentForm({
369
368
  }))
370
369
  return
371
370
  }
372
- const queueKey = `${contentType}:${id}:${source}:${durationSeconds}`
371
+ const queueKey = `${contentType}:${id}:${source}:${durationSeconds}:${draft.slug}:${draft.premium}`
373
372
  if (queuedVideoSources.current.has(queueKey)) return
374
373
 
375
374
  setForm((prev) => ({
@@ -378,7 +377,7 @@ export function ContentForm({
378
377
  videoPipelineError: null,
379
378
  }))
380
379
  try {
381
- const res = await fetch(`/admin/api/content/${id}?action=dispatch-to-foundry`, {
380
+ const res = await fetch(`/admin/api/content/${id}?action=dispatch-to-foundry&capture=1`, {
382
381
  method: 'POST',
383
382
  })
384
383
  if (!res.ok) {
@@ -407,7 +406,7 @@ export function ContentForm({
407
406
  const persist = useCallback(
408
407
  async (currentForm: FormState) => {
409
408
  const id = currentForm.savedId
410
- const draft: ContentDraftFields = currentForm
409
+ const draft = currentForm
411
410
 
412
411
  if (id === null) {
413
412
  if (