This commit is contained in:
Min Idzelis 2025-06-24 21:37:42 +00:00
parent 1923f1a887
commit 839db1e2c4
51 changed files with 41356 additions and 61718 deletions

View File

@ -73,10 +73,7 @@ install_dependencies() {
log "Installing dependencies"
(
cd "${IMMICH_WORKSPACE}" || exit 1
run_cmd make install-server
run_cmd make install-sdk
run_cmd make build-sdk
run_cmd make install-web
run_cmd make install-server install-sdk build-sdk install-web
)
log ""
}

View File

@ -11,7 +11,7 @@ cd "${IMMICH_WORKSPACE}/server" || (
)
while true; do
run_cmd node ./node_modules/.bin/nest start --debug "0.0.0.0:9230" --watch
run_cmd npx nest start --debug "0.0.0.0:9230" --watch
log "Nest API Server crashed with exit code $?. Respawning in 3s ..."
sleep 3
done

View File

@ -16,7 +16,7 @@ until curl --output /dev/null --silent --head --fail "http://127.0.0.1:${IMMICH_
done
while true; do
run_cmd node ./node_modules/.bin/vite dev --host 0.0.0.0 --port "${DEV_PORT}"
run_cmd npx vite dev --host 0.0.0.0 --port "${DEV_PORT}"
log "Web crashed with exit code $?. Respawning in 3s ..."
sleep 3
done

View File

@ -58,14 +58,14 @@ jobs:
with:
node-version-file: './docs/.nvmrc'
- name: Run npm install
run: npm ci
- name: Run install
run: pnpm install
- name: Check formatting
run: npm run format
run: pnpm run format
- name: Run build
run: npm run build
run: pnpm run build
- name: Upload build output
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2

View File

@ -85,23 +85,23 @@ jobs:
with:
node-version-file: './server/.nvmrc'
- name: Run npm install
run: npm ci
- name: Run package manager install
run: pnpm install
- name: Run linter
run: npm run lint
run: pnpm run lint
if: ${{ !cancelled() }}
- name: Run formatter
run: npm run format
run: pnpm run format
if: ${{ !cancelled() }}
- name: Run tsc
run: npm run check
run: pnpm run check
if: ${{ !cancelled() }}
- name: Run small tests & coverage
run: npm test
run: pnpm test
if: ${{ !cancelled() }}
cli-unit-tests:
@ -127,11 +127,11 @@ jobs:
node-version-file: './cli/.nvmrc'
- name: Setup typescript-sdk
run: npm ci && npm run build
run: pnpm install && pnpm run build
working-directory: ./open-api/typescript-sdk
- name: Install deps
run: npm ci
run: pnpm install
- name: Run linter
run: npm run lint

View File

@ -34,39 +34,50 @@ open-api-typescript:
cd ./open-api && bash ./bin/generate-open-api.sh typescript
sql:
npm --prefix server run sync:sql
pnpm --filter immich run sync:sql
attach-server:
docker exec -it docker_immich-server_1 sh
renovate:
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
MODULES = e2e server web cli sdk docs .github
# package names mapping function
# cli = @immich/cli
# docs = documentation
# e2e = immich-e2e
# open-api/typescript-sdk = @immich/sdk
# server = immich
# web = immich-web
map-package = $(subst sdk,@immich/sdk,$(subst cli,@immich/cli,$(subst docs,documentation,$(subst e2e,immich-e2e,$(subst server,immich,$(subst web,immich-web,$1))))))
audit-%:
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix
pnpm --filter $(call map-package,$*) audit fix
install-%:
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) i
pnpm --filter $(call map-package,$*) install
build-cli: build-sdk
build-web: build-sdk
build-%: install-%
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run build
pnpm --filter $(call map-package,$*) run build
format-%:
npm --prefix $* run format:fix
pnpm --filter $(call map-package,$*) run format:fix
lint-%:
npm --prefix $* run lint:fix
pnpm --filter $(call map-package,$*) run lint:fix
lint-web:
pnpm --filter $(call map-package,$*) run lint:p
check-%:
npm --prefix $* run check
pnpm --filter $(call map-package,$*) run check
check-web:
npm --prefix web run check:typescript
npm --prefix web run check:svelte
pnpm --filter immich-web run check:typescript
pnpm --filter immich-web run check:svelte
test-%:
npm --prefix $* run test
pnpm --filter $(call map-package,$*) run test
test-e2e:
docker compose -f ./e2e/docker-compose.yml build
npm --prefix e2e run test
npm --prefix e2e run test:web
pnpm --filter immich-e2e run test
pnpm --filter immich-e2e run test:web
test-medium:
docker run \
--rm \
@ -76,23 +87,36 @@ test-medium:
-v ./server/tsconfig.json:/usr/src/app/tsconfig.json \
-e NODE_ENV=development \
immich-server:latest \
-c "npm ci && npm run test:medium -- --run"
-c "pnpm run test:medium -- --run"
test-medium-dev:
docker exec -it immich_server /bin/sh -c "npm run test:medium"
docker exec -it immich_server /bin/sh -c "pnpm run test:medium"
build-all: $(foreach M,$(filter-out e2e .github,$(MODULES)),build-$M) ;
install-all: $(foreach M,$(MODULES),install-$M) ;
check-all: $(foreach M,$(filter-out sdk cli docs .github,$(MODULES)),check-$M) ;
lint-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),lint-$M) ;
format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ;
audit-all: $(foreach M,$(MODULES),audit-$M) ;
hygiene-all: lint-all format-all check-all sql audit-all;
test-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),test-$M) ;
install-all:
pnpm install
build-all: $(foreach M,$(filter-out e2e docs .github,$(MODULES)),build-$M) ;
check-all:
pnpm -r --filter '!docs' run "/^(check|check\:svelte|check\:typescript)$/"
lint-all:
pnpm -r --filter '!docs' run lint:fix
format-all:
pnpm -r --filter '!docs' run format:fix
audit-all:
pnpm -r --filter '!docs' audit fix
hygiene-all: audit-all
pnpm -r --filter '!docs' run "/(format:fix|check|check:svelte|check:typescript|sql)/"
test-all:
pnpm -r --filter '!docs' run "/^test/"
prune:
pnpm store prune
clean:
find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
find . -name "node_modules" -type d -prune -exec rm -rf {} +
find . -name "dist" -type d -prune -exec rm -rf '{}' +
find . -name "build" -type d -prune -exec rm -rf '{}' +
find . -name "svelte-kit" -type d -prune -exec rm -rf '{}' +
docker compose -f ./docker/docker-compose.dev.yml rm -v -f || true
docker compose -f ./e2e/docker-compose.yml rm -v -f || true
command -v docker >/dev/null 2>&1 && docker compose -f ./docker/docker-compose.dev.yml rm -v -f || true
command -v docker >/dev/null 2>&1 && docker compose -f ./e2e/docker-compose.yml rm -v -f || true

View File

@ -6,8 +6,10 @@ Please see the [Immich CLI documentation](https://immich.app/docs/features/comma
Before building the CLI, you must build the immich server and the open-api client. To build the server run the following in the server folder:
$ npm install
$ npm run build
# if you don't have node installed
$ npm install -g pnpm
$ pnpm install
$ pnpm run build
Then, to build the open-api client run the following in the open-api folder:
@ -15,7 +17,9 @@ Then, to build the open-api client run the following in the open-api folder:
To run the Immich CLI from source, run the following in the cli folder:
$ npm install
# if you don't have node installed
$ npm install -g pnpm
$ pnpm install
$ npm run build
$ ts-node .

2
cli/bin/immich Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env node
require('../dist/index.js');

4517
cli/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
"type": "module",
"exports": "./dist/index.js",
"bin": {
"immich": "dist/index.js"
"immich": "./bin/immich"
},
"license": "GNU Affero General Public License version 3",
"keywords": [

2823
cli/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

22
docker/.env.bak Normal file
View File

@ -0,0 +1,22 @@
# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables
# The location where your uploaded files are stored
UPLOAD_LOCATION=/LUNA/ALPHA/MEDIA/PHOTOS/immich_dev_library
# The location where your database files are stored. Network shares are not supported for the database
DB_DATA_LOCATION=./postgres
# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
# TZ=Etc/UTC
# The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=release
# Connection secret for postgres. You should change it to a random password
# Please use only the characters `A-Za-z0-9`, without special characters or spaces
DB_PASSWORD=postgres
# The values below this line do not need to be changed
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

View File

@ -28,7 +28,7 @@ services:
restart: unless-stopped
volumes:
- ../server:/usr/src/app
- ../open-api:/usr/src/open-api
- ../open-api/:/usr/src/open-api
- ${UPLOAD_LOCATION}/photos:/usr/src/app/upload
- ${UPLOAD_LOCATION}/photos/upload:/usr/src/app/upload/upload
- /usr/src/app/node_modules
@ -69,7 +69,8 @@ services:
# Needed for rootless docker setup, see https://github.com/moby/moby/issues/45919
# user: 0:0
build:
context: ../web
context: ../
dockerfile: web/Dockerfile
command: ['/usr/src/app/bin/immich-web']
env_file:
- .env
@ -79,7 +80,7 @@ services:
volumes:
- ../web:/usr/src/app
- ../i18n:/usr/src/i18n
- ../open-api/:/usr/src/open-api/
- ../open-api/:/usr/src/open-api
# - ../../ui:/usr/ui
- /usr/src/app/node_modules
ulimits:

View File

@ -5,7 +5,7 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati
### Installation
```
$ npm install
$ pnpm install
```
### Local Development

View File

@ -150,12 +150,10 @@ for more info read the [release notes](https://github.com/immich-app/immich/rele
- Preview images (small thumbnails and large previews) for each asset and thumbnails for recognized faces.
- Stored in `UPLOAD_LOCATION/thumbs/<userID>`.
- **Encoded Assets:**
- Videos that have been re-encoded from the original for wider compatibility. The original is not removed.
- Stored in `UPLOAD_LOCATION/encoded-video/<userID>`.
- **Postgres**
- The Immich database containing all the information to allow the system to function properly.
**Note:** This folder will only appear to users who have made the changes mentioned in [v1.102.0](https://github.com/immich-app/immich/discussions/8930) (an optional, non-mandatory change) or who started with this version.
- Stored in `DB_DATA_LOCATION`.
@ -201,7 +199,6 @@ When you turn off the storage template engine, it will leave the assets in `UPLO
- Temporarily located in `UPLOAD_LOCATION/upload/<userID>`.
- Transferred to `UPLOAD_LOCATION/library/<userID>` upon successful upload.
- **Postgres**
- The Immich database containing all the information to allow the system to function properly.
**Note:** This folder will only appear to users who have made the changes mentioned in [v1.102.0](https://github.com/immich-app/immich/discussions/8930) (an optional, non-mandatory change) or who started with this version.
- Stored in `DB_DATA_LOCATION`.

View File

@ -20,7 +20,6 @@ Immich supports 3rd party authentication via [OpenID Connect][oidc] (OIDC), an i
Before enabling OAuth in Immich, a new client application needs to be configured in the 3rd-party authentication server. While the specifics of this setup vary from provider to provider, the general approach should be the same.
1. Create a new (Client) Application
1. The **Provider** type should be `OpenID Connect` or `OAuth2`
2. The **Client type** should be `Confidential`
3. The **Application** type should be `Web`
@ -29,7 +28,6 @@ Before enabling OAuth in Immich, a new client application needs to be configured
2. Configure Redirect URIs/Origins
The **Sign-in redirect URIs** should include:
- `app.immich:///oauth-callback` - for logging in with OAuth from the [Mobile App](/docs/features/mobile-app.mdx)
- `http://DOMAIN:PORT/auth/login` - for logging in with OAuth from the Web Client
- `http://DOMAIN:PORT/user-settings` - for manually linking OAuth in the Web Client
@ -37,21 +35,17 @@ Before enabling OAuth in Immich, a new client application needs to be configured
Redirect URIs should contain all the domains you will be using to access Immich. Some examples include:
Mobile
- `app.immich:///oauth-callback` (You **MUST** include this for iOS and Android mobile apps to work properly)
Localhost
- `http://localhost:2283/auth/login`
- `http://localhost:2283/user-settings`
Local IP
- `http://192.168.0.200:2283/auth/login`
- `http://192.168.0.200:2283/user-settings`
Hostname
- `https://immich.example.com/auth/login`
- `https://immich.example.com/user-settings`

View File

@ -199,13 +199,11 @@ To use your SSH key for commit signing, see the [GitHub guide on SSH commit sign
When the Dev Container starts, it automatically:
1. **Runs post-create script** (`container-server-post-create.sh`):
- Adjusts file permissions for the `node` user
- Installs dependencies: `npm install` in all packages
- Installs dependencies: `pnpm install` in all packages
- Builds TypeScript SDK: `npm run build` in `open-api/typescript-sdk`
2. **Starts development servers** via VS Code tasks:
- `Immich API Server (Nest)` - API server with hot-reloading on port 2283
- `Immich Web Server (Vite)` - Web frontend with hot-reloading on port 3000
- Both servers watch for file changes and recompile automatically
@ -335,14 +333,12 @@ make install-all # Install all dependencies
The Dev Container is pre-configured for debugging:
1. **API Server Debugging**:
- Set breakpoints in VS Code
- Press `F5` or use "Run and Debug" panel
- Select "Attach to Server" configuration
- Debug port: 9231
2. **Worker Debugging**:
- Use "Attach to Workers" configuration
- Debug port: 9230
@ -428,7 +424,6 @@ While the Dev Container focuses on server and web development, you can connect m
```
2. **Configure mobile app**:
- Server URL: `http://YOUR_IP:2283/api`
- Ensure firewall allows port 2283

View File

@ -56,7 +56,7 @@ If you only want to do web development connected to an existing, remote backend,
1. Build the Immich SDK - `cd open-api/typescript-sdk && npm i && npm run build && cd -`
2. Enter the web directory - `cd web/`
3. Install web dependencies - `npm i`
3. Install web dependencies - `pnpm i`
4. Start the web development server
```bash

View File

@ -5,7 +5,7 @@
### Unit tests
Unit are run by calling `npm run test` from the `server/` directory.
You need to run `npm install` (in `server/`) before _once_.
You need to run `pnpm install` (in `server/`) before _once_.
### End to end tests

View File

@ -75,7 +75,6 @@ alt="Select Plugins > Compose.Manager > Add New Stack > Label it Immich"
5. Click "**Save Changes**", you will be prompted to edit stack UI labels, just leave this blank and click "**Ok**"
6. Select the cog ⚙️ next to Immich, click "**Edit Stack**", then click "**Env File**"
7. Paste the entire contents of the [Immich example.env](https://github.com/immich-app/immich/releases/latest/download/example.env) file into the Unraid editor, then **before saving** edit the following:
- `UPLOAD_LOCATION`: Create a folder in your Images Unraid share and place the **absolute** location here > For example my _"images"_ share has a folder within it called _"immich"_. If I browse to this directory in the terminal and type `pwd` the output is `/mnt/user/images/immich`. This is the exact value I need to enter as my `UPLOAD_LOCATION`
- `DB_DATA_LOCATION`: Change this to use an Unraid share (preferably a cache pool, e.g. `/mnt/user/appdata/postgresql/data`). This uses the `appdata` share. Do also create the `postgresql` folder, by running `mkdir /mnt/user/{share_location}/postgresql/data`. If left at default it will try to use Unraid's `/boot/config/plugins/compose.manager/projects/[stack_name]/postgres` folder which it doesn't have permissions to, resulting in this container continuously restarting.

20954
docs/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
"dependencies": {
"@docusaurus/core": "~3.7.0",
"@docusaurus/preset-classic": "~3.7.0",
"@docusaurus/theme-common": "~3.7.0",
"@mdi/js": "^7.3.67",
"@mdi/react": "^1.6.1",
"@mdx-js/react": "^3.0.0",
@ -26,6 +27,7 @@
"clsx": "^2.0.0",
"docusaurus-lunr-search": "^3.3.2",
"docusaurus-preset-openapi": "^0.7.5",
"lunr": "^2.3.9",
"postcss": "^8.4.25",
"prism-react-renderer": "^2.3.1",
"raw-loader": "^4.0.2",

15047
docs/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

6874
e2e/package-lock.json generated

File diff suppressed because it is too large Load Diff

4212
e2e/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

@ -1 +1 @@
Subproject commit 8885d6d01c12242785b6ea68f4a277334f60bc90
Subproject commit 18736fc27a80c99c68e856cdb4f842bc81ed3445

View File

@ -5,7 +5,7 @@ A TypeScript SDK for interfacing with the [Immich](https://immich.app/) API.
## Install
```bash
npm i --save @immich/sdk
pnpm i --save @immich/sdk
```
## Usage

View File

@ -1,57 +0,0 @@
{
"name": "@immich/sdk",
"version": "1.135.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@immich/sdk",
"version": "1.135.3",
"license": "GNU Affero General Public License version 3",
"dependencies": {
"@oazapfts/runtime": "^1.0.2"
},
"devDependencies": {
"@types/node": "^22.15.31",
"typescript": "^5.3.3"
}
},
"node_modules/@oazapfts/runtime": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@oazapfts/runtime/-/runtime-1.0.4.tgz",
"integrity": "sha512-7t6C2shug/6tZhQgkCa532oTYBLEnbASV/i1SG1rH2GB4h3aQQujYciYSPT92hvN4IwTe8S2hPkN/6iiOyTlCg==",
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.15.32",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.32.tgz",
"integrity": "sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true,
"license": "MIT"
}
}
}

View File

@ -29,5 +29,6 @@
},
"volta": {
"node": "22.16.0"
}
},
"packageManager": "pnpm@10.12.3+sha512.467df2c586056165580ad6dfb54ceaad94c5a30f80893ebdec5a44c5aa73c205ae4a5bb9d5ed6bb84ea7c249ece786642bbb49d06a307df218d03da41c317417"
}

48
open-api/typescript-sdk/pnpm-lock.yaml generated Normal file
View File

@ -0,0 +1,48 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@oazapfts/runtime':
specifier: ^1.0.2
version: 1.0.4
devDependencies:
'@types/node':
specifier: ^22.15.31
version: 22.15.32
typescript:
specifier: ^5.3.3
version: 5.8.3
packages:
'@oazapfts/runtime@1.0.4':
resolution: {integrity: sha512-7t6C2shug/6tZhQgkCa532oTYBLEnbASV/i1SG1rH2GB4h3aQQujYciYSPT92hvN4IwTe8S2hPkN/6iiOyTlCg==}
'@types/node@22.15.32':
resolution: {integrity: sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==}
typescript@5.8.3:
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
engines: {node: '>=14.17'}
hasBin: true
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
snapshots:
'@oazapfts/runtime@1.0.4': {}
'@types/node@22.15.32':
dependencies:
undici-types: 6.21.0
typescript@5.8.3: {}
undici-types@6.21.0: {}

9
package.json Normal file
View File

@ -0,0 +1,9 @@
{
"name": "immich-workspace",
"version": "1.135.3",
"private": true,
"description": "Immich workspace root",
"devDependencies": {
"pnpm": "^10.12.1"
}
}

24
pnpm-lock.yaml generated Normal file
View File

@ -0,0 +1,24 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
devDependencies:
pnpm:
specifier: ^10.12.1
version: 10.12.2
packages:
pnpm@10.12.2:
resolution: {integrity: sha512-oyVAGFuWTuMLtOl55AWtxq9ZImtDjuTMGfnodzZnpm0wL1v+5go508rGnjXkuW5winHdACt+k1nEESoXIqwyPw==}
engines: {node: '>=18.12'}
hasBin: true
snapshots:
pnpm@10.12.2: {}

20
pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,20 @@
packages:
- cli
- docs
- e2e
- open-api/typescript-sdk
- server
- web
ignoredBuiltDependencies:
- '@tailwindcss/oxide'
- es5-ext
- esbuild
onlyBuiltDependencies:
- canvas
- sharp
sharedWorkspaceLockfile: false
shamefullyHoist: true
dedupePeerDependents: false

View File

@ -1,11 +1,15 @@
# dev build
FROM ghcr.io/immich-app/base-server-dev:202505131114@sha256:cf4507bbbf307e9b6d8ee9418993321f2b85867da8ce14d0a20ccaf9574cb995 AS dev
RUN apt-get install --no-install-recommends -yqq tini
ENV COREPACK_ENABLE_AUTO_PIN=0
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
RUN corepack enable && corepack install -g pnpm && apt-get install --no-install-recommends -yqq tini
RUN mkdir -p /pnpm/store && chmod 777 /pnpm/store && mkdir -p /usr/local/etc && echo "store-dir=/pnpm/store" >> /usr/local/etc/npmrc
WORKDIR /usr/src/app
COPY server/package.json server/package-lock.json ./
COPY server/package.json server/pnpm-lock.yaml server/pnpm-workspace.yaml ./
COPY server/patches ./patches
RUN npm ci && \
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install && \
# exiftool-vendored.pl, sharp-linux-x64 and sharp-linux-arm64 are the only ones we need
# they're marked as optional dependencies, so we need to copy them manually after pruning
rm -rf node_modules/@img/sharp-libvips* && \
@ -69,11 +73,17 @@ COPY --chmod=777 ../.devcontainer/mobile/container-mobile-post-create.sh /immich
RUN dart --disable-analytics
COPY . /tmp/immich
WORKDIR /tmp/immich
RUN make install-sdk build-sdk install-cli install-e2e install-web install-server
WORKDIR /usr/src/app
RUN rm -rf /tmp/immich
FROM dev AS prod
COPY server .
RUN npm run build
RUN npm prune --omit=dev --omit=optional
RUN pnpm run build
RUN pnpm prune --prod --no-optional
COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img
COPY --from=dev /usr/src/app/node_modules/exiftool-vendored.pl ./node_modules/exiftool-vendored.pl
@ -82,16 +92,16 @@ FROM node:22.16.0-alpine3.20@sha256:2289fb1fba0f4633b08ec47b94a89c7e20b829fc5679
WORKDIR /usr/src/open-api/typescript-sdk
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
RUN npm ci
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
COPY open-api/typescript-sdk/ ./
RUN npm run build
RUN pnpm run build
WORKDIR /usr/src/app
COPY web/package*.json web/svelte.config.js ./
RUN npm ci
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
COPY web ./
COPY i18n ../i18n
RUN npm run build
RUN pnpm run build
# prod build
@ -109,7 +119,7 @@ COPY server/resources resources
COPY server/package.json server/package-lock.json ./
COPY server/start*.sh ./
COPY "docker/scripts/get-cpus.sh" ./
RUN npm install -g @immich/cli && npm cache clean --force
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install -g @immich/cli
COPY LICENSE /licenses/LICENSE.txt
COPY LICENSE /LICENSE
ENV PATH="${PATH}:/usr/src/app/bin"

View File

@ -1,3 +1,3 @@
#!/usr/bin/env bash
node /usr/src/app/node_modules/.bin/nest start --debug "0.0.0.0:9230" --watch -- "$@"
pnpm exec nest start --debug "0.0.0.0:9230" --watch -- "$@"

18931
server/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,8 +32,7 @@
"kysely:codegen": "npx kysely-codegen --include-pattern=\"(public|vectors).*\" --dialect postgres --url postgres://postgres:postgres@localhost/immich --log-level debug --out-file=./src/db.d.ts",
"sync:open-api": "node ./dist/bin/sync-open-api.js",
"sync:sql": "node ./dist/bin/sync-sql.js",
"email:dev": "email dev -p 3050 --dir src/emails",
"postinstall": "patch-package"
"email:dev": "email dev -p 3050 --dir src/emails"
},
"dependencies": {
"@nestjs/bullmq": "^11.0.1",
@ -65,14 +64,14 @@
"bcrypt": "^6.0.0",
"body-parser": "^2.2.0",
"bullmq": "^5.51.0",
"chokidar": "^3.5.3",
"chokidar": "^4.0.3",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"compression": "^1.8.0",
"cookie": "^1.0.2",
"cookie-parser": "^1.4.7",
"cron": "^3.5.0",
"exiftool-vendored": "^28.3.1",
"exiftool-vendored": "^28.8.0",
"express": "^5.1.0",
"fast-glob": "^3.3.2",
"fluent-ffmpeg": "^2.1.2",
@ -108,13 +107,14 @@
"sharp": "^0.34.2",
"sirv": "^3.0.0",
"socket.io": "^4.8.1",
"tailwindcss-preset-email": "^1.3.2",
"tailwindcss-preset-email": "^1.4.0",
"thumbhash": "^0.1.1",
"typeorm": "^0.3.17",
"ua-parser-js": "^2.0.0",
"validator": "^13.12.0"
},
"devDependencies": {
"canvas": "^3.1.0",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.8.0",
"@nestjs/cli": "^11.0.2",
@ -156,7 +156,6 @@
"mock-fs": "^5.2.0",
"node-addon-api": "^8.3.1",
"node-gyp": "^11.2.0",
"patch-package": "^8.0.0",
"pngjs": "^7.0.0",
"prettier": "^3.0.2",
"prettier-plugin-organize-imports": "^4.0.0",
@ -164,6 +163,7 @@
"source-map-support": "^0.5.21",
"sql-formatter": "^15.0.0",
"supertest": "^7.1.0",
"tailwindcss": "^3.4.0",
"testcontainers": "^11.0.0",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.3.3",
@ -178,5 +178,6 @@
},
"overrides": {
"sharp": "^0.34.2"
}
},
"packageManager": "pnpm@10.12.3+sha512.467df2c586056165580ad6dfb54ceaad94c5a30f80893ebdec5a44c5aa73c205ae4a5bb9d5ed6bb84ea7c249ece786642bbb49d06a307df218d03da41c317417"
}

View File

@ -1,7 +1,7 @@
diff --git a/node_modules/postgres/cf/src/connection.js b/node_modules/postgres/cf/src/connection.js
index ee8b1e6..acf4566 100644
--- a/node_modules/postgres/cf/src/connection.js
+++ b/node_modules/postgres/cf/src/connection.js
diff --git a/cf/src/connection.js b/cf/src/connection.js
index ee8b1e69055bef090d322a66c7d792b5b502f47a..acf45662b35a8d01fa0d198faf6337d9f6808f3f 100644
--- a/cf/src/connection.js
+++ b/cf/src/connection.js
@@ -387,8 +387,10 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
}
@ -14,10 +14,10 @@ index ee8b1e6..acf4566 100644
query: { value: query.string, enumerable: options.debug },
parameters: { value: query.parameters, enumerable: options.debug },
args: { value: query.args, enumerable: options.debug },
diff --git a/node_modules/postgres/cjs/src/connection.js b/node_modules/postgres/cjs/src/connection.js
index f7f58d1..b7f2d65 100644
--- a/node_modules/postgres/cjs/src/connection.js
+++ b/node_modules/postgres/cjs/src/connection.js
diff --git a/cjs/src/connection.js b/cjs/src/connection.js
index f7f58d147f344cb7f2420c2bd24c6b7917162033..b7f2d657c9e1d5fbc7ce4735f61abae972959b1e 100644
--- a/cjs/src/connection.js
+++ b/cjs/src/connection.js
@@ -385,8 +385,10 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
}
@ -30,10 +30,10 @@ index f7f58d1..b7f2d65 100644
query: { value: query.string, enumerable: options.debug },
parameters: { value: query.parameters, enumerable: options.debug },
args: { value: query.args, enumerable: options.debug },
diff --git a/node_modules/postgres/src/connection.js b/node_modules/postgres/src/connection.js
index 97cc97e..26f508e 100644
--- a/node_modules/postgres/src/connection.js
+++ b/node_modules/postgres/src/connection.js
diff --git a/src/connection.js b/src/connection.js
index 97cc97e1576d6c75f958c66e9cecbf8cd11ed450..26f508e2de12f09f27838aca8d88fa4721fe6677 100644
--- a/src/connection.js
+++ b/src/connection.js
@@ -385,8 +385,10 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
}

12102
server/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
ignoredBuiltDependencies:
- '@tailwindcss/oxide'
- es5-ext
- esbuild
onlyBuiltDependencies:
- canvas
- sharp

View File

@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common';
import archiver from 'archiver';
import chokidar, { WatchOptions } from 'chokidar';
import chokidar, { ChokidarOptions } from 'chokidar';
import { escapePath, glob, globStream } from 'fast-glob';
import { constants, createReadStream, createWriteStream, existsSync, mkdirSync } from 'node:fs';
import fs from 'node:fs/promises';
@ -219,14 +219,14 @@ export class StorageRepository {
}
}
watch(paths: string[], options: WatchOptions, events: Partial<WatchEvents>) {
watch(paths: string[], options: ChokidarOptions, events: Partial<WatchEvents>) {
const watcher = chokidar.watch(paths, options);
watcher.on('ready', () => events.onReady?.());
watcher.on('add', (path) => events.onAdd?.(path));
watcher.on('change', (path) => events.onChange?.(path));
watcher.on('unlink', (path) => events.onUnlink?.(path));
watcher.on('error', (error) => events.onError?.(error));
watcher.on('error', (error) => events.onError?.(error as Error));
return () => watcher.close();
}

View File

@ -1,4 +1,4 @@
import { WatchOptions } from 'chokidar';
import { ChokidarOptions } from 'chokidar';
import { StorageCore } from 'src/cores/storage.core';
import { StorageRepository, WatchEvents } from 'src/repositories/storage.repository';
import { RepositoryInterface } from 'src/types';
@ -11,7 +11,7 @@ interface MockWatcherOptions {
export const makeMockWatcher =
({ items, close }: MockWatcherOptions) =>
(paths: string[], options: WatchOptions, events: Partial<WatchEvents>) => {
(paths: string[], options: ChokidarOptions, events: Partial<WatchEvents>) => {
events.onReady?.();
for (const item of items || []) {
switch (item.event) {
@ -29,6 +29,7 @@ export const makeMockWatcher =
}
case 'error': {
events.onError?.(new Error(item.value));
break;
}
}
}

View File

@ -1 +0,0 @@
engine-strict=true

View File

@ -1,10 +1,17 @@
FROM node:22.16.0-alpine3.20@sha256:2289fb1fba0f4633b08ec47b94a89c7e20b829fc5679f9b7b298eaa2f1ed8b7e
RUN apk add --no-cache tini
ENV COREPACK_ENABLE_AUTO_PIN=0
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
RUN corepack enable && corepack install -g pnpm && apk add --no-cache tini
RUN mkdir -p /pnpm/store && chown node:node -R /pnpm && mkdir -p /usr/local/etc && echo "store-dir=/pnpm/store" >> /usr/local/etc/npmrc
USER node
WORKDIR /usr/src/app
COPY --chown=node:node package*.json ./
RUN npm ci
COPY --chown=node:node \
../open-api/typescript-sdk/package.json \
../open-api/typescript-sdk/pnpm-lock.yaml \
../open-api/typescript-sdk/
COPY --chown=node:node ./web/package.json ./web/pnpm-lock.yaml ./web/pnpm-workspace.yaml ./
COPY pnpm-workspace.yaml /usr/src
RUN pnpm install --frozen-lockfile
ENV CHOKIDAR_USEPOLLING=true
EXPOSE 24678
EXPOSE 3000

View File

@ -1,10 +1,11 @@
#!/usr/bin/env sh
TYPESCRIPT_SDK=/usr/src/open-api/typescript-sdk
npm --prefix "$TYPESCRIPT_SDK" install
npm --prefix "$TYPESCRIPT_SDK" run build
TYPESCRIPT_SDK=@immich/sdk
echo "Building TypeScript SDK..."
(cd ../open-api/typescript-sdk && pnpm run build)
echo "Installing Deps ..."
pnpm install
COUNT=0
UPSTREAM="${IMMICH_SERVER_URL:-http://immich-server:2283/}"
@ -18,4 +19,4 @@ done
echo "Connected to $UPSTREAM"
node ./node_modules/.bin/vite dev --host 0.0.0.0 --port 3000
pnpm exec vite dev --host 0.0.0.0 --port 3000

10263
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,9 @@
"@zoom-image/svelte": "^0.3.0",
"dom-to-image": "^2.6.0",
"fabric": "^6.5.4",
"geojson": "^0.5.0",
"handlebars": "^4.7.8",
"happy-dom": "^18.0.1",
"intl-messageformat": "^10.7.11",
"justified-layout": "^4.1.0",
"lodash-es": "^4.17.21",
@ -103,5 +105,6 @@
},
"volta": {
"node": "22.16.0"
}
},
"packageManager": "pnpm@10.12.3+sha512.467df2c586056165580ad6dfb54ceaad94c5a30f80893ebdec5a44c5aa73c205ae4a5bb9d5ed6bb84ea7c249ece786642bbb49d06a307df218d03da41c317417"
}

6872
web/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

8
web/pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,8 @@
ignoredBuiltDependencies:
- '@tailwindcss/oxide'
- es5-ext
- esbuild
onlyBuiltDependencies:
- canvas
- sharp

View File

@ -58,7 +58,8 @@ describe('get asset filename', () => {
});
describe('copy image to clipboard', () => {
it('should not allow copy image to clipboard', () => {
expect(canCopyImageToClipboard()).toEqual(false);
// This test is dubious, as it totally on the environment where the test is run which is mocked.
it('should allow copy image to clipboard', () => {
expect(canCopyImageToClipboard()).toEqual(true);
});
});

View File

@ -53,7 +53,7 @@ export default defineConfig({
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
globals: true,
environment: 'jsdom',
environment: 'happy-dom',
setupFiles: ['./src/test-data/setup.ts'],
sequence: {
hooks: 'list',