Compare commits

..

1 Commits

Author SHA1 Message Date
gauthier-th
637712e4fc feat: add script for SQLite to PostgreSQL migration 2026-02-18 14:50:40 +01:00
23 changed files with 422 additions and 202 deletions

View File

@@ -1,7 +1,6 @@
name: 🐛 Bug Report
description: Report a problem
labels: ['awaiting triage']
type: bug
labels: ['bug', 'awaiting triage']
body:
- type: markdown
attributes:

View File

@@ -1,63 +0,0 @@
name: 📚 Documentation
description: Report a docs problem or suggest a docs improvement
title: "[Docs]: "
labels: ["documentation", "awaiting triage"]
type: task
body:
- type: markdown
attributes:
value: |
Thanks for helping improve the docs!
Use this template for documentation issues (typos, unclear steps, missing info, outdated screenshots).
For app bugs or feature ideas, please use the other templates.
- type: input
id: doc-location
attributes:
label: Page / Location
description: Link to the docs page or the file/path (e.g. https://docs.seerr.dev/... or README.md)
placeholder: "https://docs.seerr.dev/..."
validations:
required: true
- type: dropdown
id: doc-area
attributes:
label: Docs Area
options:
- docs site
- migration guide
- README / repo docs
- API / integrations
- other
validations:
required: true
- type: textarea
id: problem
attributes:
label: Whats wrong / missing?
description: Describe the issue in the docs.
validations:
required: true
- type: textarea
id: suggested-fix
attributes:
label: Suggested change
description: If you know what should be changed, describe it (or paste proposed wording).
validations:
required: false
- type: checkboxes
id: search-existing
attributes:
label: Search Existing Issues
description: Have you searched existing issues to see if this has already been reported?
options:
- label: Yes, I have searched existing issues.
required: true
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our Code of Conduct.
options:
- label: I agree to follow Seerr's [Code of Conduct](https://github.com/seerr-team/seerr/blob/develop/CODE_OF_CONDUCT.md).
required: true

View File

@@ -1,7 +1,6 @@
name: ✨ Feature Request
description: Suggest an idea
labels: ['awaiting triage']
type: feature
labels: ['enhancement', 'awaiting triage']
body:
- type: markdown
attributes:

View File

@@ -1,65 +0,0 @@
name: 🧰 Maintenance / Chore
description: CI, GitHub Actions, build, dependencies, refactors (non-feature work)
title: "[Chore]: "
labels: ["maintenance", "awaiting triage"]
type: task
body:
- type: markdown
attributes:
value: |
Maintainers / contributors: use this for internal tasks (CI, workflows, tooling, refactors).
If you're reporting a user-facing bug or requesting a feature, use the other templates.
- type: dropdown
id: area
attributes:
label: Area
options:
- CI / GitHub Actions
- build / packaging
- dependencies
- release process
- refactor / tech debt
- tooling / scripts
- other
validations:
required: true
- type: textarea
id: summary
attributes:
label: Summary
description: What needs doing and why?
validations:
required: true
- type: textarea
id: acceptance
attributes:
label: Acceptance criteria
description: What does "done" look like?
placeholder: |
- [ ] ...
- [ ] ...
validations:
required: false
- type: input
id: related
attributes:
label: Related links
description: PRs, failing workflow runs, logs, or relevant issues.
validations:
required: false
- type: checkboxes
id: search-existing
attributes:
label: Search Existing Issues
description: Have you searched existing issues to see if this has already been reported?
options:
- label: Yes, I have searched existing issues.
required: true
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our Code of Conduct.
options:
- label: I agree to follow Seerr's [Code of Conduct](https://github.com/seerr-team/seerr/blob/develop/CODE_OF_CONDUCT.md).
required: true

View File

@@ -18,7 +18,7 @@ env:
DOCKER_HUB: seerr/seerr
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -20,7 +20,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: codeql-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -14,7 +14,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: merge-conflict-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -28,7 +28,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: cypress-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -15,7 +15,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: pages
cancel-in-progress: true
jobs:

View File

@@ -25,7 +25,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: docs-link-check-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -14,7 +14,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: helm-charts
cancel-in-progress: true
jobs:

View File

@@ -18,7 +18,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: charts-lint-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -15,7 +15,7 @@ env:
DOCKER_HUB: seerr/seerr
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: preview-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -11,7 +11,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: release-${{ github.ref }}
cancel-in-progress: true
env:

View File

@@ -12,7 +12,7 @@ on:
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: renovate-helm-hooks-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -1,28 +0,0 @@
name: "Semantic PR"
on:
pull_request_target:
types:
- opened
- reopened
- edited
- synchronize
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
main:
name: Validate PR Title
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: read
checks: write
steps:
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -9,7 +9,7 @@ on:
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: close-stale-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -14,7 +14,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: docs-pr-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -16,7 +16,7 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: trivy-scan-${{ github.ref }}
cancel-in-progress: true
jobs:

View File

@@ -122,7 +122,7 @@ Steps:
- If you are taking on an existing bug or feature ticket, please comment on the [issue](/../../issues) to avoid multiple people working on the same thing.
- All commits **must** follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
- Pull requests with titles or commits not following this standard will **not** be merged. PR titles are automatically checked for compliance.
- Pull requests with commits not following this standard will **not** be merged.
- Please make meaningful commits, or squash them prior to opening a pull request.
- Do not squash commits once people have begun reviewing your changes.
- Always rebase your commit to the latest `develop` branch. Do **not** merge `develop` into your branch.

View File

@@ -24,7 +24,8 @@
"prepare": "node bin/prepare.js",
"cypress:open": "cypress open",
"cypress:prepare": "ts-node -r tsconfig-paths/register --files --project server/tsconfig.json server/scripts/prepareTestDb.ts",
"cypress:build": "pnpm build && pnpm cypress:prepare"
"cypress:build": "pnpm build && pnpm cypress:prepare",
"db:migratetopostgres": "pnpm build:server && node dist/scripts/sqliteToPostgres.js"
},
"repository": {
"type": "git",
@@ -158,7 +159,7 @@
"eslint-plugin-no-relative-import-paths": "1.6.1",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "4.6.2",
"eslint-plugin-react-hooks": "4.6.0",
"husky": "8.0.3",
"lint-staged": "13.1.2",
"nodemon": "3.1.11",

245
pnpm-lock.yaml generated
View File

@@ -386,8 +386,8 @@ importers:
specifier: 7.37.5
version: 7.37.5(eslint@8.57.1)
eslint-plugin-react-hooks:
specifier: 4.6.2
version: 4.6.2(eslint@8.57.1)
specifier: 4.6.0
version: 4.6.0(eslint@8.57.1)
husky:
specifier: 8.0.3
version: 8.0.3
@@ -3148,6 +3148,14 @@ packages:
typescript:
optional: true
'@typescript-eslint/eslint-plugin@8.54.0':
resolution: {integrity: sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.54.0
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/parser@7.18.0':
resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==}
engines: {node: ^18.18.0 || >=20.0.0}
@@ -3158,10 +3166,33 @@ packages:
typescript:
optional: true
'@typescript-eslint/parser@8.54.0':
resolution: {integrity: sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/project-service@8.54.0':
resolution: {integrity: sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/scope-manager@7.18.0':
resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==}
engines: {node: ^18.18.0 || >=20.0.0}
'@typescript-eslint/scope-manager@8.54.0':
resolution: {integrity: sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.54.0':
resolution: {integrity: sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/type-utils@7.18.0':
resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==}
engines: {node: ^18.18.0 || >=20.0.0}
@@ -3172,6 +3203,13 @@ packages:
typescript:
optional: true
'@typescript-eslint/type-utils@8.54.0':
resolution: {integrity: sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/types@5.45.0':
resolution: {integrity: sha512-QQij+u/vgskA66azc9dCmx+rev79PzX8uDHpsqSjEFtfF2gBUTRCpvYMh2gw2ghkJabNkPlSUCimsyBEQZd1DA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3180,6 +3218,10 @@ packages:
resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==}
engines: {node: ^18.18.0 || >=20.0.0}
'@typescript-eslint/types@8.54.0':
resolution: {integrity: sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@5.45.0':
resolution: {integrity: sha512-maRhLGSzqUpFcZgXxg1qc/+H0bT36lHK4APhp0AEUVrpSwXiRAomm/JGjSG+kNUio5kAa3uekCYu/47cnGn5EQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3198,12 +3240,25 @@ packages:
typescript:
optional: true
'@typescript-eslint/typescript-estree@8.54.0':
resolution: {integrity: sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/utils@7.18.0':
resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==}
engines: {node: ^18.18.0 || >=20.0.0}
peerDependencies:
eslint: ^8.56.0
'@typescript-eslint/utils@8.54.0':
resolution: {integrity: sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/visitor-keys@5.45.0':
resolution: {integrity: sha512-jc6Eccbn2RtQPr1s7th6jJWQHBHI6GBVQkCHoJFQ5UreaKm59Vxw+ynQUPPY2u2Amquc+7tmEoC2G52ApsGNNg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3212,6 +3267,10 @@ packages:
resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==}
engines: {node: ^18.18.0 || >=20.0.0}
'@typescript-eslint/visitor-keys@8.54.0':
resolution: {integrity: sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
@@ -4604,8 +4663,8 @@ packages:
eslint-config-prettier:
optional: true
eslint-plugin-react-hooks@4.6.2:
resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==}
eslint-plugin-react-hooks@4.6.0:
resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
engines: {node: '>=10'}
peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
@@ -4624,6 +4683,10 @@ packages:
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
eslint-visitor-keys@4.2.1:
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
eslint@8.57.1:
resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -5014,22 +5077,20 @@ packages:
glob@10.3.10:
resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
engines: {node: '>=16 || 14 >=14.17'}
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
hasBin: true
glob@10.5.0:
resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
hasBin: true
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
deprecated: Glob versions prior to v9 are no longer supported
glob@8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
engines: {node: '>=12'}
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
deprecated: Glob versions prior to v9 are no longer supported
global-directory@4.0.1:
resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==}
@@ -5257,6 +5318,10 @@ packages:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
ignore@7.0.5:
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
engines: {node: '>= 4'}
image-size@1.2.1:
resolution: {integrity: sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==}
engines: {node: '>=16.x'}
@@ -5600,6 +5665,10 @@ packages:
resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
jiti@1.21.6:
resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==}
hasBin: true
jiti@1.21.7:
resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
hasBin: true
@@ -6241,6 +6310,10 @@ packages:
resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
engines: {node: '>=10'}
minimatch@9.0.4:
resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==}
engines: {node: '>=16 || 14 >=14.17'}
minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -8004,7 +8077,7 @@ packages:
tar@6.2.1:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me
temp-dir@2.0.0:
resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
@@ -8143,6 +8216,12 @@ packages:
peerDependencies:
typescript: '>=4.2.0'
ts-api-utils@2.4.0:
resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
engines: {node: '>=18.12'}
peerDependencies:
typescript: '>=4.8.4'
ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
@@ -12335,6 +12414,22 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1)(typescript@5.4.5)':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.54.0(eslint@8.57.1)(typescript@5.4.5)
'@typescript-eslint/scope-manager': 8.54.0
'@typescript-eslint/type-utils': 8.54.0(eslint@8.57.1)(typescript@5.4.5)
'@typescript-eslint/utils': 8.54.0(eslint@8.57.1)(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 8.54.0
eslint: 8.57.1
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.4.0(typescript@5.4.5)
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5)':
dependencies:
'@typescript-eslint/scope-manager': 7.18.0
@@ -12348,11 +12443,41 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.54.0(eslint@8.57.1)(typescript@5.4.5)':
dependencies:
'@typescript-eslint/scope-manager': 8.54.0
'@typescript-eslint/types': 8.54.0
'@typescript-eslint/typescript-estree': 8.54.0(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 8.54.0
debug: 4.4.3(supports-color@5.5.0)
eslint: 8.57.1
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
'@typescript-eslint/project-service@8.54.0(typescript@5.4.5)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.4.5)
'@typescript-eslint/types': 8.54.0
debug: 4.4.3(supports-color@5.5.0)
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
'@typescript-eslint/scope-manager@7.18.0':
dependencies:
'@typescript-eslint/types': 7.18.0
'@typescript-eslint/visitor-keys': 7.18.0
'@typescript-eslint/scope-manager@8.54.0':
dependencies:
'@typescript-eslint/types': 8.54.0
'@typescript-eslint/visitor-keys': 8.54.0
'@typescript-eslint/tsconfig-utils@8.54.0(typescript@5.4.5)':
dependencies:
typescript: 5.4.5
'@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.4.5)':
dependencies:
'@typescript-eslint/typescript-estree': 7.18.0(typescript@5.4.5)
@@ -12365,10 +12490,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/type-utils@8.54.0(eslint@8.57.1)(typescript@5.4.5)':
dependencies:
'@typescript-eslint/types': 8.54.0
'@typescript-eslint/typescript-estree': 8.54.0(typescript@5.4.5)
'@typescript-eslint/utils': 8.54.0(eslint@8.57.1)(typescript@5.4.5)
debug: 4.4.3(supports-color@5.5.0)
eslint: 8.57.1
ts-api-utils: 2.4.0(typescript@5.4.5)
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@5.45.0': {}
'@typescript-eslint/types@7.18.0': {}
'@typescript-eslint/types@8.54.0': {}
'@typescript-eslint/typescript-estree@5.45.0(typescript@4.9.5)':
dependencies:
'@typescript-eslint/types': 5.45.0
@@ -12398,6 +12537,21 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.54.0(typescript@5.4.5)':
dependencies:
'@typescript-eslint/project-service': 8.54.0(typescript@5.4.5)
'@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.4.5)
'@typescript-eslint/types': 8.54.0
'@typescript-eslint/visitor-keys': 8.54.0
debug: 4.4.3(supports-color@5.5.0)
minimatch: 9.0.5
semver: 7.7.3
tinyglobby: 0.2.15
ts-api-utils: 2.4.0(typescript@5.4.5)
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.4.5)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
@@ -12409,6 +12563,17 @@ snapshots:
- supports-color
- typescript
'@typescript-eslint/utils@8.54.0(eslint@8.57.1)(typescript@5.4.5)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
'@typescript-eslint/scope-manager': 8.54.0
'@typescript-eslint/types': 8.54.0
'@typescript-eslint/typescript-estree': 8.54.0(typescript@5.4.5)
eslint: 8.57.1
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
'@typescript-eslint/visitor-keys@5.45.0':
dependencies:
'@typescript-eslint/types': 5.45.0
@@ -12419,6 +12584,11 @@ snapshots:
'@typescript-eslint/types': 7.18.0
eslint-visitor-keys: 3.4.3
'@typescript-eslint/visitor-keys@8.54.0':
dependencies:
'@typescript-eslint/types': 8.54.0
eslint-visitor-keys: 4.2.1
'@ungap/structured-clone@1.3.0': {}
JSONStream@1.3.5:
@@ -13347,7 +13517,7 @@ snapshots:
dependencies:
'@types/node': 22.10.5
cosmiconfig: 9.0.0(typescript@5.4.5)
jiti: 1.21.7
jiti: 1.21.6
typescript: 5.4.5
optional: true
@@ -13979,15 +14149,15 @@ snapshots:
dependencies:
'@next/eslint-plugin-next': 14.2.35
'@rushstack/eslint-patch': 1.10.3
'@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1)(typescript@5.4.5)
'@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.4.5)
'@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1)(typescript@5.4.5)
'@typescript-eslint/parser': 8.54.0(eslint@8.57.1)(typescript@5.4.5)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.54.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1)
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
eslint-plugin-react: 7.37.5(eslint@8.57.1)
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
eslint-plugin-react-hooks: 4.6.0(eslint@8.57.1)
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
@@ -14006,13 +14176,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1):
eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.54.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1):
dependencies:
debug: 4.4.3(supports-color@5.5.0)
enhanced-resolve: 5.17.0
eslint: 8.57.1
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
eslint-module-utils: 2.8.1(@typescript-eslint/parser@8.54.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1)
fast-glob: 3.3.3
get-tsconfig: 4.13.0
is-core-module: 2.16.1
@@ -14023,14 +14193,24 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1):
eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1):
dependencies:
debug: 3.2.7(supports-color@8.1.1)
optionalDependencies:
'@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.4.5)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1)
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.8.1(@typescript-eslint/parser@8.54.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1):
dependencies:
debug: 3.2.7(supports-color@8.1.1)
optionalDependencies:
'@typescript-eslint/parser': 8.54.0(eslint@8.57.1)(typescript@5.4.5)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.54.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1)
transitivePeerDependencies:
- supports-color
@@ -14052,7 +14232,7 @@ snapshots:
- supports-color
- ts-jest
eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1):
eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1):
dependencies:
array-includes: 3.1.8
array.prototype.findlastindex: 1.2.5
@@ -14062,7 +14242,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -14108,7 +14288,7 @@ snapshots:
optionalDependencies:
eslint-config-prettier: 8.6.0(eslint@8.57.1)
eslint-plugin-react-hooks@4.6.2(eslint@8.57.1):
eslint-plugin-react-hooks@4.6.0(eslint@8.57.1):
dependencies:
eslint: 8.57.1
@@ -14141,6 +14321,8 @@ snapshots:
eslint-visitor-keys@3.4.3: {}
eslint-visitor-keys@4.2.1: {}
eslint@8.57.1:
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
@@ -14679,7 +14861,7 @@ snapshots:
dependencies:
foreground-child: 3.2.1
jackspeak: 2.3.6
minimatch: 9.0.5
minimatch: 9.0.4
minipass: 7.1.2
path-scurry: 1.11.1
@@ -14687,7 +14869,7 @@ snapshots:
dependencies:
foreground-child: 3.2.1
jackspeak: 3.4.3
minimatch: 9.0.5
minimatch: 9.0.4
minipass: 7.1.2
package-json-from-dist: 1.0.1
path-scurry: 1.11.1
@@ -14978,6 +15160,8 @@ snapshots:
ignore@5.3.2: {}
ignore@7.0.5: {}
image-size@1.2.1:
dependencies:
queue: 6.0.2
@@ -15326,6 +15510,9 @@ snapshots:
merge-stream: 2.0.0
supports-color: 8.1.1
jiti@1.21.6:
optional: true
jiti@1.21.7: {}
joi@17.13.3:
@@ -16222,6 +16409,10 @@ snapshots:
dependencies:
brace-expansion: 2.0.2
minimatch@9.0.4:
dependencies:
brace-expansion: 2.0.2
minimatch@9.0.5:
dependencies:
brace-expansion: 2.0.2
@@ -18365,6 +18556,10 @@ snapshots:
dependencies:
typescript: 5.4.5
ts-api-utils@2.4.0(typescript@5.4.5):
dependencies:
typescript: 5.4.5
ts-interface-checker@0.1.13: {}
ts-node@10.9.2(@swc/core@1.6.5(@swc/helpers@0.5.11))(@types/node@20.5.1)(typescript@5.4.5):

View File

@@ -0,0 +1,182 @@
/* eslint-disable no-console */
import fs from 'fs';
import path from 'path';
import type { TlsOptions } from 'tls';
import {
DataSource,
type DataSourceOptions,
type ObjectLiteral,
} from 'typeorm';
const DB_SSL_PREFIX = 'DB_SSL_';
function boolFromEnv(envVar: string, defaultVal = false) {
if (process.env[envVar]) {
return process.env[envVar]?.toLowerCase() === 'true';
}
return defaultVal;
}
function stringOrReadFileFromEnv(envVar: string): Buffer | string | undefined {
if (process.env[envVar]) {
return process.env[envVar];
}
const filePath = process.env[`${envVar}_FILE`];
if (filePath) {
return fs.readFileSync(filePath);
}
return undefined;
}
function buildSslConfig(): TlsOptions | undefined {
if (process.env.DB_USE_SSL?.toLowerCase() !== 'true') {
return undefined;
}
return {
rejectUnauthorized: boolFromEnv(
`${DB_SSL_PREFIX}REJECT_UNAUTHORIZED`,
true
),
ca: stringOrReadFileFromEnv(`${DB_SSL_PREFIX}CA`),
key: stringOrReadFileFromEnv(`${DB_SSL_PREFIX}KEY`),
cert: stringOrReadFileFromEnv(`${DB_SSL_PREFIX}CERT`),
};
}
const prodConfig: DataSourceOptions = {
type: 'sqlite',
database: process.env.CONFIG_DIRECTORY
? `${process.env.CONFIG_DIRECTORY}/db/db.sqlite3`
: 'config/db/db.sqlite3',
synchronize: false,
migrationsRun: false,
logging: boolFromEnv('DB_LOG_QUERIES'),
enableWAL: true,
// entities: ['dist/entity/**/*.js'],
migrations: ['dist/migration/sqlite/**/*.js'],
subscribers: ['dist/subscriber/**/*.js'],
};
const postgresProdConfig: DataSourceOptions = {
type: 'postgres',
host: process.env.DB_SOCKET_PATH || process.env.DB_HOST,
port: process.env.DB_SOCKET_PATH
? undefined
: parseInt(process.env.DB_PORT ?? '5432'),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME ?? 'seerr',
ssl: buildSslConfig(),
synchronize: false,
migrationsRun: true,
logging: boolFromEnv('DB_LOG_QUERIES'),
// entities: ['dist/entity/**/*.js'],
migrations: ['dist/migration/postgres/**/*.js'],
subscribers: ['dist/subscriber/**/*.js'],
};
async function loadEntities(type: 'sqlite' | 'postgres') {
process.env.DB_TYPE = type;
Object.keys(require.cache).forEach((key) => {
if (key.includes(path.join(__dirname, '../../dist'))) {
delete require.cache[key];
}
});
const entities = await Promise.all(
fs
.readdirSync(path.join(__dirname, '../../dist/entity'))
.filter((file) => file.endsWith('.js'))
.map((file) => {
/* eslint @typescript-eslint/no-var-requires: "off" */
const entityModule = require(
path.join(__dirname, '../../dist/entity', file)
);
return entityModule.default || entityModule[file.replace('.js', '')];
})
);
return entities;
}
async function migrate() {
const sqliteEntities = await loadEntities('sqlite');
const sqliteDataSource = new DataSource({
entities: sqliteEntities,
...prodConfig,
});
await sqliteDataSource.initialize();
console.log('SQLite DataSource initialized.');
const postgresEntities = await loadEntities('postgres');
const postgresDataSource = new DataSource({
entities: postgresEntities,
...postgresProdConfig,
});
await postgresDataSource.initialize();
console.log('Postgres DataSource initialized.');
// create query runner and disable foreign key constraints for Postgres
const queryRunner = postgresDataSource.createQueryRunner();
await queryRunner.connect();
console.log('Disabling foreign key constraints...');
await queryRunner.query(`SET session_replication_role = 'replica';`);
try {
const entities = sqliteDataSource.entityMetadatas;
for (const entity of entities) {
const entityName = entity.name;
const tableName = entity.tableName;
console.log(`Migrating table: ${tableName} (${entityName})...`);
const sourceRepo = sqliteDataSource.getRepository(entityName);
// const targetRepo = postgresDataSource.getRepository(entityName);
const targetRepo = queryRunner.manager.getRepository(entityName);
const BATCH_SIZE = 1000;
let skip = 0;
let totalCount = 0;
let rows: ObjectLiteral[];
do {
rows = await sourceRepo.find({
take: BATCH_SIZE,
skip: skip,
loadEagerRelations: false,
loadRelationIds: true,
});
for (const row of rows) {
// set postgres ID seq to because TypeORM ignores the ID field when saving
if (row.id && typeof row.id === 'number' && row.id > 1) {
await queryRunner.query(`
SELECT setval(pg_get_serial_sequence('${tableName}', 'id'), ${row.id - 1}, true);
`);
}
await targetRepo.save(row, {
transaction: false,
listeners: false,
reload: false,
});
}
skip += BATCH_SIZE;
totalCount += rows.length;
} while (rows.length !== 0);
console.log(` -> Copied ${totalCount} rows.`);
}
} catch (err) {
console.error('Migration failed:', err);
} finally {
console.log('Re-enabling foreign key constraints...');
await queryRunner.query(`SET session_replication_role = 'origin';`);
await queryRunner.release();
await sqliteDataSource.destroy();
await postgresDataSource.destroy();
console.log('Migration complete.');
}
}
migrate();