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 366 additions and 282 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.

271
gen-docs/pnpm-lock.yaml generated
View File

@@ -34,7 +34,7 @@ importers:
version: 18.3.1(react@18.3.1)
tailwindcss:
specifier: ^3.4.4
version: 3.4.19(yaml@2.8.1)
version: 3.4.17
devDependencies:
'@docusaurus/module-type-aliases':
specifier: 3.9.1
@@ -708,8 +708,8 @@ packages:
resolution: {integrity: sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==}
engines: {node: '>=6.9.0'}
'@babel/runtime@7.28.6':
resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==}
'@babel/runtime@7.28.4':
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
engines: {node: '>=6.9.0'}
'@babel/template@7.27.2':
@@ -1224,6 +1224,10 @@ packages:
'@hapi/topo@5.1.0':
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
'@jest/schemas@29.6.3':
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -1405,6 +1409,10 @@ packages:
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
engines: {node: '>=8.0.0'}
'@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
'@pnpm/config.env-replace@1.1.0':
resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
engines: {node: '>=12.22.0'}
@@ -1935,6 +1943,9 @@ packages:
brace-expansion@1.1.12:
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
brace-expansion@2.0.2:
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
@@ -2673,8 +2684,8 @@ packages:
fast-uri@3.1.0:
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
fastq@1.20.1:
resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
fault@2.0.1:
resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==}
@@ -2683,15 +2694,6 @@ packages:
resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==}
engines: {node: '>=0.8.0'}
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
peerDependencies:
picomatch: ^3 || ^4
peerDependenciesMeta:
picomatch:
optional: true
feed@4.2.2:
resolution: {integrity: sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==}
engines: {node: '>=0.4.0'}
@@ -2735,6 +2737,10 @@ packages:
debug:
optional: true
foreground-child@3.3.1:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
form-data-encoder@2.1.4:
resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==}
engines: {node: '>= 14.17'}
@@ -2809,6 +2815,10 @@ packages:
glob-to-regexp@0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
glob@10.4.5:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
hasBin: true
global-dirs@3.0.1:
resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==}
engines: {node: '>=10'}
@@ -3192,6 +3202,9 @@ packages:
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
engines: {node: '>=0.10.0'}
jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
jest-util@29.7.0:
resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -3320,6 +3333,9 @@ packages:
resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@@ -3612,9 +3628,17 @@ packages:
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
minipass@7.1.2:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
mrmime@2.0.1:
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
engines: {node: '>=10'}
@@ -3769,6 +3793,9 @@ packages:
resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==}
engines: {node: '>=8'}
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
package-json@8.1.1:
resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==}
engines: {node: '>=14.16'}
@@ -3820,6 +3847,10 @@ packages:
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
path-scurry@1.11.1:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
path-to-regexp@0.1.12:
resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
@@ -3840,10 +3871,6 @@ packages:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
picomatch@4.0.3:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'}
pify@2.3.0:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
@@ -4011,22 +4038,16 @@ packages:
peerDependencies:
postcss: ^8.4
postcss-load-config@6.0.1:
resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
engines: {node: '>= 18'}
postcss-load-config@4.0.2:
resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
engines: {node: '>= 14'}
peerDependencies:
jiti: '>=1.21.0'
postcss: '>=8.0.9'
tsx: ^4.8.1
yaml: ^2.4.2
ts-node: '>=9.0.0'
peerDependenciesMeta:
jiti:
optional: true
postcss:
optional: true
tsx:
optional: true
yaml:
ts-node:
optional: true
postcss-loader@7.3.4:
@@ -4248,8 +4269,8 @@ packages:
resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'}
postcss-selector-parser@7.1.1:
resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==}
postcss-selector-parser@7.1.0:
resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==}
engines: {node: '>=4'}
postcss-sort-media-queries@5.2.0:
@@ -4520,8 +4541,8 @@ packages:
resolve-pathname@3.0.0:
resolution: {integrity: sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==}
resolve@1.22.11:
resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
resolve@1.22.10:
resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
engines: {node: '>= 0.4'}
hasBin: true
@@ -4668,6 +4689,10 @@ packages:
signal-exit@3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
signal-exit@4.1.0:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
sirv@2.0.4:
resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
engines: {node: '>= 10'}
@@ -4802,8 +4827,8 @@ packages:
peerDependencies:
postcss: ^8.4.31
sucrase@3.35.1:
resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
sucrase@3.35.0:
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
@@ -4832,8 +4857,8 @@ packages:
peerDependencies:
react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
tailwindcss@3.4.19:
resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==}
tailwindcss@3.4.17:
resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
engines: {node: '>=14.0.0'}
hasBin: true
@@ -4888,10 +4913,6 @@ packages:
tiny-warning@1.0.3:
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
tinyglobby@0.2.15:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'}
tinypool@1.1.1:
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -5148,7 +5169,6 @@ packages:
whatwg-encoding@3.1.1:
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
engines: {node: '>=18'}
deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
whatwg-mimetype@4.0.0:
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
@@ -5445,7 +5465,7 @@ snapshots:
'@babel/helper-plugin-utils': 7.27.1
debug: 4.4.3
lodash.debounce: 4.0.8
resolve: 1.22.11
resolve: 1.22.10
transitivePeerDependencies:
- supports-color
@@ -6098,7 +6118,7 @@ snapshots:
dependencies:
core-js-pure: 3.45.1
'@babel/runtime@7.28.6': {}
'@babel/runtime@7.28.4': {}
'@babel/template@7.27.2':
dependencies:
@@ -6167,9 +6187,9 @@ snapshots:
'@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.6)':
dependencies:
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1)
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0)
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
'@csstools/postcss-color-function-display-p3-linear@1.0.1(postcss@8.5.6)':
dependencies:
@@ -6275,9 +6295,9 @@ snapshots:
'@csstools/postcss-is-pseudo-class@5.0.3(postcss@8.5.6)':
dependencies:
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1)
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0)
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
'@csstools/postcss-light-dark-function@2.0.11(postcss@8.5.6)':
dependencies:
@@ -6369,7 +6389,7 @@ snapshots:
'@csstools/postcss-scope-pseudo-class@4.0.1(postcss@8.5.6)':
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
'@csstools/postcss-sign-functions@1.1.4(postcss@8.5.6)':
dependencies:
@@ -6402,13 +6422,13 @@ snapshots:
dependencies:
postcss: 8.5.6
'@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.1)':
'@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.0)':
dependencies:
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
'@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.1)':
'@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.0)':
dependencies:
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
'@csstools/utilities@2.0.0(postcss@8.5.6)':
dependencies:
@@ -6444,7 +6464,7 @@ snapshots:
'@babel/preset-env': 7.28.3(@babel/core@7.28.4)
'@babel/preset-react': 7.27.1(@babel/core@7.28.4)
'@babel/preset-typescript': 7.27.1(@babel/core@7.28.4)
'@babel/runtime': 7.28.6
'@babel/runtime': 7.28.4
'@babel/runtime-corejs3': 7.28.4
'@babel/traverse': 7.28.4
'@docusaurus/logger': 3.9.1
@@ -7252,6 +7272,15 @@ snapshots:
dependencies:
'@hapi/hoek': 9.3.0
'@isaacs/cliui@8.0.2':
dependencies:
string-width: 5.1.2
string-width-cjs: string-width@4.2.3
strip-ansi: 7.1.2
strip-ansi-cjs: strip-ansi@6.0.1
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
'@jest/schemas@29.6.3':
dependencies:
'@sinclair/typebox': 0.27.8
@@ -7440,10 +7469,13 @@ snapshots:
'@nodelib/fs.walk@1.2.8':
dependencies:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.20.1
fastq: 1.19.1
'@opentelemetry/api@1.9.0': {}
'@pkgjs/parseargs@0.11.0':
optional: true
'@pnpm/config.env-replace@1.1.0': {}
'@pnpm/network.ca-file@1.0.2':
@@ -7474,7 +7506,7 @@ snapshots:
'@slorber/react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.28.6
'@babel/runtime': 7.28.4
invariant: 2.2.4
prop-types: 15.8.1
react: 18.3.1
@@ -7727,7 +7759,7 @@ snapshots:
'@types/sax@1.2.7':
dependencies:
'@types/node': 24.5.2
'@types/node': 17.0.45
'@types/send@0.17.5':
dependencies:
@@ -8076,6 +8108,10 @@ snapshots:
balanced-match: 1.0.2
concat-map: 0.0.1
brace-expansion@2.0.2:
dependencies:
balanced-match: 1.0.2
braces@3.0.3:
dependencies:
fill-range: 7.1.1
@@ -8362,7 +8398,7 @@ snapshots:
css-blank-pseudo@7.0.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
css-declaration-sorter@7.3.0(postcss@8.5.6):
dependencies:
@@ -8370,9 +8406,9 @@ snapshots:
css-has-pseudo@7.0.3(postcss@8.5.6):
dependencies:
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1)
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0)
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-value-parser: 4.2.0
css-loader@6.11.0(webpack@5.101.3):
@@ -8845,7 +8881,7 @@ snapshots:
fast-uri@3.1.0: {}
fastq@1.20.1:
fastq@1.19.1:
dependencies:
reusify: 1.1.0
@@ -8857,10 +8893,6 @@ snapshots:
dependencies:
websocket-driver: 0.7.4
fdir@6.5.0(picomatch@4.0.3):
optionalDependencies:
picomatch: 4.0.3
feed@4.2.2:
dependencies:
xml-js: 1.6.11
@@ -8907,6 +8939,11 @@ snapshots:
optionalDependencies:
debug: 4.4.3
foreground-child@3.3.1:
dependencies:
cross-spawn: 7.0.6
signal-exit: 4.1.0
form-data-encoder@2.1.4: {}
format@0.2.2: {}
@@ -8974,6 +9011,15 @@ snapshots:
glob-to-regexp@0.4.1: {}
glob@10.4.5:
dependencies:
foreground-child: 3.3.1
jackspeak: 3.4.3
minimatch: 9.0.5
minipass: 7.1.2
package-json-from-dist: 1.0.1
path-scurry: 1.11.1
global-dirs@3.0.1:
dependencies:
ini: 2.0.0
@@ -9140,7 +9186,7 @@ snapshots:
history@4.10.1:
dependencies:
'@babel/runtime': 7.28.6
'@babel/runtime': 7.28.4
loose-envify: 1.4.0
resolve-pathname: 3.0.0
tiny-invariant: 1.3.3
@@ -9406,6 +9452,12 @@ snapshots:
isobject@3.0.1: {}
jackspeak@3.4.3:
dependencies:
'@isaacs/cliui': 8.0.2
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
jest-util@29.7.0:
dependencies:
'@jest/types': 29.6.3
@@ -9528,6 +9580,8 @@ snapshots:
lowercase-keys@3.0.0: {}
lru-cache@10.4.3: {}
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
@@ -10099,8 +10153,14 @@ snapshots:
dependencies:
brace-expansion: 1.1.12
minimatch@9.0.5:
dependencies:
brace-expansion: 2.0.2
minimist@1.2.8: {}
minipass@7.1.2: {}
mrmime@2.0.1: {}
ms@2.0.0: {}
@@ -10239,6 +10299,8 @@ snapshots:
dependencies:
p-finally: 1.0.0
package-json-from-dist@1.0.1: {}
package-json@8.1.1:
dependencies:
got: 12.6.1
@@ -10302,6 +10364,11 @@ snapshots:
path-parse@1.0.7: {}
path-scurry@1.11.1:
dependencies:
lru-cache: 10.4.3
minipass: 7.1.2
path-to-regexp@0.1.12: {}
path-to-regexp@1.9.0:
@@ -10316,8 +10383,6 @@ snapshots:
picomatch@2.3.1: {}
picomatch@4.0.3: {}
pify@2.3.0: {}
pirates@4.0.7: {}
@@ -10329,7 +10394,7 @@ snapshots:
postcss-attribute-case-insensitive@7.0.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-calc@9.0.1(postcss@8.5.6):
dependencies:
@@ -10400,12 +10465,12 @@ snapshots:
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
'@csstools/css-tokenizer': 3.0.4
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-dir-pseudo-class@9.0.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-discard-comments@6.0.2(postcss@8.5.6):
dependencies:
@@ -10438,12 +10503,12 @@ snapshots:
postcss-focus-visible@10.0.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-focus-within@9.0.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-font-variant@5.0.0(postcss@8.5.6):
dependencies:
@@ -10464,7 +10529,7 @@ snapshots:
postcss: 8.5.6
postcss-value-parser: 4.2.0
read-cache: 1.0.0
resolve: 1.22.11
resolve: 1.22.10
postcss-js@4.1.0(postcss@8.5.6):
dependencies:
@@ -10480,13 +10545,12 @@ snapshots:
'@csstools/utilities': 2.0.0(postcss@8.5.6)
postcss: 8.5.6
postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(yaml@2.8.1):
postcss-load-config@4.0.2(postcss@8.5.6):
dependencies:
lilconfig: 3.1.3
optionalDependencies:
jiti: 1.21.7
postcss: 8.5.6
yaml: 2.8.1
optionalDependencies:
postcss: 8.5.6
postcss-loader@7.3.4(postcss@8.5.6)(typescript@5.2.2)(webpack@5.101.3):
dependencies:
@@ -10555,13 +10619,13 @@ snapshots:
dependencies:
icss-utils: 5.1.0(postcss@8.5.6)
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-value-parser: 4.2.0
postcss-modules-scope@3.2.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-modules-values@4.0.0(postcss@8.5.6):
dependencies:
@@ -10575,10 +10639,10 @@ snapshots:
postcss-nesting@13.0.2(postcss@8.5.6):
dependencies:
'@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.1)
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1)
'@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.0)
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0)
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-normalize-charset@6.0.2(postcss@8.5.6):
dependencies:
@@ -10723,7 +10787,7 @@ snapshots:
postcss-pseudo-class-any-link@10.0.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-reduce-idents@6.0.3(postcss@8.5.6):
dependencies:
@@ -10748,14 +10812,14 @@ snapshots:
postcss-selector-not@8.0.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.1
postcss-selector-parser: 7.1.0
postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss-selector-parser@7.1.1:
postcss-selector-parser@7.1.0:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
@@ -10879,19 +10943,19 @@ snapshots:
react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.101.3):
dependencies:
'@babel/runtime': 7.28.6
'@babel/runtime': 7.28.4
react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)'
webpack: 5.101.3
react-router-config@5.1.1(react-router@5.3.4(react@18.3.1))(react@18.3.1):
dependencies:
'@babel/runtime': 7.28.6
'@babel/runtime': 7.28.4
react: 18.3.1
react-router: 5.3.4(react@18.3.1)
react-router-dom@5.3.4(react@18.3.1):
dependencies:
'@babel/runtime': 7.28.6
'@babel/runtime': 7.28.4
history: 4.10.1
loose-envify: 1.4.0
prop-types: 15.8.1
@@ -10902,7 +10966,7 @@ snapshots:
react-router@5.3.4(react@18.3.1):
dependencies:
'@babel/runtime': 7.28.6
'@babel/runtime': 7.28.4
history: 4.10.1
hoist-non-react-statics: 3.3.2
loose-envify: 1.4.0
@@ -11104,7 +11168,7 @@ snapshots:
resolve-pathname@3.0.0: {}
resolve@1.22.11:
resolve@1.22.10:
dependencies:
is-core-module: 2.16.1
path-parse: 1.0.7
@@ -11290,6 +11354,8 @@ snapshots:
signal-exit@3.0.7: {}
signal-exit@4.1.0: {}
sirv@2.0.4:
dependencies:
'@polka/url': 1.0.0-next.29
@@ -11431,14 +11497,14 @@ snapshots:
postcss: 8.5.6
postcss-selector-parser: 6.1.2
sucrase@3.35.1:
sucrase@3.35.0:
dependencies:
'@jridgewell/gen-mapping': 0.3.13
commander: 4.1.1
glob: 10.4.5
lines-and-columns: 1.2.4
mz: 2.7.0
pirates: 4.0.7
tinyglobby: 0.2.15
ts-interface-checker: 0.1.13
supports-color@7.2.0:
@@ -11469,7 +11535,7 @@ snapshots:
react: 18.3.1
use-sync-external-store: 1.5.0(react@18.3.1)
tailwindcss@3.4.19(yaml@2.8.1):
tailwindcss@3.4.17:
dependencies:
'@alloc/quick-lru': 5.2.0
arg: 5.0.2
@@ -11488,14 +11554,13 @@ snapshots:
postcss: 8.5.6
postcss-import: 15.1.0(postcss@8.5.6)
postcss-js: 4.1.0(postcss@8.5.6)
postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(yaml@2.8.1)
postcss-load-config: 4.0.2(postcss@8.5.6)
postcss-nested: 6.2.0(postcss@8.5.6)
postcss-selector-parser: 6.1.2
resolve: 1.22.11
sucrase: 3.35.1
resolve: 1.22.10
sucrase: 3.35.0
transitivePeerDependencies:
- tsx
- yaml
- ts-node
tapable@2.2.3: {}
@@ -11535,11 +11600,6 @@ snapshots:
tiny-warning@1.0.3: {}
tinyglobby@0.2.15:
dependencies:
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
tinypool@1.1.1: {}
to-regex-range@5.0.1:
@@ -11905,8 +11965,7 @@ snapshots:
yallist@3.1.1: {}
yaml@2.8.1:
optional: true
yaml@2.8.1: {}
yocto-queue@1.2.1: {}

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",

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();