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,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AddStatusToCreditTransactions1713000000026 = void 0;
|
|
4
|
+
class AddStatusToCreditTransactions1713000000026 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'AddStatusToCreditTransactions1713000000026';
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
ALTER TABLE credit_transactions
|
|
11
|
+
ADD COLUMN IF NOT EXISTS status VARCHAR(20) DEFAULT 'completed';
|
|
12
|
+
`);
|
|
13
|
+
await queryRunner.query(`
|
|
14
|
+
ALTER TABLE credit_transactions
|
|
15
|
+
ADD COLUMN IF NOT EXISTS operation_type VARCHAR(50);
|
|
16
|
+
`);
|
|
17
|
+
await queryRunner.query(`
|
|
18
|
+
ALTER TABLE credit_transactions
|
|
19
|
+
ADD COLUMN IF NOT EXISTS operation_id VARCHAR(100);
|
|
20
|
+
`);
|
|
21
|
+
await queryRunner.query(`
|
|
22
|
+
ALTER TABLE credit_transactions
|
|
23
|
+
ADD COLUMN IF NOT EXISTS reservation_id UUID;
|
|
24
|
+
`);
|
|
25
|
+
await queryRunner.query(`
|
|
26
|
+
ALTER TABLE credit_transactions
|
|
27
|
+
DROP CONSTRAINT IF EXISTS credit_transactions_status_check;
|
|
28
|
+
`);
|
|
29
|
+
await queryRunner.query(`
|
|
30
|
+
ALTER TABLE credit_transactions
|
|
31
|
+
ADD CONSTRAINT credit_transactions_status_check
|
|
32
|
+
CHECK (status IN ('pending', 'reserved', 'completed', 'cancelled', 'refunded'));
|
|
33
|
+
`);
|
|
34
|
+
await queryRunner.query(`
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_credit_transactions_status ON credit_transactions(status);
|
|
36
|
+
`);
|
|
37
|
+
await queryRunner.query(`
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_credit_transactions_operation_type ON credit_transactions(operation_type) WHERE operation_type IS NOT NULL;
|
|
39
|
+
`);
|
|
40
|
+
await queryRunner.query(`
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_credit_transactions_operation_id ON credit_transactions(operation_id) WHERE operation_id IS NOT NULL;
|
|
42
|
+
`);
|
|
43
|
+
await queryRunner.query(`
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_credit_transactions_reservation_id ON credit_transactions(reservation_id) WHERE reservation_id IS NOT NULL;
|
|
45
|
+
`);
|
|
46
|
+
await queryRunner.query(`COMMENT ON COLUMN credit_transactions.status IS 'Transaction status: pending, reserved, completed, cancelled, refunded'`);
|
|
47
|
+
await queryRunner.query(`COMMENT ON COLUMN credit_transactions.operation_type IS 'Type of operation that consumed credits (e.g., video_export_1080p, ai_image_generation)'`);
|
|
48
|
+
await queryRunner.query(`COMMENT ON COLUMN credit_transactions.operation_id IS 'Links to specific job or operation ID'`);
|
|
49
|
+
await queryRunner.query(`COMMENT ON COLUMN credit_transactions.reservation_id IS 'Links reservation transactions to their finalization'`);
|
|
50
|
+
}
|
|
51
|
+
async down(queryRunner) {
|
|
52
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_credit_transactions_reservation_id`);
|
|
53
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_credit_transactions_operation_id`);
|
|
54
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_credit_transactions_operation_type`);
|
|
55
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_credit_transactions_status`);
|
|
56
|
+
await queryRunner.query(`ALTER TABLE credit_transactions DROP CONSTRAINT IF EXISTS credit_transactions_status_check`);
|
|
57
|
+
await queryRunner.query(`ALTER TABLE credit_transactions DROP COLUMN IF EXISTS reservation_id`);
|
|
58
|
+
await queryRunner.query(`ALTER TABLE credit_transactions DROP COLUMN IF EXISTS operation_id`);
|
|
59
|
+
await queryRunner.query(`ALTER TABLE credit_transactions DROP COLUMN IF EXISTS operation_type`);
|
|
60
|
+
await queryRunner.query(`ALTER TABLE credit_transactions DROP COLUMN IF EXISTS status`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.AddStatusToCreditTransactions1713000000026 = AddStatusToCreditTransactions1713000000026;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
export declare class MigrateProjectDurationToSeconds1713000000027 implements MigrationInterface {
|
|
3
|
+
name: string;
|
|
4
|
+
up(queryRunner: QueryRunner): Promise<void>;
|
|
5
|
+
down(queryRunner: QueryRunner): Promise<void>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MigrateProjectDurationToSeconds1713000000027 = void 0;
|
|
4
|
+
class MigrateProjectDurationToSeconds1713000000027 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'MigrateProjectDurationToSeconds1713000000027';
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
ALTER TABLE editor_projects
|
|
11
|
+
DROP COLUMN IF EXISTS duration_ms;
|
|
12
|
+
`);
|
|
13
|
+
await queryRunner.query(`
|
|
14
|
+
ALTER TABLE project_scene_jobs
|
|
15
|
+
DROP COLUMN IF EXISTS duration_ms;
|
|
16
|
+
`);
|
|
17
|
+
await queryRunner.query(`
|
|
18
|
+
ALTER TABLE editor_projects
|
|
19
|
+
ADD COLUMN IF NOT EXISTS duration INTEGER NOT NULL DEFAULT 0;
|
|
20
|
+
`);
|
|
21
|
+
await queryRunner.query(`
|
|
22
|
+
ALTER TABLE project_scene_jobs
|
|
23
|
+
ADD COLUMN IF NOT EXISTS duration DECIMAL(10,3) NOT NULL DEFAULT 0;
|
|
24
|
+
`);
|
|
25
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.duration IS 'Project duration in seconds (primary duration field)'`);
|
|
26
|
+
await queryRunner.query(`COMMENT ON COLUMN project_scene_jobs.duration IS 'Project duration in seconds for scene generation jobs'`);
|
|
27
|
+
}
|
|
28
|
+
async down(queryRunner) {
|
|
29
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.duration IS NULL`);
|
|
30
|
+
await queryRunner.query(`COMMENT ON COLUMN project_scene_jobs.duration IS NULL`);
|
|
31
|
+
await queryRunner.query(`
|
|
32
|
+
ALTER TABLE editor_projects
|
|
33
|
+
ADD COLUMN IF NOT EXISTS duration_ms INTEGER;
|
|
34
|
+
`);
|
|
35
|
+
await queryRunner.query(`
|
|
36
|
+
ALTER TABLE project_scene_jobs
|
|
37
|
+
ADD COLUMN IF NOT EXISTS duration_ms INTEGER;
|
|
38
|
+
`);
|
|
39
|
+
await queryRunner.query(`ALTER TABLE editor_projects DROP COLUMN IF EXISTS duration`);
|
|
40
|
+
await queryRunner.query(`ALTER TABLE project_scene_jobs DROP COLUMN IF EXISTS duration`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.MigrateProjectDurationToSeconds1713000000027 = MigrateProjectDurationToSeconds1713000000027;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CreateSceneTimelineTables1713000000028 = void 0;
|
|
4
|
+
class CreateSceneTimelineTables1713000000028 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'CreateSceneTimelineTables1713000000028';
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`);
|
|
10
|
+
await queryRunner.query(`
|
|
11
|
+
CREATE TABLE scenes (
|
|
12
|
+
id VARCHAR(36) PRIMARY KEY,
|
|
13
|
+
project_id VARCHAR(255) NOT NULL REFERENCES editor_projects(id) ON DELETE CASCADE,
|
|
14
|
+
name VARCHAR(255) NOT NULL,
|
|
15
|
+
description TEXT,
|
|
16
|
+
start_ms BIGINT NOT NULL,
|
|
17
|
+
end_ms BIGINT NOT NULL,
|
|
18
|
+
duration_ms BIGINT GENERATED ALWAYS AS (end_ms - start_ms) STORED,
|
|
19
|
+
thumbnail_url TEXT,
|
|
20
|
+
thumbnail_status VARCHAR(20) DEFAULT 'PENDING',
|
|
21
|
+
color VARCHAR(7),
|
|
22
|
+
transition_type VARCHAR(20),
|
|
23
|
+
transition_duration_ms INTEGER,
|
|
24
|
+
transition_to_scene_id VARCHAR(36),
|
|
25
|
+
locked BOOLEAN DEFAULT FALSE,
|
|
26
|
+
collapsed BOOLEAN DEFAULT FALSE,
|
|
27
|
+
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
28
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
29
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
30
|
+
CONSTRAINT scenes_valid_timing CHECK (start_ms >= 0 AND end_ms > start_ms),
|
|
31
|
+
CONSTRAINT scenes_valid_color CHECK (color IS NULL OR color ~ '^#[0-9A-Fa-f]{6}$'),
|
|
32
|
+
CONSTRAINT scenes_valid_transition_type CHECK (
|
|
33
|
+
transition_type IS NULL OR
|
|
34
|
+
transition_type IN ('FADE', 'CROSS_DISSOLVE', 'WIPE', 'SLIDE', 'NONE')
|
|
35
|
+
)
|
|
36
|
+
);
|
|
37
|
+
`);
|
|
38
|
+
await queryRunner.query(`
|
|
39
|
+
CREATE TABLE items (
|
|
40
|
+
id VARCHAR(36) PRIMARY KEY,
|
|
41
|
+
project_id VARCHAR(255) NOT NULL REFERENCES editor_projects(id) ON DELETE CASCADE,
|
|
42
|
+
unique_id VARCHAR(255) NOT NULL,
|
|
43
|
+
type VARCHAR(50) NOT NULL,
|
|
44
|
+
start_ms BIGINT NOT NULL,
|
|
45
|
+
end_ms BIGINT NOT NULL,
|
|
46
|
+
frame_start_at BIGINT,
|
|
47
|
+
frame_end_at BIGINT,
|
|
48
|
+
scene_id VARCHAR(36) REFERENCES scenes(id) ON DELETE SET NULL,
|
|
49
|
+
z_index INTEGER NOT NULL,
|
|
50
|
+
row_id INTEGER NOT NULL,
|
|
51
|
+
locked BOOLEAN DEFAULT FALSE,
|
|
52
|
+
visible BOOLEAN DEFAULT TRUE,
|
|
53
|
+
mute BOOLEAN DEFAULT FALSE,
|
|
54
|
+
is_audio BOOLEAN DEFAULT FALSE,
|
|
55
|
+
is_video BOOLEAN DEFAULT FALSE,
|
|
56
|
+
is_audio_detached BOOLEAN DEFAULT FALSE,
|
|
57
|
+
src TEXT,
|
|
58
|
+
s3_url TEXT,
|
|
59
|
+
s3_key TEXT,
|
|
60
|
+
thumb_url TEXT,
|
|
61
|
+
duration BIGINT,
|
|
62
|
+
volume DECIMAL(3,2) DEFAULT 1.0,
|
|
63
|
+
text_value TEXT,
|
|
64
|
+
style TEXT,
|
|
65
|
+
shape_name VARCHAR(255),
|
|
66
|
+
is_tintable BOOLEAN DEFAULT FALSE,
|
|
67
|
+
transformation JSONB,
|
|
68
|
+
metadata JSONB,
|
|
69
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
70
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
71
|
+
CONSTRAINT items_valid_timing CHECK (start_ms >= 0 AND end_ms >= start_ms),
|
|
72
|
+
CONSTRAINT items_valid_type CHECK (
|
|
73
|
+
type IN ('videos', 'audios', 'images', 'titles', 'shapes', 'emojis', 'gifs')
|
|
74
|
+
),
|
|
75
|
+
CONSTRAINT items_valid_volume CHECK (volume >= 0.0 AND volume <= 1.0),
|
|
76
|
+
CONSTRAINT items_unique_per_project UNIQUE (project_id, unique_id)
|
|
77
|
+
);
|
|
78
|
+
`);
|
|
79
|
+
await queryRunner.query(`
|
|
80
|
+
CREATE INDEX idx_scenes_project_id ON scenes(project_id);
|
|
81
|
+
`);
|
|
82
|
+
await queryRunner.query(`
|
|
83
|
+
CREATE INDEX idx_scenes_sort_order ON scenes(project_id, sort_order);
|
|
84
|
+
`);
|
|
85
|
+
await queryRunner.query(`
|
|
86
|
+
CREATE INDEX idx_scenes_timing ON scenes(project_id, start_ms, end_ms);
|
|
87
|
+
`);
|
|
88
|
+
await queryRunner.query(`
|
|
89
|
+
CREATE INDEX idx_scenes_thumbnail_status ON scenes(thumbnail_status) WHERE thumbnail_status = 'PENDING';
|
|
90
|
+
`);
|
|
91
|
+
await queryRunner.query(`
|
|
92
|
+
CREATE INDEX idx_items_project_id ON items(project_id);
|
|
93
|
+
`);
|
|
94
|
+
await queryRunner.query(`
|
|
95
|
+
CREATE INDEX idx_items_scene_id ON items(scene_id);
|
|
96
|
+
`);
|
|
97
|
+
await queryRunner.query(`
|
|
98
|
+
CREATE INDEX idx_items_type ON items(type);
|
|
99
|
+
`);
|
|
100
|
+
await queryRunner.query(`
|
|
101
|
+
CREATE INDEX idx_items_timing ON items(project_id, start_ms, end_ms);
|
|
102
|
+
`);
|
|
103
|
+
await queryRunner.query(`
|
|
104
|
+
CREATE INDEX idx_items_z_index ON items(project_id, row_id, z_index);
|
|
105
|
+
`);
|
|
106
|
+
await queryRunner.query(`
|
|
107
|
+
CREATE INDEX idx_items_unique_id ON items(unique_id);
|
|
108
|
+
`);
|
|
109
|
+
await queryRunner.query(`
|
|
110
|
+
ALTER TABLE editor_projects
|
|
111
|
+
ADD COLUMN scene_order JSONB DEFAULT '[]'::jsonb;
|
|
112
|
+
`);
|
|
113
|
+
await queryRunner.query(`
|
|
114
|
+
CREATE TRIGGER update_scenes_updated_at
|
|
115
|
+
BEFORE UPDATE ON scenes
|
|
116
|
+
FOR EACH ROW
|
|
117
|
+
EXECUTE FUNCTION update_updated_at_column();
|
|
118
|
+
`);
|
|
119
|
+
await queryRunner.query(`
|
|
120
|
+
CREATE TRIGGER update_items_updated_at
|
|
121
|
+
BEFORE UPDATE ON items
|
|
122
|
+
FOR EACH ROW
|
|
123
|
+
EXECUTE FUNCTION update_updated_at_column();
|
|
124
|
+
`);
|
|
125
|
+
await queryRunner.query(`COMMENT ON TABLE scenes IS 'Scene definitions for timeline-based video editing'`);
|
|
126
|
+
await queryRunner.query(`COMMENT ON TABLE items IS 'Timeline items (media elements) with scene relationships'`);
|
|
127
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.start_ms IS 'Scene start time in milliseconds'`);
|
|
128
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.end_ms IS 'Scene end time in milliseconds'`);
|
|
129
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.duration_ms IS 'Computed scene duration in milliseconds'`);
|
|
130
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.thumbnail_status IS 'Status of scene thumbnail generation: PENDING, GENERATING, READY, FAILED'`);
|
|
131
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.transition_type IS 'Type of transition to next scene'`);
|
|
132
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.transition_duration_ms IS 'Duration of transition in milliseconds'`);
|
|
133
|
+
await queryRunner.query(`COMMENT ON COLUMN items.scene_id IS 'Reference to scene this item belongs to'`);
|
|
134
|
+
await queryRunner.query(`COMMENT ON COLUMN items.unique_id IS 'Unique identifier for the item within the project'`);
|
|
135
|
+
await queryRunner.query(`COMMENT ON COLUMN items.z_index IS 'Layering order within the timeline row'`);
|
|
136
|
+
await queryRunner.query(`COMMENT ON COLUMN items.row_id IS 'Timeline row this item belongs to'`);
|
|
137
|
+
await queryRunner.query(`COMMENT ON COLUMN items.frame_start_at IS 'Frame-accurate start position for media items'`);
|
|
138
|
+
await queryRunner.query(`COMMENT ON COLUMN items.frame_end_at IS 'Frame-accurate end position for media items'`);
|
|
139
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.scene_order IS 'Array of scene IDs in display order'`);
|
|
140
|
+
}
|
|
141
|
+
async down(queryRunner) {
|
|
142
|
+
await queryRunner.query(`DROP TRIGGER IF EXISTS update_items_updated_at ON items`);
|
|
143
|
+
await queryRunner.query(`DROP TRIGGER IF EXISTS update_scenes_updated_at ON scenes`);
|
|
144
|
+
await queryRunner.query(`ALTER TABLE editor_projects DROP COLUMN IF EXISTS scene_order`);
|
|
145
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_items_unique_id`);
|
|
146
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_items_z_index`);
|
|
147
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_items_timing`);
|
|
148
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_items_type`);
|
|
149
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_items_scene_id`);
|
|
150
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_items_project_id`);
|
|
151
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_scenes_thumbnail_status`);
|
|
152
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_scenes_timing`);
|
|
153
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_scenes_sort_order`);
|
|
154
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_scenes_project_id`);
|
|
155
|
+
await queryRunner.query(`DROP TABLE IF EXISTS items`);
|
|
156
|
+
await queryRunner.query(`DROP TABLE IF EXISTS scenes`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.CreateSceneTimelineTables1713000000028 = CreateSceneTimelineTables1713000000028;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConvertScenesToSeconds1713000000029 = void 0;
|
|
4
|
+
class ConvertScenesToSeconds1713000000029 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'ConvertScenesToSeconds1713000000029';
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
DO $$
|
|
11
|
+
BEGIN
|
|
12
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'start') THEN
|
|
13
|
+
ALTER TABLE scenes ADD COLUMN start DECIMAL(10, 3);
|
|
14
|
+
END IF;
|
|
15
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'end') THEN
|
|
16
|
+
ALTER TABLE scenes ADD COLUMN "end" DECIMAL(10, 3);
|
|
17
|
+
END IF;
|
|
18
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'transition_duration') THEN
|
|
19
|
+
ALTER TABLE scenes ADD COLUMN transition_duration DECIMAL(10, 3);
|
|
20
|
+
END IF;
|
|
21
|
+
END $$;
|
|
22
|
+
`);
|
|
23
|
+
await queryRunner.query(`
|
|
24
|
+
DO $$
|
|
25
|
+
BEGIN
|
|
26
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'start_ms') THEN
|
|
27
|
+
UPDATE scenes SET
|
|
28
|
+
start = start_ms / 1000.0,
|
|
29
|
+
"end" = end_ms / 1000.0,
|
|
30
|
+
transition_duration = transition_duration_ms / 1000.0
|
|
31
|
+
WHERE start IS NULL OR "end" IS NULL;
|
|
32
|
+
END IF;
|
|
33
|
+
END $$;
|
|
34
|
+
`);
|
|
35
|
+
await queryRunner.query(`ALTER TABLE scenes ALTER COLUMN start SET NOT NULL`);
|
|
36
|
+
await queryRunner.query(`ALTER TABLE scenes ALTER COLUMN "end" SET NOT NULL`);
|
|
37
|
+
await queryRunner.query(`
|
|
38
|
+
DO $$
|
|
39
|
+
BEGIN
|
|
40
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'duration_ms') THEN
|
|
41
|
+
ALTER TABLE scenes DROP COLUMN duration_ms;
|
|
42
|
+
END IF;
|
|
43
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'start_ms') THEN
|
|
44
|
+
ALTER TABLE scenes DROP COLUMN start_ms;
|
|
45
|
+
END IF;
|
|
46
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'end_ms') THEN
|
|
47
|
+
ALTER TABLE scenes DROP COLUMN end_ms;
|
|
48
|
+
END IF;
|
|
49
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'transition_duration_ms') THEN
|
|
50
|
+
ALTER TABLE scenes DROP COLUMN transition_duration_ms;
|
|
51
|
+
END IF;
|
|
52
|
+
END $$;
|
|
53
|
+
`);
|
|
54
|
+
await queryRunner.query(`
|
|
55
|
+
DO $$
|
|
56
|
+
BEGIN
|
|
57
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'scenes' AND column_name = 'duration') THEN
|
|
58
|
+
ALTER TABLE scenes ADD COLUMN duration DECIMAL(10, 3) GENERATED ALWAYS AS ("end" - start) STORED;
|
|
59
|
+
END IF;
|
|
60
|
+
END $$;
|
|
61
|
+
`);
|
|
62
|
+
await queryRunner.query(`ALTER TABLE scenes DROP CONSTRAINT IF EXISTS scenes_valid_timing`);
|
|
63
|
+
await queryRunner.query(`ALTER TABLE scenes ADD CONSTRAINT scenes_valid_timing CHECK (start >= 0 AND "end" > start)`);
|
|
64
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_scenes_timing`);
|
|
65
|
+
await queryRunner.query(`CREATE INDEX idx_scenes_timing ON scenes(project_id, start, "end")`);
|
|
66
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.start IS 'Scene start time in seconds'`);
|
|
67
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes."end" IS 'Scene end time in seconds'`);
|
|
68
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.duration IS 'Computed scene duration in seconds'`);
|
|
69
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.transition_duration IS 'Duration of transition in seconds'`);
|
|
70
|
+
}
|
|
71
|
+
async down(queryRunner) {
|
|
72
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.start IS NULL`);
|
|
73
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes."end" IS NULL`);
|
|
74
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.duration IS NULL`);
|
|
75
|
+
await queryRunner.query(`COMMENT ON COLUMN scenes.transition_duration IS NULL`);
|
|
76
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_scenes_timing`);
|
|
77
|
+
await queryRunner.query(`ALTER TABLE scenes DROP CONSTRAINT IF EXISTS scenes_valid_timing`);
|
|
78
|
+
await queryRunner.query(`ALTER TABLE scenes ADD CONSTRAINT scenes_valid_timing CHECK (start_ms >= 0 AND end_ms > start_ms)`);
|
|
79
|
+
await queryRunner.query(`ALTER TABLE scenes DROP COLUMN IF EXISTS duration`);
|
|
80
|
+
await queryRunner.query(`
|
|
81
|
+
ALTER TABLE scenes ADD COLUMN transition_duration_ms INTEGER;
|
|
82
|
+
`);
|
|
83
|
+
await queryRunner.query(`
|
|
84
|
+
ALTER TABLE scenes ADD COLUMN end_ms BIGINT;
|
|
85
|
+
`);
|
|
86
|
+
await queryRunner.query(`
|
|
87
|
+
ALTER TABLE scenes ADD COLUMN start_ms BIGINT;
|
|
88
|
+
`);
|
|
89
|
+
await queryRunner.query(`
|
|
90
|
+
ALTER TABLE scenes ADD COLUMN duration_ms BIGINT GENERATED ALWAYS AS (end_ms - start_ms) STORED;
|
|
91
|
+
`);
|
|
92
|
+
await queryRunner.query(`
|
|
93
|
+
UPDATE scenes SET
|
|
94
|
+
start_ms = start * 1000,
|
|
95
|
+
end_ms = "end" * 1000,
|
|
96
|
+
transition_duration_ms = transition_duration * 1000;
|
|
97
|
+
`);
|
|
98
|
+
await queryRunner.query(`ALTER TABLE scenes ALTER COLUMN start_ms SET NOT NULL`);
|
|
99
|
+
await queryRunner.query(`ALTER TABLE scenes ALTER COLUMN end_ms SET NOT NULL`);
|
|
100
|
+
await queryRunner.query(`ALTER TABLE scenes DROP COLUMN IF EXISTS start`);
|
|
101
|
+
await queryRunner.query(`ALTER TABLE scenes DROP COLUMN IF EXISTS "end"`);
|
|
102
|
+
await queryRunner.query(`ALTER TABLE scenes DROP COLUMN IF EXISTS transition_duration`);
|
|
103
|
+
await queryRunner.query(`CREATE INDEX idx_scenes_timing ON scenes(project_id, start_ms, end_ms)`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.ConvertScenesToSeconds1713000000029 = ConvertScenesToSeconds1713000000029;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChangeDurationToDecimal1713000000030 = void 0;
|
|
4
|
+
class ChangeDurationToDecimal1713000000030 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'ChangeDurationToDecimal1713000000030';
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
ALTER TABLE editor_projects
|
|
11
|
+
ALTER COLUMN duration TYPE DECIMAL(10,2);
|
|
12
|
+
`);
|
|
13
|
+
await queryRunner.query(`
|
|
14
|
+
ALTER TABLE editor_projects
|
|
15
|
+
ALTER COLUMN duration SET DEFAULT 0.00;
|
|
16
|
+
`);
|
|
17
|
+
await queryRunner.query(`
|
|
18
|
+
UPDATE editor_projects
|
|
19
|
+
SET duration = duration::DECIMAL(10,2)
|
|
20
|
+
WHERE duration IS NOT NULL;
|
|
21
|
+
`);
|
|
22
|
+
}
|
|
23
|
+
async down(queryRunner) {
|
|
24
|
+
await queryRunner.query(`
|
|
25
|
+
ALTER TABLE editor_projects
|
|
26
|
+
ALTER COLUMN duration TYPE INTEGER;
|
|
27
|
+
`);
|
|
28
|
+
await queryRunner.query(`
|
|
29
|
+
ALTER TABLE editor_projects
|
|
30
|
+
ALTER COLUMN duration SET DEFAULT 0;
|
|
31
|
+
`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.ChangeDurationToDecimal1713000000030 = ChangeDurationToDecimal1713000000030;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CreateVideoSubtitlesTable1713000000031 = void 0;
|
|
4
|
+
class CreateVideoSubtitlesTable1713000000031 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'CreateVideoSubtitlesTable1713000000031';
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
DO $$ BEGIN
|
|
11
|
+
CREATE TYPE video_subtitle_status AS ENUM ('NEW', 'PROCESSING', 'SUCCESS', 'ERROR');
|
|
12
|
+
EXCEPTION
|
|
13
|
+
WHEN duplicate_object THEN null;
|
|
14
|
+
END $$;
|
|
15
|
+
`);
|
|
16
|
+
await queryRunner.query(`
|
|
17
|
+
CREATE TABLE IF NOT EXISTS video_subtitles (
|
|
18
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
19
|
+
project_id VARCHAR(255),
|
|
20
|
+
video_s3_key TEXT,
|
|
21
|
+
status video_subtitle_status DEFAULT 'NEW',
|
|
22
|
+
language VARCHAR(10),
|
|
23
|
+
data JSONB,
|
|
24
|
+
queue_status VARCHAR(50),
|
|
25
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
26
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
27
|
+
);
|
|
28
|
+
`);
|
|
29
|
+
await queryRunner.query(`
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_video_subtitles_project_id ON video_subtitles(project_id);
|
|
31
|
+
`);
|
|
32
|
+
await queryRunner.query(`
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_video_subtitles_status ON video_subtitles(status);
|
|
34
|
+
`);
|
|
35
|
+
await queryRunner.query(`COMMENT ON TABLE video_subtitles IS 'Stores subtitle generation jobs and their results'`);
|
|
36
|
+
await queryRunner.query(`COMMENT ON COLUMN video_subtitles.id IS 'Unique identifier for the subtitle job (uniqueId from request)'`);
|
|
37
|
+
await queryRunner.query(`COMMENT ON COLUMN video_subtitles.project_id IS 'Reference to the editor project'`);
|
|
38
|
+
await queryRunner.query(`COMMENT ON COLUMN video_subtitles.video_s3_key IS 'S3 key of the source video file'`);
|
|
39
|
+
await queryRunner.query(`COMMENT ON COLUMN video_subtitles.status IS 'Current status of the subtitle generation job'`);
|
|
40
|
+
await queryRunner.query(`COMMENT ON COLUMN video_subtitles.language IS 'Detected or specified language code'`);
|
|
41
|
+
await queryRunner.query(`COMMENT ON COLUMN video_subtitles.data IS 'Subtitle metadata including file URLs, word count, duration'`);
|
|
42
|
+
await queryRunner.query(`COMMENT ON COLUMN video_subtitles.queue_status IS 'Status in the processing queue'`);
|
|
43
|
+
}
|
|
44
|
+
async down(queryRunner) {
|
|
45
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_video_subtitles_status`);
|
|
46
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_video_subtitles_project_id`);
|
|
47
|
+
await queryRunner.query(`DROP TABLE IF EXISTS video_subtitles`);
|
|
48
|
+
await queryRunner.query(`DROP TYPE IF EXISTS video_subtitle_status`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.CreateVideoSubtitlesTable1713000000031 = CreateVideoSubtitlesTable1713000000031;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AddWebpThumbnailColumns1713000000032 = void 0;
|
|
4
|
+
class AddWebpThumbnailColumns1713000000032 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'AddWebpThumbnailColumns1713000000032';
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
ALTER TABLE editor_projects
|
|
11
|
+
ADD COLUMN IF NOT EXISTS thumbnail_webp_url TEXT,
|
|
12
|
+
ADD COLUMN IF NOT EXISTS thumbnail_png_url TEXT,
|
|
13
|
+
ADD COLUMN IF NOT EXISTS preview_video_url TEXT;
|
|
14
|
+
`);
|
|
15
|
+
await queryRunner.query(`
|
|
16
|
+
UPDATE editor_projects
|
|
17
|
+
SET thumbnail_png_url = thumbnail_url
|
|
18
|
+
WHERE thumbnail_url IS NOT NULL
|
|
19
|
+
AND thumbnail_png_url IS NULL;
|
|
20
|
+
`);
|
|
21
|
+
await queryRunner.query(`
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_editor_projects_thumbnail_webp
|
|
23
|
+
ON editor_projects(thumbnail_webp_url)
|
|
24
|
+
WHERE thumbnail_webp_url IS NOT NULL;
|
|
25
|
+
`);
|
|
26
|
+
await queryRunner.query(`
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_editor_projects_thumbnail_png
|
|
28
|
+
ON editor_projects(thumbnail_png_url)
|
|
29
|
+
WHERE thumbnail_png_url IS NOT NULL;
|
|
30
|
+
`);
|
|
31
|
+
await queryRunner.query(`
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_editor_projects_preview_video
|
|
33
|
+
ON editor_projects(preview_video_url)
|
|
34
|
+
WHERE preview_video_url IS NOT NULL;
|
|
35
|
+
`);
|
|
36
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.thumbnail_webp_url IS 'WebP format thumbnail URL (primary, ~30-40% smaller than PNG)'`);
|
|
37
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.thumbnail_png_url IS 'PNG format thumbnail URL (fallback for older browsers)'`);
|
|
38
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.preview_video_url IS 'Short video preview URL (2-3 seconds, for hover state - Phase 2)'`);
|
|
39
|
+
}
|
|
40
|
+
async down(queryRunner) {
|
|
41
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.thumbnail_webp_url IS NULL`);
|
|
42
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.thumbnail_png_url IS NULL`);
|
|
43
|
+
await queryRunner.query(`COMMENT ON COLUMN editor_projects.preview_video_url IS NULL`);
|
|
44
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_editor_projects_preview_video`);
|
|
45
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_editor_projects_thumbnail_png`);
|
|
46
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_editor_projects_thumbnail_webp`);
|
|
47
|
+
await queryRunner.query(`
|
|
48
|
+
UPDATE editor_projects
|
|
49
|
+
SET thumbnail_url = thumbnail_png_url
|
|
50
|
+
WHERE thumbnail_png_url IS NOT NULL
|
|
51
|
+
AND thumbnail_url IS NULL;
|
|
52
|
+
`);
|
|
53
|
+
await queryRunner.query(`ALTER TABLE editor_projects DROP COLUMN IF EXISTS preview_video_url`);
|
|
54
|
+
await queryRunner.query(`ALTER TABLE editor_projects DROP COLUMN IF EXISTS thumbnail_png_url`);
|
|
55
|
+
await queryRunner.query(`ALTER TABLE editor_projects DROP COLUMN IF EXISTS thumbnail_webp_url`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.AddWebpThumbnailColumns1713000000032 = AddWebpThumbnailColumns1713000000032;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AddFormatToProjectScenes1713000000033 = void 0;
|
|
4
|
+
class AddFormatToProjectScenes1713000000033 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'AddFormatToProjectScenes1713000000033';
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
DO $$
|
|
11
|
+
BEGIN
|
|
12
|
+
IF NOT EXISTS (
|
|
13
|
+
SELECT 1 FROM information_schema.columns
|
|
14
|
+
WHERE table_name = 'project_scenes' AND column_name = 'format'
|
|
15
|
+
) THEN
|
|
16
|
+
ALTER TABLE project_scenes ADD COLUMN format VARCHAR(10) DEFAULT 'png';
|
|
17
|
+
END IF;
|
|
18
|
+
END $$;
|
|
19
|
+
`);
|
|
20
|
+
await queryRunner.query(`
|
|
21
|
+
UPDATE project_scenes
|
|
22
|
+
SET format = 'png'
|
|
23
|
+
WHERE format IS NULL;
|
|
24
|
+
`);
|
|
25
|
+
await queryRunner.query(`ALTER TABLE project_scenes ALTER COLUMN format SET NOT NULL`);
|
|
26
|
+
await queryRunner.query(`
|
|
27
|
+
DO $$
|
|
28
|
+
BEGIN
|
|
29
|
+
IF EXISTS (
|
|
30
|
+
SELECT 1 FROM pg_constraint
|
|
31
|
+
WHERE conname = 'project_scenes_project_id_timestamp_key'
|
|
32
|
+
) THEN
|
|
33
|
+
ALTER TABLE project_scenes DROP CONSTRAINT project_scenes_project_id_timestamp_key;
|
|
34
|
+
END IF;
|
|
35
|
+
|
|
36
|
+
IF EXISTS (
|
|
37
|
+
SELECT 1 FROM pg_constraint
|
|
38
|
+
WHERE conname = 'project_scenes_project_id_timestamp_unique'
|
|
39
|
+
) THEN
|
|
40
|
+
ALTER TABLE project_scenes DROP CONSTRAINT project_scenes_project_id_timestamp_unique;
|
|
41
|
+
END IF;
|
|
42
|
+
END $$;
|
|
43
|
+
`);
|
|
44
|
+
await queryRunner.query(`
|
|
45
|
+
CREATE UNIQUE INDEX IF NOT EXISTS project_scenes_project_id_timestamp_format_unique
|
|
46
|
+
ON project_scenes (project_id, timestamp, format);
|
|
47
|
+
`);
|
|
48
|
+
await queryRunner.query(`
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_project_scenes_format
|
|
50
|
+
ON project_scenes(format);
|
|
51
|
+
`);
|
|
52
|
+
await queryRunner.query(`
|
|
53
|
+
DO $$
|
|
54
|
+
BEGIN
|
|
55
|
+
IF NOT EXISTS (
|
|
56
|
+
SELECT 1 FROM pg_constraint
|
|
57
|
+
WHERE conname = 'project_scenes_format_check'
|
|
58
|
+
) THEN
|
|
59
|
+
ALTER TABLE project_scenes
|
|
60
|
+
ADD CONSTRAINT project_scenes_format_check
|
|
61
|
+
CHECK (format IN ('png', 'webp'));
|
|
62
|
+
END IF;
|
|
63
|
+
END $$;
|
|
64
|
+
`);
|
|
65
|
+
await queryRunner.query(`COMMENT ON COLUMN project_scenes.format IS 'Output format of the scene thumbnail (png or webp). Multiple formats can exist per timestamp.'`);
|
|
66
|
+
}
|
|
67
|
+
async down(queryRunner) {
|
|
68
|
+
await queryRunner.query(`COMMENT ON COLUMN project_scenes.format IS NULL`);
|
|
69
|
+
await queryRunner.query(`DROP INDEX IF EXISTS idx_project_scenes_format`);
|
|
70
|
+
await queryRunner.query(`DROP INDEX IF EXISTS project_scenes_project_id_timestamp_format_unique`);
|
|
71
|
+
await queryRunner.query(`ALTER TABLE project_scenes DROP CONSTRAINT IF EXISTS project_scenes_format_check`);
|
|
72
|
+
await queryRunner.query(`ALTER TABLE project_scenes ALTER COLUMN format DROP NOT NULL`);
|
|
73
|
+
await queryRunner.query(`UPDATE project_scenes SET format = NULL`);
|
|
74
|
+
await queryRunner.query(`ALTER TABLE project_scenes DROP COLUMN IF EXISTS format`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.AddFormatToProjectScenes1713000000033 = AddFormatToProjectScenes1713000000033;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
export declare class FixProjectScenesUniqueConstraint1713000000034 implements MigrationInterface {
|
|
3
|
+
name: string;
|
|
4
|
+
up(queryRunner: QueryRunner): Promise<void>;
|
|
5
|
+
down(queryRunner: QueryRunner): Promise<void>;
|
|
6
|
+
}
|