From cc4bef8ec4602bfc4b1e5aa721f40a092e3a75a5 Mon Sep 17 00:00:00 2001 From: Benjamin Singleton <19498453+tetrogem@users.noreply.github.com> Date: Sat, 13 Sep 2025 13:16:23 -0500 Subject: [PATCH] fix: typing/dependecy/validation fixes, installed ts-reset & zod, fixed responses never being sent on invalid query params --- apps/vdb-backend/package.json | 10 +- apps/vdb-backend/src/auth.ts | 138 ++++++++++++++------- apps/vdb-backend/src/index.ts | 44 ++++--- pnpm-lock.yaml | 222 ++++++++++++++-------------------- 4 files changed, 211 insertions(+), 203 deletions(-) diff --git a/apps/vdb-backend/package.json b/apps/vdb-backend/package.json index c85b825..3759c5a 100644 --- a/apps/vdb-backend/package.json +++ b/apps/vdb-backend/package.json @@ -20,17 +20,19 @@ "packageManager": "pnpm@10.11.0", "dependencies": { "@feathersjs/feathers": "^5.0.6", - "@google-cloud/local-auth": "^2.1.0", + "@google-cloud/local-auth": "^3.0.1", "@repo/common": "workspace:*", "express": "^5.1.0", - "google-auth-library": "^10.3.0", - "googleapis": "^159.0.0", + "google-auth-library": "^9.15.1", + "googleapis": "^149.0.0", "node-fetch": "^3.3.2", "reflect-metadata": "^0.2.2", "sqlite3": "^5.1.7", - "typeorm": "0.3.26" + "typeorm": "0.3.26", + "zod": "^4.1.8" }, "devDependencies": { + "@total-typescript/ts-reset": "^0.6.1", "@types/express": "^5.0.3", "@types/node": "^22.5.1", "tsx": "^4.19.4" diff --git a/apps/vdb-backend/src/auth.ts b/apps/vdb-backend/src/auth.ts index 734c0cf..43422a9 100644 --- a/apps/vdb-backend/src/auth.ts +++ b/apps/vdb-backend/src/auth.ts @@ -1,62 +1,114 @@ - import { promises as fs } from "fs"; -import fetch from 'node-fetch'; import * as path from "path"; import { authenticate } from "@google-cloud/local-auth"; import { google } from "googleapis"; -import { OAuth2Client } from 'google-auth-library'; - +import { JWTInput, OAuth2Client } from "google-auth-library"; +import { + GoogleAuth, + JSONClient, +} from "google-auth-library/build/src/auth/googleauth.js"; +import z from "zod"; //setup google auth const SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"]; const TOKEN_PATH = path.join(process.cwd(), "res/token.secret.json"); -const CREDENTIALS_PATH = path.join(process.cwd(), "res/credentials.secret.json"); - +const CREDENTIALS_PATH = path.join( + process.cwd(), + "res/credentials.secret.json", +); /** * Load or request or authorization to call APIs. -*/ + */ +export async function authorize(): Promise< + GoogleAuth | OAuth2Client +> { + const savedClient = await loadSavedCredentialsIfExist(); + if (savedClient) { + return savedClient; + } -export async function authorize() { - let client: any = await loadSavedCredentialsIfExist(); - if (client) { - return client; - } - client = await authenticate({ - scopes: SCOPES, - keyfilePath: CREDENTIALS_PATH, - }); - if (client.credentials) { - await saveCredentials(client); - } - return client; + const oauthClient = await authenticate({ + scopes: SCOPES, + keyfilePath: CREDENTIALS_PATH, + }); + + if (oauthClient.credentials) { + await saveCredentials(oauthClient); + } + + return oauthClient; } -async function loadSavedCredentialsIfExist() { - try { - const content = await fs.readFile(TOKEN_PATH); - const credentials = JSON.parse(content.toString()); - return google.auth.fromJSON(credentials); - } catch (err) { - return null; - } +const jwtInputZod = z.object({ + type: z.string(), + client_id: z.string(), + client_secret: z.string(), + refresh_token: z.string(), +}) satisfies z.ZodType; + +async function loadSavedCredentialsIfExist(): Promise | null> { + try { + const content = await fs.readFile(TOKEN_PATH); + const jwtInputRaw = JSON.parse(content.toString()); + + const jwtInputRes = jwtInputZod.safeParse(jwtInputRaw); + if (!jwtInputRes.success) { + throw new Error("Malformed JWT/token credentials"); + } + + const jwtInput = jwtInputRes.data; + const jsonClient = google.auth.fromJSON(jwtInput); + const auth = new GoogleAuth({ authClient: jsonClient }); + return auth; + } catch (err) { + return null; + } } +const credentialsZod = z.object({ + installed: z.object({ + client_id: z.string(), + project_id: z.string(), + auth_uri: z.string(), + token_uri: z.string(), + auth_provider_x509_cert_url: z.string(), + client_secret: z.string(), + redirect_uris: z.array(z.string()), + }), + web: z.optional( + z.object({ + client_id: z.string(), + project_id: z.string(), + auth_uri: z.string(), + token_uri: z.string(), + auth_provider_x509_cert_url: z.string(), + client_secret: z.string(), + redirect_uris: z.array(z.string()), + }), + ), +}); + /** * Serializes credentials to a file compatible with GoogleAuth.fromJSON. - * - * @param {OAuth2Client} client - * @return {Promise} */ -async function saveCredentials(client: OAuth2Client) { - const content = await fs.readFile(CREDENTIALS_PATH); - const keys = JSON.parse(content.toString()); - const key = keys.installed || keys.web; - const payload = JSON.stringify({ - type: "authorized_user", - client_id: key.client_id, - client_secret: key.client_secret, - refresh_token: client.credentials.refresh_token, - }); - await fs.writeFile(TOKEN_PATH, payload); -} \ No newline at end of file +async function saveCredentials(client: OAuth2Client): Promise { + const content = await fs.readFile(CREDENTIALS_PATH); + const keysRaw = JSON.parse(content.toString()); + + const keysRes = credentialsZod.safeParse(keysRaw); + if (!keysRes.success) { + throw new Error("Malformed credentials/keys"); + } + + const keys = keysRes.data; + const key = keys.installed ?? keys.web; + const payload = JSON.stringify({ + type: "authorized_user", + client_id: key.client_id, + client_secret: key.client_secret, + refresh_token: client.credentials.refresh_token, + }); + + await fs.writeFile(TOKEN_PATH, payload); +} diff --git a/apps/vdb-backend/src/index.ts b/apps/vdb-backend/src/index.ts index e948ff2..5ba7124 100644 --- a/apps/vdb-backend/src/index.ts +++ b/apps/vdb-backend/src/index.ts @@ -6,16 +6,12 @@ import { google, sheets_v4 } from "googleapis"; import { OAuth2Client } from "google-auth-library"; import { appDataSource } from "./config/dbconfig.js"; import { authorize } from "./auth.js"; +import { Lemma, WordForm, Lect } from "./db/dbmodel.js"; import { - Lemma, - WordForm, - Example, - Media, - Definition, - Comment, - PartOfSpeech, - Lect, -} from "./db/dbmodel.js"; + GoogleAuth, + JSONClient, +} from "google-auth-library/build/src/auth/googleauth.js"; +import "@total-typescript/ts-reset"; const RELOAD_SHEET_ON_START = false; @@ -56,7 +52,7 @@ function initExpress() { const search_term = req.query.search_term?.toString(); if (!search_term) { - return; + return void res.sendStatus(400); } const lemmas: Lemma[] = ( @@ -81,21 +77,21 @@ function initExpress() { const name = req.query.name?.toString(); if (!name) { - return; + return void res.sendStatus(400); } const lect = await Lect.findOne({ where: { name: name }, relations: { word_forms: { lemma: true } }, }); - + res.status(200).send({ lect }); }); - app.get("/lects", async (req, res) => { - const lects = await Lect.find() - res.status(200).send({ - lects + app.get("/lects", async (_req, res) => { + const lects = await Lect.find(); + res.status(200).send({ + lects, }); }); @@ -106,13 +102,13 @@ function initExpress() { } /** - * @param {google.auth.OAuth2Client} auth The authenticated Google OAuth client. + * @param auth The authenticated Google OAuth client. */ -async function loadSheet(auth: OAuth2Client) { +async function loadSheet(auth: OAuth2Client | GoogleAuth) { const lect_repository = appDataSource.getRepository(Lect); const word_form_repository = appDataSource.getRepository(WordForm); const lemma_repository = appDataSource.getRepository(Lemma); - const options: any = { version: "v4", auth }; + const options: sheets_v4.Options = { version: "v4", auth }; const sheets = google.sheets(options); const res = await sheets.spreadsheets.values.get({ spreadsheetId: "1-YkCeynx_-KYdubvt14augSPo37_20YgUv_f-i8HVwY", @@ -181,9 +177,9 @@ async function loadSheet(auth: OAuth2Client) { for (let i = 0; i < rows.length; i++) { const cell = row?.[i]; if ( - cell === null - || cell === undefined - || (typeof cell === "string" && cell.length === 0) + cell === null || + cell === undefined || + (typeof cell === "string" && cell.length === 0) ) { continue; } @@ -201,7 +197,9 @@ async function loadSheet(auth: OAuth2Client) { for (let i = 0; i < lemmas.length; i += 100) { await lemma_repository.save(lemmas.slice(i, i + 100)); console.log( - `Saved ${Math.min(i + 100, lemmas.length)} / ${lemmas.length} lemmas...`, + `Saved ${Math.min(i + 100, lemmas.length)} / ${ + lemmas.length + } lemmas...`, ); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cb13830..6126f3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^5.0.6 version: 5.0.34 '@google-cloud/local-auth': - specifier: ^2.1.0 - version: 2.1.1(encoding@0.1.13) + specifier: ^3.0.1 + version: 3.0.1(encoding@0.1.13) '@repo/common': specifier: workspace:* version: link:../../libs/common @@ -27,11 +27,11 @@ importers: specifier: ^5.1.0 version: 5.1.0 google-auth-library: - specifier: ^10.3.0 - version: 10.3.0 + specifier: ^9.15.1 + version: 9.15.1(encoding@0.1.13) googleapis: - specifier: ^159.0.0 - version: 159.0.0 + specifier: ^149.0.0 + version: 149.0.0(encoding@0.1.13) node-fetch: specifier: ^3.3.2 version: 3.3.2 @@ -44,7 +44,13 @@ importers: typeorm: specifier: 0.3.26 version: 0.3.26(better-sqlite3@12.2.0)(reflect-metadata@0.2.2)(sqlite3@5.1.7) + zod: + specifier: ^4.1.8 + version: 4.1.8 devDependencies: + '@total-typescript/ts-reset': + specifier: ^0.6.1 + version: 0.6.1 '@types/express': specifier: ^5.0.3 version: 5.0.3 @@ -63,15 +69,15 @@ importers: '@types/node': specifier: ^22.15.17 version: 22.15.31 - axios: - specifier: ^1.11.0 - version: 1.11.0 '@vueuse/components': specifier: ^13.3.0 version: 13.3.0(vue@3.5.16(typescript@5.8.3)) '@vueuse/core': specifier: ^13.3.0 version: 13.3.0(vue@3.5.16(typescript@5.8.3)) + axios: + specifier: ^1.11.0 + version: 1.11.0 bulma: specifier: ^1.0.4 version: 1.0.4 @@ -364,9 +370,9 @@ packages: '@gar/promisify@1.1.3': resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - '@google-cloud/local-auth@2.1.1': - resolution: {integrity: sha512-tOJ73TSyPxelUEVN2AdHVzFG857U5i3wZHMUGgm6wRtz9WN4O3D761eYORB9jXfIggA3+v5BUw+VIE5wAKHhkg==} - engines: {node: '>=12.0.0'} + '@google-cloud/local-auth@3.0.1': + resolution: {integrity: sha512-YJ3GFbksfHyEarbVHPSCzhKpjbnlAhdzg2SEf79l6ODukrSM1qUOqfopY232Xkw26huKSndyzmJz+A6b2WYn7Q==} + engines: {node: '>=14.0.0'} '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} @@ -729,6 +735,9 @@ packages: resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} engines: {node: '>= 6'} + '@total-typescript/ts-reset@0.6.1': + resolution: {integrity: sha512-cka47fVSo6lfQDIATYqb/vO1nvFfbPw7uWLayIXIhGETj0wcOOlrlkobOMDNQOFr9QOafegUPq13V2+6vtD7yg==} + '@types/body-parser@1.19.6': resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} @@ -912,8 +921,6 @@ packages: vue: optional: true - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} '@vueuse/components@13.3.0': resolution: {integrity: sha512-ZnJiVknPtlWyeE4qwIXkDOlHM3W4bgMCxgeXj1Dec/aF/+8N+yAj+7rRdRUWUnqr8uKRin368RjG1FPKsF2erA==} peerDependencies: @@ -932,6 +939,9 @@ packages: peerDependencies: vue: ^3.5.0 + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -1411,9 +1421,6 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-text-encoding@1.0.6: - resolution: {integrity: sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==} - fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -1511,21 +1518,13 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} deprecated: This package is no longer supported. - gaxios@5.1.3: - resolution: {integrity: sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==} - engines: {node: '>=12'} + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} - gaxios@7.1.1: - resolution: {integrity: sha512-Odju3uBUJyVCkW64nLD4wKLhbh93bh6vIg/ZIXkWiLPBrdgtc65+tls/qml+un3pr6JqYVFDZbbmLDQT68rTOQ==} - engines: {node: '>=18'} - - gcp-metadata@5.3.0: - resolution: {integrity: sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==} - engines: {node: '>=12'} - - gcp-metadata@7.0.1: - resolution: {integrity: sha512-UcO3kefx6dCcZkgcTGgVOTFb7b1LlQ02hY1omMjjrrBzkajRMCFgYOjs7J71WqnuG1k2b+9ppGL7FsOfhZMQKQ==} - engines: {node: '>=18'} + gcp-metadata@6.1.1: + resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} + engines: {node: '>=14'} get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} @@ -1570,31 +1569,21 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - google-auth-library@10.3.0: - resolution: {integrity: sha512-ylSE3RlCRZfZB56PFJSfUCuiuPq83Fx8hqu1KPWGK8FVdSaxlp/qkeMMX/DT/18xkwXIHvXEXkZsljRwfrdEfQ==} - engines: {node: '>=18'} - - google-auth-library@8.9.0: - resolution: {integrity: sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==} - engines: {node: '>=12'} - - google-logging-utils@1.1.1: - resolution: {integrity: sha512-rcX58I7nqpu4mbKztFeOAObbomBbHU2oIb/d3tJfF3dizGSApqtSwYJigGCooHdnMyQBIw8BrWyK96w3YXgr6A==} + google-auth-library@9.15.1: + resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} engines: {node: '>=14'} - google-p12-pem@4.0.1: - resolution: {integrity: sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==} - engines: {node: '>=12.0.0'} - deprecated: Package is no longer maintained - hasBin: true + google-logging-utils@0.0.2: + resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} + engines: {node: '>=14'} - googleapis-common@8.0.0: - resolution: {integrity: sha512-66if47It7y+Sab3HMkwEXx1kCq9qUC9px8ZXoj1CMrmLmUw81GpbnsNlXnlyZyGbGPGcj+tDD9XsZ23m7GLaJQ==} - engines: {node: '>=18.0.0'} + googleapis-common@7.2.0: + resolution: {integrity: sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==} + engines: {node: '>=14.0.0'} - googleapis@159.0.0: - resolution: {integrity: sha512-halby2+lQwHNxUDk70aQNXP1BlBwdwr7svTJZvDi7vKwrWbVMKhVrZ86h8p3zRcWbO4qAgLQ4ODAf8TgD3DhGQ==} - engines: {node: '>=18'} + googleapis@149.0.0: + resolution: {integrity: sha512-LTMc/njwYy7KTeaUHDcQt7KxftHyghdzm2XzbL46PRLd1AXB09utT9Po2ZJn2X0EApz0pE2T5x5A9zM8iue6zw==} + engines: {node: '>=14.0.0'} gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} @@ -1606,13 +1595,9 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - gtoken@6.1.2: - resolution: {integrity: sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==} - engines: {node: '>=12.0.0'} - - gtoken@8.0.0: - resolution: {integrity: sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==} - engines: {node: '>=18'} + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -2067,10 +2052,6 @@ packages: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - node-forge@1.3.1: - resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} - engines: {node: '>= 6.13.0'} - node-gyp@8.4.1: resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} engines: {node: '>= 10.12.0'} @@ -2669,6 +2650,10 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -2819,6 +2804,9 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod@4.1.8: + resolution: {integrity: sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==} + snapshots: '@ampproject/remapping@2.3.0': @@ -2971,10 +2959,10 @@ snapshots: '@gar/promisify@1.1.3': optional: true - '@google-cloud/local-auth@2.1.1(encoding@0.1.13)': + '@google-cloud/local-auth@3.0.1(encoding@0.1.13)': dependencies: arrify: 2.0.1 - google-auth-library: 8.9.0(encoding@0.1.13) + google-auth-library: 9.15.1(encoding@0.1.13) open: 7.4.2 server-destroy: 1.0.1 transitivePeerDependencies: @@ -3260,6 +3248,8 @@ snapshots: '@tootallnate/once@1.1.2': optional: true + '@total-typescript/ts-reset@0.6.1': {} + '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 @@ -3512,8 +3502,6 @@ snapshots: typescript: 5.8.3 vue: 3.5.16(typescript@5.8.3) - abbrev@1.1.1: - optional: true '@vueuse/components@13.3.0(vue@3.5.16(typescript@5.8.3))': dependencies: '@vueuse/core': 13.3.0(vue@3.5.16(typescript@5.8.3)) @@ -3533,6 +3521,9 @@ snapshots: dependencies: vue: 3.5.16(typescript@5.8.3) + abbrev@1.1.1: + optional: true + accepts@2.0.0: dependencies: mime-types: 3.0.1 @@ -3549,6 +3540,7 @@ snapshots: debug: 4.4.1 transitivePeerDependencies: - supports-color + optional: true agent-base@7.1.4: {} @@ -4070,8 +4062,6 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-text-encoding@1.0.6: {} - fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -4171,38 +4161,24 @@ snapshots: wide-align: 1.1.5 optional: true - gaxios@5.1.3(encoding@0.1.13): - dependencies: - extend: 3.0.2 - https-proxy-agent: 5.0.1 - is-stream: 2.0.1 - node-fetch: 2.7.0(encoding@0.1.13) - transitivePeerDependencies: - - encoding - - supports-color - - gaxios@7.1.1: + gaxios@6.7.1(encoding@0.1.13): dependencies: extend: 3.0.2 https-proxy-agent: 7.0.6 - node-fetch: 3.3.2 - transitivePeerDependencies: - - supports-color - - gcp-metadata@5.3.0(encoding@0.1.13): - dependencies: - gaxios: 5.1.3(encoding@0.1.13) - json-bigint: 1.0.0 + is-stream: 2.0.1 + node-fetch: 2.7.0(encoding@0.1.13) + uuid: 9.0.1 transitivePeerDependencies: - encoding - supports-color - gcp-metadata@7.0.1: + gcp-metadata@6.1.1(encoding@0.1.13): dependencies: - gaxios: 7.1.1 - google-logging-utils: 1.1.1 + gaxios: 6.7.1(encoding@0.1.13) + google-logging-utils: 0.0.2 json-bigint: 1.0.0 transitivePeerDependencies: + - encoding - supports-color get-caller-file@2.0.5: {} @@ -4269,54 +4245,38 @@ snapshots: globals@14.0.0: {} - google-auth-library@10.3.0: + google-auth-library@9.15.1(encoding@0.1.13): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.1.1 - gcp-metadata: 7.0.1 - google-logging-utils: 1.1.1 - gtoken: 8.0.0 + gaxios: 6.7.1(encoding@0.1.13) + gcp-metadata: 6.1.1(encoding@0.1.13) + gtoken: 7.1.0(encoding@0.1.13) jws: 4.0.0 - transitivePeerDependencies: - - supports-color - - google-auth-library@8.9.0(encoding@0.1.13): - dependencies: - arrify: 2.0.1 - base64-js: 1.5.1 - ecdsa-sig-formatter: 1.0.11 - fast-text-encoding: 1.0.6 - gaxios: 5.1.3(encoding@0.1.13) - gcp-metadata: 5.3.0(encoding@0.1.13) - gtoken: 6.1.2(encoding@0.1.13) - jws: 4.0.0 - lru-cache: 6.0.0 transitivePeerDependencies: - encoding - supports-color - google-logging-utils@1.1.1: {} + google-logging-utils@0.0.2: {} - google-p12-pem@4.0.1: - dependencies: - node-forge: 1.3.1 - - googleapis-common@8.0.0: + googleapis-common@7.2.0(encoding@0.1.13): dependencies: extend: 3.0.2 - gaxios: 7.1.1 - google-auth-library: 10.3.0 + gaxios: 6.7.1(encoding@0.1.13) + google-auth-library: 9.15.1(encoding@0.1.13) qs: 6.14.0 url-template: 2.0.8 + uuid: 9.0.1 transitivePeerDependencies: + - encoding - supports-color - googleapis@159.0.0: + googleapis@149.0.0(encoding@0.1.13): dependencies: - google-auth-library: 10.3.0 - googleapis-common: 8.0.0 + google-auth-library: 9.15.1(encoding@0.1.13) + googleapis-common: 7.2.0(encoding@0.1.13) transitivePeerDependencies: + - encoding - supports-color gopd@1.2.0: {} @@ -4325,22 +4285,14 @@ snapshots: graphemer@1.4.0: {} - gtoken@6.1.2(encoding@0.1.13): + gtoken@7.1.0(encoding@0.1.13): dependencies: - gaxios: 5.1.3(encoding@0.1.13) - google-p12-pem: 4.0.1 + gaxios: 6.7.1(encoding@0.1.13) jws: 4.0.0 transitivePeerDependencies: - encoding - supports-color - gtoken@8.0.0: - dependencies: - gaxios: 7.1.1 - jws: 4.0.0 - transitivePeerDependencies: - - supports-color - has-flag@4.0.0: {} has-property-descriptors@1.0.2: @@ -4388,6 +4340,7 @@ snapshots: debug: 4.4.1 transitivePeerDependencies: - supports-color + optional: true https-proxy-agent@7.0.6: dependencies: @@ -4588,6 +4541,7 @@ snapshots: lru-cache@6.0.0: dependencies: yallist: 4.0.0 + optional: true magic-string-ast@0.7.1: dependencies: @@ -4755,8 +4709,6 @@ snapshots: fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 - node-forge@1.3.1: {} - node-gyp@8.4.1: dependencies: env-paths: 2.2.1 @@ -5423,6 +5375,8 @@ snapshots: uuid@11.1.0: {} + uuid@9.0.1: {} + vary@1.1.2: {} vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.2)(tsx@4.20.2)(yaml@2.8.0): @@ -5554,3 +5508,5 @@ snapshots: yargs-parser: 21.1.1 yocto-queue@0.1.0: {} + + zod@4.1.8: {}