@flamingo-stack/openframe-frontend-core 0.0.230 → 0.0.231-snapshot.20260608073228

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 (81) hide show
  1. package/dist/{chunk-XVJQ7SKB.js → chunk-5TJUN6ON.js} +2 -2
  2. package/dist/{chunk-2BMV2LVL.js → chunk-CBFXWWS7.js} +1711 -1679
  3. package/dist/chunk-CBFXWWS7.js.map +1 -0
  4. package/dist/{chunk-4VXGQIMC.cjs → chunk-KQJXNBIS.cjs} +10 -10
  5. package/dist/{chunk-4VXGQIMC.cjs.map → chunk-KQJXNBIS.cjs.map} +1 -1
  6. package/dist/{chunk-Z2KOH5S4.cjs → chunk-LG33WCJY.cjs} +9 -9
  7. package/dist/{chunk-Z2KOH5S4.cjs.map → chunk-LG33WCJY.cjs.map} +1 -1
  8. package/dist/{chunk-FLUZ2QMJ.js → chunk-MQHM7DZZ.js} +2 -2
  9. package/dist/{chunk-G5JQMCE7.js → chunk-OYG66WRJ.js} +2 -2
  10. package/dist/{chunk-6ME63EW3.js → chunk-UTUUCSKU.js} +2 -2
  11. package/dist/{chunk-GROUDMXE.cjs → chunk-XZHVCPXN.cjs} +7 -7
  12. package/dist/{chunk-GROUDMXE.cjs.map → chunk-XZHVCPXN.cjs.map} +1 -1
  13. package/dist/{chunk-AAX7PMU7.cjs → chunk-ZHGIILP7.cjs} +25 -25
  14. package/dist/{chunk-AAX7PMU7.cjs.map → chunk-ZHGIILP7.cjs.map} +1 -1
  15. package/dist/{chunk-Y4N4XWUK.cjs → chunk-ZMLYGCFD.cjs} +150 -118
  16. package/dist/chunk-ZMLYGCFD.cjs.map +1 -0
  17. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +1 -1
  18. package/dist/components/chat/index.cjs +2 -2
  19. package/dist/components/chat/index.js +1 -1
  20. package/dist/components/chat/types/api.types.d.ts +14 -0
  21. package/dist/components/chat/types/api.types.d.ts.map +1 -1
  22. package/dist/components/contact/index.cjs +3 -3
  23. package/dist/components/contact/index.js +2 -2
  24. package/dist/components/features/entity-tag-badges.d.ts +17 -0
  25. package/dist/components/features/entity-tag-badges.d.ts.map +1 -0
  26. package/dist/components/features/index.cjs +4 -2
  27. package/dist/components/features/index.cjs.map +1 -1
  28. package/dist/components/features/index.d.ts +1 -0
  29. package/dist/components/features/index.d.ts.map +1 -1
  30. package/dist/components/features/index.js +3 -1
  31. package/dist/components/index.cjs +97 -104
  32. package/dist/components/index.cjs.map +1 -1
  33. package/dist/components/index.js +9 -16
  34. package/dist/components/index.js.map +1 -1
  35. package/dist/components/navigation/index.cjs +2 -2
  36. package/dist/components/navigation/index.js +1 -1
  37. package/dist/components/onboarding-guides/index.cjs +27 -25
  38. package/dist/components/onboarding-guides/index.cjs.map +1 -1
  39. package/dist/components/onboarding-guides/index.js +5 -3
  40. package/dist/components/onboarding-guides/index.js.map +1 -1
  41. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
  42. package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
  43. package/dist/components/tickets/index.cjs +64 -64
  44. package/dist/components/tickets/index.js +4 -4
  45. package/dist/components/ui/index.cjs +2 -2
  46. package/dist/components/ui/index.js +1 -1
  47. package/dist/components/unified-filter-logic.d.ts.map +1 -1
  48. package/dist/index.cjs +4 -2
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.js +3 -1
  51. package/dist/types/blog.d.ts +13 -1
  52. package/dist/types/blog.d.ts.map +1 -1
  53. package/dist/types/case-study.d.ts +2 -5
  54. package/dist/types/case-study.d.ts.map +1 -1
  55. package/dist/types/index.cjs.map +1 -1
  56. package/dist/types/index.js.map +1 -1
  57. package/dist/types/product-release.d.ts +2 -5
  58. package/dist/types/product-release.d.ts.map +1 -1
  59. package/dist/types/supabase.d.ts +0 -40
  60. package/dist/types/supabase.d.ts.map +1 -1
  61. package/dist/utils/index.cjs.map +1 -1
  62. package/dist/utils/index.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/components/chat/hooks/use-realtime-chunk-processor.ts +28 -0
  65. package/src/components/chat/types/api.types.ts +14 -0
  66. package/src/components/features/entity-tag-badges.tsx +32 -0
  67. package/src/components/features/index.ts +1 -0
  68. package/src/components/features/tags-selector.tsx +6 -6
  69. package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +4 -0
  70. package/src/components/shared/product-release/release-detail-page.tsx +4 -14
  71. package/src/components/unified-filter-logic.tsx +4 -3
  72. package/src/types/blog.ts +15 -1
  73. package/src/types/case-study.ts +3 -5
  74. package/src/types/product-release.ts +3 -5
  75. package/src/types/supabase.ts +0 -40
  76. package/dist/chunk-2BMV2LVL.js.map +0 -1
  77. package/dist/chunk-Y4N4XWUK.cjs.map +0 -1
  78. /package/dist/{chunk-XVJQ7SKB.js.map → chunk-5TJUN6ON.js.map} +0 -0
  79. /package/dist/{chunk-FLUZ2QMJ.js.map → chunk-MQHM7DZZ.js.map} +0 -0
  80. /package/dist/{chunk-G5JQMCE7.js.map → chunk-OYG66WRJ.js.map} +0 -0
  81. /package/dist/{chunk-6ME63EW3.js.map → chunk-UTUUCSKU.js.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamingo-stack/openframe-frontend-core",
3
- "version": "0.0.230",
3
+ "version": "0.0.231-snapshot.20260608073228",
4
4
  "description": "Shared design system and components for all Flamingo platforms",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,6 +15,11 @@ import { MESSAGE_TYPE } from '../types'
15
15
  import type { UseRealtimeChunkProcessorReturn, UseRealtimeChunkProcessorOptions, ChatApprovalStatus, PendingToolCallData } from '../types'
16
16
  import { getCommandText } from '../utils/tool-call-helpers'
17
17
 
18
+ // Actions allowed through once the dialog is in direct mode. Everything else is
19
+ // an AI-assistant chunk and gets dropped — an allowlist so any future assistant
20
+ // action is blocked by default.
21
+ const DIRECT_MODE_ALLOWED = new Set(['direct_message', 'message_request', 'system', 'dialog_closed'])
22
+
18
23
  /**
19
24
  * Hook for processing real-time NATS chunks into message segments
20
25
  */
@@ -31,6 +36,7 @@ export function useRealtimeChunkProcessor(
31
36
  // tickets view). Default ON so consumers that haven't wired the flag yet
32
37
  // get the new batch UI; pass `false` explicitly to fall back to legacy.
33
38
  batchApprovalsEnabled = true,
39
+ isDirectMode = false,
34
40
  } = options
35
41
 
36
42
  const accumulatorRef = useRef<MessageSegmentAccumulator>(
@@ -72,6 +78,14 @@ export function useRealtimeChunkProcessor(
72
78
  // resumed-dialog initializeWithState.
73
79
  const hasEverStreamedRef = useRef(false)
74
80
 
81
+ // Direct-mode barrier: once engaged, AI-assistant chunks are dropped. Engaged
82
+ // by the host flag (optimistic) or by an in-order DIRECT_MESSAGE chunk.
83
+ const directModeFlagRef = useRef(isDirectMode)
84
+ const sawDirectMessageRef = useRef(false)
85
+ useEffect(() => {
86
+ directModeFlagRef.current = isDirectMode
87
+ }, [isDirectMode])
88
+
75
89
  // Track pending escalated approvals (single or batch)
76
90
  const pendingEscalatedRef = useRef<
77
91
  Map<string, { command: string; explanation?: string; approvalType: string; toolCalls?: PendingToolCallData[] }>
@@ -93,6 +107,19 @@ export function useRealtimeChunkProcessor(
93
107
 
94
108
  const accumulator = accumulatorRef.current
95
109
 
110
+ if (action.action === 'direct_message') sawDirectMessageRef.current = true
111
+
112
+ if ((directModeFlagRef.current || sawDirectMessageRef.current) && !DIRECT_MODE_ALLOWED.has(action.action)) {
113
+ // Hard stop: tear down an open AI stream exactly once so the typing
114
+ // indicator and half-rendered bubble clear, then drop the chunk.
115
+ if (isInStreamRef.current) {
116
+ isInStreamRef.current = false
117
+ callbacks.onStreamEnd?.()
118
+ accumulator.resetSegments()
119
+ }
120
+ return
121
+ }
122
+
96
123
  switch (action.action) {
97
124
  case 'message_start':
98
125
  isInStreamRef.current = true
@@ -362,6 +389,7 @@ export function useRealtimeChunkProcessor(
362
389
  accumulatorRef.current.reset()
363
390
  pendingEscalatedRef.current.clear()
364
391
  hasInitializedWithData.current = false
392
+ sawDirectMessageRef.current = false
365
393
  }, [])
366
394
 
367
395
  const updateApprovalStatus = useCallback(
@@ -243,6 +243,20 @@ export interface UseRealtimeChunkProcessorOptions {
243
243
  * dropped from the UI in the unfolded mode.
244
244
  */
245
245
  batchApprovalsEnabled?: boolean
246
+ /**
247
+ * Engages the direct-mode barrier optimistically: once true, all AI-assistant
248
+ * chunks (text, thinking, tool executions, approvals, metadata, errors, etc.)
249
+ * are dropped and any open stream is torn down, leaving only human/control
250
+ * messages. A `DIRECT_MESSAGE` chunk engages the same barrier automatically
251
+ * regardless of this flag. Pass this from a host that already knows the dialog
252
+ * switched to direct mode (e.g. an optimistic mode toggle) to close the race
253
+ * window before the server emits the first `DIRECT_MESSAGE`.
254
+ *
255
+ * Do NOT set this when the host reconstructs history by replaying chunks
256
+ * through `processChunk` — a static flag would drop legitimate pre-switch AI
257
+ * history. Rely on the in-order `DIRECT_MESSAGE` detection instead.
258
+ */
259
+ isDirectMode?: boolean
246
260
  }
247
261
 
248
262
  export interface UseRealtimeChunkProcessorReturn {
@@ -0,0 +1,32 @@
1
+ import { StatusBadge } from '../ui/status-badge'
2
+ import type { TagAssoc } from '../../types/blog'
3
+
4
+ interface EntityTagBadgesProps {
5
+ /** Flat `<entity>_tags[]` association array (from entity_tags hydration). */
6
+ tags?: TagAssoc[] | null
7
+ /** Extra classes on the wrapper row. */
8
+ className?: string
9
+ }
10
+
11
+ /**
12
+ * The single lib-side tag-badge renderer for detail views (release, onboarding
13
+ * guide, …). Lib-package analogue of the hub's `EntityTagList` — the hub can't
14
+ * be imported here, so this lives in the lib and is reused across lib detail
15
+ * pages instead of each one re-implementing the StatusBadge chip row. Renders
16
+ * nothing when there are no tags.
17
+ */
18
+ export function EntityTagBadges({ tags, className }: EntityTagBadgesProps) {
19
+ if (!tags || tags.length === 0) return null
20
+ return (
21
+ <div className={`flex flex-wrap gap-2 w-full ${className || ''}`}>
22
+ {tags.map((tag) => (
23
+ <StatusBadge
24
+ key={tag.tag_id ?? tag.id}
25
+ text={(tag.name || '').toUpperCase()}
26
+ variant="card"
27
+ className="bg-ods-card border border-ods-border"
28
+ />
29
+ ))}
30
+ </div>
31
+ )
32
+ }
@@ -23,6 +23,7 @@ export * from './changelog-manager'
23
23
  export * from './changelog-sections-manager'
24
24
  export * from './clickup-tasks-manager'
25
25
  export * from './command-box'
26
+ export * from './entity-tag-badges'
26
27
  export * from './error-boundary'
27
28
  export * from './figma-prototype-viewer'
28
29
  export * from './filters-dropdown'
@@ -117,22 +117,22 @@ export function TagsSelector({
117
117
  {getSelectedTags().map((tag) => (
118
118
  <span
119
119
  key={tag.id}
120
- className="inline-flex items-center gap-1 px-2 py-0.5 rounded bg-ods-accent text-ods-bg text-xs font-medium font-['DM_Sans']"
120
+ className="inline-flex items-center gap-1 pl-2.5 pr-1 py-1 rounded-md bg-ods-accent/15 border border-ods-accent/30 text-ods-text-primary text-[13px] leading-none font-medium font-['DM_Sans']"
121
121
  >
122
122
  {tag.name}
123
123
  {!disabled && (
124
- <Button
125
- variant="transparent"
124
+ <button
126
125
  type="button"
127
126
  onClick={(e) => {
128
127
  e.preventDefault();
129
128
  e.stopPropagation();
130
129
  handleTagRemove(tag.id);
131
130
  }}
132
- leftIcon={<X className="w-2.5 h-2.5" />}
133
- className="w-3 h-3 p-0 min-h-0 min-w-0 ml-0.5 hover:opacity-70 text-ods-bg hover:bg-transparent"
131
+ className="inline-flex items-center justify-center w-4 h-4 rounded-full text-ods-text-secondary hover:text-ods-text-primary hover:bg-ods-accent/20 transition-colors"
134
132
  aria-label={`Remove ${tag.name}`}
135
- />
133
+ >
134
+ <X className="w-3 h-3" />
135
+ </button>
136
136
  )}
137
137
  </span>
138
138
  ))}
@@ -26,6 +26,7 @@ import { VideoBitesDisplay } from '../features/video-bites-display'
26
26
  import { useVideoWarmup } from '../features/use-video-warmup'
27
27
  import { getCaptionsUrl } from '../features/captions-url'
28
28
  import { SimpleMarkdownRenderer } from '../ui/simple-markdown-renderer'
29
+ import { EntityTagBadges } from '../features/entity-tag-badges'
29
30
  import { LoadError } from '../ui/error-state'
30
31
  import { EntityAuthorCard } from '../chat/entity-cards/entity-author-card'
31
32
  import { OnboardingGuideCard } from '../chat/entity-cards/onboarding-guide-card'
@@ -128,6 +129,9 @@ export function OnboardingGuideDetailView({
128
129
 
129
130
  <h1 className="text-h1 tracking-[-1.12px] text-ods-text-primary">{guide.title}</h1>
130
131
 
132
+ {/* Tags — flat onboarding_guide_tags[] from entity_tags. */}
133
+ <EntityTagBadges tags={(guide as any).onboarding_guide_tags} />
134
+
131
135
  {/* Metadata grid — Section · Step | Published | Author. */}
132
136
  <EntityAuthorCard
133
137
  author={guide.author}
@@ -7,7 +7,7 @@ import { Card, CardContent } from '../../ui/card';
7
7
  import { ArticleDetailLayout } from '../../layout/article-detail-layout';
8
8
  import { BackButton } from '../../layout/back-button';
9
9
  import { ReleaseChangelogSection } from '../../ui/release-changelog-section';
10
- import { StatusBadge } from '../../ui/status-badge';
10
+ import { EntityTagBadges } from '../../features/entity-tag-badges';
11
11
  import { SquareAvatar } from '../../ui/square-avatar';
12
12
  import { ImageGalleryModal } from '../../ui/image-gallery-modal';
13
13
  import { GitHubIcon } from '../../icons/github-icon';
@@ -17,6 +17,7 @@ import { nameInitials } from '../../../utils/format';
17
17
  import { Video } from '../../features/video';
18
18
  import { DetailPageSkeleton } from '../detail-page-skeleton';
19
19
  import type { ChangelogEntry } from '../../../types/product-release';
20
+ import type { TagAssoc } from '../../../types/blog';
20
21
  import type { VideoTeaser } from '../../../types/video-processing';
21
22
 
22
23
  // Types for injectable components
@@ -202,7 +203,6 @@ export function ReleaseDetailPage({
202
203
  const releaseDate = release.release_date as string;
203
204
  const releaseType = release.release_type as string;
204
205
  const releaseStatus = release.release_status as string;
205
- const blogTags = release.blog_tags as Array<{ id?: string; name?: string; blog_tags?: { id: string; name: string } }> | undefined;
206
206
  const releaseMedia = release.release_media as Array<{ id?: string; media_type: string; media_url: string; title?: string }> | undefined;
207
207
  const author = release.author as { avatar_url?: string; full_name?: string } | undefined;
208
208
  const githubReleases = release.github_releases as Array<{ id: string; github_release_url: string }> | undefined;
@@ -246,18 +246,8 @@ export function ReleaseDetailPage({
246
246
  </div>
247
247
  </div>
248
248
 
249
- {/* Category Tags */}
250
- <div className="flex flex-wrap gap-2 w-full">
251
- {/* Blog Tags */}
252
- {blogTags?.map((tag) => (
253
- <StatusBadge
254
- key={tag.id || tag.blog_tags?.id}
255
- text={(tag.name || tag.blog_tags?.name || '').toUpperCase()}
256
- variant="card"
257
- className="bg-ods-card border border-ods-border"
258
- />
259
- ))}
260
- </div>
249
+ {/* Tags — flat product_release_tags[] from entity_tags */}
250
+ <EntityTagBadges tags={release.product_release_tags as TagAssoc[] | undefined} />
261
251
 
262
252
  {/* Metadata Grid */}
263
253
  <div className="grid grid-cols-1 md:grid-cols-4 border border-ods-border rounded-md overflow-hidden w-full">
@@ -45,7 +45,7 @@ export function useUnifiedFiltering(config: FilterConfig) {
45
45
  const search = searchParams?.get('search') || undefined
46
46
  const categories = searchParams?.get('category')?.split(',').filter(Boolean) || []
47
47
  const subcategories = searchParams?.get('subcategory')?.split(',').filter(Boolean) || []
48
- const tags = searchParams?.get('tag')?.split(',').filter(Boolean) || []
48
+ const tags = searchParams?.get('tags')?.split(',').filter(Boolean) || []
49
49
  const filters = searchParams?.getAll('filter') || []
50
50
  const pricing = searchParams?.get('pricing') || undefined
51
51
  const page = parseInt(searchParams?.get('page') || "1")
@@ -88,9 +88,10 @@ export function useUnifiedFiltering(config: FilterConfig) {
88
88
  params.set('subcategory', updatedState.subcategories.join(','))
89
89
  }
90
90
 
91
- // Add tag parameters (AND logic - all must match)
91
+ // Add tag parameters (AND logic - all must match). Unified `?tags=` param
92
+ // (matches blog/case-study/media/publication).
92
93
  if (updatedState.tags && updatedState.tags.length > 0 && config.supportedFilters.tags) {
93
- params.set('tag', updatedState.tags.join(','))
94
+ params.set('tags', updatedState.tags.join(','))
94
95
  }
95
96
 
96
97
  // Add filter parameters (AND logic - all must match)
package/src/types/blog.ts CHANGED
@@ -45,7 +45,8 @@ export interface BlogPost {
45
45
  };
46
46
  blog_post_platforms?: BlogPostPlatform[];
47
47
  blog_post_categories?: BlogPostCategory[];
48
- blog_post_tags?: BlogPostTag[];
48
+ // Flat unified tag-association shape (hydrated by entity-tag-utils).
49
+ blog_post_tags?: TagAssoc[];
49
50
  blog_media_assets?: BlogMediaAsset[];
50
51
  }
51
52
 
@@ -70,6 +71,19 @@ export interface BlogPostTag {
70
71
  blog_tags?: BlogTag;
71
72
  }
72
73
 
74
+ /**
75
+ * Flat per-entity tag association — the unified shape hydrated onto every
76
+ * taggable entity's `<entity>_tags[]` array (mirrors the platform `*_platforms`
77
+ * association shape). `tag_id` is always present; `id`/`name`/`slug` come from
78
+ * the embedded vocabulary row. Replaces the legacy nested `{ blog_tags: {...} }`.
79
+ */
80
+ export interface TagAssoc {
81
+ tag_id: number;
82
+ id?: number;
83
+ name?: string;
84
+ slug?: string;
85
+ }
86
+
73
87
  export interface BlogCategory {
74
88
  id: number;
75
89
  name: string;
@@ -2,7 +2,7 @@
2
2
  // Following the blog.ts pattern for consistency
3
3
 
4
4
  import type { PlatformRecord } from './platform'
5
- import type { BlogTag } from './blog'
5
+ import type { BlogTag, TagAssoc } from './blog'
6
6
  import type { MSP } from './stack'
7
7
  import type { UserProfile } from './user'
8
8
  import type { VideoTeaser, CustomerInterview } from './customer-interview'
@@ -64,10 +64,8 @@ export interface CaseStudy {
64
64
  is_featured: boolean
65
65
  featured_order: number | null
66
66
  }>
67
- case_study_tags?: Array<{
68
- tag_id: number
69
- }>
70
- blog_tags?: BlogTag[]
67
+ // Flat unified tag-association shape (hydrated by entity-tag-utils).
68
+ case_study_tags?: TagAssoc[]
71
69
  }
72
70
 
73
71
  export interface CreateCaseStudyData {
@@ -2,7 +2,7 @@
2
2
  // Following the blog.ts pattern for consistency
3
3
 
4
4
  import type { PlatformRecord } from './platform'
5
- import type { BlogTag } from './blog'
5
+ import type { BlogTag, TagAssoc } from './blog'
6
6
  import type { VideoTeaser, TranscriptWord, SpeakerMapping } from './video-processing'
7
7
 
8
8
  export interface ChangelogEntry {
@@ -162,10 +162,8 @@ export interface ProductRelease {
162
162
  name?: string
163
163
  display_name?: string
164
164
  }>
165
- product_release_tags?: Array<{
166
- tag_id: number
167
- }>
168
- blog_tags?: BlogTag[]
165
+ // Flat unified tag-association shape (hydrated by entity-tag-utils).
166
+ product_release_tags?: TagAssoc[]
169
167
  }
170
168
 
171
169
  export interface CreateProductReleaseData {
@@ -61,7 +61,6 @@ export type Database = {
61
61
  icon_type: string | null
62
62
  id: string
63
63
  is_active: boolean | null
64
- platform_id: string | null
65
64
  title: string
66
65
  updated_at: string | null
67
66
  }
@@ -75,7 +74,6 @@ export type Database = {
75
74
  icon_type?: string | null
76
75
  id?: string
77
76
  is_active?: boolean | null
78
- platform_id?: string | null
79
77
  title: string
80
78
  updated_at?: string | null
81
79
  }
@@ -89,18 +87,10 @@ export type Database = {
89
87
  icon_type?: string | null
90
88
  id?: string
91
89
  is_active?: boolean | null
92
- platform_id?: string | null
93
90
  title?: string
94
91
  updated_at?: string | null
95
92
  }
96
93
  Relationships: [
97
- {
98
- foreignKeyName: "announcements_platform_id_fkey"
99
- columns: ["platform_id"]
100
- isOneToOne: false
101
- referencedRelation: "platforms"
102
- referencedColumns: ["id"]
103
- },
104
94
  ]
105
95
  }
106
96
  slack_channels: {
@@ -299,7 +289,6 @@ export type Database = {
299
289
  published_at: string | null
300
290
  external_url: string | null
301
291
  hosts: Json | null
302
- platform_id: string
303
292
  is_deleted: boolean | null
304
293
  last_synced_at: string | null
305
294
  created_at: string | null
@@ -320,7 +309,6 @@ export type Database = {
320
309
  published_at?: string | null
321
310
  external_url?: string | null
322
311
  hosts?: Json | null
323
- platform_id: string
324
312
  is_deleted?: boolean | null
325
313
  last_synced_at?: string | null
326
314
  created_at?: string | null
@@ -341,20 +329,12 @@ export type Database = {
341
329
  published_at?: string | null
342
330
  external_url?: string | null
343
331
  hosts?: Json | null
344
- platform_id?: string
345
332
  is_deleted?: boolean | null
346
333
  last_synced_at?: string | null
347
334
  created_at?: string | null
348
335
  updated_at?: string | null
349
336
  }
350
337
  Relationships: [
351
- {
352
- foreignKeyName: "podcast_episodes_platform_id_fkey"
353
- columns: ["platform_id"]
354
- isOneToOne: false
355
- referencedRelation: "platforms"
356
- referencedColumns: ["id"]
357
- },
358
338
  ]
359
339
  }
360
340
  webinars: {
@@ -370,7 +350,6 @@ export type Database = {
370
350
  registration_url: string | null
371
351
  main_video_url: string | null
372
352
  hosts: Json | null
373
- platform_id: string
374
353
  is_deleted: boolean | null
375
354
  last_synced_at: string | null
376
355
  created_at: string | null
@@ -388,7 +367,6 @@ export type Database = {
388
367
  registration_url?: string | null
389
368
  main_video_url?: string | null
390
369
  hosts?: Json | null
391
- platform_id: string
392
370
  is_deleted?: boolean | null
393
371
  last_synced_at?: string | null
394
372
  created_at?: string | null
@@ -406,20 +384,12 @@ export type Database = {
406
384
  registration_url?: string | null
407
385
  main_video_url?: string | null
408
386
  hosts?: Json | null
409
- platform_id?: string
410
387
  is_deleted?: boolean | null
411
388
  last_synced_at?: string | null
412
389
  created_at?: string | null
413
390
  updated_at?: string | null
414
391
  }
415
392
  Relationships: [
416
- {
417
- foreignKeyName: "webinars_platform_id_fkey"
418
- columns: ["platform_id"]
419
- isOneToOne: false
420
- referencedRelation: "platforms"
421
- referencedColumns: ["id"]
422
- },
423
393
  ]
424
394
  }
425
395
  luma_events: {
@@ -445,7 +415,6 @@ export type Database = {
445
415
  registration_questions: Json | null
446
416
  tags: string[] | null
447
417
  guest_count: number | null
448
- platform_id: string
449
418
  is_deleted: boolean | null
450
419
  last_synced_at: string | null
451
420
  created_at: string | null
@@ -473,7 +442,6 @@ export type Database = {
473
442
  registration_questions?: Json | null
474
443
  tags?: string[] | null
475
444
  guest_count?: number | null
476
- platform_id: string
477
445
  is_deleted?: boolean | null
478
446
  last_synced_at?: string | null
479
447
  created_at?: string | null
@@ -501,20 +469,12 @@ export type Database = {
501
469
  registration_questions?: Json | null
502
470
  tags?: string[] | null
503
471
  guest_count?: number | null
504
- platform_id?: string
505
472
  is_deleted?: boolean | null
506
473
  last_synced_at?: string | null
507
474
  created_at?: string | null
508
475
  updated_at?: string | null
509
476
  }
510
477
  Relationships: [
511
- {
512
- foreignKeyName: "luma_events_platform_id_fkey"
513
- columns: ["platform_id"]
514
- isOneToOne: false
515
- referencedRelation: "platforms"
516
- referencedColumns: ["id"]
517
- },
518
478
  ]
519
479
  }
520
480
  vendor_github_stats: {