diff --git a/db-datos/drizzle.config.js b/db-datos/drizzle.config.js index 3a95609..282e9ad 100644 --- a/db-datos/drizzle.config.js +++ b/db-datos/drizzle.config.js @@ -1,4 +1,4 @@ -export const DB_PATH = process.env.DB_PATH ?? "../scraper/sqlite.db"; +export const DB_PATH = process.env.DB_PATH ?? "../sqlite.db"; /** @type { import("drizzle-kit").Config } */ export default { diff --git a/link-scrapers/carrefour.ts b/link-scrapers/carrefour.ts deleted file mode 100644 index ce92306..0000000 --- a/link-scrapers/carrefour.ts +++ /dev/null @@ -1,33 +0,0 @@ -import pMap from "p-map"; -import { saveUrls } from "db-datos/urlHelpers.js"; -import { getUrlsFromSitemap } from "./common.js"; - -export async function scrapCarrefourProducts() { - await scrapBySitemap(); -} - -async function scrapBySitemap() { - // de https://www.carrefour.com.ar/sitemap.xml - const sitemaps = [ - "https://www.carrefour.com.ar/sitemap/product-0.xml", - "https://www.carrefour.com.ar/sitemap/product-1.xml", - "https://www.carrefour.com.ar/sitemap/product-2.xml", - "https://www.carrefour.com.ar/sitemap/product-3.xml", - "https://www.carrefour.com.ar/sitemap/product-4.xml", - "https://www.carrefour.com.ar/sitemap/product-5.xml", - "https://www.carrefour.com.ar/sitemap/product-6.xml", - "https://www.carrefour.com.ar/sitemap/product-7.xml", - "https://www.carrefour.com.ar/sitemap/product-8.xml", - "https://www.carrefour.com.ar/sitemap/product-9.xml", - ]; - - await pMap( - sitemaps, - async (sitemapUrl) => { - const res = await fetch(sitemapUrl); - const xml = await res.text(); - saveUrls(getUrlsFromSitemap(xml)); - }, - { concurrency: 3 } - ); -} diff --git a/link-scrapers/common.ts b/link-scrapers/common.ts deleted file mode 100644 index f4107a0..0000000 --- a/link-scrapers/common.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { decodeXML } from "entities"; -export function getUrlsFromSitemap(xml: string) { - let urls = new Set(); - new HTMLRewriter() - .on("loc", { - text(element) { - const txt = element.text.trim(); - if (!txt) return; - urls.add(decodeXML(txt)); - }, - }) - .transform(new Response(xml)); - return Array.from(urls); -} diff --git a/link-scrapers/coto.ts b/link-scrapers/coto.ts deleted file mode 100644 index d3de22d..0000000 --- a/link-scrapers/coto.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { parseHTML } from "linkedom"; -import PQueue from "p-queue"; -import { saveUrls } from "db-datos/urlHelpers.js"; - -export async function scrapCotoProducts() { - const initial = - "https://www.cotodigital3.com.ar/sitios/cdigi/browse?Nf=product.endDate%7CGTEQ+1.7032032E12%7C%7Cproduct.startDate%7CLTEQ+1.7032032E12&No=2200&Nr=AND%28product.sDisp_200%3A1004%2Cproduct.language%3Aespa%C3%B1ol%2COR%28product.siteId%3ACotoDigital%29%29&Nrpp=200"; - - const queue = new PQueue({ concurrency: 4 }); - - const pageSize = 300; // hasta 1000 - const links = Array.from( - { length: Math.ceil(29000 / pageSize) }, - (x, i) => i - ).map((i) => { - const url = new URL(initial); - url.searchParams.set("No", `${i * pageSize}`); - url.searchParams.set("Nrpp", `${pageSize}`); - return url.toString(); - }); - - const promises = links.map((l) => queue.add(getPage(l))); - await Promise.all(promises); -} - -function getPage(url: string) { - return async () => { - let html; - try { - const res = await fetch(url); - html = await res.text(); - } catch (error) { - await getPage(url)(); - return; - } - const { document } = parseHTML(html); - - const hrefs = Array.from( - document.querySelectorAll(".product_info_container a"), - (a) => new URL(a.href, url).toString() - ); - saveUrls(hrefs); - }; -} diff --git a/link-scrapers/dia.ts b/link-scrapers/dia.ts deleted file mode 100644 index 0464ded..0000000 --- a/link-scrapers/dia.ts +++ /dev/null @@ -1,124 +0,0 @@ -import pMap from "p-map"; -import { parseHTML } from "linkedom"; -import { saveUrls } from "db-datos/urlHelpers.js"; -import { getUrlsFromSitemap } from "./common.js"; - -const categorias = [ - "https://diaonline.supermercadosdia.com.ar/almacen", - "https://diaonline.supermercadosdia.com.ar/almacen/conservas", - "https://diaonline.supermercadosdia.com.ar/almacen/aceites-y-aderezos", - "https://diaonline.supermercadosdia.com.ar/almacen/pastas-secas", - "https://diaonline.supermercadosdia.com.ar/almacen/arroz-y-legumbres", - "https://diaonline.supermercadosdia.com.ar/almacen/panaderia", - "https://diaonline.supermercadosdia.com.ar/almacen/golosinas-y-alfajores", - "https://diaonline.supermercadosdia.com.ar/almacen/reposteria", - "https://diaonline.supermercadosdia.com.ar/almacen/comidas-listas", - "https://diaonline.supermercadosdia.com.ar/almacen/harinas", - "https://diaonline.supermercadosdia.com.ar/almacen/picadas", - "https://diaonline.supermercadosdia.com.ar/almacen/panaderia/pan-rallado-y-rebozadores", - "https://diaonline.supermercadosdia.com.ar/desayuno", - "https://diaonline.supermercadosdia.com.ar/desayuno/galletitas-y-cereales", - "https://diaonline.supermercadosdia.com.ar/desayuno/infusiones-y-endulzantes", - "https://diaonline.supermercadosdia.com.ar/desayuno/para-untar", - "https://diaonline.supermercadosdia.com.ar/frescos", - "https://diaonline.supermercadosdia.com.ar/frescos/leches", - "https://diaonline.supermercadosdia.com.ar/frescos/fiambreria", - "https://diaonline.supermercadosdia.com.ar/frescos/lacteos", - "https://diaonline.supermercadosdia.com.ar/frescos/carniceria", - "https://diaonline.supermercadosdia.com.ar/frescos/frutas-y-verduras", - "https://diaonline.supermercadosdia.com.ar/frescos/pastas-frescas", - "https://diaonline.supermercadosdia.com.ar/frescos/listos-para-disfrutar", - "https://diaonline.supermercadosdia.com.ar/frescos/frutas-y-verduras/frutas", - "https://diaonline.supermercadosdia.com.ar/frescos/frutas-y-verduras/verduras", - "https://diaonline.supermercadosdia.com.ar/frescos/frutas-y-verduras/huevos", - "https://diaonline.supermercadosdia.com.ar/frescos/frutas-y-verduras/frutos-secos", - "https://diaonline.supermercadosdia.com.ar/bebidas", - "https://diaonline.supermercadosdia.com.ar/bebidas/gaseosas", - "https://diaonline.supermercadosdia.com.ar/bebidas/cervezas", - "https://diaonline.supermercadosdia.com.ar/bebidas/aguas", - "https://diaonline.supermercadosdia.com.ar/bebidas/bodega", - "https://diaonline.supermercadosdia.com.ar/bebidas/jugos-e-isot%C3%B3nicas", - "https://diaonline.supermercadosdia.com.ar/bebidas/aperitivos", - "https://diaonline.supermercadosdia.com.ar/bebidas/bebidas-blancas-y-licores", - "https://diaonline.supermercadosdia.com.ar/congelados", - "https://diaonline.supermercadosdia.com.ar/congelados/hamburguesas-y-medallones", - "https://diaonline.supermercadosdia.com.ar/congelados/rebozados", - "https://diaonline.supermercadosdia.com.ar/congelados/vegetales-congelados", - "https://diaonline.supermercadosdia.com.ar/congelados/postres-congelados", - "https://diaonline.supermercadosdia.com.ar/congelados/pescaderia", - "https://diaonline.supermercadosdia.com.ar/congelados/papas-congeladas", - "https://diaonline.supermercadosdia.com.ar/congelados/comidas-congeladas", - "https://diaonline.supermercadosdia.com.ar/congelados/hielo", - "https://diaonline.supermercadosdia.com.ar/limpieza", - "https://diaonline.supermercadosdia.com.ar/limpieza/cuidado-de-la-ropa", - "https://diaonline.supermercadosdia.com.ar/limpieza/papeleria", - "https://diaonline.supermercadosdia.com.ar/limpieza/limpiadores", - "https://diaonline.supermercadosdia.com.ar/limpieza/limpieza-de-cocina", - "https://diaonline.supermercadosdia.com.ar/limpieza/accesorios-de-limpieza", - "https://diaonline.supermercadosdia.com.ar/limpieza/desodorantes-de-ambiente", - "https://diaonline.supermercadosdia.com.ar/limpieza/insecticidas", - "https://diaonline.supermercadosdia.com.ar/limpieza/fosforos-y-velas", - "https://diaonline.supermercadosdia.com.ar/limpieza/bolsas", - "https://diaonline.supermercadosdia.com.ar/4160?map=productClusterIds&order=OrderByBestDiscountDESC", - "https://diaonline.supermercadosdia.com.ar/4136?map=productClusterIds&order=OrderByBestDiscountDESC", - "https://diaonline.supermercadosdia.com.ar/4143?map=productClusterIds&order=OrderByBestDiscountDESC", - "https://diaonline.supermercadosdia.com.ar/4189?map=productClusterIds&order=OrderByBestDiscountDESC", - "https://diaonline.supermercadosdia.com.ar/4086?map=productClusterIds&order=OrderByBestDiscountDESC", - "https://diaonline.supermercadosdia.com.ar/2089?map=productClusterIds&order=OrderByBestDiscountDESC", -]; - -export async function scrapDiaProducts() { - await Promise.all([ - // scrapBySite(), - scrapBySitemap(), - ]); -} - -async function scrapBySitemap() { - // de https://diaonline.supermercadosdia.com.ar/sitemap.xml - const sitemaps = [ - "https://diaonline.supermercadosdia.com.ar/sitemap/product-1.xml", - "https://diaonline.supermercadosdia.com.ar/sitemap/product-2.xml", - "https://diaonline.supermercadosdia.com.ar/sitemap/product-3.xml", - "https://diaonline.supermercadosdia.com.ar/sitemap/product-4.xml", - "https://diaonline.supermercadosdia.com.ar/sitemap/product-5.xml", - ]; - - await pMap( - sitemaps, - async (sitemapUrl) => { - const res = await fetch(sitemapUrl); - const xml = await res.text(); - saveUrls(getUrlsFromSitemap(xml)); - }, - { concurrency: 3 } - ); -} - -async function scrapBySite() { - const links = categorias.flatMap((link) => - Array.from({ length: 51 }, (x, i) => i).map((i) => { - const url = new URL(link); - url.searchParams.set("page", `${i}`); - return url.toString(); - }) - ); - - await pMap( - links, - async (url) => { - const res = await fetch(url, { timeout: false }); - const html = await res.text(); - const { document } = parseHTML(html); - - const hrefs = Array.from( - document.querySelectorAll( - "a.vtex-product-summary-2-x-clearLink" - ), - (a) => new URL(a.href, url).toString() - ); - saveUrls(hrefs); - }, - { concurrency: 32 } - ); -} diff --git a/link-scrapers/jumbo.ts b/link-scrapers/jumbo.ts deleted file mode 100644 index 77356d5..0000000 --- a/link-scrapers/jumbo.ts +++ /dev/null @@ -1,38 +0,0 @@ -import pMap from "p-map"; -import { saveUrls } from "db-datos/urlHelpers.js"; -import { getUrlsFromSitemap } from "./common.js"; - -export async function scrapJumboProducts() { - await scrapBySitemap(); -} - -async function scrapBySitemap() { - // de https://www.jumbo.com.ar/sitemap.xml - const sitemaps = [ - "https://www.jumbo.com.ar/sitemap/product-1.xml", - "https://www.jumbo.com.ar/sitemap/product-10.xml", - "https://www.jumbo.com.ar/sitemap/product-11.xml", - "https://www.jumbo.com.ar/sitemap/product-12.xml", - "https://www.jumbo.com.ar/sitemap/product-13.xml", - "https://www.jumbo.com.ar/sitemap/product-14.xml", - "https://www.jumbo.com.ar/sitemap/product-15.xml", - "https://www.jumbo.com.ar/sitemap/product-2.xml", - "https://www.jumbo.com.ar/sitemap/product-3.xml", - "https://www.jumbo.com.ar/sitemap/product-4.xml", - "https://www.jumbo.com.ar/sitemap/product-5.xml", - "https://www.jumbo.com.ar/sitemap/product-6.xml", - "https://www.jumbo.com.ar/sitemap/product-7.xml", - "https://www.jumbo.com.ar/sitemap/product-8.xml", - "https://www.jumbo.com.ar/sitemap/product-9.xml", - ]; - - await pMap( - sitemaps, - async (sitemapUrl) => { - const res = await fetch(sitemapUrl); - const xml = await res.text(); - saveUrls(getUrlsFromSitemap(xml)); - }, - { concurrency: 3 } - ); -} diff --git a/link-scrapers/package.json b/link-scrapers/package.json deleted file mode 100644 index 9ae66f9..0000000 --- a/link-scrapers/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "link-scrapers", - "type": "module", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "entities": "^4.5.0", - "linkedom": "^0.16.5", - "p-queue": "^8.0.1" - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c2f61a..97a73bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,58 +25,6 @@ importers: specifier: ^0.20.7 version: 0.20.12 - link-scrapers: - dependencies: - entities: - specifier: ^4.5.0 - version: 4.5.0 - linkedom: - specifier: ^0.16.5 - version: 0.16.6 - p-queue: - specifier: ^8.0.1 - version: 8.0.1 - - scraper: - dependencies: - '@aws-sdk/client-s3': - specifier: ^3.478.0 - version: 3.490.0 - '@aws-sdk/lib-storage': - specifier: ^3.478.0 - version: 3.490.0(@aws-sdk/client-s3@3.490.0) - croner: - specifier: ^8.0.0 - version: 8.0.0 - date-fns: - specifier: ^3.0.6 - version: 3.2.0 - db-datos: - specifier: workspace:^ - version: link:../db-datos - drizzle-orm: - specifier: ^0.29.1 - version: 0.29.3(@types/better-sqlite3@7.6.8)(better-sqlite3@9.2.2) - linkedom: - specifier: ^0.16.5 - version: 0.16.6 - nanoid: - specifier: ^5.0.4 - version: 5.0.4 - p-map: - specifier: ^7.0.1 - version: 7.0.1 - p-queue: - specifier: ^8.0.1 - version: 8.0.1 - zod: - specifier: ^3.22.4 - version: 3.22.4 - devDependencies: - typescript: - specifier: ^5.3.3 - version: 5.3.3 - sitio: dependencies: better-sqlite3: @@ -165,607 +113,6 @@ packages: '@jridgewell/trace-mapping': 0.3.21 dev: true - /@aws-crypto/crc32@3.0.0: - resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} - dependencies: - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 - tslib: 1.14.1 - dev: false - - /@aws-crypto/crc32c@3.0.0: - resolution: {integrity: sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==} - dependencies: - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 - tslib: 1.14.1 - dev: false - - /@aws-crypto/ie11-detection@3.0.0: - resolution: {integrity: sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==} - dependencies: - tslib: 1.14.1 - dev: false - - /@aws-crypto/sha1-browser@3.0.0: - resolution: {integrity: sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==} - dependencies: - '@aws-crypto/ie11-detection': 3.0.0 - '@aws-crypto/supports-web-crypto': 3.0.0 - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-locate-window': 3.465.0 - '@aws-sdk/util-utf8-browser': 3.259.0 - tslib: 1.14.1 - dev: false - - /@aws-crypto/sha256-browser@3.0.0: - resolution: {integrity: sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==} - dependencies: - '@aws-crypto/ie11-detection': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-crypto/supports-web-crypto': 3.0.0 - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-locate-window': 3.465.0 - '@aws-sdk/util-utf8-browser': 3.259.0 - tslib: 1.14.1 - dev: false - - /@aws-crypto/sha256-js@3.0.0: - resolution: {integrity: sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==} - dependencies: - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 - tslib: 1.14.1 - dev: false - - /@aws-crypto/supports-web-crypto@3.0.0: - resolution: {integrity: sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==} - dependencies: - tslib: 1.14.1 - dev: false - - /@aws-crypto/util@3.0.0: - resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} - dependencies: - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-utf8-browser': 3.259.0 - tslib: 1.14.1 - dev: false - - /@aws-sdk/client-s3@3.490.0: - resolution: {integrity: sha512-fBj3CJ3+5R+l/sc93Z9mKw8gM2b9K6vEhC9qSCG2XNymLd9YqlRft1peQ7VymrWywAHX3Koz1GCUrFEVNONiMw==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-crypto/sha1-browser': 3.0.0 - '@aws-crypto/sha256-browser': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.490.0 - '@aws-sdk/core': 3.490.0 - '@aws-sdk/credential-provider-node': 3.490.0 - '@aws-sdk/middleware-bucket-endpoint': 3.489.0 - '@aws-sdk/middleware-expect-continue': 3.489.0 - '@aws-sdk/middleware-flexible-checksums': 3.489.0 - '@aws-sdk/middleware-host-header': 3.489.0 - '@aws-sdk/middleware-location-constraint': 3.489.0 - '@aws-sdk/middleware-logger': 3.489.0 - '@aws-sdk/middleware-recursion-detection': 3.489.0 - '@aws-sdk/middleware-sdk-s3': 3.489.0 - '@aws-sdk/middleware-signing': 3.489.0 - '@aws-sdk/middleware-ssec': 3.489.0 - '@aws-sdk/middleware-user-agent': 3.489.0 - '@aws-sdk/region-config-resolver': 3.489.0 - '@aws-sdk/signature-v4-multi-region': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@aws-sdk/util-user-agent-browser': 3.489.0 - '@aws-sdk/util-user-agent-node': 3.489.0 - '@aws-sdk/xml-builder': 3.485.0 - '@smithy/config-resolver': 2.0.23 - '@smithy/core': 1.2.2 - '@smithy/eventstream-serde-browser': 2.0.16 - '@smithy/eventstream-serde-config-resolver': 2.0.16 - '@smithy/eventstream-serde-node': 2.0.16 - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/hash-blob-browser': 2.0.17 - '@smithy/hash-node': 2.0.18 - '@smithy/hash-stream-node': 2.0.18 - '@smithy/invalid-dependency': 2.0.16 - '@smithy/md5-js': 2.0.18 - '@smithy/middleware-content-length': 2.0.18 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/middleware-stack': 2.0.10 - '@smithy/node-config-provider': 2.1.9 - '@smithy/node-http-handler': 2.2.2 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-base64': 2.0.1 - '@smithy/util-body-length-browser': 2.0.1 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.24 - '@smithy/util-defaults-mode-node': 2.0.32 - '@smithy/util-endpoints': 1.0.8 - '@smithy/util-retry': 2.0.9 - '@smithy/util-stream': 2.0.24 - '@smithy/util-utf8': 2.0.2 - '@smithy/util-waiter': 2.0.16 - fast-xml-parser: 4.2.5 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - dev: false - - /@aws-sdk/client-sso@3.490.0: - resolution: {integrity: sha512-yfxoHmCL1w/IKmFRfzCxdVCQrGlSQf4eei9iVEm5oi3iE8REFyPj3o/BmKQEHG3h2ITK5UbdYDb5TY4xoYHsyA==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-crypto/sha256-browser': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/core': 3.490.0 - '@aws-sdk/middleware-host-header': 3.489.0 - '@aws-sdk/middleware-logger': 3.489.0 - '@aws-sdk/middleware-recursion-detection': 3.489.0 - '@aws-sdk/middleware-user-agent': 3.489.0 - '@aws-sdk/region-config-resolver': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@aws-sdk/util-user-agent-browser': 3.489.0 - '@aws-sdk/util-user-agent-node': 3.489.0 - '@smithy/config-resolver': 2.0.23 - '@smithy/core': 1.2.2 - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/hash-node': 2.0.18 - '@smithy/invalid-dependency': 2.0.16 - '@smithy/middleware-content-length': 2.0.18 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/middleware-stack': 2.0.10 - '@smithy/node-config-provider': 2.1.9 - '@smithy/node-http-handler': 2.2.2 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-base64': 2.0.1 - '@smithy/util-body-length-browser': 2.0.1 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.24 - '@smithy/util-defaults-mode-node': 2.0.32 - '@smithy/util-endpoints': 1.0.8 - '@smithy/util-retry': 2.0.9 - '@smithy/util-utf8': 2.0.2 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - dev: false - - /@aws-sdk/client-sts@3.490.0: - resolution: {integrity: sha512-n2vQ5Qu2qi2I0XMI+IH99ElpIRHOJTa1+sqNC4juMYxKQBMvw+EnsqUtaL3QvTHoyxNB/R7mpkeBB6SzPQ1TtA==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-crypto/sha256-browser': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/core': 3.490.0 - '@aws-sdk/credential-provider-node': 3.490.0 - '@aws-sdk/middleware-host-header': 3.489.0 - '@aws-sdk/middleware-logger': 3.489.0 - '@aws-sdk/middleware-recursion-detection': 3.489.0 - '@aws-sdk/middleware-user-agent': 3.489.0 - '@aws-sdk/region-config-resolver': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@aws-sdk/util-user-agent-browser': 3.489.0 - '@aws-sdk/util-user-agent-node': 3.489.0 - '@smithy/config-resolver': 2.0.23 - '@smithy/core': 1.2.2 - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/hash-node': 2.0.18 - '@smithy/invalid-dependency': 2.0.16 - '@smithy/middleware-content-length': 2.0.18 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/middleware-stack': 2.0.10 - '@smithy/node-config-provider': 2.1.9 - '@smithy/node-http-handler': 2.2.2 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-base64': 2.0.1 - '@smithy/util-body-length-browser': 2.0.1 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.24 - '@smithy/util-defaults-mode-node': 2.0.32 - '@smithy/util-endpoints': 1.0.8 - '@smithy/util-middleware': 2.0.9 - '@smithy/util-retry': 2.0.9 - '@smithy/util-utf8': 2.0.2 - fast-xml-parser: 4.2.5 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - dev: false - - /@aws-sdk/core@3.490.0: - resolution: {integrity: sha512-TSBWkXtxMU7q1Zo6w3v5wIOr/sj7P5Jw3OyO7lJrFGsPsDC2xwpxkVqTesDxkzgMRypO52xjYEmveagn1xxBHg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/core': 1.2.2 - '@smithy/protocol-http': 3.0.12 - '@smithy/signature-v4': 2.0.19 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/credential-provider-env@3.489.0: - resolution: {integrity: sha512-5PqYsx9G5SB2tqPT9/z/u0EkF6D4wP6HTMWQs+DfMdmwXihrqQAgeYaTtV3KbXqb88p6sfacwxhUvE6+Rm494w==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/credential-provider-ini@3.490.0: - resolution: {integrity: sha512-7m63zyCpVqj9FsoDxWMWWRvL6c7zZzOcXYkHZmHujVVlmAXH0RT/vkXFkYgt+Ku+ov+v5NQrzwO5TmVoRt6O8g==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/credential-provider-env': 3.489.0 - '@aws-sdk/credential-provider-process': 3.489.0 - '@aws-sdk/credential-provider-sso': 3.490.0 - '@aws-sdk/credential-provider-web-identity': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@smithy/credential-provider-imds': 2.1.5 - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - dev: false - - /@aws-sdk/credential-provider-node@3.490.0: - resolution: {integrity: sha512-Gh33u2O5Xbout8G3z/Z5H/CZzdG1ophxf/XS3iMFxA1cazQ7swY1UMmGvB7Lm7upvax5anXouItD1Ph3gzKc4w==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/credential-provider-env': 3.489.0 - '@aws-sdk/credential-provider-ini': 3.490.0 - '@aws-sdk/credential-provider-process': 3.489.0 - '@aws-sdk/credential-provider-sso': 3.490.0 - '@aws-sdk/credential-provider-web-identity': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@smithy/credential-provider-imds': 2.1.5 - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - dev: false - - /@aws-sdk/credential-provider-process@3.489.0: - resolution: {integrity: sha512-3vKQYJZ5cZYjy0870CPmbmKRBgATw2xCygxhn4m4UDCjOXVXcGUtYD51DMWsvBo3S0W8kH+FIJV4yuEDMFqLFQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/credential-provider-sso@3.490.0: - resolution: {integrity: sha512-3UUBUoPbFvT58IhS4Vb23omYj/QPNkjgxu9p9ruQ3KSjLkanI4w8t/l/jljA65q83P7CoLnM5UKG9L7RA8/V1Q==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/client-sso': 3.490.0 - '@aws-sdk/token-providers': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - dev: false - - /@aws-sdk/credential-provider-web-identity@3.489.0: - resolution: {integrity: sha512-mjIuE2Wg1H/ds0nXQ/7vfusEDudmdd8YzKZI1y5O4n60iZZtyB2RNIECtvLMx1EQAKclidY7/06qQkArrGau5Q==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/lib-storage@3.490.0(@aws-sdk/client-s3@3.490.0): - resolution: {integrity: sha512-JLRabk0bHzEd0G5RF+62/kyiIKSwrstW9WC0/CEvIfZbFbDPE4Ncd8q97YLUTFiIGDNsEcjW8DSbA6Feezcwhg==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@aws-sdk/client-s3': ^3.0.0 - dependencies: - '@aws-sdk/client-s3': 3.490.0 - '@smithy/abort-controller': 2.0.16 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/smithy-client': 2.2.1 - buffer: 5.6.0 - events: 3.3.0 - stream-browserify: 3.0.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-bucket-endpoint@3.489.0: - resolution: {integrity: sha512-6rJ5bpNMKo7sEKQ6p2DMbQwM+ahMYASRxfdyH7hs18blvlcS20H1RYpNmJMqPPjxMwUWruty2JPMIRl4DFcv8w==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-arn-parser': 3.465.0 - '@smithy/node-config-provider': 2.1.9 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - '@smithy/util-config-provider': 2.1.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-expect-continue@3.489.0: - resolution: {integrity: sha512-2RZfnVZFaGHwzPDQJsyf9SXufu1gUd4VsMhm7dC7SWF85XmpDrozbFznS/tD22QdtyWjerLoydZJMq229hpPqg==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-flexible-checksums@3.489.0: - resolution: {integrity: sha512-Cy3rBUMr4P7raxzrJFWNRshfKrKV2EojawaC9Bfk/T8aFlV+FmVrRg4ISAXMOfS5pfy3xfAbvkzjOaeqCsGfrA==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-crypto/crc32': 3.0.0 - '@aws-crypto/crc32c': 3.0.0 - '@aws-sdk/types': 3.489.0 - '@smithy/is-array-buffer': 2.0.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - '@smithy/util-utf8': 2.0.2 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-host-header@3.489.0: - resolution: {integrity: sha512-Cl7HJ1jhOfllwf0CRx1eB4ypRGMqdGKWpc0eSTXty7wWSvCdMZUhwfjQqu2bIOIlgYxg/gFu6TVmVZ6g4O8PlA==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-location-constraint@3.489.0: - resolution: {integrity: sha512-NIVr+kHR2N6gxFeE3TNw2mEBxgj0N9xXBLy3dNYMMlAUvQlT/0z9HlC9+3XqcTS/Z5ElF/+pei6nqXTVt0He9A==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-logger@3.489.0: - resolution: {integrity: sha512-+EVDnWese61MdImcBNAgz/AhTcIZJaska/xsU3GWU9CP905x4a4qZdB7fExFMDu1Jlz5pJqNteFYYHCFMJhHfg==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-recursion-detection@3.489.0: - resolution: {integrity: sha512-m4rU+fTzziQcu9DKjRNZ4nQlXENEd2ZnJblJV4ONdWqqEjbmOgOj3P6aCCQlJdIbzuNvX1FBOZ5tY59ZpERo7Q==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-sdk-s3@3.489.0: - resolution: {integrity: sha512-/GGASx7mK9qEgy1znvleYMZKVqm3sOdGghqKdy2zgoGcH2jH+fZrLM0lDMT9bvdITmOCbJJs2rVHP3xm/ZWcXg==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-arn-parser': 3.465.0 - '@smithy/node-config-provider': 2.1.9 - '@smithy/protocol-http': 3.0.12 - '@smithy/signature-v4': 2.0.19 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/util-config-provider': 2.1.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-signing@3.489.0: - resolution: {integrity: sha512-rlHcWYZn6Ym3v/u0DvKNDiD7ogIzEsHlerm0lowTiQbszkFobOiUClRTALwvsUZdAAztl706qO1OKbnGnD6Ubw==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/protocol-http': 3.0.12 - '@smithy/signature-v4': 2.0.19 - '@smithy/types': 2.8.0 - '@smithy/util-middleware': 2.0.9 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-ssec@3.489.0: - resolution: {integrity: sha512-5RQg8dqERAmi1OfVEV9fbTA5NKmcvKDYP79YtH08IEFIsHWU1Y5NoqL7mXkkNyBrJNBVyasYijAbTzOuM707eg==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/middleware-user-agent@3.489.0: - resolution: {integrity: sha512-M54Cv2fAN3GGgdfUjLtZ4wFUIrfM/ivbXv4DgpcNsacEQ2g4H+weQgKp41X7XZW8MWAzl+k1zJaryK69RYNQkQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/region-config-resolver@3.489.0: - resolution: {integrity: sha512-UvrnB78XTz9ddby7mr0vuUHn2MO3VTjzaIu+GQhyedMGQU0QlIQrYOlzbbu4LC5rL1O8FxFLUxRe/AAjgwyuGw==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/node-config-provider': 2.1.9 - '@smithy/types': 2.8.0 - '@smithy/util-config-provider': 2.1.0 - '@smithy/util-middleware': 2.0.9 - tslib: 2.6.2 - dev: false - - /@aws-sdk/signature-v4-multi-region@3.489.0: - resolution: {integrity: sha512-kYFM7Opu36EkFlzXdVNOBFpQApgnuaTu/U/qYhGyuzeD+HNnYgZEsd/tDro1DQ074jVy3GN9ttJSYxq5I4oTkA==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/middleware-sdk-s3': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/signature-v4': 2.0.19 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/token-providers@3.489.0: - resolution: {integrity: sha512-hSgjB8CMQoA8EIQ0ripDjDtbBcWDSa+7vSBYPIzksyknaGERR/GUfGXLV2dpm5t17FgFG6irT5f3ZlBzarL8Dw==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-crypto/sha256-browser': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/middleware-host-header': 3.489.0 - '@aws-sdk/middleware-logger': 3.489.0 - '@aws-sdk/middleware-recursion-detection': 3.489.0 - '@aws-sdk/middleware-user-agent': 3.489.0 - '@aws-sdk/region-config-resolver': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@aws-sdk/util-user-agent-browser': 3.489.0 - '@aws-sdk/util-user-agent-node': 3.489.0 - '@smithy/config-resolver': 2.0.23 - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/hash-node': 2.0.18 - '@smithy/invalid-dependency': 2.0.16 - '@smithy/middleware-content-length': 2.0.18 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/middleware-stack': 2.0.10 - '@smithy/node-config-provider': 2.1.9 - '@smithy/node-http-handler': 2.2.2 - '@smithy/property-provider': 2.0.17 - '@smithy/protocol-http': 3.0.12 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-base64': 2.0.1 - '@smithy/util-body-length-browser': 2.0.1 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.24 - '@smithy/util-defaults-mode-node': 2.0.32 - '@smithy/util-endpoints': 1.0.8 - '@smithy/util-retry': 2.0.9 - '@smithy/util-utf8': 2.0.2 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - dev: false - - /@aws-sdk/types@3.489.0: - resolution: {integrity: sha512-kcDtLfKog/p0tC4gAeqJqWxAiEzfe2LRPnKamvSG2Mjbthx4R/alE2dxyIq/wW+nvRv0fqR3OD5kD1+eVfdr/w==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/util-arn-parser@3.465.0: - resolution: {integrity: sha512-zOJ82vzDJFqBX9yZBlNeHHrul/kpx/DCoxzW5UBbZeb26kfV53QhMSoEmY8/lEbBqlqargJ/sgRC845GFhHNQw==} - engines: {node: '>=14.0.0'} - dependencies: - tslib: 2.6.2 - dev: false - - /@aws-sdk/util-endpoints@3.489.0: - resolution: {integrity: sha512-uGyG1u84ATX03mf7bT4xD9XD/vlYJGD5+RxMN/UpzeTfzXfh+jvCQWbOQ44z8ttFJWYQQqrLxkfpF/JgvALzLA==} - engines: {node: '>=14.0.0'} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 - '@smithy/util-endpoints': 1.0.8 - tslib: 2.6.2 - dev: false - - /@aws-sdk/util-locate-window@3.465.0: - resolution: {integrity: sha512-f+QNcWGswredzC1ExNAB/QzODlxwaTdXkNT5cvke2RLX8SFU5pYk6h4uCtWC0vWPELzOfMfloBrJefBzlarhsw==} - engines: {node: '>=14.0.0'} - dependencies: - tslib: 2.6.2 - dev: false - - /@aws-sdk/util-user-agent-browser@3.489.0: - resolution: {integrity: sha512-85B9KMsuMpAZauzWQ16r52ZBAHYnznW6BVitnBglsibN7oJKn10Hggt4QGuRhvQFCxQ8YhvBl7r+vQGFO4hxIw==} - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 - bowser: 2.11.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/util-user-agent-node@3.489.0: - resolution: {integrity: sha512-CYdkBHig8sFNc0dv11Ni9WXvZQHeI5+z77OrDHKkbidFx/V4BDTuwZw4K1vWg62pzFOEfzunJFiULRcDZWJR3w==} - engines: {node: '>=14.0.0'} - peerDependencies: - aws-crt: '>=1.0.0' - peerDependenciesMeta: - aws-crt: - optional: true - dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/node-config-provider': 2.1.9 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@aws-sdk/util-utf8-browser@3.259.0: - resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} - dependencies: - tslib: 2.6.2 - dev: false - - /@aws-sdk/xml-builder@3.485.0: - resolution: {integrity: sha512-xQexPM6LINOIkf3NLFywplcbApifZRMWFN41TDWYSNgCUa5uC9fntfenw8N/HTx1n+McRCWSAFBTjDqY/2OLCQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - /@drizzle-team/studio@0.0.37: resolution: {integrity: sha512-LZyAPGJBX43jsrVZh7+w1Jig/BC6PJx63ReHUYK+GRQYNY9UJNlPXmn1uC/LMRX+A7JwYM4Sr4Fg/hnJSqlfgA==} dependencies: @@ -1437,461 +784,6 @@ packages: dev: true optional: true - /@smithy/abort-controller@2.0.16: - resolution: {integrity: sha512-4foO7738k8kM9flMHu3VLabqu7nPgvIj8TB909S0CnKx0YZz/dcDH3pZ/4JHdatfxlZdKF1JWOYCw9+v3HVVsw==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/chunked-blob-reader-native@2.0.1: - resolution: {integrity: sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==} - dependencies: - '@smithy/util-base64': 2.0.1 - tslib: 2.6.2 - dev: false - - /@smithy/chunked-blob-reader@2.0.0: - resolution: {integrity: sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==} - dependencies: - tslib: 2.6.2 - dev: false - - /@smithy/config-resolver@2.0.23: - resolution: {integrity: sha512-XakUqgtP2YY8Mi+Nlif5BiqJgWdvfxJafSpOSQeCOMizu+PUhE4fBQSy6xFcR+eInrwVadaABNxoJyGUMn15ew==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/node-config-provider': 2.1.9 - '@smithy/types': 2.8.0 - '@smithy/util-config-provider': 2.1.0 - '@smithy/util-middleware': 2.0.9 - tslib: 2.6.2 - dev: false - - /@smithy/core@1.2.2: - resolution: {integrity: sha512-uLjrskLT+mWb0emTR5QaiAIxVEU7ndpptDaVDrTwwhD+RjvHhjIiGQ3YL5jKk1a5VSDQUA2RGkXvJ6XKRcz6Dg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/util-middleware': 2.0.9 - tslib: 2.6.2 - dev: false - - /@smithy/credential-provider-imds@2.1.5: - resolution: {integrity: sha512-VfvE6Wg1MUWwpTZFBnUD7zxvPhLY8jlHCzu6bCjlIYoWgXCDzZAML76IlZUEf45nib3rjehnFgg0s1rgsuN/bg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/node-config-provider': 2.1.9 - '@smithy/property-provider': 2.0.17 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - tslib: 2.6.2 - dev: false - - /@smithy/eventstream-codec@2.0.16: - resolution: {integrity: sha512-umYh5pdCE9GHgiMAH49zu9wXWZKNHHdKPm/lK22WYISTjqu29SepmpWNmPiBLy/yUu4HFEGJHIFrDWhbDlApaw==} - dependencies: - '@aws-crypto/crc32': 3.0.0 - '@smithy/types': 2.8.0 - '@smithy/util-hex-encoding': 2.0.0 - tslib: 2.6.2 - dev: false - - /@smithy/eventstream-serde-browser@2.0.16: - resolution: {integrity: sha512-W+BdiN728R57KuZOcG0GczpIOEFf8S5RP/OdVH7T3FMCy8HU2bBU0vB5xZZR5c00VRdoeWrohNv3XlHoZuGRoA==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/eventstream-serde-universal': 2.0.16 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/eventstream-serde-config-resolver@2.0.16: - resolution: {integrity: sha512-8qrE4nh+Tg6m1SMFK8vlzoK+8bUFTlIhXidmmQfASMninXW3Iu0T0bI4YcIk4nLznHZdybQ0qGydIanvVZxzVg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/eventstream-serde-node@2.0.16: - resolution: {integrity: sha512-NRNQuOa6mQdFSkqzY0IV37swHWx0SEoKxFtUfdZvfv0AVQPlSw4N7E3kcRSCpnHBr1kCuWWirdDlWcjWuD81MA==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/eventstream-serde-universal': 2.0.16 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/eventstream-serde-universal@2.0.16: - resolution: {integrity: sha512-ZyLnGaYQMLc75j9kKEVMJ3X6bdBE9qWxhZdTXM5RIltuytxJC3FaOhawBxjE+IL1enmWSIohHGZCm/pLwEliQA==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/eventstream-codec': 2.0.16 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/fetch-http-handler@2.3.2: - resolution: {integrity: sha512-O9R/OlnAOTsnysuSDjt0v2q6DcSvCz5cCFC/CFAWWcLyBwJDeFyGTCTszgpQTb19+Fi8uRwZE5/3ziAQBFeDMQ==} - dependencies: - '@smithy/protocol-http': 3.0.12 - '@smithy/querystring-builder': 2.0.16 - '@smithy/types': 2.8.0 - '@smithy/util-base64': 2.0.1 - tslib: 2.6.2 - dev: false - - /@smithy/hash-blob-browser@2.0.17: - resolution: {integrity: sha512-/mPpv1sRiRDdjO4zZuO8be6eeabmg5AVgKDfnmmqkpBtRyMGSJb968fjRuHt+FRAsIGywgIKJFmUUAYjhsi1oQ==} - dependencies: - '@smithy/chunked-blob-reader': 2.0.0 - '@smithy/chunked-blob-reader-native': 2.0.1 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/hash-node@2.0.18: - resolution: {integrity: sha512-gN2JFvAgnZCyDN9rJgcejfpK0uPPJrSortVVVVWsru9whS7eQey6+gj2eM5ln2i6rHNntIXzal1Fm9XOPuoaKA==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - '@smithy/util-buffer-from': 2.0.0 - '@smithy/util-utf8': 2.0.2 - tslib: 2.6.2 - dev: false - - /@smithy/hash-stream-node@2.0.18: - resolution: {integrity: sha512-OuFk+ITpv8CtxGjQcS8GA04faNycu9UMm6YobvQzjeEoXZ0dLF6sRfuzD+3S8RHPKpTyLuXtKG1+GiJycZ5TcA==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - '@smithy/util-utf8': 2.0.2 - tslib: 2.6.2 - dev: false - - /@smithy/invalid-dependency@2.0.16: - resolution: {integrity: sha512-apEHakT/kmpNo1VFHP4W/cjfeP9U0x5qvfsLJubgp7UM/gq4qYp0GbqdE7QhsjUaYvEnrftRqs7+YrtWreV0wA==} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/is-array-buffer@2.0.0: - resolution: {integrity: sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==} - engines: {node: '>=14.0.0'} - dependencies: - tslib: 2.6.2 - dev: false - - /@smithy/md5-js@2.0.18: - resolution: {integrity: sha512-bHwZ8/m6RbERQdVW5rJ2LzeW8qxfXv6Q/S7Fiudhso4pWRrksqLx3nsGZw7bmqqfN4zLqkxydxSa9+4c7s5zxg==} - dependencies: - '@smithy/types': 2.8.0 - '@smithy/util-utf8': 2.0.2 - tslib: 2.6.2 - dev: false - - /@smithy/middleware-content-length@2.0.18: - resolution: {integrity: sha512-ZJ9uKPTfxYheTKSKYB+GCvcj+izw9WGzRLhjn8n254q0jWLojUzn7Vw0l4R/Gq7Wdpf/qmk/ptD+6CCXHNVCaw==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/middleware-endpoint@2.3.0: - resolution: {integrity: sha512-VsOAG2YQ8ykjSmKO+CIXdJBIWFo6AAvG6Iw95BakBTqk66/4BI7XyqLevoNSq/lZ6NgZv24sLmrcIN+fLDWBCg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/middleware-serde': 2.0.16 - '@smithy/node-config-provider': 2.1.9 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-middleware': 2.0.9 - tslib: 2.6.2 - dev: false - - /@smithy/middleware-retry@2.0.26: - resolution: {integrity: sha512-Qzpxo0U5jfNiq9iD38U3e2bheXwvTEX4eue9xruIvEgh+UKq6dKuGqcB66oBDV7TD/mfoJi9Q/VmaiqwWbEp7A==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/node-config-provider': 2.1.9 - '@smithy/protocol-http': 3.0.12 - '@smithy/service-error-classification': 2.0.9 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/util-middleware': 2.0.9 - '@smithy/util-retry': 2.0.9 - tslib: 2.6.2 - uuid: 8.3.2 - dev: false - - /@smithy/middleware-serde@2.0.16: - resolution: {integrity: sha512-5EAd4t30pcc4M8TSSGq7q/x5IKrxfXR5+SrU4bgxNy7RPHQo2PSWBUco9C+D9Tfqp/JZvprRpK42dnupZafk2g==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/middleware-stack@2.0.10: - resolution: {integrity: sha512-I2rbxctNq9FAPPEcuA1ntZxkTKOPQFy7YBPOaD/MLg1zCvzv21CoNxR0py6J8ZVC35l4qE4nhxB0f7TF5/+Ldw==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/node-config-provider@2.1.9: - resolution: {integrity: sha512-tUyW/9xrRy+s7RXkmQhgYkAPMpTIF8izK4orhHjNFEKR3QZiOCbWB546Y8iB/Fpbm3O9+q0Af9rpywLKJOwtaQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/node-http-handler@2.2.2: - resolution: {integrity: sha512-XO58TO/Eul/IBQKFKaaBtXJi0ItEQQCT+NI4IiKHCY/4KtqaUT6y/wC1EvDqlA9cP7Dyjdj7FdPs4DyynH3u7g==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/abort-controller': 2.0.16 - '@smithy/protocol-http': 3.0.12 - '@smithy/querystring-builder': 2.0.16 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/property-provider@2.0.17: - resolution: {integrity: sha512-+VkeZbVu7qtQ2DjI48Qwaf9fPOr3gZIwxQpuLJgRRSkWsdSvmaTCxI3gzRFKePB63Ts9r4yjn4HkxSCSkdWmcQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/protocol-http@3.0.12: - resolution: {integrity: sha512-Xz4iaqLiaBfbQpB9Hgi3VcZYbP7xRDXYhd8XWChh4v94uw7qwmvlxdU5yxzfm6ACJM66phHrTbS5TVvj5uQ72w==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/querystring-builder@2.0.16: - resolution: {integrity: sha512-Q/GsJT0C0mijXMRs7YhZLLCP5FcuC4797lYjKQkME5CZohnLC4bEhylAd2QcD3gbMKNjCw8+T2I27WKiV/wToA==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - '@smithy/util-uri-escape': 2.0.0 - tslib: 2.6.2 - dev: false - - /@smithy/querystring-parser@2.0.16: - resolution: {integrity: sha512-c4ueAuL6BDYKWpkubjrQthZKoC3L5kql5O++ovekNxiexRXTlLIVlCR4q3KziOktLIw66EU9SQljPXd/oN6Okg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/service-error-classification@2.0.9: - resolution: {integrity: sha512-0K+8GvtwI7VkGmmInPydM2XZyBfIqLIbfR7mDQ+oPiz8mIinuHbV6sxOLdvX1Jv/myk7XTK9orgt3tuEpBu/zg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - dev: false - - /@smithy/shared-ini-file-loader@2.2.8: - resolution: {integrity: sha512-E62byatbwSWrtq9RJ7xN40tqrRKDGrEL4EluyNpaIDvfvet06a/QC58oHw2FgVaEgkj0tXZPjZaKrhPfpoU0qw==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/signature-v4@2.0.19: - resolution: {integrity: sha512-nwc3JihdM+kcJjtORv/n7qRHN2Kfh7S2RJI2qr8pz9UcY5TD8rSCRGQ0g81HgyS3jZ5X9U/L4p014P3FonBPhg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/eventstream-codec': 2.0.16 - '@smithy/is-array-buffer': 2.0.0 - '@smithy/types': 2.8.0 - '@smithy/util-hex-encoding': 2.0.0 - '@smithy/util-middleware': 2.0.9 - '@smithy/util-uri-escape': 2.0.0 - '@smithy/util-utf8': 2.0.2 - tslib: 2.6.2 - dev: false - - /@smithy/smithy-client@2.2.1: - resolution: {integrity: sha512-SpD7FLK92XV2fon2hMotaNDa2w5VAy5/uVjP9WFmjGSgWM8pTPVkHcDl1yFs5Z8LYbij0FSz+DbCBK6i+uXXUA==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-stack': 2.0.10 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - '@smithy/util-stream': 2.0.24 - tslib: 2.6.2 - dev: false - - /@smithy/types@2.8.0: - resolution: {integrity: sha512-h9sz24cFgt/W1Re22OlhQKmUZkNh244ApgRsUDYinqF8R+QgcsBIX344u2j61TPshsTz3CvL6HYU1DnQdsSrHA==} - engines: {node: '>=14.0.0'} - dependencies: - tslib: 2.6.2 - dev: false - - /@smithy/url-parser@2.0.16: - resolution: {integrity: sha512-Wfz5WqAoRT91TjRy1JeLR0fXtkIXHGsMbgzKFTx7E68SrZ55TB8xoG+vm11Ru4gheFTMXjAjwAxv1jQdC+pAQA==} - dependencies: - '@smithy/querystring-parser': 2.0.16 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-base64@2.0.1: - resolution: {integrity: sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/util-buffer-from': 2.0.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-body-length-browser@2.0.1: - resolution: {integrity: sha512-NXYp3ttgUlwkaug4bjBzJ5+yIbUbUx8VsSLuHZROQpoik+gRkIBeEG9MPVYfvPNpuXb/puqodeeUXcKFe7BLOQ==} - dependencies: - tslib: 2.6.2 - dev: false - - /@smithy/util-body-length-node@2.1.0: - resolution: {integrity: sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==} - engines: {node: '>=14.0.0'} - dependencies: - tslib: 2.6.2 - dev: false - - /@smithy/util-buffer-from@2.0.0: - resolution: {integrity: sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/is-array-buffer': 2.0.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-config-provider@2.1.0: - resolution: {integrity: sha512-S6V0JvvhQgFSGLcJeT1CBsaTR03MM8qTuxMH9WPCCddlSo2W0V5jIHimHtIQALMLEDPGQ0ROSRr/dU0O+mxiQg==} - engines: {node: '>=14.0.0'} - dependencies: - tslib: 2.6.2 - dev: false - - /@smithy/util-defaults-mode-browser@2.0.24: - resolution: {integrity: sha512-TsP5mBuLgO2C21+laNG2nHYZEyUdkbGURv2tHvSuQQxLz952MegX95uwdxOY2jR2H4GoKuVRfdJq7w4eIjGYeg==} - engines: {node: '>= 10.0.0'} - dependencies: - '@smithy/property-provider': 2.0.17 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - bowser: 2.11.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-defaults-mode-node@2.0.32: - resolution: {integrity: sha512-d0S33dXA2cq1NyorVMroMrEtqKMr3MlyLITcfTBf9pXiigYiPMOtbSI7czHIfDbuVuM89Cg0urAgpt73QV9mPQ==} - engines: {node: '>= 10.0.0'} - dependencies: - '@smithy/config-resolver': 2.0.23 - '@smithy/credential-provider-imds': 2.1.5 - '@smithy/node-config-provider': 2.1.9 - '@smithy/property-provider': 2.0.17 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-endpoints@1.0.8: - resolution: {integrity: sha512-l8zVuyZZ61IzZBYp5NWvsAhbaAjYkt0xg9R4xUASkg5SEeTT2meHOJwJHctKMFUXe4QZbn9fR2MaBYjP2119+w==} - engines: {node: '>= 14.0.0'} - dependencies: - '@smithy/node-config-provider': 2.1.9 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-hex-encoding@2.0.0: - resolution: {integrity: sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==} - engines: {node: '>=14.0.0'} - dependencies: - tslib: 2.6.2 - dev: false - - /@smithy/util-middleware@2.0.9: - resolution: {integrity: sha512-PnCnBJ07noMX1lMDTEefmxSlusWJUiLfrme++MfK5TD0xz8NYmakgoXy5zkF/16zKGmiwOeKAztWT/Vjk1KRIQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-retry@2.0.9: - resolution: {integrity: sha512-46BFWe9RqB6g7f4mxm3W3HlqknqQQmWHKlhoqSFZuGNuiDU5KqmpebMbvC3tjTlUkqn4xa2Z7s3Hwb0HNs5scw==} - engines: {node: '>= 14.0.0'} - dependencies: - '@smithy/service-error-classification': 2.0.9 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-stream@2.0.24: - resolution: {integrity: sha512-hRpbcRrOxDriMVmbya+Mv77VZVupxRAsfxVDKS54XuiURhdiwCUXJP0X1iJhHinuUf6n8pBF0MkG9C8VooMnWw==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/node-http-handler': 2.2.2 - '@smithy/types': 2.8.0 - '@smithy/util-base64': 2.0.1 - '@smithy/util-buffer-from': 2.0.0 - '@smithy/util-hex-encoding': 2.0.0 - '@smithy/util-utf8': 2.0.2 - tslib: 2.6.2 - dev: false - - /@smithy/util-uri-escape@2.0.0: - resolution: {integrity: sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==} - engines: {node: '>=14.0.0'} - dependencies: - tslib: 2.6.2 - dev: false - - /@smithy/util-utf8@2.0.2: - resolution: {integrity: sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/util-buffer-from': 2.0.0 - tslib: 2.6.2 - dev: false - - /@smithy/util-waiter@2.0.16: - resolution: {integrity: sha512-5i4YONHQ6HoUWDd+X0frpxTXxSXgJhUFl+z0iMy/zpUmVeCQY2or3Vss6DzHKKMMQL4pmVHpQm9WayHDorFdZg==} - engines: {node: '>=14.0.0'} - dependencies: - '@smithy/abort-controller': 2.0.16 - '@smithy/types': 2.8.0 - tslib: 2.6.2 - dev: false - /@sveltejs/adapter-node@2.1.1(@sveltejs/kit@2.3.2): resolution: {integrity: sha512-ypAqdvjoyfOEgucDbY3P6DM6nLEQ7OwiWMfyITKF8svffe9FIx1ow6uELJd1BzbCrouYndkQfc5m6ihj0xxqTg==} peerDependencies: @@ -2100,14 +992,6 @@ packages: readable-stream: 3.6.2 dev: false - /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: false - - /bowser@2.11.0: - resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} - dev: false - /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -2147,13 +1031,6 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true - /buffer@5.6.0: - resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: false - /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -2289,11 +1166,6 @@ packages: is-what: 4.1.16 dev: true - /croner@8.0.0: - resolution: {integrity: sha512-NhZ7wV9L0nxbSJKYp6u+OHCytFv4RlCu0O6GsglJIZMpMqmtb0kcNNPS5lv1O8qclhDA1NffLSsGx2ftbWQamw==} - engines: {node: '>=18.0'} - dev: false - /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -2303,16 +1175,6 @@ packages: which: 2.0.2 dev: true - /css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.1.0 - nth-check: 2.1.1 - dev: false - /css-tree@2.3.1: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -2321,21 +1183,12 @@ packages: source-map-js: 1.0.2 dev: true - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: false - /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true dev: true - /cssom@0.5.0: - resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} - dev: false - /d@1.0.1: resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} dependencies: @@ -2343,10 +1196,6 @@ packages: type: 1.2.0 dev: true - /date-fns@3.2.0: - resolution: {integrity: sha512-E4KWKavANzeuusPi0jUjpuI22SURAznGkx7eZV+4i6x2A+IZxAMcajgkvuDAU1bg40+xuhW1zRdVIIM/4khuIg==} - dev: false - /dayjs@1.11.10: resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} dev: false @@ -2413,33 +1262,6 @@ packages: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} dev: true - /dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - dev: false - - /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: false - - /domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - dev: false - - /domutils@3.1.0: - resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dev: false - /dreamopt@0.8.0: resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==} engines: {node: '>=0.4.0'} @@ -2566,11 +1388,6 @@ packages: once: 1.4.0 dev: false - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - dev: false - /env-paths@3.0.0: resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2712,15 +1529,6 @@ packages: es5-ext: 0.10.62 dev: true - /eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - dev: false - - /events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: false - /expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -2743,13 +1551,6 @@ packages: micromatch: 4.0.5 dev: true - /fast-xml-parser@4.2.5: - resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==} - hasBin: true - dependencies: - strnum: 1.0.5 - dev: false - /fastq@1.16.0: resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==} dependencies: @@ -2887,19 +1688,6 @@ packages: resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} dev: true - /html-escaper@3.0.3: - resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} - dev: false - - /htmlparser2@9.1.0: - resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.1.0 - entities: 4.5.0 - dev: false - /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} dev: false @@ -3043,16 +1831,6 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true - /linkedom@0.16.6: - resolution: {integrity: sha512-vJ8oadtJe3DM4FNW15Fj5NLIJlJk+AOypoRxzq9prLx+gAKvHYcTfV98pzOoRkwx4ZvvYzqT1bcDKluHH72apg==} - dependencies: - css-select: 5.1.0 - cssom: 0.5.0 - html-escaper: 3.0.3 - htmlparser2: 9.1.0 - uhyphen: 0.2.0 - dev: false - /locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} dev: true @@ -3199,12 +1977,6 @@ packages: hasBin: true dev: true - /nanoid@5.0.4: - resolution: {integrity: sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==} - engines: {node: ^18 || >=20} - hasBin: true - dev: false - /napi-build-utils@1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} dev: false @@ -3234,12 +2006,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - dependencies: - boolbase: 1.0.0 - dev: false - /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -3255,24 +2021,6 @@ packages: dependencies: wrappy: 1.0.2 - /p-map@7.0.1: - resolution: {integrity: sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==} - engines: {node: '>=18'} - dev: false - - /p-queue@8.0.1: - resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} - engines: {node: '>=18'} - dependencies: - eventemitter3: 5.0.1 - p-timeout: 6.1.2 - dev: false - - /p-timeout@6.1.2: - resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} - engines: {node: '>=14.16'} - dev: false - /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -3706,13 +2454,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /stream-browserify@3.0.0: - resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: false - /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -3763,10 +2504,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /strnum@1.0.5: - resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} - dev: false - /sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -3991,12 +2728,9 @@ packages: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} dev: true - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: false - /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true /tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} @@ -4018,10 +2752,6 @@ packages: hasBin: true dev: true - /uhyphen@0.2.0: - resolution: {integrity: sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==} - dev: false - /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -4039,11 +2769,6 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: false - /vite@5.0.11(@types/node@20.11.0): resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -4134,3 +2859,4 @@ packages: /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4379e8a..a2d163a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,3 @@ packages: - - link-scrapers - - scraper - sitio - db-datos diff --git a/scraper-rs/src/main.rs b/scraper-rs/src/main.rs index 0d7282b..30ce723 100644 --- a/scraper-rs/src/main.rs +++ b/scraper-rs/src/main.rs @@ -111,7 +111,7 @@ async fn fetch_list(pool: &Pool, links: Vec) -> Counters { } fn connect_db() -> Pool { - let db_path = env::var("DB_PATH").unwrap_or("../scraper/sqlite.db".to_string()); + let db_path = env::var("DB_PATH").unwrap_or("../sqlite.db".to_string()); let cfg = deadpool_sqlite::Config::new(db_path); let pool = cfg.create_pool(deadpool_sqlite::Runtime::Tokio1).unwrap(); pool diff --git a/scraper/auto.ts b/scraper/auto.ts deleted file mode 100644 index 764fa34..0000000 --- a/scraper/auto.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { mkdtemp, writeFile } from "node:fs/promises"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; -import { Supermercado, hosts, supermercados } from "db-datos/supermercado.js"; -import PQueue from "p-queue"; -import { formatDuration, intervalToDuration } from "date-fns"; -import { db } from "db-datos/db.js"; -import { like } from "drizzle-orm"; -import { productoUrls } from "db-datos/schema.js"; -import { scrapDiaProducts } from "../link-scrapers/dia.js"; -import { scrapCotoProducts } from "../link-scrapers/coto.js"; -import { scrapCarrefourProducts } from "../link-scrapers/carrefour.js"; -import { scrapJumboProducts } from "../link-scrapers/jumbo.js"; -import { readableStreamToText } from "bun"; - -// hacemos una cola para el scrapeo para no tener varios writers a la BD y no sobrecargar la CPU -const scrapQueue = new PQueue({ concurrency: 1 }); - -export async function auto() { - const a = new Auto(); - await Promise.all(supermercados.map((supr) => a.downloadList(supr))); -} - -class Auto { - telegramConfig?: { token: string; chatId: string }; - - constructor() { - if (!process.env.TELEGRAM_BOT_TOKEN) - console.warn("no hay TELEGRAM_BOT_TOKEN, no voy a loggear por allá"); - else if (!process.env.TELEGRAM_BOT_CHAT_ID) - console.warn("no hay TELEGRAM_BOT_CHAT_ID, no voy a loggear por allá"); - else - this.telegramConfig = { - token: process.env.TELEGRAM_BOT_TOKEN, - chatId: process.env.TELEGRAM_BOT_CHAT_ID, - }; - - this.inform("[auto] Empezando scrap"); - } - - async scrapUrls(supermercado: Supermercado) { - const t0 = performance.now(); - switch (supermercado) { - case "Dia": - await scrapDiaProducts(); - break; - case "Coto": - await scrapCotoProducts(); - break; - case "Carrefour": - await scrapCarrefourProducts(); - break; - case "Jumbo": - await scrapJumboProducts(); - break; - } - this.inform( - `[scrapUrls[${supermercado}]] Tardó ${formatMs(performance.now() - t0)}` - ); - } - - async downloadList(supermercado: Supermercado) { - const ctxPath = await mkdtemp(join(tmpdir(), "preciazo-scraper-download-")); - - await scrapQueue.add(async () => { - await this.scrapUrls(supermercado); - }); - - const listPath = join(ctxPath, `lista-${supermercado}.txt`); - const host = Object.entries(hosts).find( - ([host, supe]) => supe === supermercado - )![0]; - const results = await db.query.productoUrls - .findMany({ - where: like(productoUrls.url, `%${host}%`), - }) - .execute(); - const urls = results.map((r) => r.url); - await writeFile(listPath, urls.join("\n") + "\n"); - - this.scrapAndInform({ listPath }); - // TODO: borrar archivos temporales - } - - async scrapAndInform({ listPath }: { listPath: string }) { - const res = await scrapQueue.add(async () => { - const t0 = performance.now(); - - const sub = Bun.spawn({ - cmd: ["scraper-rs", "fetch-list", listPath], - stdio: ["ignore", "pipe", "inherit"], - }); - const text = await readableStreamToText(sub.stdout); - const code = await sub.exited; - if (code !== 0) throw new Error(`scraper-rs threw ${code}`); - - return { took: performance.now() - t0, text }; - }); - - if (res) { - const { took, text } = res; - this.inform( - `Procesado ${listPath} (${text}) (tardó ${formatMs(took)})` - //(${progress.done} ok, ${ - // progress.skipped - // } skipped, ${progress.errors.length} errores) - ); - } else { - this.inform(`Algo falló en ${listPath}`); - } - } - - inform(msg: string) { - this.sendTelegramMsg(msg); - console.info(msg); - } - report(msg: string) { - this.inform(msg); - const error = new Error(msg); - - return error; - } - - async sendTelegramMsg(text: string) { - if (!this.telegramConfig) return; - const url = new URL( - `https://api.telegram.org/bot${this.telegramConfig.token}/sendMessage` - ); - url.searchParams.set("chat_id", this.telegramConfig.chatId); - url.searchParams.set("text", text); - await fetch(url); - } -} - -function formatMs(ms: number) { - return formatDuration(intervalToDuration({ start: 0, end: Math.round(ms) })); -} diff --git a/scraper/cli.ts b/scraper/cli.ts deleted file mode 100644 index d4bcdc8..0000000 --- a/scraper/cli.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { scrapCarrefourProducts } from "../link-scrapers/carrefour.js"; -import { scrapCotoProducts } from "../link-scrapers/coto.js"; -import { scrapDiaProducts } from "../link-scrapers/dia.js"; -import { scrapJumboProducts } from "../link-scrapers/jumbo.js"; -import { auto } from "./auto.js"; -import { downloadList, getProduct } from "./scrap.js"; -import Cron from "croner"; - -if (process.argv[2] === "auto") { - await auto(); -} else if (process.argv[2] === "cron") { - Cron("0 2 * * *", () => { - auto(); - }); -} else if (process.argv[2] === "scrap-carrefour-links") { - await scrapCarrefourProducts(); -} else if (process.argv[2] === "scrap-dia-links") { - await scrapDiaProducts(); -} else if (process.argv[2] === "scrap-coto-links") { - await scrapCotoProducts(); -} else if (process.argv[2] === "scrap-jumbo-links") { - await scrapJumboProducts(); -} else if (process.argv[2] === "scrap-link") { - const url = new URL(process.argv[3]); - const res = await fetch(url); - const text = await res.text(); - console.info(await getProduct(url, text)); -} else if (process.argv[2] === "scrap") { - const urlLists = process.argv.slice(3); - if (urlLists.length > 0) { - for (const path of urlLists) { - const res = await downloadList(path); - console.info("======================================="); - console.info(path, res); - console.info("======================================="); - } - } else { - console.error("Especificá listas de urls para scrapear."); - process.exit(1); - } -} else { - console.error("Especificá una acción (tipo `auto` o `scrap`) para hacer."); - process.exit(1); -} diff --git a/scraper/package.json b/scraper/package.json deleted file mode 100644 index ce89d1d..0000000 --- a/scraper/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "scraper", - "type": "module", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "check": "tsc" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@aws-sdk/client-s3": "^3.478.0", - "@aws-sdk/lib-storage": "^3.478.0", - "croner": "^8.0.0", - "date-fns": "^3.0.6", - "db-datos": "workspace:^", - "drizzle-orm": "^0.29.1", - "linkedom": "^0.16.5", - "nanoid": "^5.0.4", - "p-map": "^7.0.1", - "p-queue": "^8.0.1", - "zod": "^3.22.4" - }, - "devDependencies": { - "typescript": "^5.3.3" - } -} diff --git a/scraper/parsers/carrefour.ts b/scraper/parsers/carrefour.ts deleted file mode 100644 index b025f62..0000000 --- a/scraper/parsers/carrefour.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { parseHTML } from "linkedom"; -import { Precioish } from "../scrap.js"; -import { getProductJsonLd, priceFromMeta, stockFromMeta } from "./common.js"; - -function parseScriptJson(dom: Window, varname: string): T { - const script = dom.window.document.querySelector( - `template[data-type="json"][data-varname="${varname}"]` - )?.content?.children[0]; - if (!script) throw new Error("no encuentro el script"); - return JSON.parse(script.innerHTML); -} -function eanFromSeedState(dom: Window): string { - const json = parseScriptJson(dom, "__STATE__"); - const productJson = Object.entries(json).find( - ([key, val]) => key.startsWith("Product:") && val.__typename === "Product" - ); - if (!productJson) throw new Error("no encontré el product en el json"); - - const productSkuJson = Object.entries(json).find( - ([key, val]) => - key.startsWith(`Product:${productJson[1].cacheId}`) && - val.__typename === "SKU" - ); - if (!productSkuJson) throw new Error("no encontré el sku en el json"); - return productSkuJson[1].ean; -} - -export function getCarrefourProduct(html: string | Buffer): Precioish { - const dom = parseHTML(html); - - const precioCentavos = priceFromMeta(dom); - const inStock = stockFromMeta(dom); - - const ean = eanFromSeedState(dom); - - let name, imageUrl; - try { - const ld = getProductJsonLd(dom); - name = ld.name; - imageUrl = ld.image; - } catch (error) { - if (inStock) { - throw error; - } else { - // algunas paginas sin stock no tienen json ld - } - } - - return { - name, - imageUrl, - ean, - precioCentavos, - inStock, - }; -} diff --git a/scraper/parsers/common.ts b/scraper/parsers/common.ts deleted file mode 100644 index 34804aa..0000000 --- a/scraper/parsers/common.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { z } from "zod"; - -export function getMetaProp(dom: Window, prop: string) { - return dom.window.document - .querySelector(`meta[property="${prop}"]`) - ?.getAttribute("content"); -} - -export function priceFromMeta(dom: Window) { - const precioMeta = getMetaProp(dom, "product:price:amount"); - if (!precioMeta) return null; - const precioCentavos = parseFloat(precioMeta) * 100; - return precioCentavos; -} -export function stockFromMeta(dom: Window) { - const stockMeta = getMetaProp(dom, "product:availability"); - return stockMeta === "instock"; -} - -function parseJsonLds(dom: Window): object[] { - const scripts = dom.window.document.querySelectorAll( - 'script[type="application/ld+json"]' - ); - return Array.from(scripts, (script) => JSON.parse(script.innerHTML)); -} -function findJsonLd(dom: Window, type: string): object | undefined { - return parseJsonLds(dom).find((x) => "@type" in x && x["@type"] === type); -} - -const zProductLd = z.object({ - "@type": z.literal("Product"), - name: z.string(), - image: z.string(), - sku: z.string().optional(), - offers: z.object({ - offers: z.array( - z.object({ - "@type": z.literal("Offer"), - price: z.number(), - priceCurrency: z.literal("ARS"), - availability: z.enum([ - "http://schema.org/OutOfStock", - "http://schema.org/InStock", - ]), - }) - ), - }), -}); -type ProductLd = z.infer; - -export function getProductJsonLd(dom: Window): ProductLd { - const ld = findJsonLd(dom, "Product"); - const productLd = zProductLd.parse(ld); - return productLd; -} diff --git a/scraper/parsers/coto.ts b/scraper/parsers/coto.ts deleted file mode 100644 index 0e92642..0000000 --- a/scraper/parsers/coto.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { parseHTML } from "linkedom"; -import { type Precioish } from "../scrap.js"; - -function getEanFromText({ document }: Window) { - const potentialEanEls = Array.from( - document.querySelectorAll("div#brandText") - ); - const eanParent = potentialEanEls.find( - (el) => el.textContent?.includes("| EAN: ") - ); - if (!eanParent) throw new Error("no encuentro el eanparent"); - - const eanEl = Array.from( - eanParent?.querySelectorAll("span.span_codigoplu") - )[1]; - const ean = eanEl?.textContent?.trim(); - if (!ean) throw new Error("no encuentro el ean"); - return ean; -} -function getPriceFromText({ document }: Window) { - const el = document.querySelector(".atg_store_newPrice"); - if (!el?.textContent) return null; - const nStr = el.textContent - .trim() - .replace("$", "") - .replaceAll(".", "") - .replace(",", "."); - return parseFloat(nStr) * 100; -} -function getInStock({ document }: Window) { - return !document.querySelector(".product_not_available"); -} - -export function getCotoProduct(html: string | Buffer): Precioish { - const dom = parseHTML(html); - - const ean = getEanFromText(dom); - const precioCentavos = getPriceFromText(dom); - const inStock = getInStock(dom); - - const name = dom.document - .querySelector("h1.product_page") - ?.textContent?.trim(); - const imageUrl = - dom.document.querySelector(".zoom img")?.src; - - return { name, imageUrl, ean, precioCentavos, inStock }; -} diff --git a/scraper/parsers/dia.ts b/scraper/parsers/dia.ts deleted file mode 100644 index 5fdd1ca..0000000 --- a/scraper/parsers/dia.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { parseHTML } from "linkedom"; -import { type Precioish } from "../scrap.js"; -import { getMetaProp, getProductJsonLd, priceFromMeta } from "./common.js"; - -export function getDiaProduct(html: string | Buffer): Precioish { - const dom = parseHTML(html); - - const ean = getMetaProp(dom, "product:retailer_item_id"); - if (!ean) throw new Error("No encontré el ean"); - const precioCentavos = priceFromMeta(dom); - - const ld = getProductJsonLd(dom); - const name = ld.name; - const imageUrl = ld.image; - const inStock = - ld.offers.offers[0].availability === "http://schema.org/InStock"; - - return { - name, - imageUrl, - ean, - precioCentavos, - inStock, - }; -} diff --git a/scraper/parsers/jumbo.ts b/scraper/parsers/jumbo.ts deleted file mode 100644 index b26b09f..0000000 --- a/scraper/parsers/jumbo.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { parseHTML } from "linkedom"; -import { type Precioish } from "../scrap.js"; -import { getProductJsonLd, priceFromMeta, stockFromMeta } from "./common.js"; -import { z } from "zod"; - -const zJumboSearch = z.tuple([ - z.object({ - items: z.array( - z.object({ - ean: z.string(), - }) - ), - }), -]); - -async function getEanFromSearch(sku: string) { - const url = new URL( - "https://www.jumbo.com.ar/api/catalog_system/pub/products/search" - ); - url.searchParams.set("fq", `skuId:${sku}`); - const res = await fetch(url); - const json = await res.json(); - const parsed = zJumboSearch.parse(json); - const ean = parsed[0].items[0].ean; - if (!parsed[0].items.every((x) => x.ean === ean)) { - throw new Error("Inesperado: no todos los items tienen el mismo EAN"); - } - return ean; -} - -export async function getJumboProduct( - html: string | Buffer -): Promise { - const dom = parseHTML(html); - const precioCentavos = priceFromMeta(dom); - const inStock = stockFromMeta(dom); - - const ld = getProductJsonLd(dom); - const name = ld.name; - const imageUrl = ld.image; - - const retailerSku = ld.sku; - if (!retailerSku) - throw new Error("No encontré el SKU de Jumbo para pedir el EAN"); - const ean = await getEanFromSearch(retailerSku); - - return { - name, - imageUrl, - ean, - precioCentavos, - inStock, - }; -} diff --git a/scraper/scrap.ts b/scraper/scrap.ts deleted file mode 100644 index d8acc55..0000000 --- a/scraper/scrap.ts +++ /dev/null @@ -1,127 +0,0 @@ -/// -import * as schema from "db-datos/schema.js"; -import { writeFile, mkdir } from "fs/promises"; -import { createHash } from "crypto"; -import { getCarrefourProduct } from "./parsers/carrefour.js"; -import { getDiaProduct } from "./parsers/dia.js"; -import { getCotoProduct } from "./parsers/coto.js"; -import { join } from "path"; -import { db } from "db-datos/db.js"; -import pMap from "p-map"; -import { getJumboProduct } from "./parsers/jumbo.js"; - -const DEBUG = true; -const PARSER_VERSION = 4; - -export type Precio = typeof schema.precios.$inferInsert; -export type Precioish = Omit< - Precio, - "fetchedAt" | "url" | "id" | "warcRecordId" | "parserVersion" ->; - -export async function downloadList(path: string) { - let list = (await Bun.file(path).text()) - .split("\n") - .filter((s) => s.length > 0); - - const results = await pMap( - list, - async (urlS) => { - let res: ScrapResult = { type: "skipped" }; - for (let attempts = 0; attempts < 6; attempts++) { - if (attempts !== 0) await wait(1500); - res = await scrap(urlS); - if (res.type === "done" || res.type === "skipped") { - break; - } - } - if (res.type === "error") console.error(res); - return res; - }, - { concurrency: 32 } - ); - - let progress: { - done: number; - skipped: number; - errors: { error: any; url: string; debugPath: string }[]; - } = { done: 0, skipped: 0, errors: [] }; - for (const result of results) { - switch (result.type) { - case "done": - progress.done++; - break; - case "error": - progress.errors.push(result); - break; - case "skipped": - progress.skipped++; - break; - } - } - return progress; -} - -export async function getProduct(url: URL, html: string): Promise { - if (url.hostname === "www.carrefour.com.ar") return getCarrefourProduct(html); - else if (url.hostname === "diaonline.supermercadosdia.com.ar") - return getDiaProduct(html); - else if (url.hostname === "www.cotodigital3.com.ar") - return getCotoProduct(html); - else if (url.hostname === "www.jumbo.com.ar") - return await getJumboProduct(html); - else throw new Error(`Unknown host ${url.hostname}`); -} - -type ScrapResult = - | { type: "skipped" } - | { type: "done" } - | { type: "error"; url: string; error: any; debugPath: string }; -async function scrap(urlS: string): Promise { - let url; - try { - url = new URL(urlS); - } catch (err) { - console.error(`skipped ${urlS} because ${err}`); - return { type: "skipped" }; - } - const res = await fetch(url); - if (!res.ok) { - console.debug(`skipped ${urlS} because status=${res.status} (!=200)`); - return { type: "skipped" }; - } - - const html = await res.text(); - - try { - let ish = await getProduct(url, html); - - const p: Precio = { - ...ish, - fetchedAt: new Date(), - url: urlS, - parserVersion: PARSER_VERSION, - }; - - await db.insert(schema.precios).values(p); - - return { type: "done" }; - } catch (error) { - const urlHash = createHash("md5").update(urlS).digest("hex"); - const output = join("debug", `${urlHash}.html`); - if (DEBUG) { - await mkdir("debug", { recursive: true }); - await writeFile(output, html); - } - return { - type: "error", - url: urlS, - error, - debugPath: output, - }; - } -} - -function wait(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} diff --git a/scraper/tsconfig.json b/scraper/tsconfig.json deleted file mode 100644 index 18a0a92..0000000 --- a/scraper/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../tsconfig.json", - "exclude": ["../sitio"] -}