clhq-postgres-module 1.1.0-alpha.172 → 1.1.0-alpha.174

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 (107) hide show
  1. package/dist/config/data-source.local.d.ts +3 -0
  2. package/dist/config/data-source.local.js +15 -0
  3. package/dist/migrations/1713000000001-InitialSchema.d.ts +6 -0
  4. package/dist/migrations/1713000000001-InitialSchema.js +196 -0
  5. package/dist/migrations/1713000000002-CoreBusinessTables.d.ts +6 -0
  6. package/dist/migrations/1713000000002-CoreBusinessTables.js +198 -0
  7. package/dist/migrations/1713000000003-RemainingCoreTables.d.ts +6 -0
  8. package/dist/migrations/1713000000003-RemainingCoreTables.js +160 -0
  9. package/dist/migrations/1713000000004-MediaConfigReferenceTables.d.ts +6 -0
  10. package/dist/migrations/1713000000004-MediaConfigReferenceTables.js +241 -0
  11. package/dist/migrations/1713000000005-VideoMediaTables.d.ts +6 -0
  12. package/dist/migrations/1713000000005-VideoMediaTables.js +98 -0
  13. package/dist/migrations/1713000000006-AddUserReferralColumns.d.ts +6 -0
  14. package/dist/migrations/1713000000006-AddUserReferralColumns.js +55 -0
  15. package/dist/migrations/1713000000007-AddUserProfileColumns.d.ts +6 -0
  16. package/dist/migrations/1713000000007-AddUserProfileColumns.js +73 -0
  17. package/dist/migrations/1713000000008-AddBillingInfoColumn.d.ts +6 -0
  18. package/dist/migrations/1713000000008-AddBillingInfoColumn.js +23 -0
  19. package/dist/migrations/1713000000009-AddWorkspaceStorageColumns.d.ts +6 -0
  20. package/dist/migrations/1713000000009-AddWorkspaceStorageColumns.js +49 -0
  21. package/dist/migrations/1713000000010-AddUniqueIdToAssets.d.ts +6 -0
  22. package/dist/migrations/1713000000010-AddUniqueIdToAssets.js +29 -0
  23. package/dist/migrations/{1713000000003-AddDescriptionToBrandKits.d.ts → 1713000000011-CreateReferralEventsTable.d.ts} +1 -1
  24. package/dist/migrations/1713000000011-CreateReferralEventsTable.js +72 -0
  25. package/dist/migrations/1713000000012-ExtendCreditTransactions.d.ts +6 -0
  26. package/dist/migrations/1713000000012-ExtendCreditTransactions.js +70 -0
  27. package/dist/migrations/1713000000013-AiVideoMakerTables.d.ts +6 -0
  28. package/dist/migrations/1713000000013-AiVideoMakerTables.js +122 -0
  29. package/dist/migrations/1713000000014-SeedReferralRewardRules.d.ts +6 -0
  30. package/dist/migrations/1713000000014-SeedReferralRewardRules.js +135 -0
  31. package/dist/migrations/{1713000000001-CreateSocialConnectionTables.d.ts → 1713000000015-CreateCreditAllocationsTable.d.ts} +1 -1
  32. package/dist/migrations/1713000000015-CreateCreditAllocationsTable.js +49 -0
  33. package/dist/migrations/1713000000016-CreateCreditConsumptionLogTable.d.ts +6 -0
  34. package/dist/migrations/1713000000016-CreateCreditConsumptionLogTable.js +55 -0
  35. package/dist/migrations/1713000000017-UpdateSubscriptionPlansCreditFields.d.ts +6 -0
  36. package/dist/migrations/1713000000017-UpdateSubscriptionPlansCreditFields.js +121 -0
  37. package/dist/migrations/1713000000018-CreateVideoProcessingTables.d.ts +6 -0
  38. package/dist/migrations/1713000000018-CreateVideoProcessingTables.js +111 -0
  39. package/dist/migrations/1713000000019-CreateAudioWaveformsTable.d.ts +6 -0
  40. package/dist/migrations/1713000000019-CreateAudioWaveformsTable.js +62 -0
  41. package/dist/migrations/1713000000020-EnablePgvectorExtension.d.ts +6 -0
  42. package/dist/migrations/1713000000020-EnablePgvectorExtension.js +30 -0
  43. package/dist/migrations/1713000000021-CreateMetadataServiceTables.d.ts +6 -0
  44. package/dist/migrations/1713000000021-CreateMetadataServiceTables.js +410 -0
  45. package/dist/migrations/1713000000022-OptimizeMetadataIndexes.d.ts +6 -0
  46. package/dist/migrations/1713000000022-OptimizeMetadataIndexes.js +334 -0
  47. package/dist/migrations/1713000000023-CreateSceneGeneratorTables.d.ts +6 -0
  48. package/dist/migrations/1713000000023-CreateSceneGeneratorTables.js +97 -0
  49. package/dist/migrations/1713000000024-CreateRemotionRendersTable.d.ts +6 -0
  50. package/dist/migrations/1713000000024-CreateRemotionRendersTable.js +71 -0
  51. package/dist/migrations/1713000000025-ExtendCreditAllocationSystem.d.ts +6 -0
  52. package/dist/migrations/1713000000025-ExtendCreditAllocationSystem.js +114 -0
  53. package/dist/migrations/{1713000000002-AddIsActiveToWorkspaceMembers.d.ts → 1713000000026-AddStatusToCreditTransactions.d.ts} +1 -1
  54. package/dist/migrations/1713000000026-AddStatusToCreditTransactions.js +63 -0
  55. package/dist/migrations/1713000000027-MigrateProjectDurationToSeconds.d.ts +6 -0
  56. package/dist/migrations/1713000000027-MigrateProjectDurationToSeconds.js +43 -0
  57. package/dist/migrations/1713000000028-CreateSceneTimelineTables.d.ts +6 -0
  58. package/dist/migrations/1713000000028-CreateSceneTimelineTables.js +159 -0
  59. package/dist/migrations/1713000000029-ConvertScenesToSeconds.d.ts +6 -0
  60. package/dist/migrations/1713000000029-ConvertScenesToSeconds.js +106 -0
  61. package/dist/migrations/1713000000030-ChangeDurationToDecimal.d.ts +6 -0
  62. package/dist/migrations/1713000000030-ChangeDurationToDecimal.js +34 -0
  63. package/dist/migrations/1713000000031-CreateVideoSubtitlesTable.d.ts +6 -0
  64. package/dist/migrations/1713000000031-CreateVideoSubtitlesTable.js +51 -0
  65. package/dist/migrations/1713000000032-AddWebpThumbnailColumns.d.ts +6 -0
  66. package/dist/migrations/1713000000032-AddWebpThumbnailColumns.js +58 -0
  67. package/dist/migrations/1713000000033-AddFormatToProjectScenes.d.ts +6 -0
  68. package/dist/migrations/1713000000033-AddFormatToProjectScenes.js +77 -0
  69. package/dist/migrations/1713000000034-FixProjectScenesUniqueConstraint.d.ts +6 -0
  70. package/dist/migrations/1713000000034-FixProjectScenesUniqueConstraint.js +39 -0
  71. package/dist/migrations/1713000000035-AddMissingVideoSubtitlesColumns.d.ts +6 -0
  72. package/dist/migrations/1713000000035-AddMissingVideoSubtitlesColumns.js +29 -0
  73. package/dist/migrations/1713000000036-AddRemotionRenderCreditColumns.d.ts +6 -0
  74. package/dist/migrations/1713000000036-AddRemotionRenderCreditColumns.js +50 -0
  75. package/dist/migrations/1713000000037-CreateProjectSharesTable.d.ts +6 -0
  76. package/dist/migrations/1713000000037-CreateProjectSharesTable.js +60 -0
  77. package/dist/migrations/1713000000038-EnableRlsOnAllTables.d.ts +6 -0
  78. package/dist/migrations/1713000000038-EnableRlsOnAllTables.js +97 -0
  79. package/dist/migrations/1713000000039-AiVideoMakerKlingFreeColumns.d.ts +6 -0
  80. package/dist/migrations/1713000000039-AiVideoMakerKlingFreeColumns.js +85 -0
  81. package/dist/migrations/1713000000040-CreateBrandKitsTable.d.ts +6 -0
  82. package/dist/migrations/1713000000040-CreateBrandKitsTable.js +44 -0
  83. package/dist/migrations/1713000000041-CreateBrandAssetsTable.d.ts +6 -0
  84. package/dist/migrations/1713000000041-CreateBrandAssetsTable.js +57 -0
  85. package/dist/migrations/1713000000042-AddActiveBrandKitToWorkspaces.d.ts +6 -0
  86. package/dist/migrations/1713000000042-AddActiveBrandKitToWorkspaces.js +43 -0
  87. package/dist/migrations/1713000000043-CreateAssetCategoriesTable.d.ts +6 -0
  88. package/dist/migrations/1713000000043-CreateAssetCategoriesTable.js +47 -0
  89. package/dist/migrations/1713000000044-AddEnforcementModeToWorkspaces.d.ts +6 -0
  90. package/dist/migrations/1713000000044-AddEnforcementModeToWorkspaces.js +21 -0
  91. package/dist/migrations/1713000000045-CreateProjectBrandOverridesTable.d.ts +6 -0
  92. package/dist/migrations/1713000000045-CreateProjectBrandOverridesTable.js +33 -0
  93. package/dist/migrations/1713000000046-AddPdfRenderSupport.d.ts +6 -0
  94. package/dist/migrations/1713000000046-AddPdfRenderSupport.js +14 -0
  95. package/dist/migrations/1713000000047-CreateSocialConnectionTables.d.ts +6 -0
  96. package/dist/migrations/{1713000000001-CreateSocialConnectionTables.js → 1713000000047-CreateSocialConnectionTables.js} +4 -4
  97. package/dist/migrations/1713000000048-AddIsActiveToWorkspaceMembers.d.ts +6 -0
  98. package/dist/migrations/{1713000000002-AddIsActiveToWorkspaceMembers.js → 1713000000048-AddIsActiveToWorkspaceMembers.js} +4 -4
  99. package/dist/migrations/1713000000049-AddDescriptionToBrandKits.d.ts +6 -0
  100. package/dist/migrations/{1713000000003-AddDescriptionToBrandKits.js → 1713000000049-AddDescriptionToBrandKits.js} +4 -4
  101. package/dist/migrations/1713000000050-CreateKlingGenerationTables.d.ts +6 -0
  102. package/dist/migrations/1713000000050-CreateKlingGenerationTables.js +76 -0
  103. package/dist/migrations/1713000000051-AddAiVideoSceneCanvasIdsAndThumbnail.d.ts +6 -0
  104. package/dist/migrations/1713000000051-AddAiVideoSceneCanvasIdsAndThumbnail.js +49 -0
  105. package/dist/migrations/1713000000052-AddAiVideoSourceMetadataAndMusicMeta.d.ts +6 -0
  106. package/dist/migrations/1713000000052-AddAiVideoSourceMetadataAndMusicMeta.js +67 -0
  107. package/package.json +8 -1
@@ -0,0 +1,334 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OptimizeMetadataIndexes1713000000022 = void 0;
4
+ class OptimizeMetadataIndexes1713000000022 {
5
+ constructor() {
6
+ this.name = 'OptimizeMetadataIndexes1713000000022';
7
+ }
8
+ async up(queryRunner) {
9
+ await queryRunner.query(`
10
+ ALTER TABLE asset_metadata
11
+ ADD COLUMN IF NOT EXISTS content_embedding_vec vector(1536);
12
+ `);
13
+ await queryRunner.query(`
14
+ UPDATE asset_metadata
15
+ SET content_embedding_vec = (
16
+ SELECT array_agg(elem::float)::vector(1536)
17
+ FROM jsonb_array_elements_text(content_embedding) AS elem
18
+ )
19
+ WHERE content_embedding IS NOT NULL
20
+ AND jsonb_typeof(content_embedding) = 'array'
21
+ AND content_embedding_vec IS NULL;
22
+ `);
23
+ await queryRunner.query(`
24
+ CREATE INDEX IF NOT EXISTS idx_asset_metadata_embedding_hnsw
25
+ ON asset_metadata
26
+ USING hnsw (content_embedding_vec vector_cosine_ops)
27
+ WITH (m = 16, ef_construction = 64);
28
+ `);
29
+ await queryRunner.query(`
30
+ ALTER TABLE project_metadata
31
+ ADD COLUMN IF NOT EXISTS project_embedding_vec vector(1536);
32
+ `);
33
+ await queryRunner.query(`
34
+ UPDATE project_metadata
35
+ SET project_embedding_vec = (
36
+ SELECT array_agg(elem::float)::vector(1536)
37
+ FROM jsonb_array_elements_text(project_embedding) AS elem
38
+ )
39
+ WHERE project_embedding IS NOT NULL
40
+ AND jsonb_typeof(project_embedding) = 'array'
41
+ AND project_embedding_vec IS NULL;
42
+ `);
43
+ await queryRunner.query(`
44
+ CREATE INDEX IF NOT EXISTS idx_project_metadata_embedding_hnsw
45
+ ON project_metadata
46
+ USING hnsw (project_embedding_vec vector_cosine_ops)
47
+ WITH (m = 16, ef_construction = 64);
48
+ `);
49
+ await queryRunner.query(`
50
+ ALTER TABLE ai_embeddings
51
+ ADD COLUMN IF NOT EXISTS embedding_vec vector(1536);
52
+ `);
53
+ await queryRunner.query(`
54
+ UPDATE ai_embeddings
55
+ SET embedding_vec = (
56
+ SELECT array_agg(elem::float)::vector(1536)
57
+ FROM jsonb_array_elements_text(embedding) AS elem
58
+ )
59
+ WHERE embedding IS NOT NULL
60
+ AND jsonb_typeof(embedding) = 'array'
61
+ AND embedding_vec IS NULL;
62
+ `);
63
+ await queryRunner.query(`
64
+ CREATE INDEX IF NOT EXISTS idx_ai_embeddings_vec_hnsw
65
+ ON ai_embeddings
66
+ USING hnsw (embedding_vec vector_cosine_ops)
67
+ WITH (m = 16, ef_construction = 64);
68
+ `);
69
+ await queryRunner.query(`
70
+ CREATE INDEX IF NOT EXISTS idx_asset_metadata_user_status
71
+ ON asset_metadata(user_id, status);
72
+ `);
73
+ await queryRunner.query(`
74
+ CREATE INDEX IF NOT EXISTS idx_asset_metadata_user_category
75
+ ON asset_metadata(user_id, category);
76
+ `);
77
+ await queryRunner.query(`
78
+ CREATE INDEX IF NOT EXISTS idx_asset_metadata_workspace_status
79
+ ON asset_metadata(workspace_id, status);
80
+ `);
81
+ await queryRunner.query(`
82
+ CREATE INDEX IF NOT EXISTS idx_asset_metadata_user_last_used
83
+ ON asset_metadata(user_id, last_used_at DESC NULLS LAST);
84
+ `);
85
+ await queryRunner.query(`
86
+ CREATE INDEX IF NOT EXISTS idx_asset_metadata_user_usage
87
+ ON asset_metadata(user_id, usage_count DESC);
88
+ `);
89
+ await queryRunner.query(`
90
+ CREATE INDEX IF NOT EXISTS idx_project_metadata_user_updated
91
+ ON project_metadata(user_id, updated_at DESC);
92
+ `);
93
+ await queryRunner.query(`
94
+ CREATE INDEX IF NOT EXISTS idx_project_metadata_workspace_mood
95
+ ON project_metadata(workspace_id, mood);
96
+ `);
97
+ await queryRunner.query(`
98
+ CREATE INDEX IF NOT EXISTS idx_ai_embeddings_user_entity_type
99
+ ON ai_embeddings(user_id, entity_type);
100
+ `);
101
+ await queryRunner.query(`
102
+ CREATE INDEX IF NOT EXISTS idx_activity_user_action_created
103
+ ON metadata_activity_log(user_id, action, created_at DESC);
104
+ `);
105
+ await queryRunner.query(`
106
+ CREATE INDEX IF NOT EXISTS idx_activity_entity_created
107
+ ON metadata_activity_log(entity_type, entity_id, created_at DESC);
108
+ `);
109
+ await queryRunner.query(`
110
+ CREATE INDEX IF NOT EXISTS idx_asset_metadata_completed
111
+ ON asset_metadata(user_id, updated_at DESC)
112
+ WHERE status = 'completed';
113
+ `);
114
+ await queryRunner.query(`
115
+ CREATE INDEX IF NOT EXISTS idx_asset_metadata_with_embeddings
116
+ ON asset_metadata(user_id)
117
+ WHERE content_embedding_vec IS NOT NULL;
118
+ `);
119
+ await queryRunner.query(`
120
+ CREATE OR REPLACE FUNCTION search_similar_assets_optimized(
121
+ query_embedding vector(1536),
122
+ p_user_id UUID,
123
+ p_limit INTEGER DEFAULT 20,
124
+ p_min_similarity FLOAT DEFAULT 0.5
125
+ )
126
+ RETURNS TABLE (
127
+ asset_id UUID,
128
+ similarity FLOAT,
129
+ category TEXT,
130
+ tags TEXT[],
131
+ description TEXT,
132
+ usage_count INTEGER,
133
+ last_used_at TIMESTAMP WITH TIME ZONE
134
+ ) AS $$
135
+ BEGIN
136
+ RETURN QUERY
137
+ SELECT
138
+ am.asset_id,
139
+ (1 - (am.content_embedding_vec <=> query_embedding))::FLOAT as similarity,
140
+ am.category,
141
+ am.tags,
142
+ am.description,
143
+ am.usage_count,
144
+ am.last_used_at
145
+ FROM asset_metadata am
146
+ WHERE am.user_id = p_user_id
147
+ AND am.content_embedding_vec IS NOT NULL
148
+ AND (1 - (am.content_embedding_vec <=> query_embedding)) >= p_min_similarity
149
+ ORDER BY am.content_embedding_vec <=> query_embedding
150
+ LIMIT p_limit;
151
+ END;
152
+ $$ LANGUAGE plpgsql;
153
+ `);
154
+ await queryRunner.query(`
155
+ CREATE OR REPLACE FUNCTION search_similar_projects_optimized(
156
+ query_embedding vector(1536),
157
+ p_user_id UUID,
158
+ p_limit INTEGER DEFAULT 10,
159
+ p_min_similarity FLOAT DEFAULT 0.5
160
+ )
161
+ RETURNS TABLE (
162
+ project_id VARCHAR(255),
163
+ similarity FLOAT,
164
+ project_type VARCHAR(100),
165
+ mood VARCHAR(100),
166
+ style VARCHAR(100),
167
+ genre VARCHAR(100)
168
+ ) AS $$
169
+ BEGIN
170
+ RETURN QUERY
171
+ SELECT
172
+ pm.project_id,
173
+ (1 - (pm.project_embedding_vec <=> query_embedding))::FLOAT as similarity,
174
+ pm.project_type,
175
+ pm.mood,
176
+ pm.style,
177
+ pm.genre
178
+ FROM project_metadata pm
179
+ WHERE pm.user_id = p_user_id
180
+ AND pm.project_embedding_vec IS NOT NULL
181
+ AND (1 - (pm.project_embedding_vec <=> query_embedding)) >= p_min_similarity
182
+ ORDER BY pm.project_embedding_vec <=> query_embedding
183
+ LIMIT p_limit;
184
+ END;
185
+ $$ LANGUAGE plpgsql;
186
+ `);
187
+ await queryRunner.query(`
188
+ CREATE OR REPLACE FUNCTION search_embeddings_by_type(
189
+ query_embedding vector(1536),
190
+ p_entity_type embedding_entity_type,
191
+ p_user_id UUID DEFAULT NULL,
192
+ p_limit INTEGER DEFAULT 20,
193
+ p_min_similarity FLOAT DEFAULT 0.5
194
+ )
195
+ RETURNS TABLE (
196
+ entity_id VARCHAR(255),
197
+ similarity FLOAT,
198
+ source_text TEXT,
199
+ metadata JSONB
200
+ ) AS $$
201
+ BEGIN
202
+ RETURN QUERY
203
+ SELECT
204
+ ae.entity_id,
205
+ (1 - (ae.embedding_vec <=> query_embedding))::FLOAT as similarity,
206
+ ae.source_text,
207
+ ae.metadata
208
+ FROM ai_embeddings ae
209
+ WHERE ae.entity_type = p_entity_type
210
+ AND ae.embedding_vec IS NOT NULL
211
+ AND (p_user_id IS NULL OR ae.user_id = p_user_id)
212
+ AND (1 - (ae.embedding_vec <=> query_embedding)) >= p_min_similarity
213
+ ORDER BY ae.embedding_vec <=> query_embedding
214
+ LIMIT p_limit;
215
+ END;
216
+ $$ LANGUAGE plpgsql;
217
+ `);
218
+ await queryRunner.query(`
219
+ CREATE OR REPLACE FUNCTION sync_embedding_vector()
220
+ RETURNS TRIGGER AS $$
221
+ DECLARE
222
+ vec_result vector(1536);
223
+ BEGIN
224
+ IF TG_TABLE_NAME = 'asset_metadata' THEN
225
+ IF NEW.content_embedding IS NOT NULL AND jsonb_typeof(NEW.content_embedding) = 'array' THEN
226
+ SELECT array_agg(elem::float)::vector(1536) INTO vec_result
227
+ FROM jsonb_array_elements_text(NEW.content_embedding) AS elem;
228
+ NEW.content_embedding_vec := vec_result;
229
+ ELSE
230
+ NEW.content_embedding_vec := NULL;
231
+ END IF;
232
+ ELSIF TG_TABLE_NAME = 'project_metadata' THEN
233
+ IF NEW.project_embedding IS NOT NULL AND jsonb_typeof(NEW.project_embedding) = 'array' THEN
234
+ SELECT array_agg(elem::float)::vector(1536) INTO vec_result
235
+ FROM jsonb_array_elements_text(NEW.project_embedding) AS elem;
236
+ NEW.project_embedding_vec := vec_result;
237
+ ELSE
238
+ NEW.project_embedding_vec := NULL;
239
+ END IF;
240
+ ELSIF TG_TABLE_NAME = 'ai_embeddings' THEN
241
+ IF NEW.embedding IS NOT NULL AND jsonb_typeof(NEW.embedding) = 'array' THEN
242
+ SELECT array_agg(elem::float)::vector(1536) INTO vec_result
243
+ FROM jsonb_array_elements_text(NEW.embedding) AS elem;
244
+ NEW.embedding_vec := vec_result;
245
+ ELSE
246
+ NEW.embedding_vec := NULL;
247
+ END IF;
248
+ END IF;
249
+ RETURN NEW;
250
+ END;
251
+ $$ LANGUAGE plpgsql;
252
+ `);
253
+ await queryRunner.query(`
254
+ DROP TRIGGER IF EXISTS sync_asset_metadata_embedding ON asset_metadata;
255
+ CREATE TRIGGER sync_asset_metadata_embedding
256
+ BEFORE INSERT OR UPDATE OF content_embedding ON asset_metadata
257
+ FOR EACH ROW
258
+ EXECUTE FUNCTION sync_embedding_vector();
259
+ `);
260
+ await queryRunner.query(`
261
+ DROP TRIGGER IF EXISTS sync_project_metadata_embedding ON project_metadata;
262
+ CREATE TRIGGER sync_project_metadata_embedding
263
+ BEFORE INSERT OR UPDATE OF project_embedding ON project_metadata
264
+ FOR EACH ROW
265
+ EXECUTE FUNCTION sync_embedding_vector();
266
+ `);
267
+ await queryRunner.query(`
268
+ DROP TRIGGER IF EXISTS sync_ai_embeddings_embedding ON ai_embeddings;
269
+ CREATE TRIGGER sync_ai_embeddings_embedding
270
+ BEFORE INSERT OR UPDATE OF embedding ON ai_embeddings
271
+ FOR EACH ROW
272
+ EXECUTE FUNCTION sync_embedding_vector();
273
+ `);
274
+ await queryRunner.query(`
275
+ CREATE OR REPLACE VIEW v_embedding_stats AS
276
+ SELECT
277
+ 'asset_metadata' as table_name,
278
+ COUNT(*) as total_records,
279
+ COUNT(content_embedding_vec) as records_with_embeddings,
280
+ ROUND(100.0 * COUNT(content_embedding_vec) / NULLIF(COUNT(*), 0), 2) as embedding_coverage_pct
281
+ FROM asset_metadata
282
+ UNION ALL
283
+ SELECT
284
+ 'project_metadata' as table_name,
285
+ COUNT(*) as total_records,
286
+ COUNT(project_embedding_vec) as records_with_embeddings,
287
+ ROUND(100.0 * COUNT(project_embedding_vec) / NULLIF(COUNT(*), 0), 2) as embedding_coverage_pct
288
+ FROM project_metadata
289
+ UNION ALL
290
+ SELECT
291
+ 'ai_embeddings' as table_name,
292
+ COUNT(*) as total_records,
293
+ COUNT(embedding_vec) as records_with_embeddings,
294
+ ROUND(100.0 * COUNT(embedding_vec) / NULLIF(COUNT(*), 0), 2) as embedding_coverage_pct
295
+ FROM ai_embeddings;
296
+ `);
297
+ await queryRunner.query(`COMMENT ON COLUMN asset_metadata.content_embedding_vec IS 'Native vector column for HNSW-indexed similarity search'`);
298
+ await queryRunner.query(`COMMENT ON COLUMN project_metadata.project_embedding_vec IS 'Native vector column for HNSW-indexed similarity search'`);
299
+ await queryRunner.query(`COMMENT ON COLUMN ai_embeddings.embedding_vec IS 'Native vector column for HNSW-indexed similarity search'`);
300
+ await queryRunner.query(`COMMENT ON FUNCTION search_similar_assets_optimized IS 'Optimized asset search using HNSW index with minimum similarity threshold'`);
301
+ await queryRunner.query(`COMMENT ON FUNCTION search_similar_projects_optimized IS 'Optimized project search using HNSW index with minimum similarity threshold'`);
302
+ await queryRunner.query(`COMMENT ON FUNCTION search_embeddings_by_type IS 'Generic embedding search by entity type with optional user filter'`);
303
+ await queryRunner.query(`COMMENT ON VIEW v_embedding_stats IS 'Monitoring view for embedding coverage across tables'`);
304
+ }
305
+ async down(queryRunner) {
306
+ await queryRunner.query(`DROP TRIGGER IF EXISTS sync_asset_metadata_embedding ON asset_metadata`);
307
+ await queryRunner.query(`DROP TRIGGER IF EXISTS sync_project_metadata_embedding ON project_metadata`);
308
+ await queryRunner.query(`DROP TRIGGER IF EXISTS sync_ai_embeddings_embedding ON ai_embeddings`);
309
+ await queryRunner.query(`DROP FUNCTION IF EXISTS sync_embedding_vector`);
310
+ await queryRunner.query(`DROP FUNCTION IF EXISTS search_similar_assets_optimized`);
311
+ await queryRunner.query(`DROP FUNCTION IF EXISTS search_similar_projects_optimized`);
312
+ await queryRunner.query(`DROP FUNCTION IF EXISTS search_embeddings_by_type`);
313
+ await queryRunner.query(`DROP VIEW IF EXISTS v_embedding_stats`);
314
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_asset_metadata_embedding_hnsw`);
315
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_project_metadata_embedding_hnsw`);
316
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_ai_embeddings_vec_hnsw`);
317
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_asset_metadata_user_status`);
318
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_asset_metadata_user_category`);
319
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_asset_metadata_workspace_status`);
320
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_asset_metadata_user_last_used`);
321
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_asset_metadata_user_usage`);
322
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_project_metadata_user_updated`);
323
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_project_metadata_workspace_mood`);
324
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_ai_embeddings_user_entity_type`);
325
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_activity_user_action_created`);
326
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_activity_entity_created`);
327
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_asset_metadata_completed`);
328
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_asset_metadata_with_embeddings`);
329
+ await queryRunner.query(`ALTER TABLE asset_metadata DROP COLUMN IF EXISTS content_embedding_vec`);
330
+ await queryRunner.query(`ALTER TABLE project_metadata DROP COLUMN IF EXISTS project_embedding_vec`);
331
+ await queryRunner.query(`ALTER TABLE ai_embeddings DROP COLUMN IF EXISTS embedding_vec`);
332
+ }
333
+ }
334
+ exports.OptimizeMetadataIndexes1713000000022 = OptimizeMetadataIndexes1713000000022;
@@ -0,0 +1,6 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ export declare class CreateSceneGeneratorTables1713000000023 implements MigrationInterface {
3
+ name: string;
4
+ up(queryRunner: QueryRunner): Promise<void>;
5
+ down(queryRunner: QueryRunner): Promise<void>;
6
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreateSceneGeneratorTables1713000000023 = void 0;
4
+ class CreateSceneGeneratorTables1713000000023 {
5
+ constructor() {
6
+ this.name = 'CreateSceneGeneratorTables1713000000023';
7
+ }
8
+ async up(queryRunner) {
9
+ await queryRunner.query(`
10
+ DO $$ BEGIN
11
+ CREATE TYPE project_scene_job_status AS ENUM ('NEW', 'PROCESSING', 'SUCCESS', 'ERROR');
12
+ EXCEPTION
13
+ WHEN duplicate_object THEN null;
14
+ END $$;
15
+ `);
16
+ await queryRunner.query(`
17
+ DO $$ BEGIN
18
+ CREATE TYPE project_scene_status AS ENUM ('PENDING', 'GENERATING', 'READY', 'FAILED');
19
+ EXCEPTION
20
+ WHEN duplicate_object THEN null;
21
+ END $$;
22
+ `);
23
+ await queryRunner.query(`
24
+ CREATE TABLE project_scene_jobs (
25
+ id VARCHAR(255) PRIMARY KEY,
26
+ project_id VARCHAR(255) NOT NULL,
27
+ user_id UUID NOT NULL REFERENCES users(id),
28
+ workspace_id UUID,
29
+ status project_scene_job_status DEFAULT 'NEW',
30
+ total_scenes INTEGER DEFAULT 0,
31
+ completed_scenes INTEGER DEFAULT 0,
32
+ failed_scenes INTEGER DEFAULT 0,
33
+ interval_seconds INTEGER DEFAULT 5,
34
+ duration_ms INTEGER,
35
+ data JSONB,
36
+ error_message TEXT,
37
+ started_at TIMESTAMP,
38
+ completed_at TIMESTAMP,
39
+ created_at TIMESTAMP DEFAULT NOW(),
40
+ updated_at TIMESTAMP DEFAULT NOW()
41
+ );
42
+ `);
43
+ await queryRunner.query(`
44
+ CREATE TABLE project_scenes (
45
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
46
+ project_id VARCHAR(255) NOT NULL,
47
+ job_id VARCHAR(255) REFERENCES project_scene_jobs(id),
48
+ timestamp FLOAT NOT NULL,
49
+ status project_scene_status DEFAULT 'PENDING',
50
+ s3_url TEXT,
51
+ s3_key TEXT,
52
+ file_size INTEGER,
53
+ width INTEGER,
54
+ height INTEGER,
55
+ generation_time_ms INTEGER,
56
+ error_message TEXT,
57
+ metadata JSONB,
58
+ created_at TIMESTAMP DEFAULT NOW(),
59
+ updated_at TIMESTAMP DEFAULT NOW(),
60
+ UNIQUE(project_id, timestamp)
61
+ );
62
+ `);
63
+ await queryRunner.query(`
64
+ CREATE INDEX idx_project_scene_jobs_project_id ON project_scene_jobs(project_id);
65
+ `);
66
+ await queryRunner.query(`
67
+ CREATE INDEX idx_project_scene_jobs_user_id ON project_scene_jobs(user_id);
68
+ `);
69
+ await queryRunner.query(`
70
+ CREATE INDEX idx_project_scene_jobs_status ON project_scene_jobs(status);
71
+ `);
72
+ await queryRunner.query(`
73
+ CREATE INDEX idx_project_scenes_project_id ON project_scenes(project_id);
74
+ `);
75
+ await queryRunner.query(`
76
+ CREATE INDEX idx_project_scenes_project_timestamp ON project_scenes(project_id, timestamp);
77
+ `);
78
+ await queryRunner.query(`COMMENT ON TABLE project_scene_jobs IS 'Tracks scene generation jobs for video editor projects'`);
79
+ await queryRunner.query(`COMMENT ON TABLE project_scenes IS 'Stores individual scene metadata and S3 references'`);
80
+ await queryRunner.query(`COMMENT ON COLUMN project_scene_jobs.id IS 'Job ID with format scene_job_{uuid}'`);
81
+ await queryRunner.query(`COMMENT ON COLUMN project_scene_jobs.data IS 'JSONB storage for job results, scene URLs, and error details'`);
82
+ await queryRunner.query(`COMMENT ON COLUMN project_scenes.timestamp IS 'Scene timestamp in seconds (0, 5, 10, ...)'`);
83
+ await queryRunner.query(`COMMENT ON COLUMN project_scenes.metadata IS 'JSONB storage for scene generation metadata'`);
84
+ }
85
+ async down(queryRunner) {
86
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_project_scenes_project_timestamp`);
87
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_project_scenes_project_id`);
88
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_project_scene_jobs_status`);
89
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_project_scene_jobs_user_id`);
90
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_project_scene_jobs_project_id`);
91
+ await queryRunner.query(`DROP TABLE IF EXISTS project_scenes`);
92
+ await queryRunner.query(`DROP TABLE IF EXISTS project_scene_jobs`);
93
+ await queryRunner.query(`DROP TYPE IF EXISTS project_scene_status`);
94
+ await queryRunner.query(`DROP TYPE IF EXISTS project_scene_job_status`);
95
+ }
96
+ }
97
+ exports.CreateSceneGeneratorTables1713000000023 = CreateSceneGeneratorTables1713000000023;
@@ -0,0 +1,6 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ export declare class CreateRemotionRendersTable1713000000024 implements MigrationInterface {
3
+ name: string;
4
+ up(queryRunner: QueryRunner): Promise<void>;
5
+ down(queryRunner: QueryRunner): Promise<void>;
6
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreateRemotionRendersTable1713000000024 = void 0;
4
+ class CreateRemotionRendersTable1713000000024 {
5
+ constructor() {
6
+ this.name = 'CreateRemotionRendersTable1713000000024';
7
+ }
8
+ async up(queryRunner) {
9
+ await queryRunner.query(`
10
+ DO $$ BEGIN
11
+ CREATE TYPE render_status AS ENUM ('pending', 'rendering', 'completed', 'failed');
12
+ EXCEPTION
13
+ WHEN duplicate_object THEN null;
14
+ END $$;
15
+ `);
16
+ await queryRunner.query(`
17
+ CREATE TABLE remotion_renders (
18
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
19
+ project_id VARCHAR(255) NOT NULL,
20
+ user_id UUID NOT NULL REFERENCES users(id),
21
+ workspace_id UUID,
22
+ render_id VARCHAR(255),
23
+ status render_status DEFAULT 'pending',
24
+ bucket_name VARCHAR(255) NOT NULL,
25
+ function_name VARCHAR(255) NOT NULL,
26
+ region VARCHAR(50) DEFAULT 'ap-southeast-2',
27
+ output_file_url TEXT,
28
+ error_message TEXT,
29
+ retry_count INTEGER DEFAULT 0,
30
+ composition_id VARCHAR(255),
31
+ input_props JSONB,
32
+ render_metadata JSONB,
33
+ credits_reserved DECIMAL(10, 2),
34
+ credits_consumed DECIMAL(10, 2),
35
+ reservation_id UUID,
36
+ render_cost_metadata JSONB,
37
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
38
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
39
+ );
40
+ `);
41
+ await queryRunner.query(`
42
+ CREATE INDEX idx_remotion_renders_project_id ON remotion_renders(project_id);
43
+ `);
44
+ await queryRunner.query(`
45
+ CREATE INDEX idx_remotion_renders_user_id ON remotion_renders(user_id);
46
+ `);
47
+ await queryRunner.query(`
48
+ CREATE INDEX idx_remotion_renders_render_id ON remotion_renders(render_id);
49
+ `);
50
+ await queryRunner.query(`
51
+ CREATE INDEX idx_remotion_renders_status ON remotion_renders(status);
52
+ `);
53
+ await queryRunner.query(`
54
+ CREATE INDEX idx_remotion_renders_reservation_id ON remotion_renders(reservation_id);
55
+ `);
56
+ await queryRunner.query(`COMMENT ON TABLE remotion_renders IS 'Tracks Remotion video rendering jobs'`);
57
+ await queryRunner.query(`COMMENT ON COLUMN remotion_renders.render_id IS 'Remotion Lambda render ID'`);
58
+ await queryRunner.query(`COMMENT ON COLUMN remotion_renders.input_props IS 'JSONB storage for Remotion composition input props'`);
59
+ await queryRunner.query(`COMMENT ON COLUMN remotion_renders.render_metadata IS 'JSONB storage for render metadata (dimensions, fps, etc.)'`);
60
+ }
61
+ async down(queryRunner) {
62
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_remotion_renders_reservation_id`);
63
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_remotion_renders_status`);
64
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_remotion_renders_render_id`);
65
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_remotion_renders_user_id`);
66
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_remotion_renders_project_id`);
67
+ await queryRunner.query(`DROP TABLE IF EXISTS remotion_renders`);
68
+ await queryRunner.query(`DROP TYPE IF EXISTS render_status`);
69
+ }
70
+ }
71
+ exports.CreateRemotionRendersTable1713000000024 = CreateRemotionRendersTable1713000000024;
@@ -0,0 +1,6 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ export declare class ExtendCreditAllocationSystem1713000000025 implements MigrationInterface {
3
+ name: string;
4
+ up(queryRunner: QueryRunner): Promise<void>;
5
+ down(queryRunner: QueryRunner): Promise<void>;
6
+ }
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExtendCreditAllocationSystem1713000000025 = void 0;
4
+ class ExtendCreditAllocationSystem1713000000025 {
5
+ constructor() {
6
+ this.name = 'ExtendCreditAllocationSystem1713000000025';
7
+ }
8
+ async up(queryRunner) {
9
+ await queryRunner.query(`
10
+ CREATE TABLE IF NOT EXISTS plan_credit_configurations (
11
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
12
+ plan_id VARCHAR(100) UNIQUE NOT NULL,
13
+ plan_name VARCHAR(100) NOT NULL,
14
+ cloud_credits_monthly INTEGER DEFAULT 0,
15
+ cloud_credits_max_rollover INTEGER DEFAULT 0,
16
+ ai_credits_monthly INTEGER DEFAULT 0,
17
+ ai_credits_max_rollover INTEGER DEFAULT 0,
18
+ signup_cloud_bonus INTEGER DEFAULT 0,
19
+ signup_ai_bonus INTEGER DEFAULT 0,
20
+ upgrade_bonus_multiplier DECIMAL(5,2) DEFAULT 0.20,
21
+ is_active BOOLEAN DEFAULT true,
22
+ features JSONB,
23
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
24
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
25
+ );
26
+ `);
27
+ await queryRunner.query(`
28
+ INSERT INTO plan_credit_configurations
29
+ (plan_id, plan_name, cloud_credits_monthly, cloud_credits_max_rollover, ai_credits_monthly, ai_credits_max_rollover, signup_cloud_bonus, signup_ai_bonus)
30
+ VALUES
31
+ ('free', 'Free', 100, 0, 50, 0, 50, 25),
32
+ ('pro', 'Pro', 500, 500, 250, 250, 100, 50),
33
+ ('business', 'Business', 2000, 1000, 1000, 500, 500, 250),
34
+ ('enterprise', 'Enterprise', 10000, 5000, 5000, 2500, 1000, 500)
35
+ ON CONFLICT (plan_id) DO NOTHING;
36
+ `);
37
+ await queryRunner.query(`
38
+ ALTER TABLE credit_allocations
39
+ ADD COLUMN IF NOT EXISTS cloud_credits_allocated DECIMAL(10,2) DEFAULT 0,
40
+ ADD COLUMN IF NOT EXISTS cloud_credits_remaining DECIMAL(10,2) DEFAULT 0,
41
+ ADD COLUMN IF NOT EXISTS cloud_credits_rollover DECIMAL(10,2) DEFAULT 0,
42
+ ADD COLUMN IF NOT EXISTS ai_credits_allocated DECIMAL(10,2) DEFAULT 0,
43
+ ADD COLUMN IF NOT EXISTS ai_credits_remaining DECIMAL(10,2) DEFAULT 0,
44
+ ADD COLUMN IF NOT EXISTS ai_credits_rollover DECIMAL(10,2) DEFAULT 0,
45
+ ADD COLUMN IF NOT EXISTS billing_cycle VARCHAR(20) DEFAULT 'monthly',
46
+ ADD COLUMN IF NOT EXISTS metadata JSONB;
47
+ `);
48
+ await queryRunner.query(`
49
+ UPDATE credit_allocations
50
+ SET
51
+ plan_id = 'free',
52
+ cloud_credits_allocated = credits_allocated,
53
+ cloud_credits_remaining = credits_remaining,
54
+ cloud_credits_rollover = rollover_credits,
55
+ ai_credits_allocated = ai_credits_allocated,
56
+ ai_credits_remaining = ai_credits_remaining,
57
+ ai_credits_rollover = 0,
58
+ billing_cycle = 'monthly'
59
+ WHERE plan_id IS NULL OR plan_id = '';
60
+ `);
61
+ await queryRunner.query(`
62
+ CREATE INDEX IF NOT EXISTS idx_credit_allocations_user_status ON credit_allocations(user_id, status);
63
+ `);
64
+ await queryRunner.query(`
65
+ CREATE INDEX IF NOT EXISTS idx_credit_allocations_period ON credit_allocations(period_start, period_end);
66
+ `);
67
+ await queryRunner.query(`
68
+ CREATE INDEX IF NOT EXISTS idx_plan_credit_configurations_plan_id ON plan_credit_configurations(plan_id);
69
+ `);
70
+ await queryRunner.query(`
71
+ CREATE INDEX IF NOT EXISTS idx_plan_credit_configurations_active ON plan_credit_configurations(is_active);
72
+ `);
73
+ await queryRunner.query(`COMMENT ON TABLE plan_credit_configurations IS 'Credit allocation configurations for each subscription plan'`);
74
+ await queryRunner.query(`COMMENT ON TABLE credit_allocations IS 'User credit allocations with Cloud and AI credit separation'`);
75
+ await queryRunner.query(`COMMENT ON COLUMN credit_allocations.cloud_credits_allocated IS 'Monthly allocated Cloud/Render credits'`);
76
+ await queryRunner.query(`COMMENT ON COLUMN credit_allocations.ai_credits_allocated IS 'Monthly allocated AI credits'`);
77
+ await queryRunner.query(`COMMENT ON COLUMN credit_allocations.cloud_credits_rollover IS 'Cloud credits rolled over from previous period'`);
78
+ await queryRunner.query(`COMMENT ON COLUMN credit_allocations.ai_credits_rollover IS 'AI credits rolled over from previous period'`);
79
+ }
80
+ async down(queryRunner) {
81
+ await queryRunner.query(`COMMENT ON TABLE plan_credit_configurations IS NULL`);
82
+ await queryRunner.query(`COMMENT ON TABLE credit_allocations IS NULL`);
83
+ await queryRunner.query(`COMMENT ON COLUMN credit_allocations.cloud_credits_allocated IS NULL`);
84
+ await queryRunner.query(`COMMENT ON COLUMN credit_allocations.ai_credits_allocated IS NULL`);
85
+ await queryRunner.query(`COMMENT ON COLUMN credit_allocations.cloud_credits_rollover IS NULL`);
86
+ await queryRunner.query(`COMMENT ON COLUMN credit_allocations.ai_credits_rollover IS NULL`);
87
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_plan_credit_configurations_active`);
88
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_plan_credit_configurations_plan_id`);
89
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_credit_allocations_period`);
90
+ await queryRunner.query(`DROP INDEX IF EXISTS idx_credit_allocations_user_status`);
91
+ await queryRunner.query(`
92
+ UPDATE credit_allocations
93
+ SET
94
+ plan_id = NULL,
95
+ credits_allocated = cloud_credits_allocated,
96
+ credits_remaining = cloud_credits_remaining,
97
+ rollover_credits = cloud_credits_rollover
98
+ WHERE plan_id = 'free';
99
+ `);
100
+ await queryRunner.query(`
101
+ ALTER TABLE credit_allocations
102
+ DROP COLUMN IF EXISTS cloud_credits_allocated,
103
+ DROP COLUMN IF EXISTS cloud_credits_remaining,
104
+ DROP COLUMN IF EXISTS cloud_credits_rollover,
105
+ DROP COLUMN IF EXISTS ai_credits_allocated,
106
+ DROP COLUMN IF EXISTS ai_credits_remaining,
107
+ DROP COLUMN IF EXISTS ai_credits_rollover,
108
+ DROP COLUMN IF EXISTS billing_cycle,
109
+ DROP COLUMN IF EXISTS metadata;
110
+ `);
111
+ await queryRunner.query(`DROP TABLE IF EXISTS plan_credit_configurations`);
112
+ }
113
+ }
114
+ exports.ExtendCreditAllocationSystem1713000000025 = ExtendCreditAllocationSystem1713000000025;
@@ -1,5 +1,5 @@
1
1
  import { MigrationInterface, QueryRunner } from 'typeorm';
2
- export declare class AddIsActiveToWorkspaceMembers1713000000002 implements MigrationInterface {
2
+ export declare class AddStatusToCreditTransactions1713000000026 implements MigrationInterface {
3
3
  name: string;
4
4
  up(queryRunner: QueryRunner): Promise<void>;
5
5
  down(queryRunner: QueryRunner): Promise<void>;