Dependencies current: npm audit 0 (was 7, six of them high)
nodemailer and basic-ftp are only fixed in their next major, so this takes both, along with argon2 0.45, ssh2-sftp-client 12, archiver 8, @astrojs/react 7 and the minor bumps. - archiver 8 has no default export any more, only `ZipArchive`. Our own `src/types/archiver.d.ts` still declared the old default, so `tsc` would have stayed green while every ZIP download threw at runtime. The local declaration is gone; `@types/archiver` 8 matches the real API now. - nodemailer 10 ships its own types; `@types/nodemailer` is gone. - Existing argon2 hashes still verify (hash made with 0.41, verified with 0.45). - basic-ftp 6 no longer silently redirects the data connection when an FTP server behind NAT announces its private address. That is the library's deliberate secure default. If a delivery target that worked before fails now, press "Test connection" — the error names the cause. - `baseUrl` is out of tsconfig.json (TypeScript 7 removed it; the `@/` alias was never used). - engines: Node >= 22.12, which pg-boss and @astrojs/react now require. Deliberately not taken: pg-boss 12 cannot migrate the v10 queue schema in place, and TypeScript 7 is a toolchain switch with no security gain. Both get their own change.
This commit is contained in:
6 files changed
+838
-1750
No files matched your search
Generated
+814
-1685
File diff suppressed because it is too large.
Load diff
+20
-20
@@ -26,7 +26,7 @@
|
|||||||
],
|
],
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.6"
|
"node": ">=22.12"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
@@ -38,32 +38,32 @@
|
|||||||
"scan": "node scripts/secret-scan.mjs"
|
"scan": "node scripts/secret-scan.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/node": "^11.1.5",
|
"@astrojs/node": "^11.1.7",
|
||||||
"@astrojs/react": "^6.0.5",
|
"@astrojs/react": "^7.0.1",
|
||||||
"@aws-sdk/client-s3": "^3.700.0",
|
"@aws-sdk/client-s3": "^3.1149.0",
|
||||||
"@fontsource/space-grotesk": "^5.1.0",
|
"@fontsource/space-grotesk": "^5.1.0",
|
||||||
"@fontsource/space-mono": "^5.1.0",
|
"@fontsource/space-mono": "^5.1.0",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^8.0.0",
|
||||||
"argon2": "^0.41.1",
|
"argon2": "^0.45.1",
|
||||||
"astro": "^7.3.2",
|
"astro": "^7.3.8",
|
||||||
"basic-ftp": "^5.0.5",
|
"basic-ftp": "^6.2.3",
|
||||||
"grammy": "^1.30.0",
|
"grammy": "^1.46.0",
|
||||||
"heic-convert": "^2.1.0",
|
"heic-convert": "^2.1.0",
|
||||||
"nodemailer": "^9.1.0",
|
"nodemailer": "^10.0.16",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
"pg": "^8.13.1",
|
"pg": "^8.23.1",
|
||||||
"pg-boss": "^10.1.5",
|
"pg-boss": "^10.1.5",
|
||||||
"react": "^19.0.0",
|
"react": "^19.3.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.3.0",
|
||||||
"sharp": "^0.35.4",
|
"sharp": "^0.35.5",
|
||||||
"ssh2-sftp-client": "^11.0.0"
|
"ssh2-sftp-client": "^12.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^26.5.1",
|
"@types/archiver": "^8.0.0",
|
||||||
"@types/nodemailer": "^8.0.1",
|
"@types/node": "^26.6.5",
|
||||||
"@types/pg": "^8.11.10",
|
"@types/pg": "^8.23.1",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.3.0",
|
||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.3.0",
|
||||||
"@types/ssh2-sftp-client": "^9.0.6",
|
"@types/ssh2-sftp-client": "^9.0.6",
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { APIRoute } from 'astro';
|
import type { APIRoute } from 'astro';
|
||||||
import { buildSelectionZipName } from '../../../lib/naming';
|
import { buildSelectionZipName } from '../../../lib/naming';
|
||||||
import archiver from 'archiver';
|
import { ZipArchive } from 'archiver';
|
||||||
import { query } from '../../../lib/db';
|
import { query } from '../../../lib/db';
|
||||||
import { getObject } from '../../../lib/storage';
|
import { getObject } from '../../../lib/storage';
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ export const POST: APIRoute = async ({ request, locals }) => {
|
|||||||
`SELECT id, result_path, filename FROM items WHERE id = ANY($1) AND result_path IS NOT NULL`, [ids]);
|
`SELECT id, result_path, filename FROM items WHERE id = ANY($1) AND result_path IS NOT NULL`, [ids]);
|
||||||
if (!rows.length) return new Response('No results.', { status: 404 });
|
if (!rows.length) return new Response('No results.', { status: 404 });
|
||||||
|
|
||||||
const archive = archiver('zip', { zlib: { level: 6 } });
|
const archive = new ZipArchive({ zlib: { level: 6 } });
|
||||||
const seen: Record<string, number> = {};
|
const seen: Record<string, number> = {};
|
||||||
for (const r of rows) {
|
for (const r of rows) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { APIRoute } from 'astro';
|
import type { APIRoute } from 'astro';
|
||||||
import archiver from 'archiver';
|
import { ZipArchive } from 'archiver';
|
||||||
import { Readable } from 'node:stream';
|
import { Readable } from 'node:stream';
|
||||||
import { once } from 'node:events';
|
import { once } from 'node:events';
|
||||||
import { query } from '../../../../lib/db';
|
import { query } from '../../../../lib/db';
|
||||||
@@ -66,7 +66,7 @@ export const GET: APIRoute = async ({ params, request, clientAddress }) => {
|
|||||||
[images.map((b) => b.id)]);
|
[images.map((b) => b.id)]);
|
||||||
const byId = new Map(paths.map((p) => [p.id, p]));
|
const byId = new Map(paths.map((p) => [p.id, p]));
|
||||||
|
|
||||||
const archive = archiver('zip', { zlib: { level: 6 } });
|
const archive = new ZipArchive({ zlib: { level: 6 } });
|
||||||
// Errors must not take the process with them; the stream then breaks off.
|
// Errors must not take the process with them; the stream then breaks off.
|
||||||
archive.on('error', (e: any) => console.error('[share/zip]', e?.message || e));
|
archive.on('error', (e: any) => console.error('[share/zip]', e?.message || e));
|
||||||
archive.on('warning', (e: any) => console.error('[share/zip] warning:', e?.message || e));
|
archive.on('warning', (e: any) => console.error('[share/zip] warning:', e?.message || e));
|
||||||
|
|||||||
Vendored
-35
@@ -1,35 +0,0 @@
|
|||||||
/**
|
|
||||||
* Minimal typings for `archiver`.
|
|
||||||
*
|
|
||||||
* The published `@types/archiver` describes an API this version does not have:
|
|
||||||
* it exports classes (`ZipArchive`, …) but no callable default, while the
|
|
||||||
* runtime is exactly the other way round — `archiver('zip', opts)` works and
|
|
||||||
* the classes do not exist. Rather than pin a mismatched types package, this
|
|
||||||
* declares the two things Klarbild actually uses.
|
|
||||||
*/
|
|
||||||
declare module 'archiver' {
|
|
||||||
import { Transform } from 'node:stream';
|
|
||||||
|
|
||||||
interface ArchiverOptions {
|
|
||||||
zlib?: { level?: number };
|
|
||||||
store?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EntryData {
|
|
||||||
name: string;
|
|
||||||
date?: Date | string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Archiver extends Transform {
|
|
||||||
append(source: Buffer | NodeJS.ReadableStream | string, data: EntryData): this;
|
|
||||||
finalize(): Promise<void>;
|
|
||||||
abort(): this;
|
|
||||||
pointer(): number;
|
|
||||||
on(event: 'error' | 'warning', listener: (err: Error & { code?: string }) => void): this;
|
|
||||||
on(event: 'entry', listener: (entry: EntryData) => void): this;
|
|
||||||
on(event: string, listener: (...args: any[]) => void): this;
|
|
||||||
}
|
|
||||||
|
|
||||||
function archiver(format: 'zip' | 'tar', options?: ArchiverOptions): Archiver;
|
|
||||||
export default archiver;
|
|
||||||
}
|
|
||||||
@@ -2,12 +2,6 @@
|
|||||||
"extends": "astro/tsconfigs/strict",
|
"extends": "astro/tsconfigs/strict",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"@/*": [
|
|
||||||
"src/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"types": [
|
"types": [
|
||||||
|
|||||||
Reference in new issue
Block a user