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.
- package/dist/config/data-source.local.d.ts +3 -0
- package/dist/config/data-source.local.js +15 -0
- package/dist/migrations/1713000000001-InitialSchema.d.ts +6 -0
- package/dist/migrations/1713000000001-InitialSchema.js +196 -0
- package/dist/migrations/1713000000002-CoreBusinessTables.d.ts +6 -0
- package/dist/migrations/1713000000002-CoreBusinessTables.js +198 -0
- package/dist/migrations/1713000000003-RemainingCoreTables.d.ts +6 -0
- package/dist/migrations/1713000000003-RemainingCoreTables.js +160 -0
- package/dist/migrations/1713000000004-MediaConfigReferenceTables.d.ts +6 -0
- package/dist/migrations/1713000000004-MediaConfigReferenceTables.js +241 -0
- package/dist/migrations/1713000000005-VideoMediaTables.d.ts +6 -0
- package/dist/migrations/1713000000005-VideoMediaTables.js +98 -0
- package/dist/migrations/1713000000006-AddUserReferralColumns.d.ts +6 -0
- package/dist/migrations/1713000000006-AddUserReferralColumns.js +55 -0
- package/dist/migrations/1713000000007-AddUserProfileColumns.d.ts +6 -0
- package/dist/migrations/1713000000007-AddUserProfileColumns.js +73 -0
- package/dist/migrations/1713000000008-AddBillingInfoColumn.d.ts +6 -0
- package/dist/migrations/1713000000008-AddBillingInfoColumn.js +23 -0
- package/dist/migrations/1713000000009-AddWorkspaceStorageColumns.d.ts +6 -0
- package/dist/migrations/1713000000009-AddWorkspaceStorageColumns.js +49 -0
- package/dist/migrations/1713000000010-AddUniqueIdToAssets.d.ts +6 -0
- package/dist/migrations/1713000000010-AddUniqueIdToAssets.js +29 -0
- package/dist/migrations/{1713000000003-AddDescriptionToBrandKits.d.ts → 1713000000011-CreateReferralEventsTable.d.ts} +1 -1
- package/dist/migrations/1713000000011-CreateReferralEventsTable.js +72 -0
- package/dist/migrations/1713000000012-ExtendCreditTransactions.d.ts +6 -0
- package/dist/migrations/1713000000012-ExtendCreditTransactions.js +70 -0
- package/dist/migrations/1713000000013-AiVideoMakerTables.d.ts +6 -0
- package/dist/migrations/1713000000013-AiVideoMakerTables.js +122 -0
- package/dist/migrations/1713000000014-SeedReferralRewardRules.d.ts +6 -0
- package/dist/migrations/1713000000014-SeedReferralRewardRules.js +135 -0
- package/dist/migrations/{1713000000001-CreateSocialConnectionTables.d.ts → 1713000000015-CreateCreditAllocationsTable.d.ts} +1 -1
- package/dist/migrations/1713000000015-CreateCreditAllocationsTable.js +49 -0
- package/dist/migrations/1713000000016-CreateCreditConsumptionLogTable.d.ts +6 -0
- package/dist/migrations/1713000000016-CreateCreditConsumptionLogTable.js +55 -0
- package/dist/migrations/1713000000017-UpdateSubscriptionPlansCreditFields.d.ts +6 -0
- package/dist/migrations/1713000000017-UpdateSubscriptionPlansCreditFields.js +121 -0
- package/dist/migrations/1713000000018-CreateVideoProcessingTables.d.ts +6 -0
- package/dist/migrations/1713000000018-CreateVideoProcessingTables.js +111 -0
- package/dist/migrations/1713000000019-CreateAudioWaveformsTable.d.ts +6 -0
- package/dist/migrations/1713000000019-CreateAudioWaveformsTable.js +62 -0
- package/dist/migrations/1713000000020-EnablePgvectorExtension.d.ts +6 -0
- package/dist/migrations/1713000000020-EnablePgvectorExtension.js +30 -0
- package/dist/migrations/1713000000021-CreateMetadataServiceTables.d.ts +6 -0
- package/dist/migrations/1713000000021-CreateMetadataServiceTables.js +410 -0
- package/dist/migrations/1713000000022-OptimizeMetadataIndexes.d.ts +6 -0
- package/dist/migrations/1713000000022-OptimizeMetadataIndexes.js +334 -0
- package/dist/migrations/1713000000023-CreateSceneGeneratorTables.d.ts +6 -0
- package/dist/migrations/1713000000023-CreateSceneGeneratorTables.js +97 -0
- package/dist/migrations/1713000000024-CreateRemotionRendersTable.d.ts +6 -0
- package/dist/migrations/1713000000024-CreateRemotionRendersTable.js +71 -0
- package/dist/migrations/1713000000025-ExtendCreditAllocationSystem.d.ts +6 -0
- package/dist/migrations/1713000000025-ExtendCreditAllocationSystem.js +114 -0
- package/dist/migrations/{1713000000002-AddIsActiveToWorkspaceMembers.d.ts → 1713000000026-AddStatusToCreditTransactions.d.ts} +1 -1
- package/dist/migrations/1713000000026-AddStatusToCreditTransactions.js +63 -0
- package/dist/migrations/1713000000027-MigrateProjectDurationToSeconds.d.ts +6 -0
- package/dist/migrations/1713000000027-MigrateProjectDurationToSeconds.js +43 -0
- package/dist/migrations/1713000000028-CreateSceneTimelineTables.d.ts +6 -0
- package/dist/migrations/1713000000028-CreateSceneTimelineTables.js +159 -0
- package/dist/migrations/1713000000029-ConvertScenesToSeconds.d.ts +6 -0
- package/dist/migrations/1713000000029-ConvertScenesToSeconds.js +106 -0
- package/dist/migrations/1713000000030-ChangeDurationToDecimal.d.ts +6 -0
- package/dist/migrations/1713000000030-ChangeDurationToDecimal.js +34 -0
- package/dist/migrations/1713000000031-CreateVideoSubtitlesTable.d.ts +6 -0
- package/dist/migrations/1713000000031-CreateVideoSubtitlesTable.js +51 -0
- package/dist/migrations/1713000000032-AddWebpThumbnailColumns.d.ts +6 -0
- package/dist/migrations/1713000000032-AddWebpThumbnailColumns.js +58 -0
- package/dist/migrations/1713000000033-AddFormatToProjectScenes.d.ts +6 -0
- package/dist/migrations/1713000000033-AddFormatToProjectScenes.js +77 -0
- package/dist/migrations/1713000000034-FixProjectScenesUniqueConstraint.d.ts +6 -0
- package/dist/migrations/1713000000034-FixProjectScenesUniqueConstraint.js +39 -0
- package/dist/migrations/1713000000035-AddMissingVideoSubtitlesColumns.d.ts +6 -0
- package/dist/migrations/1713000000035-AddMissingVideoSubtitlesColumns.js +29 -0
- package/dist/migrations/1713000000036-AddRemotionRenderCreditColumns.d.ts +6 -0
- package/dist/migrations/1713000000036-AddRemotionRenderCreditColumns.js +50 -0
- package/dist/migrations/1713000000037-CreateProjectSharesTable.d.ts +6 -0
- package/dist/migrations/1713000000037-CreateProjectSharesTable.js +60 -0
- package/dist/migrations/1713000000038-EnableRlsOnAllTables.d.ts +6 -0
- package/dist/migrations/1713000000038-EnableRlsOnAllTables.js +97 -0
- package/dist/migrations/1713000000039-AiVideoMakerKlingFreeColumns.d.ts +6 -0
- package/dist/migrations/1713000000039-AiVideoMakerKlingFreeColumns.js +85 -0
- package/dist/migrations/1713000000040-CreateBrandKitsTable.d.ts +6 -0
- package/dist/migrations/1713000000040-CreateBrandKitsTable.js +44 -0
- package/dist/migrations/1713000000041-CreateBrandAssetsTable.d.ts +6 -0
- package/dist/migrations/1713000000041-CreateBrandAssetsTable.js +57 -0
- package/dist/migrations/1713000000042-AddActiveBrandKitToWorkspaces.d.ts +6 -0
- package/dist/migrations/1713000000042-AddActiveBrandKitToWorkspaces.js +43 -0
- package/dist/migrations/1713000000043-CreateAssetCategoriesTable.d.ts +6 -0
- package/dist/migrations/1713000000043-CreateAssetCategoriesTable.js +47 -0
- package/dist/migrations/1713000000044-AddEnforcementModeToWorkspaces.d.ts +6 -0
- package/dist/migrations/1713000000044-AddEnforcementModeToWorkspaces.js +21 -0
- package/dist/migrations/1713000000045-CreateProjectBrandOverridesTable.d.ts +6 -0
- package/dist/migrations/1713000000045-CreateProjectBrandOverridesTable.js +33 -0
- package/dist/migrations/1713000000046-AddPdfRenderSupport.d.ts +6 -0
- package/dist/migrations/1713000000046-AddPdfRenderSupport.js +14 -0
- package/dist/migrations/1713000000047-CreateSocialConnectionTables.d.ts +6 -0
- package/dist/migrations/{1713000000001-CreateSocialConnectionTables.js → 1713000000047-CreateSocialConnectionTables.js} +4 -4
- package/dist/migrations/1713000000048-AddIsActiveToWorkspaceMembers.d.ts +6 -0
- package/dist/migrations/{1713000000002-AddIsActiveToWorkspaceMembers.js → 1713000000048-AddIsActiveToWorkspaceMembers.js} +4 -4
- package/dist/migrations/1713000000049-AddDescriptionToBrandKits.d.ts +6 -0
- package/dist/migrations/{1713000000003-AddDescriptionToBrandKits.js → 1713000000049-AddDescriptionToBrandKits.js} +4 -4
- package/dist/migrations/1713000000050-CreateKlingGenerationTables.d.ts +6 -0
- package/dist/migrations/1713000000050-CreateKlingGenerationTables.js +76 -0
- package/dist/migrations/1713000000051-AddAiVideoSceneCanvasIdsAndThumbnail.d.ts +6 -0
- package/dist/migrations/1713000000051-AddAiVideoSceneCanvasIdsAndThumbnail.js +49 -0
- package/dist/migrations/1713000000052-AddAiVideoSourceMetadataAndMusicMeta.d.ts +6 -0
- package/dist/migrations/1713000000052-AddAiVideoSourceMetadataAndMusicMeta.js +67 -0
- 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,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,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
|
|
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>;
|