aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/shared/sql-command.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/tests/shared/sql-command.ts
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'server/tests/shared/sql-command.ts')
-rw-r--r--server/tests/shared/sql-command.ts150
1 files changed, 0 insertions, 150 deletions
diff --git a/server/tests/shared/sql-command.ts b/server/tests/shared/sql-command.ts
deleted file mode 100644
index 5c53a8ac6..000000000
--- a/server/tests/shared/sql-command.ts
+++ /dev/null
@@ -1,150 +0,0 @@
1import { QueryTypes, Sequelize } from 'sequelize'
2import { forceNumber } from '@shared/core-utils'
3import { PeerTubeServer } from '@shared/server-commands'
4
5export class SQLCommand {
6 private sequelize: Sequelize
7
8 constructor (private readonly server: PeerTubeServer) {
9
10 }
11
12 deleteAll (table: string) {
13 const seq = this.getSequelize()
14
15 const options = { type: QueryTypes.DELETE }
16
17 return seq.query(`DELETE FROM "${table}"`, options)
18 }
19
20 async getVideoShareCount () {
21 const [ { total } ] = await this.selectQuery<{ total: string }>(`SELECT COUNT(*) as total FROM "videoShare"`)
22 if (total === null) return 0
23
24 return parseInt(total, 10)
25 }
26
27 async getInternalFileUrl (fileId: number) {
28 return this.selectQuery<{ fileUrl: string }>(`SELECT "fileUrl" FROM "videoFile" WHERE id = :fileId`, { fileId })
29 .then(rows => rows[0].fileUrl)
30 }
31
32 setActorField (to: string, field: string, value: string) {
33 return this.updateQuery(`UPDATE actor SET ${this.escapeColumnName(field)} = :value WHERE url = :to`, { value, to })
34 }
35
36 setVideoField (uuid: string, field: string, value: string) {
37 return this.updateQuery(`UPDATE video SET ${this.escapeColumnName(field)} = :value WHERE uuid = :uuid`, { value, uuid })
38 }
39
40 setPlaylistField (uuid: string, field: string, value: string) {
41 return this.updateQuery(`UPDATE "videoPlaylist" SET ${this.escapeColumnName(field)} = :value WHERE uuid = :uuid`, { value, uuid })
42 }
43
44 async countVideoViewsOf (uuid: string) {
45 const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' +
46 `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = :uuid`
47
48 const [ { total } ] = await this.selectQuery<{ total: number }>(query, { uuid })
49 if (!total) return 0
50
51 return forceNumber(total)
52 }
53
54 getActorImage (filename: string) {
55 return this.selectQuery<{ width: number, height: number }>(`SELECT * FROM "actorImage" WHERE filename = :filename`, { filename })
56 .then(rows => rows[0])
57 }
58
59 // ---------------------------------------------------------------------------
60
61 setPluginVersion (pluginName: string, newVersion: string) {
62 return this.setPluginField(pluginName, 'version', newVersion)
63 }
64
65 setPluginLatestVersion (pluginName: string, newVersion: string) {
66 return this.setPluginField(pluginName, 'latestVersion', newVersion)
67 }
68
69 setPluginField (pluginName: string, field: string, value: string) {
70 return this.updateQuery(
71 `UPDATE "plugin" SET ${this.escapeColumnName(field)} = :value WHERE "name" = :pluginName`,
72 { pluginName, value }
73 )
74 }
75
76 // ---------------------------------------------------------------------------
77
78 selectQuery <T extends object> (query: string, replacements: { [id: string]: string | number } = {}) {
79 const seq = this.getSequelize()
80 const options = {
81 type: QueryTypes.SELECT as QueryTypes.SELECT,
82 replacements
83 }
84
85 return seq.query<T>(query, options)
86 }
87
88 updateQuery (query: string, replacements: { [id: string]: string | number } = {}) {
89 const seq = this.getSequelize()
90 const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE, replacements }
91
92 return seq.query(query, options)
93 }
94
95 // ---------------------------------------------------------------------------
96
97 async getPlaylistInfohash (playlistId: number) {
98 const query = 'SELECT "p2pMediaLoaderInfohashes" FROM "videoStreamingPlaylist" WHERE id = :playlistId'
99
100 const result = await this.selectQuery<{ p2pMediaLoaderInfohashes: string }>(query, { playlistId })
101 if (!result || result.length === 0) return []
102
103 return result[0].p2pMediaLoaderInfohashes
104 }
105
106 // ---------------------------------------------------------------------------
107
108 setActorFollowScores (newScore: number) {
109 return this.updateQuery(`UPDATE "actorFollow" SET "score" = :newScore`, { newScore })
110 }
111
112 setTokenField (accessToken: string, field: string, value: string) {
113 return this.updateQuery(
114 `UPDATE "oAuthToken" SET ${this.escapeColumnName(field)} = :value WHERE "accessToken" = :accessToken`,
115 { value, accessToken }
116 )
117 }
118
119 async cleanup () {
120 if (!this.sequelize) return
121
122 await this.sequelize.close()
123 this.sequelize = undefined
124 }
125
126 private getSequelize () {
127 if (this.sequelize) return this.sequelize
128
129 const dbname = 'peertube_test' + this.server.internalServerNumber
130 const username = 'peertube'
131 const password = 'peertube'
132 const host = '127.0.0.1'
133 const port = 5432
134
135 this.sequelize = new Sequelize(dbname, username, password, {
136 dialect: 'postgres',
137 host,
138 port,
139 logging: false
140 })
141
142 return this.sequelize
143 }
144
145 private escapeColumnName (columnName: string) {
146 return this.getSequelize().escape(columnName)
147 .replace(/^'/, '"')
148 .replace(/'$/, '"')
149 }
150}