chore(deps): update dependency eslint-plugin-unicorn to v75 (#31721)

Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
This commit is contained in:
renovate[bot]
2026-09-23 18:19:03 +00:00
committed by GitHub
co-authored by Daniel Dietzler
parent 92f498d23d
commit e66f2c7615
42 changed files with 300 additions and 288 deletions
+5
View File
@@ -55,6 +55,11 @@ export default typescriptEslint.config([
'unicorn/prefer-event-target': 'off',
'unicorn/no-thenable': 'off',
'object-shorthand': ['error', 'always'],
'unicorn/prefer-combined-guards': 'off',
'unicorn/prefer-ternary': 'off',
'unicorn/prefer-early-return': 'off',
'unicorn/prefer-continue': 'off',
'unicorn/no-immediate-mutation': 'off',
},
},
]);
+1 -1
View File
@@ -40,7 +40,7 @@
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^73.0.0",
"eslint-plugin-unicorn": "^75.0.0",
"exiftool-vendored": "^35.0.0",
"globals": "^17.0.0",
"luxon": "^3.4.4",
+1 -1
View File
@@ -33,7 +33,7 @@
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^73.0.0",
"eslint-plugin-unicorn": "^75.0.0",
"globals": "^17.0.0",
"mock-fs": "^5.2.0",
"prettier": "^3.7.4",
+6 -6
View File
@@ -199,10 +199,7 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas
format: '{message} | {bar} | {percentage}% | ETA: {eta_formatted} | {value}/{total}',
formatValue: (v: number, options, type) => {
// Don't format percentage
if (type === 'percentage') {
return v.toString();
}
return byteSize(v).toString();
return type === 'percentage' ? v.toString() : byteSize(v).toString();
},
etaBuffer: 100, // Increase samples for ETA calculation
},
@@ -563,13 +560,16 @@ const updateAlbums = async (assets: Asset[], options: UploadOptionsDto) => {
continue;
}
const albumId = existingAlbums.get(albumName);
if (albumId) {
if (!albumId) {
continue;
}
if (!albumToAssets.has(albumId)) {
albumToAssets.set(albumId, []);
}
albumToAssets.get(albumId)?.push(asset.id);
}
}
const albumUpdateProgress = new SingleBar(
{ format: 'Adding assets to albums | {bar} | {percentage}% | ETA: {eta}s | {value}/{total} assets' },
+5 -6
View File
@@ -63,14 +63,16 @@ export const requirePermissions = async (permissions: Permission[]) => {
}
}
if (missing.length > 0) {
if (missing.length === 0) {
return;
}
const combined = missing.map((permission) => `"${permission}"`).join(', ');
console.log(
`Missing required permission${s(missing.length)}: ${combined}.
Please make sure your API key has the correct permissions.`,
);
process.exit(1);
}
};
export const connect = async (url: string, key: string) => {
@@ -120,10 +122,7 @@ export const readAuthFile = async (dir: string) => {
// TODO add class-transform/validation
const auth = yaml.parse(data.toString()) as AuthDto | OldAuthDto;
const { instanceUrl, apiKey } = auth as OldAuthDto;
if (instanceUrl && apiKey) {
return { url: instanceUrl, key: apiKey };
}
return auth as AuthDto;
return instanceUrl && apiKey ? { url: instanceUrl, key: apiKey } : (auth as AuthDto);
} catch (error: Error | any) {
if (error.code === 'ENOENT' || error.code === 'ENOTDIR') {
console.log('No auth file exists. Please login first.');
+27 -94
View File
@@ -157,8 +157,8 @@ importers:
specifier: ^5.1.3
version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)))(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))(prettier@3.9.8)
eslint-plugin-unicorn:
specifier: ^73.0.0
version: 73.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
specifier: ^75.0.0
version: 75.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
exiftool-vendored:
specifier: ^35.0.0
version: 35.21.0
@@ -272,8 +272,8 @@ importers:
specifier: ^5.1.3
version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)))(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))(prettier@3.9.8)
eslint-plugin-unicorn:
specifier: ^73.0.0
version: 73.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
specifier: ^75.0.0
version: 75.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
globals:
specifier: ^17.0.0
version: 17.12.0
@@ -750,8 +750,8 @@ importers:
specifier: ^5.1.3
version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)))(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))(prettier@3.9.8)
eslint-plugin-unicorn:
specifier: ^73.0.0
version: 73.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
specifier: ^75.0.0
version: 75.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
globals:
specifier: ^17.0.0
version: 17.12.0
@@ -1009,8 +1009,8 @@ importers:
specifier: ^3.12.4
version: 3.23.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))(svelte@5.57.0(@typescript-eslint/types@8.70.0))
eslint-plugin-unicorn:
specifier: ^73.0.0
version: 73.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
specifier: ^75.0.0
version: 75.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
factory.ts:
specifier: ^1.4.1
version: 1.4.2
@@ -6853,10 +6853,6 @@ packages:
resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==}
engines: {node: '>=18'}
convert-hrtime@5.0.0:
resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==}
engines: {node: '>=12'}
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
@@ -6903,8 +6899,9 @@ packages:
peerDependencies:
webpack: ^5.1.0
core-js-compat@3.49.0:
resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==}
core-js-compat@3.50.0:
resolution: {integrity: sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==}
engines: {node: '>=6.4.0'}
core-js@3.49.0:
resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
@@ -7618,6 +7615,10 @@ packages:
resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
engines: {node: '>=0.12'}
entities@8.1.0:
resolution: {integrity: sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==}
engines: {node: '>=20.19.0'}
env-paths@2.2.1:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'}
@@ -7812,8 +7813,8 @@ packages:
svelte:
optional: true
eslint-plugin-unicorn@73.0.0:
resolution: {integrity: sha512-V0YatLe9nkGhXEXKe2Qljb1EY0sJHwDV0HUF1NKFwtsHh/fU7qGHDgv+6fchzZcgU2/7noHo2gdjnmo0P2uDPw==}
eslint-plugin-unicorn@75.0.0:
resolution: {integrity: sha512-72I7eSn+/z5CpgValFBl9mp2JE5UPD+nUUyB/VIGUMF1rCP1i37mA05zfIAVIU312A+qCZ38T8tSZr3oaMv4Mw==}
engines: {node: '>=22'}
peerDependencies:
eslint: '>=10.4'
@@ -8224,10 +8225,6 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
function-timeout@1.0.2:
resolution: {integrity: sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==}
engines: {node: '>=18'}
function.prototype.name@1.2.0:
resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==}
engines: {node: '>= 0.4'}
@@ -8894,10 +8891,6 @@ packages:
is-hexadecimal@2.0.1:
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
is-identifier@1.1.0:
resolution: {integrity: sha512-NhOds0mDx9lJu+1lBRO0xbwFo5nobA7GCk/0e5xjr6+6XugX985+0OyGX35BNrTkPAsdLcIKg02HUQJOK8D8kw==}
engines: {node: '>=18'}
is-in-ssh@1.0.0:
resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==}
engines: {node: '>=20'}
@@ -9610,10 +9603,6 @@ packages:
magicast@0.5.3:
resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==}
make-asynchronous@1.1.0:
resolution: {integrity: sha512-ayF7iT+44LXdxJLTrTd3TLQpFDDvPCBxXxbv+pMUSuHA5Q8zyAfwkRP6aHHwNVFBUFWtxAHqwNJxF8vMZLAbVg==}
engines: {node: '>=18'}
make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
engines: {node: '>=8'}
@@ -10414,10 +10403,6 @@ packages:
resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==}
engines: {node: '>=12.20'}
p-event@6.0.1:
resolution: {integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==}
engines: {node: '>=16.17'}
p-finally@1.0.0:
resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
engines: {node: '>=4'}
@@ -10462,10 +10447,6 @@ packages:
resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==}
engines: {node: '>=8'}
p-timeout@6.1.4:
resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==}
engines: {node: '>=14.16'}
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
@@ -12185,10 +12166,6 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
super-regex@1.1.0:
resolution: {integrity: sha512-WHkws2ZflZe41zj6AolvvmaTrWds/VuyeYr9iPVv/oQeaIoVxMKaushfFWpOGDT+GuBrM/sVqF8KUCYQlSSTdQ==}
engines: {node: '>=18'}
superagent@10.3.0:
resolution: {integrity: sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==}
engines: {node: '>=14.18.0'}
@@ -12487,10 +12464,6 @@ packages:
thunky@1.1.0:
resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==}
time-span@5.1.0:
resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==}
engines: {node: '>=12'}
timers-ext@0.1.8:
resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==}
engines: {node: '>=0.12'}
@@ -12655,10 +12628,6 @@ packages:
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
engines: {node: '>=12.20'}
type-fest@4.41.0:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
type-fest@5.7.0:
resolution: {integrity: sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==}
engines: {node: '>=20'}
@@ -13095,9 +13064,6 @@ packages:
web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
web-worker@1.5.0:
resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==}
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@@ -14336,7 +14302,7 @@ snapshots:
babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)
babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)
babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)
core-js-compat: 3.49.0
core-js-compat: 3.50.0
semver: 6.3.1
transitivePeerDependencies:
- supports-color
@@ -19432,7 +19398,7 @@ snapshots:
dependencies:
'@babel/core': 7.29.7(supports-color@8.1.1)
'@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)
core-js-compat: 3.49.0
core-js-compat: 3.50.0
transitivePeerDependencies:
- supports-color
@@ -19440,7 +19406,7 @@ snapshots:
dependencies:
'@babel/core': 7.29.7(supports-color@8.1.1)
'@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)
core-js-compat: 3.49.0
core-js-compat: 3.50.0
transitivePeerDependencies:
- supports-color
@@ -20039,8 +20005,6 @@ snapshots:
content-type@2.0.0: {}
convert-hrtime@5.0.0: {}
convert-source-map@2.0.0: {}
cookie-parser@1.4.7:
@@ -20079,7 +20043,7 @@ snapshots:
serialize-javascript: 6.0.2
webpack: 5.108.4(@swc/core@1.16.2(@swc/helpers@0.5.23))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.28))(csso@5.0.5)(esbuild@0.28.2)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.28)(uglify-js@3.19.3)
core-js-compat@3.49.0:
core-js-compat@3.50.0:
dependencies:
browserslist: 4.29.0
@@ -20853,6 +20817,8 @@ snapshots:
entities@7.0.1: {}
entities@8.1.0: {}
env-paths@2.2.1: {}
env-paths@3.0.0: {}
@@ -21205,22 +21171,22 @@ snapshots:
transitivePeerDependencies:
- ts-node
eslint-plugin-unicorn@73.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)):
eslint-plugin-unicorn@75.0.0(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1)):
dependencies:
'@eslint-community/eslint-utils': 4.10.1(eslint@10.10.0(jiti@2.7.0)(supports-color@8.1.1))
'@eslint/css-tree': 4.0.5
browserslist: 4.29.0
change-case: 5.4.4
ci-info: 4.4.0
core-js-compat: 3.49.0
core-js-compat: 3.50.0
detect-indent: 7.0.2
entities: 4.5.0
entities: 8.1.0
eslint: 10.10.0(jiti@2.7.0)(supports-color@8.1.1)
find-up-simple: 1.0.1
globals: 17.12.0
identifier-regex: 1.1.0
indent-string: 5.0.0
is-builtin-module: 5.0.0
is-identifier: 1.1.0
pluralize: 8.0.0
quote-js-string: 0.1.0
regjsparser: 0.13.2
@@ -21759,8 +21725,6 @@ snapshots:
function-bind@1.1.2: {}
function-timeout@1.0.2: {}
function.prototype.name@1.2.0:
dependencies:
call-bind: 1.0.9
@@ -22620,11 +22584,6 @@ snapshots:
is-hexadecimal@2.0.1: {}
is-identifier@1.1.0:
dependencies:
identifier-regex: 1.1.0
super-regex: 1.1.0
is-in-ssh@1.0.0: {}
is-inside-container@1.0.0:
@@ -23283,12 +23242,6 @@ snapshots:
'@babel/types': 7.29.7
source-map-js: 1.2.1
make-asynchronous@1.1.0:
dependencies:
p-event: 6.0.1
type-fest: 4.41.0
web-worker: 1.5.0
make-dir@3.1.0:
dependencies:
semver: 6.3.1
@@ -24399,10 +24352,6 @@ snapshots:
p-cancelable@3.0.0: {}
p-event@6.0.1:
dependencies:
p-timeout: 6.1.4
p-finally@1.0.0: {}
p-limit@2.3.0:
@@ -24448,8 +24397,6 @@ snapshots:
dependencies:
p-finally: 1.0.0
p-timeout@6.1.4: {}
p-try@2.2.0: {}
package-json-from-dist@1.0.1: {}
@@ -26497,12 +26444,6 @@ snapshots:
tinyglobby: 0.2.17
ts-interface-checker: 0.1.13
super-regex@1.1.0:
dependencies:
function-timeout: 1.0.2
make-asynchronous: 1.1.0
time-span: 5.1.0
superagent@10.3.0(supports-color@8.1.1):
dependencies:
component-emitter: 1.3.1
@@ -26890,10 +26831,6 @@ snapshots:
thunky@1.1.0: {}
time-span@5.1.0:
dependencies:
convert-hrtime: 5.0.0
timers-ext@0.1.8:
dependencies:
es5-ext: 0.10.64
@@ -27044,8 +26981,6 @@ snapshots:
type-fest@2.19.0: {}
type-fest@4.41.0: {}
type-fest@5.7.0:
dependencies:
tagged-tag: 1.0.0
@@ -27551,8 +27486,6 @@ snapshots:
web-namespaces@2.0.1: {}
web-worker@1.5.0: {}
webidl-conversions@3.0.1: {}
webidl-conversions@7.0.0:
+4
View File
@@ -64,6 +64,10 @@ export default defineConfig([
'unicorn/no-computed-property-existence-check': 'off',
'unicorn/no-non-function-verb-prefix': 'off',
'unicorn/prefer-simple-condition-first': 'off',
'unicorn/prefer-ternary': 'off',
'unicorn/prefer-combined-guards': 'off',
'unicorn/no-immediate-mutation': 'off',
'unicorn/prefer-minimal-ternary': 'off',
// prefer the typescript-eslint type-aware version
'unicorn/require-array-sort-compare': 'off',
'@typescript-eslint/require-array-sort-compare': 'error',
+1 -1
View File
@@ -157,7 +157,7 @@
"eslint-import-resolver-typescript": "^4.4.5",
"eslint-plugin-import-x": "^4.17.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^73.0.0",
"eslint-plugin-unicorn": "^75.0.0",
"globals": "^17.0.0",
"mock-fs": "^5.2.0",
"pngjs": "^7.0.0",
@@ -17,7 +17,10 @@ export class ChangeMediaLocationCommand extends CommandRunner {
hint = hint ? ` (${hint})` : '';
const paths = await this.service.getSampleFilePaths();
if (paths.length > 0) {
if (paths.length === 0) {
return;
}
let message = ` Examples from the database${hint}:\n`;
for (const path of paths) {
message += ` - ${path}\n`;
@@ -25,7 +28,6 @@ export class ChangeMediaLocationCommand extends CommandRunner {
console.log(`\n${message}`);
}
}
async run(): Promise<void> {
try {
+3 -2
View File
@@ -45,11 +45,12 @@ function chunks<T>(collection: Array<T> | Set<T>, size: number): Array<Array<T>>
let chunk = new Set<T>();
for (const element of collection) {
chunk.add(element);
if (chunk.size === size) {
if (chunk.size !== size) {
continue;
}
result.push(chunk);
chunk = new Set<T>();
}
}
if (chunk.size > 0) {
result.push(chunk);
}
@@ -29,10 +29,12 @@ export class MaintenanceHealthRepository {
output += data;
if (output.includes(IMMICH_SERVER_START)) {
if (!output.includes(IMMICH_SERVER_START)) {
return;
}
resolve();
worker.kill('SIGTERM');
}
});
worker.on('exit', (code, signal) =>
@@ -113,12 +113,14 @@ export class DatabaseRepository {
async createExtension(extension: DatabaseExtension): Promise<void> {
this.logger.log(`Creating ${EXTENSION_NAMES[extension]} extension`);
await sql`CREATE EXTENSION IF NOT EXISTS ${sql.raw(extension)} CASCADE`.execute(this.db);
if (extension === DatabaseExtension.VectorChord) {
if (extension !== DatabaseExtension.VectorChord) {
return;
}
const dbName = sql.id(await this.getDatabaseName());
await sql`ALTER DATABASE ${dbName} SET vchordrq.probes = 1`.execute(this.db);
await sql`SET vchordrq.probes = 1`.execute(this.db);
}
}
async dropExtension(extension: DatabaseExtension): Promise<void> {
this.logger.log(`Dropping ${EXTENSION_NAMES[extension]} extension`);
@@ -362,7 +364,7 @@ export class DatabaseRepository {
if (count < 128_000) {
return 1;
}
// eslint-disable-next-line unicorn/prefer-minimal-ternary
return count < 2_048_000 ? 1 << (32 - Math.clz32(count / 1000)) : 1 << (33 - Math.clz32(Math.sqrt(count)));
}
@@ -303,6 +303,7 @@ export class MapRepository {
admin2Name: admin2Map.get(`${lineSplit[8]}.${lineSplit[10]}.${lineSplit[11]}`) ?? null,
};
bufferGeodata.push(geoData);
// eslint-disable-next-line unicorn/prefer-continue
if (bufferGeodata.length >= 5000) {
const curLength = bufferGeodata.length;
futures.push(
+5 -2
View File
@@ -329,14 +329,17 @@ export class MediaRepository {
if (flags[1] !== 'D') {
postDiscard.push({ pts, duration });
}
if (flags[0] === 'K') {
if (flags[0] !== 'K') {
return;
}
keyframePts.push(pts);
keyframeAccDuration.push(totalDuration);
// VFR content can have variable duration keyframes,
// so we need to track their duration separately for accurate segment boundaries.
// Non-keyframes are accounted for in totalDuration.
keyframeOwnDuration.push(duration);
}
};
let stderr = '';
@@ -58,7 +58,6 @@ export class OcrRepository {
})
upsert(assetId: string, ocrDataList: Insertable<AssetOcrTable>[], searchText: string) {
let query = this.db.with('deleted_ocr', (db) => db.deleteFrom('asset_ocr').where('assetId', '=', assetId));
// eslint-disable-next-line unicorn/prefer-ternary
if (ocrDataList.length > 0) {
(query as any) = query
.with('inserted_ocr', (db) => db.insertInto('asset_ocr').values(ocrDataList))
@@ -186,7 +186,10 @@ export class StorageRepository {
const files = await fs.readdir(directory);
await Promise.all(files.map((file) => this.removeEmptyDirs(path.join(directory, file), true)));
if (self) {
if (!self) {
return;
}
const updated = await fs.readdir(directory);
if (updated.length === 0) {
try {
@@ -198,7 +201,6 @@ export class StorageRepository {
}
}
}
}
mkdirSync(filepath: string): void {
if (!existsSync(filepath)) {
@@ -258,11 +260,13 @@ export class StorageRepository {
let batch: string[] = [];
for await (const value of stream) {
batch.push(value.toString());
if (batch.length === walkOptions.take) {
if (batch.length !== walkOptions.take) {
continue;
}
yield batch;
batch = [];
}
}
if (batch.length > 0) {
yield batch;
+4 -2
View File
@@ -507,7 +507,10 @@ export class AssetService extends BaseService {
isUndefined,
);
if (Object.keys(writes).length > 0) {
if (Object.keys(writes).length === 0) {
return;
}
await this.assetRepository.upsertExif({
exif: updateLockedColumns({
assetId: id,
@@ -517,7 +520,6 @@ export class AssetService extends BaseService {
});
await this.jobRepository.queue({ name: JobName.SidecarWrite, data: { id } });
}
}
async getAssetEdits(auth: AuthDto, id: string): Promise<AssetEditsResponseDto> {
await this.requireAccess({ auth, permission: Permission.AssetRead, ids: [id] });
+4 -2
View File
@@ -47,10 +47,12 @@ export class DownloadService extends BaseService {
archive.assetIds.push(id);
archive.size += Number(size || 0);
if (archive.size > targetSize) {
if (archive.size <= targetSize) {
return;
}
archives.push(archive);
archive = { size: 0, assetIds: [] };
}
};
for await (const asset of assets) {
+4 -2
View File
@@ -27,11 +27,13 @@ export class HlsService extends BaseService {
@OnEvent({ name: 'HlsSessionResult', server: true, workers: [ImmichWorker.Api] })
onSessionResult(event: ArgOf<'HlsSessionResult'>) {
this.pendingSessions.complete(event.sessionId, event);
if (event.error) {
if (!event.error) {
return;
}
this.sessions.delete(event.sessionId);
this.pendingSegments.rejectByPrefix(`${event.sessionId}:`, event.error);
}
}
@OnEvent({ name: 'HlsSessionEnd', server: true, workers: [ImmichWorker.Api] })
onSessionEnd({ sessionId }: ArgOf<'HlsSessionEnd'>) {
+4 -2
View File
@@ -79,12 +79,14 @@ export class LibraryService extends BaseService {
start: library.scan.enabled,
});
if (library.watch.enabled !== this.watchLibraries) {
if (library.watch.enabled === this.watchLibraries) {
return;
}
// Watch configuration changed, update accordingly
this.watchLibraries = library.watch.enabled;
await (this.watchLibraries ? this.watchAll() : this.unwatchAll());
}
}
private async watch(id: string): Promise<boolean> {
if (!this.watchLibraries) {
+1
View File
@@ -782,6 +782,7 @@ export class MediaService extends BaseService {
}
// upsert new file path
// eslint-disable-next-line unicorn/prefer-continue
if (
existingFile?.path !== newFile.path ||
existingFile.isProgressive !== newFile.isProgressive ||
+4 -2
View File
@@ -943,7 +943,10 @@ export class MetadataService extends BaseService {
};
facesToAdd.push(face);
if (!existingNameMap.has(loweredName)) {
if (existingNameMap.has(loweredName)) {
continue;
}
missing.push({
personGroupId,
ownerId: asset.ownerId,
@@ -952,7 +955,6 @@ export class MetadataService extends BaseService {
});
missingWithFaceAsset.push({ personGroupId, ownerId: asset.ownerId, faceAssetId: face.id });
}
}
if (missing.length > 0) {
this.logger.debugFn(() => `Creating missing persons: ${missing.map((p) => `${p.name}/${p.personGroupId}`)}`);
+4 -2
View File
@@ -155,11 +155,13 @@ export class PersonService extends BaseService {
for (const { ownerId, personGroupId } of changeFeaturePhoto) {
const assetFace = await this.personRepository.getRandomFace(personGroupId);
if (assetFace) {
if (!assetFace) {
continue;
}
await this.personRepository.update({ ownerId, personGroupId, faceAssetId: assetFace.id });
jobs.push({ name: JobName.PersonGenerateThumbnail, data: { ownerId, personGroupId } });
}
}
await this.jobRepository.queueAll(jobs);
}
+8 -4
View File
@@ -49,7 +49,10 @@ export class QueueService extends BaseService {
}
this.nightlyJobsLock = await this.databaseRepository.tryLock(DatabaseLock.NightlyJobs);
if (this.nightlyJobsLock) {
if (!this.nightlyJobsLock) {
return;
}
const cronExpression = asNightlyTasksCron(config);
this.logger.debug(`Scheduling nightly jobs for ${cronExpression}`);
this.cronRepository.create({
@@ -59,7 +62,6 @@ export class QueueService extends BaseService {
onTick: () => handlePromiseError(this.handleNightlyJobs(), this.logger),
});
}
}
@OnEvent({ name: 'ConfigUpdate', server: true })
onConfigUpdate({ newConfig: config }: ArgOf<'ConfigUpdate'>) {
@@ -68,12 +70,14 @@ export class QueueService extends BaseService {
return;
}
if (this.nightlyJobsLock) {
if (!this.nightlyJobsLock) {
return;
}
const cronExpression = asNightlyTasksCron(config);
this.logger.debug(`Scheduling nightly jobs for ${cronExpression}`);
this.cronRepository.update({ name: CronJob.NightlyJobs, expression: cronExpression, start: true });
}
}
@OnEvent({ name: 'AppBootstrap', priority: BootstrapEventPriority.JobService })
onBootstrap() {
@@ -92,11 +92,13 @@ export class StorageTemplateService extends BaseService {
@OnEvent({ name: 'ConfigInit' })
onConfigInit({ newConfig }: ArgOf<'ConfigInit'>) {
const template = newConfig.storageTemplate.template;
if (!this._template || template !== this.template.raw) {
if (this._template && template === this.template.raw) {
return;
}
this.logger.debug(`Compiling new storage template: ${template}`);
this._template = this.compile(template);
}
}
@OnEvent({ name: 'ConfigUpdate', server: true })
onConfigUpdate({ newConfig }: ArgOf<'ConfigUpdate'>) {
@@ -191,17 +193,21 @@ export class StorageTemplateService extends BaseService {
const filename = asset.originalFileName || asset.id;
await this.moveAsset(asset, { storageLabel, filename });
if (!asset.livePhotoVideoId) {
continue;
}
// move motion part of live photo
if (asset.livePhotoVideoId) {
const livePhotoVideo = await this.assetJobRepository.getForStorageTemplateJob(asset.livePhotoVideoId, {
includeHidden: true,
});
if (livePhotoVideo) {
if (!livePhotoVideo) {
continue;
}
const motionFilename = getLivePhotoMotionFilename(filename, livePhotoVideo.originalPath);
await this.moveAsset(livePhotoVideo, { storageLabel, filename: motionFilename }, asset);
}
}
}
this.logger.debug('Cleaning up empty directories...');
const libraryFolder = StorageCore.getBaseFolder(StorageFolder.Library);
@@ -417,14 +423,16 @@ export class StorageTemplateService extends BaseService {
for (const token of Object.values(storageTokens).flat()) {
substitutions[token] = dt.toFormat(token);
if (albumName) {
if (!albumName) {
continue;
}
// Album date tokens are rendered in the server time zone to match storage template datetime behavior.
substitutions['album-startDate-' + token] = albumStartDate
? DateTime.fromJSDate(albumStartDate).toFormat(token)
: '';
substitutions['album-endDate-' + token] = albumEndDate ? DateTime.fromJSDate(albumEndDate).toFormat(token) : '';
}
}
return template(substitutions).replaceAll(/\/{2,}/gm, '/');
}
+4 -2
View File
@@ -71,11 +71,13 @@ export class StorageService extends BaseService {
await this.verifyReadAccess(folder);
await this.verifyWriteAccess(folder);
if (!flags.mountChecks[folder]) {
if (flags.mountChecks[folder]) {
continue;
}
flags.mountChecks[folder] = true;
isUpdated = true;
}
}
if (isUpdated) {
await this.systemMetadataRepository.set(SystemMetadataKey.SystemFlags, flags);
+1
View File
@@ -73,6 +73,7 @@ export class TimelineService extends BaseService {
dto.withCoordinates = false;
}
// eslint-disable-next-line unicorn/prefer-early-return
if (dto.withPartners) {
const isRequestedLocked = dto.visibility === AssetVisibility.Locked;
const isRequestedArchived = dto.visibility === AssetVisibility.Archive || dto.visibility === undefined;
+6 -2
View File
@@ -123,6 +123,7 @@ export class TranscodingService extends BaseService {
}
const remaining = session.expiresAt.getTime() - Date.now();
// eslint-disable-next-line unicorn/prefer-early-return
if (remaining < HLS_LEASE_DURATION_MS / 2) {
session.expiresAt = new Date(Date.now() + HLS_LEASE_DURATION_MS);
await this.videoStreamRepository.extendSession(sessionId, session.expiresAt);
@@ -317,14 +318,17 @@ export class TranscodingService extends BaseService {
session.paused = false;
session.process = null;
session.lastCompletedSegment = null;
if (code) {
if (!code) {
return;
}
this.logger.error(
`FFmpeg exited with code ${code} for variant ${variantIndex} asset ${session.assetId}\n${stderr}`,
);
void this.failSession(session, `Transcoding process exited unexpectedly with code ${code}`).catch((error) =>
this.logger.error(`Failed to end session ${session.id} after ffmpeg exit: ${error}`),
);
}
});
}
+4 -2
View File
@@ -62,7 +62,10 @@ export class VersionService extends BaseService {
return;
}
if (previous.version !== current) {
if (previous.version === current) {
return;
}
const previousVersion = new SemVer(previous.version);
this.logger.log(`Adding ${current} to upgrade history`);
@@ -72,7 +75,6 @@ export class VersionService extends BaseService {
if (isNeedsNewMemories) {
await this.jobRepository.queue({ name: JobName.MemoryGenerate });
}
}
});
}
@@ -147,7 +147,10 @@ export class WorkflowExecutionService extends BaseService {
}
const isMethodWithFunction = methods.some(({ hostFunctions }) => hostFunctions);
if (isMethodWithFunction) {
if (!isMethodWithFunction) {
continue;
}
const label = `${name}@${version}/worker`;
const key = this.getPluginKey({ id, hostFunctions: true });
try {
@@ -158,7 +161,6 @@ export class WorkflowExecutionService extends BaseService {
}
}
}
}
private getPluginKey({ id, hostFunctions }: { id: string; hostFunctions: boolean }) {
return id + (hostFunctions ? '/worker' : '');
+4 -2
View File
@@ -157,10 +157,12 @@ export const onBeforeLink = async (
throw new BadRequestException('Live photo video does not belong to the user');
}
if (motionAsset && motionAsset.visibility === AssetVisibility.Timeline) {
if (!motionAsset || motionAsset.visibility !== AssetVisibility.Timeline) {
return;
}
await assetRepository.update({ id: livePhotoVideoId, visibility: AssetVisibility.Hidden });
await eventRepository.emit('AssetHide', { assetId: motionAsset.id, userId });
}
};
export const onBeforeUnlink = async (
+12 -6
View File
@@ -123,11 +123,13 @@ export async function* batched<T>(items: AsyncIterable<T>, size = JOBS_ASSET_PAG
for await (const item of items) {
batch.push(item);
if (batch.length >= size) {
if (batch.length < size) {
continue;
}
yield batch;
batch = [];
}
}
if (batch.length > 0) {
yield batch;
@@ -243,7 +245,10 @@ const patchOpenAPI = (document: OpenAPIObject) => {
value = value.items;
}
if (isSchema(value) && value.type === 'number') {
if (!(isSchema(value) && value.type === 'number')) {
continue;
}
if (value.format === 'float') {
errors.push(`Invalid number format: ${schemaName}.${key}=float (use double instead). `);
}
@@ -255,7 +260,6 @@ const patchOpenAPI = (document: OpenAPIObject) => {
);
}
}
}
schema.required?.sort();
if (errors.length > 0) {
@@ -359,11 +363,13 @@ export const useSwagger = (app: INestApplication, { write }: { write: boolean })
SwaggerModule.setup('doc', app, openApiDoc, customOptions);
if (write) {
// Generate API Documentation only in development mode
if (!write) {
return;
}
const outputPath = path.resolve(process.cwd(), '../open-api/immich-openapi-specs.json');
writeFileSync(outputPath, JSON.stringify(patchOpenAPI(openApiDoc), null, 2), { encoding: 'utf8' });
}
};
// Compiles a glob to the equivalent Postgres regex (Postgres's Advanced Regular Expression
+4 -2
View File
@@ -106,8 +106,6 @@ export default typescriptEslint.config(
},
},
ignores: ['**/service-worker/**'],
rules: {
'@typescript-eslint/no-unused-vars': [
'warn',
@@ -173,6 +171,10 @@ export default typescriptEslint.config(
'svelte/button-has-type': 'error',
'object-shorthand': ['error', 'always'],
'svelte/no-navigation-without-resolve': 'off',
'unicorn/prefer-early-return': 'off',
'unicorn/prefer-ternary': 'off',
'unicorn/prefer-combined-guards': 'off',
'unicorn/no-immediate-mutation': 'off',
eqeqeq: 'error',
},
},
+1 -1
View File
@@ -98,7 +98,7 @@
"eslint-plugin-better-tailwindcss": "^4.5.0",
"eslint-plugin-compat": "^7.0.0",
"eslint-plugin-svelte": "^3.12.4",
"eslint-plugin-unicorn": "^73.0.0",
"eslint-plugin-unicorn": "^75.0.0",
"factory.ts": "^1.4.1",
"globals": "^17.0.0",
"happy-dom": "^20.0.0",
@@ -209,14 +209,16 @@
for (const position of positions) {
const overlap = overlapArea(position);
if (overlap < leastOverlap) {
if (overlap >= leastOverlap) {
continue;
}
leastOverlap = overlap;
bestPosition = position;
if (overlap === 0) {
break;
}
}
}
faceSelectorEl.style.top = `${bestPosition.top}px`;
faceSelectorEl.style.left = `${bestPosition.left}px`;
@@ -172,11 +172,13 @@ export function findClosestTimelineMonthForDate(months: TimelineMonth[], targetY
const monthDate = DateTime.fromObject({ year: month.yearMonth.year, month: month.yearMonth.month });
const totalDiff = Math.abs(monthDate.diff(targetDate, 'months').months);
if (totalDiff < minDifference) {
if (totalDiff >= minDifference) {
continue;
}
minDifference = totalDiff;
closestMonth = month;
}
}
return closestMonth;
}
@@ -150,6 +150,7 @@ export class TimelineDay {
}
unprocessedIds.delete(assetId);
processedIds.add(assetId);
// eslint-disable-next-line unicorn/prefer-continue
if (remove || this.timelineMonth.timelineManager.isExcluded(asset)) {
this.viewerAssets.splice(index, 1);
changedGeometry = true;
@@ -159,11 +159,14 @@ export class TimelineMonth {
idsProcessed.add(id);
}
combinedChangedGeometry ||= changedGeometry;
if (group.viewerAssets.length === 0) {
if (group.viewerAssets.length > 0) {
continue;
}
timelineDays.splice(index, 1);
combinedChangedGeometry = true;
}
}
return {
moveAssets: combinedMoveAssets.flat(),
unprocessedIds: idsToProcess,
@@ -382,11 +385,14 @@ export class TimelineMonth {
for (const current of this.assetsIterator()) {
const currentAssetDate = fromTimelinePlainDateTime(getOrderingDate(current, this.#orderBy));
const diff = Math.abs(targetDate.diff(currentAssetDate).as('milliseconds'));
if (diff < smallestDiff) {
if (diff >= smallestDiff) {
continue;
}
smallestDiff = diff;
closest = current;
}
}
return closest;
}
+4 -2
View File
@@ -49,11 +49,13 @@ export class TreeNode extends Map<string, TreeNode> {
// segments common to all subtrees can be collapsed together
curPart = curPart === null ? part : joinPaths(curPart, part);
const next = current.get(curPart);
if (next) {
if (!next) {
continue;
}
current = next;
curPart = null;
}
}
return current;
}
+1
View File
@@ -1,3 +1,4 @@
/* eslint-disable unicorn/no-unnecessary-global-this */
/// <reference types="@sveltejs/kit" />
/// <reference no-default-lib="true"/>
/// <reference lib="esnext" />
+1
View File
@@ -1,3 +1,4 @@
/* eslint-disable unicorn/no-unnecessary-global-this */
/// <reference types="@sveltejs/kit" />
/// <reference no-default-lib="true"/>
/// <reference lib="esnext" />
-4
View File
@@ -23,7 +23,6 @@ export const handleFetch = async (request: URL | Request): Promise<Response> =>
if (existing) {
// Clone the response since response bodies can only be read once
// Each caller gets an independent clone they can consume
// eslint-disable-next-line unicorn/prefer-await
return existing.promise.then((response) => response.clone());
}
@@ -36,7 +35,6 @@ export const handleFetch = async (request: URL | Request): Promise<Response> =>
// NOTE: fetch returns after headers received, not the body
pendingRequest.promise = fetch(request, { signal: pendingRequest.controller.signal })
// eslint-disable-next-line unicorn/prefer-await
.catch((error: unknown) => {
const standardError = error instanceof Error ? error : new Error(String(error));
if (standardError.name === 'AbortError' || standardError.message === CANCELATION_MESSAGE) {
@@ -45,7 +43,6 @@ export const handleFetch = async (request: URL | Request): Promise<Response> =>
}
throw standardError;
})
// eslint-disable-next-line unicorn/prefer-await
.finally(() => {
// Schedule cleanup after timeout to allow response body streaming to complete
const cleanupTimeout = setTimeout(() => {
@@ -55,7 +52,6 @@ export const handleFetch = async (request: URL | Request): Promise<Response> =>
});
// Clone for the first caller to keep the original response unconsumed for future callers
// eslint-disable-next-line unicorn/prefer-await
return pendingRequest.promise.then((response) => response.clone());
};