A discord bot for teal.fm
discord tealfm music

Compare changes

Choose any two refs to compare.

-17
.env.example
··· 1 - DISCORD_BOT_TOKEN= 2 - DISCORD_APPLICATION_ID= 3 - DISCORD_GUILD_ID= 4 - TAP_ADMIN_PASSWORD= 5 - 6 - # database credentials 7 - POSTGRES_USER=postgres 8 - POSTGRES_PASSWORD=password 9 - POSTGRES_DB=tealfmbotdb 10 - 11 - # needed for kysely codegen 12 - DATABASE_URL=postgres://postgres:password@localhost:5432/tealfmbotdb 13 - 14 - # oauth 15 - PUBLIC_URL= 16 - PRIVATE_KEYS= 17 - COOKIE_SECRET=
-25
.tangled/workflows/docker-atcr.yml
··· 1 - when: 2 - - event: ["push"] 3 - branch: main 4 - # tag: ["v*"] 5 - 6 - engine: nixery 7 - 8 - dependencies: 9 - nixpkgs: 10 - - docker 11 - 12 - steps: 13 - - name: build 14 - command: | 15 - VCS_REF=$(git rev-parse HEAD) 16 - BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) 17 - DEBUG1=$(git remote -v || true) 18 - DEBUG2=$(git fetch --prune --unshallow 2>/dev/null || true) 19 - DEBUG3=$(git fetch --prune --tags --force origin 'refs/tags/*:refs/tags/*') 20 - 21 - echo $DEBUG1 22 - echo $DEBUG2 23 - echo $DEBUG3 24 - 25 - exit 1
+68
CONTRIBUTING.md
··· 1 + # Contributing to Disco Stu 2 + 3 + Thanks for your interest in contributing! This document gives a short quickstart and guidelines to help you get changes ready for review. 4 + 5 + ## Quickstart 6 + 7 + 1. Fork the repository and create a feature branch from `main`: 8 + 9 + ```bash 10 + git checkout -b feat/describe-thing 11 + ``` 12 + 13 + 2. Install dependencies: 14 + 15 + ```bash 16 + pnpm install 17 + ``` 18 + 19 + 3. Run the app you are working on (examples): 20 + 21 + ```bash 22 + # Bot 23 + pnpm bot 24 + 25 + # Tapper 26 + pnpm tap 27 + 28 + # Web 29 + pnpm web 30 + 31 + # Build everything 32 + pnpm build 33 + ``` 34 + 35 + 4. Run typechecks and format/lint before pushing: 36 + 37 + ```bash 38 + pnpm typecheck 39 + pnpm lint 40 + pnpm format 41 + ``` 42 + 43 + ## Development workflow 44 + 45 + - Work on a small, focused branch per change. 46 + - Keep commits atomic and with clear messages (imperative tense): `add ping command`, `fix db migration`. 47 + - Rebase or squash as appropriate to keep history clean for PRs. 48 + 49 + ## Tests, linting, and formatting 50 + 51 + - This repo uses `oxfmt` and `oxlint` at the workspace root. Run them locally before opening a PR. 52 + - Run TypeScript checks with `pnpm typecheck`. 53 + 54 + ## Submitting a PR 55 + 56 + - Open a pull request against `main` with a clear description of the change and why itโ€™s needed. 57 + - Include any relevant reproduction steps, screenshots, or logs. 58 + - If your change affects runtime behavior, add or update documentation in `README.md`. 59 + - Link any related issue numbers in the PR description. 60 + 61 + ## Commit message guidance 62 + 63 + - Use short, descriptive commit messages. 64 + - Prefer present-tense verbs: `add`, `fix`, `update`. 65 + 66 + ## Reporting bugs 67 + 68 + - Open an issue with steps to reproduce, expected vs actual behavior, and relevant logs or error messages.
+39 -16
Dockerfile
··· 2 2 ENV PNPM_HOME="/pnpm" 3 3 ENV PATH="$PNPM_HOME:$PATH" 4 4 RUN corepack enable 5 + 6 + USER root 7 + RUN mkdir -p /prod/web /prod/bot /prod/tapper && chown -R 1000:1000 /prod 5 8 USER 1000 6 9 7 10 ARG BUILD_DATE 8 11 ARG SHA 12 + ARG VERSION 13 + ARG DID 9 14 10 15 FROM base AS build 11 - COPY --chown=1000:1000 /apps/bot /app 12 - COPY --chown=1000:1000 /apps/tapper /app 13 - COPY --chown=1000:1000 /apps/web /app 16 + COPY --chown=1000:1000 apps/bot /app 17 + COPY --chown=1000:1000 apps/tapper /app 18 + COPY --chown=1000:1000 apps/web /app 14 19 15 - COPY --chown=1000:1000 /packages/common /app 16 - COPY --chown=1000:1000 /packages/database /app 17 - COPY --chown=1000:1000 /packages/tsconfig /app 20 + COPY --chown=1000:1000 packages/common /app 21 + COPY --chown=1000:1000 packages/database /app 22 + COPY --chown=1000:1000 packages/tsconfig /app 18 23 19 24 COPY --chown=1000:1000 package.json pnpm-lock.yaml pnpm-workspace.yaml /app/ 20 25 WORKDIR /app 21 26 22 - RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile \ 23 - pnpm run -r build \ 24 - pnpm deploy --filter=./apps/web --prod /prod/web \ 25 - pnpm deploy --filter=./apps/bot --prod /prod/bot \ 26 - pnpm deploy --filter=./apps/tapper --prod /prod/tapper 27 + RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile 28 + RUN pnpm run -r build 29 + RUN pnpm deploy --filter=./apps/web --prod /prod/web 30 + RUN pnpm deploy --filter=./apps/bot --prod /prod/bot 31 + RUN pnpm deploy --filter=./apps/tapper --prod /prod/tapper 27 32 28 33 29 34 FROM base AS web ··· 31 36 WORKDIR /prod/web 32 37 EXPOSE 8002 33 38 CMD ["node", "dist/index.js"] 39 + LABEL org.opencontainers.image.authors="Dane Miller 'me@dane.computer'" \ 40 + org.opencontainers.image.source="https://tangled.org/${DID}/tealfmbot" \ 41 + org.opencontainers.image.title="discostuweb" \ 42 + org.opencontainers.image.description="The web service for authentication for the disco stu discord bot" \ 43 + org.opencontainers.image.version=$VERSION \ 44 + org.opencontainers.image.created=$BUILD_DATE \ 45 + org.opencontainers.image.revision=$SHA \ 46 + org.opencontainers.image.licenses="MIT" 47 + 34 48 35 49 FROM base AS bot 36 50 COPY --from=build --chown=1000:1000 /prod/bot /prod/bot 37 51 WORKDIR /prod/bot 38 52 CMD ["node", "dist/main.js"] 53 + LABEL org.opencontainers.image.authors="Dane Miller 'me@dane.computer'" \ 54 + org.opencontainers.image.source="https://tangled.org/${DID}/tealfmbot" \ 55 + org.opencontainers.image.title="discostubot" \ 56 + org.opencontainers.image.description="A discord bot that displays your music listens based on your teal.fm records" \ 57 + org.opencontainers.image.version=$VERSION \ 58 + org.opencontainers.image.created=$BUILD_DATE \ 59 + org.opencontainers.image.revision=$SHA \ 60 + org.opencontainers.image.licenses="MIT" 61 + 39 62 40 63 FROM base AS tapper 41 64 COPY --from=build --chown=1000:1000 /prod/tapper /prod/tapper 42 65 WORKDIR /prod/tapper 43 66 CMD ["node", "dist/index.js"] 44 - 45 - LABEL org.opencontainers.image.authors="Dane Miller <me@dane.computer>" \ 46 - org.opencontainers.image.source="https://tangled.org/dane.is.extraordinarily.cool/tealfmbot" \ 47 - org.opencontainers.image.title="discostu" \ 48 - org.opencontainers.image.description="A discord bot that displays your music listens based on your teal.fm records" \ 67 + LABEL org.opencontainers.image.authors="Dane Miller 'me@dane.computer'" \ 68 + org.opencontainers.image.source="https://tangled.org/${DID}/tealfmbot" \ 69 + org.opencontainers.image.title="discostutap" \ 70 + org.opencontainers.image.description="The backfill and firehose listener for teal.fm records" \ 71 + org.opencontainers.image.version=$VERSION \ 49 72 org.opencontainers.image.created=$BUILD_DATE \ 50 73 org.opencontainers.image.revision=$SHA \ 51 74 org.opencontainers.image.licenses="MIT"
+167 -2
README.md
··· 1 - # Teal.fm Discord Bot 1 + # Disco Stu - Teal.fm Discord Bot 2 + 3 + This repository contains the Disco Stu Discord bot, supporting services, and shared packages used by the project. The workspace is a monorepo managed with pnpm and TypeScript; each app and package has its own package.json and build/dev scripts. 4 + 5 + **Repository Structure** 6 + 7 + - `apps/` : Application code (runtime programs and services) 8 + - `bot/` : Discord bot (commands, deploy script) 9 + - `tapper/` : Backfill client for Tap service 10 + - `web/` : Web server to handle OAuth 11 + - `packages/` : Shared libraries used across apps 12 + - `common/` : Logging and shared utilities 13 + - `database/` : Database access, Kysely migrations and seed scripts 14 + - `tsconfig/` : Shared TypeScript config packages 15 + 16 + **Apps** 17 + 18 + - `apps/bot` โ€” Discord bot 19 + - Entry: `apps/bot/main.ts`. 20 + - Key files: `apps/bot/commands/*.ts` (command handlers), `apps/bot/deploy-commands.ts` (registers commands with Discord), `apps/bot/discord.d.ts` (types). 21 + - Useful scripts (see [apps/bot/package.json](apps/bot/package.json)): 22 + - `dev` โ€” run bot in watch mode with `tsx --watch main.ts` 23 + - `deploy-commands` โ€” run `deploy-commands.ts` to push slash-command definitions to Discord 24 + - `build` โ€” compile TypeScript to `dist/` 25 + - `start` โ€” run compiled bot from `dist/main.js` 26 + 27 + - `apps/tapper` โ€” Tap client 28 + - Entry: `apps/tapper/index.ts`. 29 + - Purpose: Interact with tap service running at https://tap.xero.systems 30 + - Useful scripts (see [apps/tapper/package.json](apps/tapper/package.json)): 31 + - `dev` โ€” runs `NODE_ENV=development tsx index.ts` 32 + - `start` โ€” run compiled `dist/index.js` in production 33 + 34 + - `apps/web` โ€” Web server 35 + - Entry: `apps/web/index.ts`. 36 + - Integrates with AT Protocol APIs and provides OAuth/web endpoints. 37 + - Useful scripts (see [apps/web/package.json](apps/web/package.json)): 38 + - `dev` โ€” `tsx --watch index.ts` to run in dev 39 + - `build` โ€” compile TypeScript 40 + - `start` โ€” run compiled server from `dist/index.js` 41 + 42 + **Packages** 43 + 44 + - `packages/common` โ€” shared utilities and logging 45 + - Exports logging helpers and other common utilities used by apps. Build with `pnpm --filter @tealfmbot/common build` or use workspace protocol. 46 + - Scripts: `build`, `build:watch`, `typecheck` (see [packages/common/package.json](packages/common/package.json)). 47 + 48 + - `packages/database` โ€” Kysely-based database layer 49 + - Contains DB helpers, `migrate.ts`, `seed.ts`, and Kysely codegen support. 50 + - Scripts (see [packages/database/package.json](packages/database/package.json)): 51 + - `migrate` โ€” run `kysely migrate latest` to apply migrations 52 + - `codegen` โ€” run `kysely-codegen` to regenerate `database.d.ts` 53 + - `seed` โ€” run `tsx seed.ts` to seed data 54 + - `build`, `build:watch`, `typecheck` 55 + 56 + - `packages/tsconfig` โ€” shared TypeScript configs 57 + - Provides base tsconfig settings shared by other packages. 58 + 59 + **Top-level scripts** (see [package.json](package.json)) 60 + 61 + - `pnpm bot` โ€” start the bot dev script (`pnpm --filter bot dev`) 62 + - `pnpm tap` โ€” start the tapper dev script (`pnpm --filter tapper dev`) 63 + - `pnpm web` โ€” start the web app dev script (`pnpm --filter web dev`) 64 + - `pnpm build` โ€” run `pnpm -r build` to build all packages and apps 65 + - `pnpm build:watch` โ€” run watch builds across the monorepo 66 + - `pnpm dev:all` โ€” runs `dev` for all apps under `apps/` 67 + - `pnpm typecheck` โ€” run TypeScript checks across apps 68 + - `pnpm lint` โ€” run `oxlint` (project linter) 69 + - `pnpm format` โ€” run `oxfmt` to format code 70 + 71 + Developer workflow 72 + 73 + - Install dependencies: `pnpm install` (pnpm v10+ recommended) 74 + - Develop a single app: 75 + - Bot: `pnpm --filter bot dev` or `pnpm bot` 76 + - Tapper: `pnpm --filter tapper dev` or `pnpm tap` 77 + - Web: `pnpm --filter web dev` or `pnpm web` 78 + - Develop all apps concurrently: `pnpm dev:all` 79 + - Build all packages and apps: `pnpm build` 80 + 81 + Database tasks 82 + 83 + - Migrations are managed via Kysely. Run migrations from the `packages/database` package: 84 + 85 + ```bash 86 + pnpm --filter @tealfmbot/database migrate 87 + ``` 88 + 89 + - Regenerate types (codegen): 90 + 91 + ```bash 92 + pnpm --filter @tealfmbot/database codegen 93 + ``` 94 + 95 + Docker / deployment 96 + 97 + - `Dockerfile` and `docker-compose.prod.yml` are included for building and deploying container images. 98 + - The repository contains `build-and-publish-images.sh` to build and publish images (will be a CI thing eventually). 2 99 3 - who knows if i'll finish this 100 + Project tooling 101 + 102 + - `lefthook.yml` configures git hooks. 103 + - `oxlint` and `oxfmt` are used for linting and formatting. 104 + 105 + Notes & tips 106 + 107 + - To deploy Discord commands after changes, run the bot package `deploy-commands` script: 108 + 109 + ```bash 110 + pnpm --filter bot deploy-commands 111 + ``` 112 + 113 + **Contributing & Quickstart** 114 + 115 + If you want to contribute or get a local development environment running quickly, follow these steps: 116 + 117 + - Clone the repo and install dependencies: 118 + 119 + ```bash 120 + git clone https://tangled.org/dane.is.extraordinarily.cool/tealfmbot 121 + cd tealfmbot 122 + pnpm install 123 + ``` 124 + 125 + - Start and run database migrations 126 + 127 + ```bash 128 + docker compose -f docker-compose.dev.yml up -d 129 + 130 + cd packages/database 131 + 132 + pnpm migrate 133 + ``` 134 + 135 + - Start individual apps in development: 136 + 137 + ```bash 138 + # Bot 139 + pnpm bot 140 + 141 + # Tapper 142 + pnpm tap 143 + 144 + # Web 145 + pnpm web 146 + ``` 147 + 148 + - Start all apps concurrently (monorepo dev): 149 + 150 + ```bash 151 + pnpm dev:all 152 + ``` 153 + 154 + - Build everything: 155 + 156 + ```bash 157 + pnpm build 158 + ``` 159 + 160 + - Run TypeScript checks and format/lint before opening a PR: 161 + 162 + ```bash 163 + pnpm typecheck 164 + pnpm lint 165 + pnpm format 166 + ``` 167 + 168 + Please open issues or PRs for new features, and include clear reproduction steps and expected behavior.
+13 -18
apps/bot/commands/auth.ts
··· 1 + import { env } from "@tealfmbot/common/constants"; 1 2 import { logger } from "@tealfmbot/common/logger"; 2 - import { 3 - ChatInputCommandInteraction, 4 - InteractionContextType, 5 - SlashCommandBuilder, 6 - } from "discord.js"; 3 + import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; 4 + 5 + const LOGIN_URL = 6 + process.env.NODE_ENV === "development" ? `127.0.0.1:${env.WEB_SERVICE_PORT}` : env.PUBLIC_URL; 7 7 8 8 export default { 9 9 data: new SlashCommandBuilder() 10 - .setName("auth") 11 - .setDescription("Authenticate your account with the teal.fm bot to start tracking your listens") 12 - .addStringOption((option) => 13 - option 14 - .setName("identifier") 15 - .setDescription("e.g. 'handle.bsky.social or did:plc...'") 16 - .setRequired(true) 17 - .setMinLength(1), 18 - ) 19 - .setContexts(InteractionContextType.Guild), 10 + .setName("login") 11 + .setDescription( 12 + "Authenticate with your Atmosphere account and request your listens to be tracked", 13 + ), 20 14 async execute(interaction: ChatInputCommandInteraction) { 21 - const identifier = interaction.options.getString("identifier"); 22 - await interaction.reply(`hello ${identifier}`); 23 - logger.info(`starting authentication process for ${identifier} at ${new Date().toJSON()}`); 15 + await interaction.reply(`Log in here and request to be tracked: ${LOGIN_URL}/login`); 16 + logger.info( 17 + `starting authentication process for ${interaction.user.username} in guild ${interaction.guildId} at ${new Date().toJSON()}`, 18 + ); 24 19 }, 25 20 };
+17
apps/bot/commands/recent.ts
··· 1 + import { logger } from "@tealfmbot/common/logger"; 2 + // import {db} from "@tealfmbot/database/db" 3 + import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; 4 + 5 + export default { 6 + data: new SlashCommandBuilder() 7 + .setName("recent") 8 + .setDescription( 9 + "Show your most recently played track", 10 + ), 11 + async execute(interaction: ChatInputCommandInteraction) { 12 + await interaction.reply("recent"); 13 + logger.info( 14 + `fetching recent track for ${interaction.user.username} in guild ${interaction.guildId} at ${new Date().toJSON()}`, 15 + ); 16 + }, 17 + };
+4 -8
apps/bot/deploy-commands.ts
··· 1 - import { 2 - DISCORD_APPLICATION_ID, 3 - DISCORD_BOT_TOKEN, 4 - DISCORD_GUILD_ID, 5 - } from "@tealfmbot/common/constants"; 1 + import { env } from "@tealfmbot/common/constants"; 6 2 import { REST, Routes } from "discord.js"; 7 3 import fs from "node:fs"; 8 4 import path from "node:path"; 9 5 10 6 const commands = []; 11 - const commandPaths = fs.globSync("commands/**/*.js"); 7 + const commandPaths = fs.globSync("dist/commands/*.js"); 12 8 13 9 for await (const cmdPath of commandPaths) { 14 10 const absoluteCommandPath = path.join(import.meta.dirname, cmdPath); ··· 22 18 } 23 19 } 24 20 25 - const rest = new REST().setToken(DISCORD_BOT_TOKEN); 21 + const rest = new REST().setToken(env.DISCORD_BOT_TOKEN); 26 22 27 23 (async () => { 28 24 try { 29 25 console.log(`Started refreshing ${commands.length} application (/) commands.`); 30 26 31 27 const data = (await rest.put( 32 - Routes.applicationGuildCommands(DISCORD_APPLICATION_ID, DISCORD_GUILD_ID), 28 + Routes.applicationGuildCommands(env.DISCORD_APPLICATION_ID, env.DISCORD_GUILD_ID), 33 29 { body: commands }, 34 30 )) as unknown[]; 35 31
+3 -3
apps/bot/main.ts
··· 1 - import { DISCORD_BOT_TOKEN } from "@tealfmbot/common/constants"; 1 + import { env } from "@tealfmbot/common/constants"; 2 2 import { logger } from "@tealfmbot/common/logger"; 3 3 import { Client, Collection, Events, GatewayIntentBits, MessageFlags } from "discord.js"; 4 4 import fs from "node:fs"; ··· 10 10 console.log(`teal.fm bot ready and logged in as ${readyClient.user.tag}`); 11 11 }); 12 12 13 - client.login(DISCORD_BOT_TOKEN); 13 + client.login(env.DISCORD_BOT_TOKEN); 14 14 15 15 client.on(Events.InteractionCreate, async (interaction) => { 16 16 if (!interaction.isChatInputCommand()) return; ··· 39 39 40 40 client.commands = new Collection(); 41 41 42 - const commandPaths = fs.globSync("commands/*.js"); 42 + const commandPaths = fs.globSync("dist/commands/*.js"); 43 43 for await (const file of commandPaths) { 44 44 const absoluteCommandPath = path.join(import.meta.dirname, file); 45 45 const command = await import(absoluteCommandPath);
+4 -2
apps/bot/package.json
··· 4 4 "private": true, 5 5 "type": "module", 6 6 "scripts": { 7 - "dev": "tsx --watch main.ts", 7 + "dev": "NODE_ENV=development tsx --watch main.ts", 8 8 "deploy-commands": "tsx deploy-commands.ts", 9 9 "build": "tsc", 10 + "watch": "tsc --watch", 10 11 "start": "node dist/main.js", 11 12 "typecheck": "tsc --noEmit" 12 13 }, 13 14 "dependencies": { 14 15 "@tealfmbot/common": "workspace:*", 15 - "@tealfmbot/tsconfig": "workspace:*", 16 + "@tealfmbot/database": "workspace:*", 16 17 "discord.js": "^14.25.1" 17 18 }, 18 19 "devDependencies": { 20 + "@tealfmbot/tsconfig": "workspace:*", 19 21 "@types/node": "^25.0.3", 20 22 "tsx": "^4.21.0", 21 23 "typescript": "^5.9.3"
+22 -10
apps/tapper/index.ts
··· 1 1 import { SimpleIndexer, Tap } from "@atproto/tap"; 2 - import { TAP_ADMIN_PASSWORD } from "@tealfmbot/common/constants"; 3 - // import { db } from "./kysely/db.ts" 2 + import { env } from "@tealfmbot/common/constants"; 3 + import { db } from "@tealfmbot/database/db"; 4 + 5 + import { isTealRecord } from "./utils"; 4 6 5 7 const tap = new Tap("https://tap.xero.systems", { 6 - adminPassword: TAP_ADMIN_PASSWORD, 8 + adminPassword: env.TAP_ADMIN_PASSWORD, 7 9 }); 8 10 9 11 const indexer = new SimpleIndexer(); 10 12 11 13 indexer.record(async (evt, opts) => { 12 14 const uri = `at://${evt.did}/${evt.collection}/${evt.rkey}`; 13 - if (evt.action === "create" || evt.action === "update") { 14 - // await db.insertInto("plays").values({ 15 - // played_time: evt?.record?.playedTime, 16 - // release_name: evt?.record?.releaseName, 17 - // track_name: evt?.record?.trackName, 18 - // user_id: 4 19 - // }).execute() 15 + if (evt.action === "create") { 16 + if (isTealRecord(evt.record)) { 17 + await db 18 + .insertInto("plays") 19 + .values({ 20 + cid: evt?.cid, 21 + rkey: evt?.rkey, 22 + uri, 23 + release_name: evt?.record?.releaseName, 24 + played_time: evt?.record?.playedTime, 25 + track_name: evt?.record?.trackName, 26 + indexed_at: new Date().toJSON(), 27 + live: evt.live, 28 + user_id: 1, 29 + }) 30 + .execute(); 31 + } 20 32 console.log(evt.record); 21 33 } else { 22 34 console.log(`deleted: ${uri}`);
+2 -1
apps/tapper/package.json
··· 11 11 "dependencies": { 12 12 "@atproto/tap": "^0.0.2", 13 13 "@tealfmbot/common": "workspace:*", 14 - "@tealfmbot/tsconfig": "workspace:*" 14 + "@tealfmbot/database": "workspace:*" 15 15 }, 16 16 "devDependencies": { 17 + "@tealfmbot/tsconfig": "workspace:*", 17 18 "@types/node": "^25.0.3", 18 19 "tsx": "^4.21.0", 19 20 "typescript": "^5.9.3"
+24
apps/tapper/utils.ts
··· 1 + type TealRecord = { 2 + $type: "fm.teal.alpha.feed.play"; 3 + trackName: string; 4 + trackMbId?: string; 5 + recordingMbId?: string; 6 + duration?: number; 7 + releaseName?: string; 8 + releaseMbId?: string; 9 + isrc?: string; 10 + originUrl?: string; 11 + musicServiceBaseDomain?: string; 12 + submissionClientAgent?: string; 13 + playedTime?: Date; 14 + artists: Artist[]; 15 + }; 16 + 17 + type Artist = { 18 + artistMbId?: string; 19 + artistName?: string; 20 + }; 21 + 22 + export function isTealRecord(record: unknown): record is TealRecord { 23 + return (record as TealRecord).$type === "fm.teal.alpha.feed.play"; 24 + }
+19 -11
apps/web/client.ts
··· 5 5 NodeOAuthClient, 6 6 type OAuthClientMetadataInput, 7 7 } from "@atproto/oauth-client-node"; 8 - import { PUBLIC_URL, PRIVATE_KEYS } from "@tealfmbot/common/constants"; 8 + import { env } from "@tealfmbot/common/constants"; 9 9 import { db } from "@tealfmbot/database/db"; 10 10 import assert from "node:assert"; 11 11 12 12 import { SessionStore, StateStore } from "./storage.js"; 13 13 14 - const keyset = 15 - PUBLIC_URL && PRIVATE_KEYS 16 - ? new Keyset(await Promise.all(PRIVATE_KEYS.map((jwk) => JoseKey.fromJWK(jwk)))) 17 - : undefined; 14 + const loadJwk = async () => { 15 + const raw = env.PRIVATE_KEYS; 16 + if (!raw) return undefined; 17 + const json = JSON.parse(raw); 18 + if (!json) return undefined; 19 + const keys = await Promise.all( 20 + json.map((jwk: string | Record<string, unknown>) => JoseKey.fromJWK(jwk)), 21 + ); 22 + return new Keyset(keys); 23 + }; 18 24 19 - assert(!PUBLIC_URL || keyset?.size, "PRIVATE_KEYS environment variable must be set"); 25 + const keyset = env.PUBLIC_URL && env.PRIVATE_KEYS ? await loadJwk() : undefined; 26 + 27 + assert(!env.PUBLIC_URL || keyset?.size, "PRIVATE_KEYS environment variable must be set"); 20 28 21 29 const pk = keyset?.findPrivateKey({ usage: "sign" }); 22 30 23 - const metadata: OAuthClientMetadataInput = PUBLIC_URL 31 + const metadata: OAuthClientMetadataInput = env.PUBLIC_URL 24 32 ? { 25 33 client_name: "Disco Stu - Teal.fm Discord Bot", 26 - client_id: `${PUBLIC_URL}/oauth-client-metadata.json`, 27 - jwks_uri: `${PUBLIC_URL}/.well-known/jwks.json`, 28 - redirect_uris: [`${PUBLIC_URL}/oauth/callback`], 34 + client_id: `${env.PUBLIC_URL}/oauth-client-metadata.json`, 35 + jwks_uri: `${env.PUBLIC_URL}/.well-known/jwks.json`, 36 + redirect_uris: [`${env.PUBLIC_URL}/oauth/callback`], 29 37 scope: "atproto", 30 38 grant_types: ["authorization_code", "refresh_token"], 31 39 response_types: ["code"], ··· 36 44 } 37 45 : atprotoLoopbackClientMetadata( 38 46 `http://localhost?${new URLSearchParams([ 39 - ["redirect_uri", "http://127.0.0.1:8002/oauth/callback"], 47 + ["redirect_uri", `http://127.0.0.1:${env.WEB_SERVICE_PORT}/oauth/callback`], 40 48 ["scope", "atproto"], 41 49 ])}`, 42 50 );
+27 -15
apps/web/index.ts
··· 1 1 import { serve, type HttpBindings } from "@hono/node-server"; 2 - import { COOKIE_SECRET } from "@tealfmbot/common/constants"; 2 + import { env } from "@tealfmbot/common/constants"; 3 3 import { logger } from "@tealfmbot/common/logger"; 4 4 import { Hono } from "hono"; 5 5 import { deleteCookie, getSignedCookie } from "hono/cookie"; ··· 8 8 import pinoHttpLogger from "pino-http"; 9 9 10 10 import { client } from "./client.js"; 11 - import { createSession, getSessionAgent, MAX_AGE, validateIdentifier } from "./utils.js"; 11 + import { 12 + createSession, 13 + getSessionAgent, 14 + MAX_AGE, 15 + validateIdentifier, 16 + getSession, 17 + } from "./utils.js"; 12 18 13 19 type Variables = { 14 20 logger: typeof logger; ··· 29 35 }); 30 36 31 37 app.get("/dashboard", async (c) => { 32 - const agent = await getSessionAgent(c); 33 - if (agent?.assertAuthenticated()) { 34 - return c.redirect("/login"); 38 + const session = await getSession(c, env); 39 + if (session) { 40 + const agent = await getSessionAgent(c); 41 + return c.html(html` 42 + <h1>Dashboard</h1> 43 + <p>DID: ${agent?.assertDid}</p> 44 + <form method="post" action="/logout"> 45 + <button type="submit">Log out</button> 46 + </form> 47 + `); 35 48 } 36 - return c.html(html` 37 - <h1>Dashboard</h1> 38 - <p>DID: ${agent?.assertDid}</p> 39 - <form method="post" action="/logout"> 40 - <button type="submit">Log out</button> 41 - </form> 42 - `); 49 + return c.redirect("/login"); 43 50 }); 44 51 45 52 app.get("/health", (c) => { ··· 61 68 const params = new URLSearchParams(c.req.url.split("?")[1]); 62 69 63 70 try { 64 - const session = await getSignedCookie(c, COOKIE_SECRET, "__teal_fm_bot_session"); 71 + const session = await getSession(c, env); 65 72 if (session) { 66 73 try { 67 74 const oauthSession = await client.restore(session); ··· 80 87 return c.redirect("/dashboard"); 81 88 }); 82 89 83 - app.get("/login", (c) => { 90 + app.get("/login", async (c) => { 91 + const session = await getSession(c, env); 92 + if (session) { 93 + return c.redirect("/dashboard"); 94 + } 95 + 84 96 return c.html( 85 97 html` 86 98 <form action="/login" method="post"> ··· 122 134 123 135 app.post("/logout", async (c) => { 124 136 c.header("Cache-Control", "no-store"); 125 - const session = await getSignedCookie(c, COOKIE_SECRET, "__teal_fm_bot_session"); 137 + const session = await getSession(c, env); 126 138 if (session) { 127 139 try { 128 140 const oauthSession = await client.restore(session);
+2 -1
apps/web/package.json
··· 7 7 "dev": "tsx --watch index.ts", 8 8 "build": "tsc", 9 9 "start": "node dist/index.js", 10 + "watch": "tsc --watch", 10 11 "typecheck": "tsc --noEmit" 11 12 }, 12 13 "dependencies": { ··· 17 18 "@hono/node-server": "^1.19.7", 18 19 "@tealfmbot/common": "workspace:*", 19 20 "@tealfmbot/database": "workspace:*", 20 - "@tealfmbot/tsconfig": "workspace:*", 21 21 "hono": "^4.11.3", 22 22 "pino-http": "^11.0.0" 23 23 }, 24 24 "devDependencies": { 25 + "@tealfmbot/tsconfig": "workspace:*", 25 26 "@types/node": "^25.0.3", 26 27 "tsx": "^4.21.0", 27 28 "typescript": "^5.9.3"
+8 -3
apps/web/utils.ts
··· 3 3 import { Agent } from "@atproto/api"; 4 4 import { isAtprotoDid, isAtprotoDidWeb } from "@atproto/did"; 5 5 import { isValidHandle } from "@atproto/syntax"; 6 - import { COOKIE_SECRET } from "@tealfmbot/common/constants"; 6 + import { env } from "@tealfmbot/common/constants"; 7 7 import { logger } from "@tealfmbot/common/logger"; 8 8 import { deleteCookie, generateSignedCookie, getSignedCookie } from "hono/cookie"; 9 9 ··· 12 12 export const MAX_AGE = process.env.NODE_ENV === "production" ? 60 : 0; 13 13 14 14 export async function createSession(value: string) { 15 - const cookie = await generateSignedCookie("__teal_fm_bot_session", value, COOKIE_SECRET, { 15 + const cookie = await generateSignedCookie("__teal_fm_bot_session", value, env.COOKIE_SECRET, { 16 16 path: "/", 17 17 secure: process.env.NODE_ENV === "production", 18 18 httpOnly: true, ··· 25 25 26 26 export async function getSessionAgent(c: Context) { 27 27 c.header("Vary", "Cookie"); 28 - const session = await getSignedCookie(c, COOKIE_SECRET, "__teal_fm_bot_session"); 28 + const session = await getSignedCookie(c, env.COOKIE_SECRET, "__teal_fm_bot_session"); 29 29 if (!session) return null; 30 30 c.header("Cache-Control", `max-age=${MAX_AGE}, private`); 31 31 ··· 37 37 deleteCookie(c, "__teal_fm_bot_session"); 38 38 return null; 39 39 } 40 + } 41 + 42 + export async function getSession(c: Context, e: typeof env) { 43 + const session = await getSignedCookie(c, e.COOKIE_SECRET, "__teal_fm_bot_session"); 44 + return session; 40 45 } 41 46 42 47 export function isValidUrl(url: string) {
+28
build-and-publish-images.sh
··· 1 + SHA=$(git rev-parse HEAD) 2 + BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) 3 + LAST_BUILT=$(date -u +%Y%m%d) 4 + VERSION=$(git describe --tags --abbrev=0) 5 + REGISTRY=atcr.io/besaid.zone 6 + 7 + services=( 8 + web 9 + bot 10 + tapper 11 + ) 12 + 13 + echo "building versioned containers with version ${VERSION#v} and tagging :latest" 14 + 15 + for svc in ${services[@]}; do 16 + docker buildx build \ 17 + -t $REGISTRY/discostu$svc:${VERSION#v} \ 18 + -t $REGISTRY/discostu$svc:latest \ 19 + --platform linux/amd64,linux/arm64 \ 20 + --target $svc \ 21 + --build-arg VERSION=${VERSION#v} \ 22 + --build-arg SHA=$SHA \ 23 + --build-arg DID=did:plc:qttsv4e7pu2jl3ilanfgc3zn \ 24 + --build-arg BUILD_DATE=$BUILD_DATE \ 25 + --pull \ 26 + --no-cache . 27 + # --push . 28 + done
+16
docker-compose.dev.yml
··· 1 + services: 2 + db: 3 + image: postgres:18.1 4 + healthcheck: 5 + test: ["CMD-SHELL", "pg_isready -U postgres -d tealfmbotdb"] 6 + interval: 10s 7 + retries: 5 8 + start_period: 30s 9 + timeout: 10s 10 + restart: always 11 + environment: 12 + POSTGRES_USER: postgres 13 + POSTGRES_PASSWORD: password 14 + POSTGRES_DB: tealfmbotdb 15 + ports: 16 + - 5432:5432
+5 -3
docker-compose.prod.yml
··· 1 + name: "Disco Stu Compose - Prod" 1 2 services: 2 3 web: 3 4 container_name: web 4 5 restart: always 5 6 build: 6 7 context: . 7 - dockerfile: Dockerfile 8 + dockerfile: atcr.io/besaid.zone/discostuweb:1.0 8 9 target: web 9 10 ports: 10 11 - 8002:8002 ··· 29 30 container_name: tapper 30 31 build: 31 32 context: . 32 - dockerfile: Dockerfile 33 + dockerfile: atcr.io/besaid.zone/discostutapper:1.0 33 34 target: tapper 34 35 35 36 depends_on: ··· 44 45 restart: always 45 46 build: 46 47 context: . 47 - dockerfile: Dockerfile 48 + dockerfile: atcr.io/besaid.zone/discostubot:1.0 48 49 target: bot 49 50 50 51 depends_on: ··· 52 53 condition: service_healthy 53 54 54 55 environment: 56 + NODE_ENV: production 55 57 DISCORD_BOT_TOKEN: "${DISCORD_BOT_TOKEN:?DISCORD_BOT_TOKEN is required}" 56 58 DISCORD_APPLICATION_ID: "${DISCORD_APPLICATION_ID:?DISCORD_APPLICATION_ID is required}" 57 59 DISCORD_GUILD_ID: "${DISCORD_GUILD_ID:?DISCORD_GUILD_ID is required}"
+53
justfile
··· 1 + sha := `git rev-parse HEAD` 2 + build_date := `date -u +%Y-%m-%dT%H:%M:%SZ` 3 + registry := "atcr.io/besaid.zone" 4 + 5 + default: 6 + @just --list 7 + 8 + release: 9 + #!/usr/bin/env bash 10 + VERSION=$(git describe --tags --abbrev=0) 11 + services=( 12 + web 13 + tapper 14 + bot 15 + ) 16 + 17 + echo "building versioned containers with version ${VERSION#v} and tagging :latest" 18 + 19 + for svc in ${services[@]}; do 20 + docker buildx build \ 21 + -t "{{registry}}"/discostu$svc:${VERSION#v} \ 22 + -t "{{registry}}"/discostu$svc:latest \ 23 + --target $svc \ 24 + --build-arg VERSION=${VERSION#v} \ 25 + --build-arg SHA="{{sha}}" \ 26 + --build-arg DID=did:plc:qttsv4e7pu2jl3ilanfgc3zn \ 27 + --build-arg BUILD_DATE="{{build_date}}" \ 28 + --pull \ 29 + --no-cache \ 30 + --push . 31 + done 32 + 33 + latest: 34 + #!/usr/bin/env bash 35 + VERSION=$(git describe --tags --abbrev=0) 36 + services=( 37 + web 38 + tapper 39 + bot 40 + ) 41 + 42 + for svc in ${services[@]}; do 43 + docker buildx build \ 44 + -t "{{registry}}"/discostu$svc:latest \ 45 + --target $svc \ 46 + --build-arg VERSION=${VERSION#v} \ 47 + --build-arg SHA="{{sha}}" \ 48 + --build-arg DID=did:plc:qttsv4e7pu2jl3ilanfgc3zn \ 49 + --build-arg BUILD_DATE="{{build_date}}" \ 50 + --pull \ 51 + --no-cache \ 52 + --push . 53 + done
+7 -2
package.json
··· 16 16 "tap": "pnpm --filter tapper dev", 17 17 "web": "pnpm --filter web dev", 18 18 "build": "pnpm -r build", 19 - "build:watch": "pnpm -r build:watch", 19 + "web:watch": "pnpm --filter web watch", 20 + "bot:watch": "pnpm --filter bot watch", 21 + "common:watch": "pnpm --filter common watch", 22 + "database:watch": "pnpm --filter database watch", 23 + "watch": "run-p *:watch", 20 24 "dev:all": "pnpm --filter './apps/**' dev", 21 - "typecheck": "pnpm --filter './apps/**' typecheck", 25 + "typecheck": "pnpm --filter './{packages,apps}/**' typecheck", 22 26 "lint": "oxlint", 23 27 "format": "oxfmt --no-error-on-unmatched-pattern" 24 28 }, 25 29 "devDependencies": { 26 30 "lefthook": "^2.0.13", 31 + "npm-run-all": "^4.1.5", 27 32 "oxfmt": "^0.20.0", 28 33 "oxlint": "^1.35.0", 29 34 "typescript": "^5.9.3"
+17
packages/.env.example
··· 1 + DISCORD_BOT_TOKEN= 2 + DISCORD_APPLICATION_ID= 3 + DISCORD_GUILD_ID= 4 + TAP_ADMIN_PASSWORD= 5 + 6 + # database credentials 7 + POSTGRES_USER=postgres 8 + POSTGRES_PASSWORD=password 9 + POSTGRES_DB=tealfmbotdb 10 + 11 + # needed for kysely codegen 12 + DATABASE_URL=postgres://postgres:password@localhost:5432/tealfmbotdb 13 + 14 + # oauth 15 + PUBLIC_URL= 16 + PRIVATE_KEYS= 17 + COOKIE_SECRET=
+12 -8
packages/common/constants.ts
··· 1 + import { cleanEnv, str, num } from "envalid"; 1 2 import path from "node:path"; 2 3 import { loadEnvFile } from "node:process"; 3 4 ··· 5 6 loadEnvFile(path.join(import.meta.dirname, "../../.env")); 6 7 } 7 8 8 - export const DISCORD_BOT_TOKEN = process.env.DISCORD_BOT_TOKEN as string; 9 - export const DISCORD_APPLICATION_ID = process.env.DISCORD_APPLICATION_ID as string; 10 - export const DISCORD_GUILD_ID = process.env.DISCORD_GUILD_ID as string; 11 - export const TAP_ADMIN_PASSWORD = process.env.TAP_ADMIN_PASSWORD as string; 12 - export const DATABASE_URL = process.env.DATABASE_URL as string; 13 - export const PUBLIC_URL = process.env.PUBLIC_URL as string; 14 - export const COOKIE_SECRET = process.env.COOKIE_SECRET as string; 15 - export const PRIVATE_KEYS = process.env.PRIVATE_KEYS as unknown as string[]; 9 + export const env = cleanEnv(process.env, { 10 + DISCORD_BOT_TOKEN: str(), 11 + DISCORD_APPLICATION_ID: str(), 12 + DISCORD_GUILD_ID: str(), 13 + TAP_ADMIN_PASSWORD: str(), 14 + DATABASE_URL: str({ devDefault: "postgres://postgres:password@localhost:5432/tealfmbotdb" }), 15 + PUBLIC_URL: str(), 16 + COOKIE_SECRET: str({ devDefault: "00000000000000000000000000000000" }), 17 + PRIVATE_KEYS: str(), 18 + WEB_SERVICE_PORT: num({ devDefault: 8002 }), 19 + });
+2 -1
packages/common/package.json
··· 13 13 } 14 14 }, 15 15 "scripts": { 16 - "build:watch": "tsc --watch", 16 + "watch": "tsc --watch", 17 17 "build": "tsc", 18 18 "typecheck": "tsc --noEmit" 19 19 }, 20 20 "dependencies": { 21 + "envalid": "^8.1.1", 21 22 "pino": "^10.1.0" 22 23 }, 23 24 "devDependencies": {
+3 -1
packages/common/tsconfig.json
··· 1 1 { 2 2 "extends": "@tealfmbot/tsconfig/tsconfig.node.json", 3 3 "compilerOptions": { 4 - "rootDir": ".", 4 + "module": "NodeNext", 5 + "moduleResolution": "nodenext", 6 + "esModuleInterop": true, 5 7 "declaration": true, 6 8 "declarationMap": true, 7 9 "outDir": "./dist"
+6 -2
packages/database/database.d.ts
··· 28 28 } 29 29 30 30 export interface Plays { 31 + cid: string | null; 31 32 id: Generated<number>; 32 33 indexed_at: Generated<Timestamp>; 33 - played_time: Timestamp; 34 - release_name: string; 34 + live: boolean | null; 35 + played_time: Timestamp | null; 36 + release_name: string | null; 37 + rkey: string | null; 35 38 track_name: string; 39 + uri: string | null; 36 40 user_id: number; 37 41 } 38 42
+2 -2
packages/database/db.ts
··· 1 - import { DATABASE_URL } from "@tealfmbot/common/constants"; 1 + import { env } from "@tealfmbot/common/constants"; 2 2 import { Kysely, PostgresDialect } from "kysely"; 3 3 import { Pool } from "pg"; 4 4 ··· 6 6 7 7 const dialect = new PostgresDialect({ 8 8 pool: new Pool({ 9 - connectionString: DATABASE_URL, 9 + connectionString: env.DATABASE_URL, 10 10 }), 11 11 }); 12 12
+2 -2
packages/database/migrate.ts
··· 1 - import { DATABASE_URL } from "@tealfmbot/common/constants.js"; 1 + import { env } from "@tealfmbot/common/constants"; 2 2 import { Kysely, Migrator, PostgresDialect, FileMigrationProvider } from "kysely"; 3 3 import { run } from "kysely-migration-cli"; 4 4 import fs from "node:fs/promises"; ··· 13 13 const db = new Kysely<DB>({ 14 14 dialect: new PostgresDialect({ 15 15 pool: new Pool({ 16 - connectionString: DATABASE_URL, 16 + connectionString: env.DATABASE_URL, 17 17 }), 18 18 }), 19 19 });
+17
packages/database/migrations/1767547891854_track_record_status.ts
··· 1 + import type { Kysely } from 'kysely' 2 + 3 + // `any` is required here since migrations should be frozen in time. alternatively, keep a "snapshot" db interface. 4 + export async function up(db: Kysely<any>): Promise<void> { 5 + // up migration code goes here... 6 + // note: up migrations are mandatory. you must implement this function. 7 + // For more info, see: https://kysely.dev/docs/migrations 8 + await db.schema.alterTable("plays").addColumn("live", "boolean").execute() 9 + } 10 + 11 + // `any` is required here since migrations should be frozen in time. alternatively, keep a "snapshot" db interface. 12 + export async function down(db: Kysely<any>): Promise<void> { 13 + // down migration code goes here... 14 + // note: down migrations are optional. you can safely delete this function. 15 + // For more info, see: https://kysely.dev/docs/migrations 16 + await db.schema.alterTable("plays").dropColumn("live").execute() 17 + }
+17
packages/database/migrations/1767553973566_add_cid_uri_rkey.ts
··· 1 + import type { Kysely } from 'kysely' 2 + 3 + // `any` is required here since migrations should be frozen in time. alternatively, keep a "snapshot" db interface. 4 + export async function up(db: Kysely<any>): Promise<void> { 5 + // up migration code goes here... 6 + // note: up migrations are mandatory. you must implement this function. 7 + // For more info, see: https://kysely.dev/docs/migrations 8 + await db.schema.alterTable("plays").addColumn("cid", "varchar").addColumn("uri", "varchar").addColumn("rkey", "varchar").execute() 9 + } 10 + 11 + // `any` is required here since migrations should be frozen in time. alternatively, keep a "snapshot" db interface. 12 + export async function down(db: Kysely<any>): Promise<void> { 13 + // down migration code goes here... 14 + // note: down migrations are optional. you can safely delete this function. 15 + // For more info, see: https://kysely.dev/docs/migrations 16 + await db.schema.alterTable("plays").dropColumn("cid").dropColumn("uri").dropColumn("rkey").execute() 17 + }
+18
packages/database/migrations/1767554974033_release_name_and_played_time_optional.ts
··· 1 + import type { Kysely } from 'kysely' 2 + 3 + // `any` is required here since migrations should be frozen in time. alternatively, keep a "snapshot" db interface. 4 + export async function up(db: Kysely<any>): Promise<void> { 5 + // up migration code goes here... 6 + // note: up migrations are mandatory. you must implement this function. 7 + // For more info, see: https://kysely.dev/docs/migrations 8 + await db.schema.alterTable("plays").alterColumn("release_name", (col) => col.dropNotNull()).alterColumn("played_time", (col) => col.dropNotNull()).execute() 9 + } 10 + 11 + // `any` is required here since migrations should be frozen in time. alternatively, keep a "snapshot" db interface. 12 + export async function down(db: Kysely<any>): Promise<void> { 13 + // down migration code goes here... 14 + // note: down migrations are optional. you can safely delete this function. 15 + // For more info, see: https://kysely.dev/docs/migrations 16 + await db.schema.alterTable("plays").alterColumn("played_time", (col) => col.setNotNull()) 17 + .alterColumn("release_name", (col) => col.setNotNull()).execute() 18 + }
+2 -2
packages/database/package.json
··· 14 14 } 15 15 }, 16 16 "scripts": { 17 - "build:watch": "tsc --watch", 17 + "watch": "tsc --watch", 18 18 "build": "tsc", 19 19 "migrate": "kysely migrate latest", 20 - "codegen": "kysely-codegen --dialect postgres --env-file='../../.env' --out-file ./database.d.ts", 20 + "codegen": "kysely-codegen --dialect postgres --env-file='../.env' --out-file ./database.d.ts", 21 21 "seed": "tsx seed.ts", 22 22 "typecheck": "tsc --noEmit" 23 23 },
+1124 -6
pnpm-lock.yaml
··· 12 12 lefthook: 13 13 specifier: ^2.0.13 14 14 version: 2.0.13 15 + npm-run-all: 16 + specifier: ^4.1.5 17 + version: 4.1.5 15 18 oxfmt: 16 19 specifier: ^0.20.0 17 20 version: 0.20.0 ··· 27 30 '@tealfmbot/common': 28 31 specifier: workspace:* 29 32 version: link:../../packages/common 30 - '@tealfmbot/tsconfig': 33 + '@tealfmbot/database': 31 34 specifier: workspace:* 32 - version: link:../../packages/tsconfig 35 + version: link:../../packages/database 33 36 discord.js: 34 37 specifier: ^14.25.1 35 38 version: 14.25.1 36 39 devDependencies: 40 + '@tealfmbot/tsconfig': 41 + specifier: workspace:* 42 + version: link:../../packages/tsconfig 37 43 '@types/node': 38 44 specifier: ^25.0.3 39 45 version: 25.0.3 ··· 52 58 '@tealfmbot/common': 53 59 specifier: workspace:* 54 60 version: link:../../packages/common 61 + '@tealfmbot/database': 62 + specifier: workspace:* 63 + version: link:../../packages/database 64 + devDependencies: 55 65 '@tealfmbot/tsconfig': 56 66 specifier: workspace:* 57 67 version: link:../../packages/tsconfig 58 - devDependencies: 59 68 '@types/node': 60 69 specifier: ^25.0.3 61 70 version: 25.0.3 ··· 89 98 '@tealfmbot/database': 90 99 specifier: workspace:* 91 100 version: link:../../packages/database 92 - '@tealfmbot/tsconfig': 93 - specifier: workspace:* 94 - version: link:../../packages/tsconfig 95 101 hono: 96 102 specifier: ^4.11.3 97 103 version: 4.11.3 ··· 99 105 specifier: ^11.0.0 100 106 version: 11.0.0 101 107 devDependencies: 108 + '@tealfmbot/tsconfig': 109 + specifier: workspace:* 110 + version: link:../../packages/tsconfig 102 111 '@types/node': 103 112 specifier: ^25.0.3 104 113 version: 25.0.3 ··· 111 120 112 121 packages/common: 113 122 dependencies: 123 + envalid: 124 + specifier: ^8.1.1 125 + version: 8.1.1 114 126 pino: 115 127 specifier: ^10.1.0 116 128 version: 10.1.0 ··· 585 597 argparse@2.0.1: 586 598 resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 587 599 600 + array-buffer-byte-length@1.0.2: 601 + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} 602 + engines: {node: '>= 0.4'} 603 + 604 + arraybuffer.prototype.slice@1.0.4: 605 + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} 606 + engines: {node: '>= 0.4'} 607 + 608 + async-function@1.0.0: 609 + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} 610 + engines: {node: '>= 0.4'} 611 + 588 612 atomic-sleep@1.0.0: 589 613 resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} 590 614 engines: {node: '>=8.0.0'} 591 615 616 + available-typed-arrays@1.0.7: 617 + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} 618 + engines: {node: '>= 0.4'} 619 + 592 620 await-lock@2.2.2: 593 621 resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==} 594 622 ··· 615 643 peerDependenciesMeta: 616 644 magicast: 617 645 optional: true 646 + 647 + call-bind-apply-helpers@1.0.2: 648 + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} 649 + engines: {node: '>= 0.4'} 650 + 651 + call-bind@1.0.8: 652 + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} 653 + engines: {node: '>= 0.4'} 654 + 655 + call-bound@1.0.4: 656 + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} 657 + engines: {node: '>= 0.4'} 618 658 619 659 callsites@3.1.0: 620 660 resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} ··· 677 717 typescript: 678 718 optional: true 679 719 720 + cross-spawn@6.0.6: 721 + resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} 722 + engines: {node: '>=4.8'} 723 + 724 + data-view-buffer@1.0.2: 725 + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} 726 + engines: {node: '>= 0.4'} 727 + 728 + data-view-byte-length@1.0.2: 729 + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} 730 + engines: {node: '>= 0.4'} 731 + 732 + data-view-byte-offset@1.0.1: 733 + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} 734 + engines: {node: '>= 0.4'} 735 + 680 736 dateformat@4.6.3: 681 737 resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} 682 738 739 + define-data-property@1.1.4: 740 + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} 741 + engines: {node: '>= 0.4'} 742 + 743 + define-properties@1.2.1: 744 + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} 745 + engines: {node: '>= 0.4'} 746 + 683 747 defu@6.1.4: 684 748 resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} 685 749 ··· 709 773 resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} 710 774 engines: {node: '>=12'} 711 775 776 + dunder-proto@1.0.1: 777 + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} 778 + engines: {node: '>= 0.4'} 779 + 712 780 end-of-stream@1.4.5: 713 781 resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} 714 782 ··· 716 784 resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} 717 785 engines: {node: '>=6'} 718 786 787 + envalid@8.1.1: 788 + resolution: {integrity: sha512-vOUfHxAFFvkBjbVQbBfgnCO9d3GcNfMMTtVfgqSU2rQGMFEVqWy9GBuoSfHnwGu7EqR0/GeukQcL3KjFBaga9w==} 789 + engines: {node: '>=18'} 790 + 719 791 error-ex@1.3.4: 720 792 resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} 721 793 794 + es-abstract@1.24.1: 795 + resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} 796 + engines: {node: '>= 0.4'} 797 + 798 + es-define-property@1.0.1: 799 + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} 800 + engines: {node: '>= 0.4'} 801 + 802 + es-errors@1.3.0: 803 + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 804 + engines: {node: '>= 0.4'} 805 + 806 + es-object-atoms@1.1.1: 807 + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} 808 + engines: {node: '>= 0.4'} 809 + 810 + es-set-tostringtag@2.1.0: 811 + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} 812 + engines: {node: '>= 0.4'} 813 + 814 + es-to-primitive@1.3.0: 815 + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} 816 + engines: {node: '>= 0.4'} 817 + 722 818 esbuild@0.27.2: 723 819 resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} 724 820 engines: {node: '>=18'} ··· 756 852 resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 757 853 engines: {node: '>=8'} 758 854 855 + for-each@0.3.5: 856 + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} 857 + engines: {node: '>= 0.4'} 858 + 759 859 fs.realpath@1.0.0: 760 860 resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 761 861 ··· 767 867 function-bind@1.1.2: 768 868 resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 769 869 870 + function.prototype.name@1.1.8: 871 + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} 872 + engines: {node: '>= 0.4'} 873 + 874 + functions-have-names@1.2.3: 875 + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} 876 + 877 + generator-function@2.0.1: 878 + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} 879 + engines: {node: '>= 0.4'} 880 + 770 881 get-caller-file@2.0.5: 771 882 resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 772 883 engines: {node: 6.* || 8.* || >= 10.*} 773 884 885 + get-intrinsic@1.3.0: 886 + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} 887 + engines: {node: '>= 0.4'} 888 + 889 + get-proto@1.0.1: 890 + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} 891 + engines: {node: '>= 0.4'} 892 + 893 + get-symbol-description@1.1.0: 894 + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} 895 + engines: {node: '>= 0.4'} 896 + 774 897 get-tsconfig@4.13.0: 775 898 resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} 776 899 ··· 786 909 resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 787 910 deprecated: Glob versions prior to v9 are no longer supported 788 911 912 + globalthis@1.0.4: 913 + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} 914 + engines: {node: '>= 0.4'} 915 + 916 + gopd@1.2.0: 917 + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} 918 + engines: {node: '>= 0.4'} 919 + 920 + graceful-fs@4.2.11: 921 + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 922 + 923 + has-bigints@1.1.0: 924 + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} 925 + engines: {node: '>= 0.4'} 926 + 789 927 has-flag@3.0.0: 790 928 resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 791 929 engines: {node: '>=4'} ··· 794 932 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 795 933 engines: {node: '>=8'} 796 934 935 + has-property-descriptors@1.0.2: 936 + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} 937 + 938 + has-proto@1.2.0: 939 + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} 940 + engines: {node: '>= 0.4'} 941 + 942 + has-symbols@1.1.0: 943 + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} 944 + engines: {node: '>= 0.4'} 945 + 946 + has-tostringtag@1.0.2: 947 + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} 948 + engines: {node: '>= 0.4'} 949 + 797 950 hasown@2.0.2: 798 951 resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 799 952 engines: {node: '>= 0.4'} ··· 805 958 resolution: {integrity: sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w==} 806 959 engines: {node: '>=16.9.0'} 807 960 961 + hosted-git-info@2.8.9: 962 + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} 963 + 808 964 ieee754@1.2.1: 809 965 resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 810 966 ··· 819 975 inherits@2.0.4: 820 976 resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 821 977 978 + internal-slot@1.1.0: 979 + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} 980 + engines: {node: '>= 0.4'} 981 + 822 982 interpret@1.4.0: 823 983 resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} 824 984 engines: {node: '>= 0.10'} ··· 827 987 resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} 828 988 engines: {node: '>= 10'} 829 989 990 + is-array-buffer@3.0.5: 991 + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} 992 + engines: {node: '>= 0.4'} 993 + 830 994 is-arrayish@0.2.1: 831 995 resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} 832 996 997 + is-async-function@2.1.1: 998 + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} 999 + engines: {node: '>= 0.4'} 1000 + 1001 + is-bigint@1.1.0: 1002 + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} 1003 + engines: {node: '>= 0.4'} 1004 + 1005 + is-boolean-object@1.2.2: 1006 + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} 1007 + engines: {node: '>= 0.4'} 1008 + 1009 + is-callable@1.2.7: 1010 + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} 1011 + engines: {node: '>= 0.4'} 1012 + 833 1013 is-core-module@2.16.1: 834 1014 resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} 835 1015 engines: {node: '>= 0.4'} 836 1016 1017 + is-data-view@1.0.2: 1018 + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} 1019 + engines: {node: '>= 0.4'} 1020 + 1021 + is-date-object@1.1.0: 1022 + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} 1023 + engines: {node: '>= 0.4'} 1024 + 1025 + is-finalizationregistry@1.1.1: 1026 + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} 1027 + engines: {node: '>= 0.4'} 1028 + 1029 + is-generator-function@1.1.2: 1030 + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} 1031 + engines: {node: '>= 0.4'} 1032 + 1033 + is-map@2.0.3: 1034 + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} 1035 + engines: {node: '>= 0.4'} 1036 + 1037 + is-negative-zero@2.0.3: 1038 + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} 1039 + engines: {node: '>= 0.4'} 1040 + 1041 + is-number-object@1.1.1: 1042 + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} 1043 + engines: {node: '>= 0.4'} 1044 + 837 1045 is-number@7.0.0: 838 1046 resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 839 1047 engines: {node: '>=0.12.0'} 840 1048 1049 + is-regex@1.2.1: 1050 + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} 1051 + engines: {node: '>= 0.4'} 1052 + 1053 + is-set@2.0.3: 1054 + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} 1055 + engines: {node: '>= 0.4'} 1056 + 1057 + is-shared-array-buffer@1.0.4: 1058 + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} 1059 + engines: {node: '>= 0.4'} 1060 + 1061 + is-string@1.1.1: 1062 + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} 1063 + engines: {node: '>= 0.4'} 1064 + 1065 + is-symbol@1.1.1: 1066 + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} 1067 + engines: {node: '>= 0.4'} 1068 + 1069 + is-typed-array@1.1.15: 1070 + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} 1071 + engines: {node: '>= 0.4'} 1072 + 1073 + is-weakmap@2.0.2: 1074 + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} 1075 + engines: {node: '>= 0.4'} 1076 + 1077 + is-weakref@1.1.1: 1078 + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} 1079 + engines: {node: '>= 0.4'} 1080 + 1081 + is-weakset@2.0.4: 1082 + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} 1083 + engines: {node: '>= 0.4'} 1084 + 1085 + isarray@2.0.5: 1086 + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} 1087 + 1088 + isexe@2.0.0: 1089 + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1090 + 841 1091 iso-datestring-validator@2.2.2: 842 1092 resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} 843 1093 ··· 858 1108 js-yaml@4.1.1: 859 1109 resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} 860 1110 hasBin: true 1111 + 1112 + json-parse-better-errors@1.0.2: 1113 + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} 861 1114 862 1115 json-parse-even-better-errors@2.3.1: 863 1116 resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} ··· 979 1232 lines-and-columns@1.2.4: 980 1233 resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 981 1234 1235 + load-json-file@4.0.0: 1236 + resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} 1237 + engines: {node: '>=4'} 1238 + 982 1239 lodash.snakecase@4.1.1: 983 1240 resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} 984 1241 ··· 995 1252 magic-bytes.js@1.12.1: 996 1253 resolution: {integrity: sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==} 997 1254 1255 + math-intrinsics@1.1.0: 1256 + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} 1257 + engines: {node: '>= 0.4'} 1258 + 1259 + memorystream@0.3.1: 1260 + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} 1261 + engines: {node: '>= 0.10.0'} 1262 + 998 1263 micromatch@4.0.8: 999 1264 resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1000 1265 engines: {node: '>=8.6'} ··· 1008 1273 multiformats@9.9.0: 1009 1274 resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} 1010 1275 1276 + nice-try@1.0.5: 1277 + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} 1278 + 1011 1279 node-fetch-native@1.6.7: 1012 1280 resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} 1013 1281 1282 + normalize-package-data@2.5.0: 1283 + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} 1284 + 1285 + npm-run-all@4.1.5: 1286 + resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==} 1287 + engines: {node: '>= 4'} 1288 + hasBin: true 1289 + 1014 1290 nypm@0.6.2: 1015 1291 resolution: {integrity: sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==} 1016 1292 engines: {node: ^14.16.0 || >=16.10.0} 1017 1293 hasBin: true 1018 1294 1295 + object-inspect@1.13.4: 1296 + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} 1297 + engines: {node: '>= 0.4'} 1298 + 1299 + object-keys@1.1.1: 1300 + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} 1301 + engines: {node: '>= 0.4'} 1302 + 1303 + object.assign@4.1.7: 1304 + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} 1305 + engines: {node: '>= 0.4'} 1306 + 1019 1307 ofetch@1.5.1: 1020 1308 resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} 1021 1309 ··· 1029 1317 once@1.4.0: 1030 1318 resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1031 1319 1320 + own-keys@1.0.1: 1321 + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} 1322 + engines: {node: '>= 0.4'} 1323 + 1032 1324 oxfmt@0.20.0: 1033 1325 resolution: {integrity: sha512-+7f8eV8iaK3tENN/FUVxZM1g78HjPehybN8/+/dvEA1O893Dcvk6O7/Q1wTQOHMD7wvdwWdujKl+Uo8QMiKDrQ==} 1034 1326 engines: {node: ^20.19.0 || >=22.12.0} ··· 1048 1340 resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1049 1341 engines: {node: '>=6'} 1050 1342 1343 + parse-json@4.0.0: 1344 + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} 1345 + engines: {node: '>=4'} 1346 + 1051 1347 parse-json@5.2.0: 1052 1348 resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} 1053 1349 engines: {node: '>=8'} ··· 1056 1352 resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 1057 1353 engines: {node: '>=0.10.0'} 1058 1354 1355 + path-key@2.0.1: 1356 + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} 1357 + engines: {node: '>=4'} 1358 + 1059 1359 path-parse@1.0.7: 1060 1360 resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1361 + 1362 + path-type@3.0.0: 1363 + resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} 1364 + engines: {node: '>=4'} 1061 1365 1062 1366 pathe@2.0.3: 1063 1367 resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} ··· 1106 1410 resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1107 1411 engines: {node: '>=8.6'} 1108 1412 1413 + pidtree@0.3.1: 1414 + resolution: {integrity: sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==} 1415 + engines: {node: '>=0.10'} 1416 + hasBin: true 1417 + 1418 + pify@3.0.0: 1419 + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} 1420 + engines: {node: '>=4'} 1421 + 1109 1422 pino-abstract-transport@1.2.0: 1110 1423 resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} 1111 1424 ··· 1143 1456 resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} 1144 1457 engines: {node: '>=4'} 1145 1458 1459 + possible-typed-array-names@1.1.0: 1460 + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} 1461 + engines: {node: '>= 0.4'} 1462 + 1146 1463 postgres-array@2.0.0: 1147 1464 resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} 1148 1465 engines: {node: '>=4'} ··· 1178 1495 rc9@2.1.2: 1179 1496 resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} 1180 1497 1498 + read-pkg@3.0.0: 1499 + resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} 1500 + engines: {node: '>=4'} 1501 + 1181 1502 readable-stream@4.7.0: 1182 1503 resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} 1183 1504 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} ··· 1194 1515 resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} 1195 1516 engines: {node: '>= 0.10'} 1196 1517 1518 + reflect.getprototypeof@1.0.10: 1519 + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} 1520 + engines: {node: '>= 0.4'} 1521 + 1522 + regexp.prototype.flags@1.5.4: 1523 + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} 1524 + engines: {node: '>= 0.4'} 1525 + 1197 1526 resolve-from@4.0.0: 1198 1527 resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1199 1528 engines: {node: '>=4'} ··· 1206 1535 engines: {node: '>= 0.4'} 1207 1536 hasBin: true 1208 1537 1538 + safe-array-concat@1.1.3: 1539 + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} 1540 + engines: {node: '>=0.4'} 1541 + 1209 1542 safe-buffer@5.2.1: 1210 1543 resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1211 1544 1545 + safe-push-apply@1.0.0: 1546 + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} 1547 + engines: {node: '>= 0.4'} 1548 + 1549 + safe-regex-test@1.1.0: 1550 + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} 1551 + engines: {node: '>= 0.4'} 1552 + 1212 1553 safe-stable-stringify@2.5.0: 1213 1554 resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} 1214 1555 engines: {node: '>=10'} ··· 1216 1557 secure-json-parse@4.1.0: 1217 1558 resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} 1218 1559 1560 + semver@5.7.2: 1561 + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} 1562 + hasBin: true 1563 + 1564 + set-function-length@1.2.2: 1565 + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} 1566 + engines: {node: '>= 0.4'} 1567 + 1568 + set-function-name@2.0.2: 1569 + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} 1570 + engines: {node: '>= 0.4'} 1571 + 1572 + set-proto@1.0.0: 1573 + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} 1574 + engines: {node: '>= 0.4'} 1575 + 1576 + shebang-command@1.2.0: 1577 + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} 1578 + engines: {node: '>=0.10.0'} 1579 + 1580 + shebang-regex@1.0.0: 1581 + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} 1582 + engines: {node: '>=0.10.0'} 1583 + 1584 + shell-quote@1.8.3: 1585 + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} 1586 + engines: {node: '>= 0.4'} 1587 + 1219 1588 shelljs.exec@1.1.8: 1220 1589 resolution: {integrity: sha512-vFILCw+lzUtiwBAHV8/Ex8JsFjelFMdhONIsgKNLgTzeRckp2AOYRQtHJE/9LhNvdMmE27AGtzWx0+DHpwIwSw==} 1221 1590 engines: {node: '>= 4.0.0'} ··· 1225 1594 engines: {node: '>=4'} 1226 1595 hasBin: true 1227 1596 1597 + side-channel-list@1.0.0: 1598 + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} 1599 + engines: {node: '>= 0.4'} 1600 + 1601 + side-channel-map@1.0.1: 1602 + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} 1603 + engines: {node: '>= 0.4'} 1604 + 1605 + side-channel-weakmap@1.0.2: 1606 + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} 1607 + engines: {node: '>= 0.4'} 1608 + 1609 + side-channel@1.1.0: 1610 + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} 1611 + engines: {node: '>= 0.4'} 1612 + 1228 1613 sonic-boom@3.8.1: 1229 1614 resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} 1230 1615 1231 1616 sonic-boom@4.2.0: 1232 1617 resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} 1233 1618 1619 + spdx-correct@3.2.0: 1620 + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} 1621 + 1622 + spdx-exceptions@2.5.0: 1623 + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} 1624 + 1625 + spdx-expression-parse@3.0.1: 1626 + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} 1627 + 1628 + spdx-license-ids@3.0.22: 1629 + resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} 1630 + 1234 1631 split2@4.2.0: 1235 1632 resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} 1236 1633 engines: {node: '>= 10.x'} ··· 1238 1635 std-env@3.10.0: 1239 1636 resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} 1240 1637 1638 + stop-iteration-iterator@1.1.0: 1639 + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} 1640 + engines: {node: '>= 0.4'} 1641 + 1642 + string.prototype.padend@3.1.6: 1643 + resolution: {integrity: sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==} 1644 + engines: {node: '>= 0.4'} 1645 + 1646 + string.prototype.trim@1.2.10: 1647 + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} 1648 + engines: {node: '>= 0.4'} 1649 + 1650 + string.prototype.trimend@1.0.9: 1651 + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} 1652 + engines: {node: '>= 0.4'} 1653 + 1654 + string.prototype.trimstart@1.0.8: 1655 + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} 1656 + engines: {node: '>= 0.4'} 1657 + 1241 1658 string_decoder@1.3.0: 1242 1659 resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 1660 + 1661 + strip-bom@3.0.0: 1662 + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 1663 + engines: {node: '>=4'} 1243 1664 1244 1665 strip-json-comments@5.0.3: 1245 1666 resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} ··· 1300 1721 engines: {node: '>=18.0.0'} 1301 1722 hasBin: true 1302 1723 1724 + typed-array-buffer@1.0.3: 1725 + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} 1726 + engines: {node: '>= 0.4'} 1727 + 1728 + typed-array-byte-length@1.0.3: 1729 + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} 1730 + engines: {node: '>= 0.4'} 1731 + 1732 + typed-array-byte-offset@1.0.4: 1733 + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} 1734 + engines: {node: '>= 0.4'} 1735 + 1736 + typed-array-length@1.0.7: 1737 + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} 1738 + engines: {node: '>= 0.4'} 1739 + 1303 1740 typescript@5.9.2: 1304 1741 resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} 1305 1742 engines: {node: '>=14.17'} ··· 1316 1753 uint8arrays@3.0.0: 1317 1754 resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} 1318 1755 1756 + unbox-primitive@1.1.0: 1757 + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} 1758 + engines: {node: '>= 0.4'} 1759 + 1319 1760 undici-types@6.21.0: 1320 1761 resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 1321 1762 ··· 1328 1769 1329 1770 unicode-segmenter@0.14.4: 1330 1771 resolution: {integrity: sha512-pR5VCiCrLrKOL6FRW61jnk9+wyMtKKowq+jyFY9oc6uHbWKhDL4yVRiI4YZPksGMK72Pahh8m0cn/0JvbDDyJg==} 1772 + 1773 + validate-npm-package-license@3.0.4: 1774 + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} 1775 + 1776 + which-boxed-primitive@1.1.1: 1777 + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} 1778 + engines: {node: '>= 0.4'} 1779 + 1780 + which-builtin-type@1.2.1: 1781 + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} 1782 + engines: {node: '>= 0.4'} 1783 + 1784 + which-collection@1.0.2: 1785 + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} 1786 + engines: {node: '>= 0.4'} 1787 + 1788 + which-typed-array@1.1.19: 1789 + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} 1790 + engines: {node: '>= 0.4'} 1791 + 1792 + which@1.3.1: 1793 + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} 1794 + hasBin: true 1331 1795 1332 1796 wrappy@1.0.2: 1333 1797 resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} ··· 1772 2236 1773 2237 argparse@2.0.1: {} 1774 2238 2239 + array-buffer-byte-length@1.0.2: 2240 + dependencies: 2241 + call-bound: 1.0.4 2242 + is-array-buffer: 3.0.5 2243 + 2244 + arraybuffer.prototype.slice@1.0.4: 2245 + dependencies: 2246 + array-buffer-byte-length: 1.0.2 2247 + call-bind: 1.0.8 2248 + define-properties: 1.2.1 2249 + es-abstract: 1.24.1 2250 + es-errors: 1.3.0 2251 + get-intrinsic: 1.3.0 2252 + is-array-buffer: 3.0.5 2253 + 2254 + async-function@1.0.0: {} 2255 + 1775 2256 atomic-sleep@1.0.0: {} 2257 + 2258 + available-typed-arrays@1.0.7: 2259 + dependencies: 2260 + possible-typed-array-names: 1.1.0 1776 2261 1777 2262 await-lock@2.2.2: {} 1778 2263 ··· 1809 2294 pkg-types: 2.3.0 1810 2295 rc9: 2.1.2 1811 2296 2297 + call-bind-apply-helpers@1.0.2: 2298 + dependencies: 2299 + es-errors: 1.3.0 2300 + function-bind: 1.1.2 2301 + 2302 + call-bind@1.0.8: 2303 + dependencies: 2304 + call-bind-apply-helpers: 1.0.2 2305 + es-define-property: 1.0.1 2306 + get-intrinsic: 1.3.0 2307 + set-function-length: 1.2.2 2308 + 2309 + call-bound@1.0.4: 2310 + dependencies: 2311 + call-bind-apply-helpers: 1.0.2 2312 + get-intrinsic: 1.3.0 2313 + 1812 2314 callsites@3.1.0: {} 1813 2315 1814 2316 chalk@2.4.2: ··· 1863 2365 optionalDependencies: 1864 2366 typescript: 5.9.2 1865 2367 2368 + cross-spawn@6.0.6: 2369 + dependencies: 2370 + nice-try: 1.0.5 2371 + path-key: 2.0.1 2372 + semver: 5.7.2 2373 + shebang-command: 1.2.0 2374 + which: 1.3.1 2375 + 2376 + data-view-buffer@1.0.2: 2377 + dependencies: 2378 + call-bound: 1.0.4 2379 + es-errors: 1.3.0 2380 + is-data-view: 1.0.2 2381 + 2382 + data-view-byte-length@1.0.2: 2383 + dependencies: 2384 + call-bound: 1.0.4 2385 + es-errors: 1.3.0 2386 + is-data-view: 1.0.2 2387 + 2388 + data-view-byte-offset@1.0.1: 2389 + dependencies: 2390 + call-bound: 1.0.4 2391 + es-errors: 1.3.0 2392 + is-data-view: 1.0.2 2393 + 1866 2394 dateformat@4.6.3: {} 1867 2395 2396 + define-data-property@1.1.4: 2397 + dependencies: 2398 + es-define-property: 1.0.1 2399 + es-errors: 1.3.0 2400 + gopd: 1.2.0 2401 + 2402 + define-properties@1.2.1: 2403 + dependencies: 2404 + define-data-property: 1.1.4 2405 + has-property-descriptors: 1.0.2 2406 + object-keys: 1.1.1 2407 + 1868 2408 defu@6.1.4: {} 1869 2409 1870 2410 destr@2.0.5: {} ··· 1900 2440 1901 2441 dotenv@17.2.3: {} 1902 2442 2443 + dunder-proto@1.0.1: 2444 + dependencies: 2445 + call-bind-apply-helpers: 1.0.2 2446 + es-errors: 1.3.0 2447 + gopd: 1.2.0 2448 + 1903 2449 end-of-stream@1.4.5: 1904 2450 dependencies: 1905 2451 once: 1.4.0 1906 2452 1907 2453 env-paths@2.2.1: {} 1908 2454 2455 + envalid@8.1.1: 2456 + dependencies: 2457 + tslib: 2.8.1 2458 + 1909 2459 error-ex@1.3.4: 1910 2460 dependencies: 1911 2461 is-arrayish: 0.2.1 1912 2462 2463 + es-abstract@1.24.1: 2464 + dependencies: 2465 + array-buffer-byte-length: 1.0.2 2466 + arraybuffer.prototype.slice: 1.0.4 2467 + available-typed-arrays: 1.0.7 2468 + call-bind: 1.0.8 2469 + call-bound: 1.0.4 2470 + data-view-buffer: 1.0.2 2471 + data-view-byte-length: 1.0.2 2472 + data-view-byte-offset: 1.0.1 2473 + es-define-property: 1.0.1 2474 + es-errors: 1.3.0 2475 + es-object-atoms: 1.1.1 2476 + es-set-tostringtag: 2.1.0 2477 + es-to-primitive: 1.3.0 2478 + function.prototype.name: 1.1.8 2479 + get-intrinsic: 1.3.0 2480 + get-proto: 1.0.1 2481 + get-symbol-description: 1.1.0 2482 + globalthis: 1.0.4 2483 + gopd: 1.2.0 2484 + has-property-descriptors: 1.0.2 2485 + has-proto: 1.2.0 2486 + has-symbols: 1.1.0 2487 + hasown: 2.0.2 2488 + internal-slot: 1.1.0 2489 + is-array-buffer: 3.0.5 2490 + is-callable: 1.2.7 2491 + is-data-view: 1.0.2 2492 + is-negative-zero: 2.0.3 2493 + is-regex: 1.2.1 2494 + is-set: 2.0.3 2495 + is-shared-array-buffer: 1.0.4 2496 + is-string: 1.1.1 2497 + is-typed-array: 1.1.15 2498 + is-weakref: 1.1.1 2499 + math-intrinsics: 1.1.0 2500 + object-inspect: 1.13.4 2501 + object-keys: 1.1.1 2502 + object.assign: 4.1.7 2503 + own-keys: 1.0.1 2504 + regexp.prototype.flags: 1.5.4 2505 + safe-array-concat: 1.1.3 2506 + safe-push-apply: 1.0.0 2507 + safe-regex-test: 1.1.0 2508 + set-proto: 1.0.0 2509 + stop-iteration-iterator: 1.1.0 2510 + string.prototype.trim: 1.2.10 2511 + string.prototype.trimend: 1.0.9 2512 + string.prototype.trimstart: 1.0.8 2513 + typed-array-buffer: 1.0.3 2514 + typed-array-byte-length: 1.0.3 2515 + typed-array-byte-offset: 1.0.4 2516 + typed-array-length: 1.0.7 2517 + unbox-primitive: 1.1.0 2518 + which-typed-array: 1.1.19 2519 + 2520 + es-define-property@1.0.1: {} 2521 + 2522 + es-errors@1.3.0: {} 2523 + 2524 + es-object-atoms@1.1.1: 2525 + dependencies: 2526 + es-errors: 1.3.0 2527 + 2528 + es-set-tostringtag@2.1.0: 2529 + dependencies: 2530 + es-errors: 1.3.0 2531 + get-intrinsic: 1.3.0 2532 + has-tostringtag: 1.0.2 2533 + hasown: 2.0.2 2534 + 2535 + es-to-primitive@1.3.0: 2536 + dependencies: 2537 + is-callable: 1.2.7 2538 + is-date-object: 1.1.0 2539 + is-symbol: 1.1.1 2540 + 1913 2541 esbuild@0.27.2: 1914 2542 optionalDependencies: 1915 2543 '@esbuild/aix-ppc64': 0.27.2 ··· 1959 2587 dependencies: 1960 2588 to-regex-range: 5.0.1 1961 2589 2590 + for-each@0.3.5: 2591 + dependencies: 2592 + is-callable: 1.2.7 2593 + 1962 2594 fs.realpath@1.0.0: {} 1963 2595 1964 2596 fsevents@2.3.3: ··· 1966 2598 1967 2599 function-bind@1.1.2: {} 1968 2600 2601 + function.prototype.name@1.1.8: 2602 + dependencies: 2603 + call-bind: 1.0.8 2604 + call-bound: 1.0.4 2605 + define-properties: 1.2.1 2606 + functions-have-names: 1.2.3 2607 + hasown: 2.0.2 2608 + is-callable: 1.2.7 2609 + 2610 + functions-have-names@1.2.3: {} 2611 + 2612 + generator-function@2.0.1: {} 2613 + 1969 2614 get-caller-file@2.0.5: {} 1970 2615 2616 + get-intrinsic@1.3.0: 2617 + dependencies: 2618 + call-bind-apply-helpers: 1.0.2 2619 + es-define-property: 1.0.1 2620 + es-errors: 1.3.0 2621 + es-object-atoms: 1.1.1 2622 + function-bind: 1.1.2 2623 + get-proto: 1.0.1 2624 + gopd: 1.2.0 2625 + has-symbols: 1.1.0 2626 + hasown: 2.0.2 2627 + math-intrinsics: 1.1.0 2628 + 2629 + get-proto@1.0.1: 2630 + dependencies: 2631 + dunder-proto: 1.0.1 2632 + es-object-atoms: 1.1.1 2633 + 2634 + get-symbol-description@1.1.0: 2635 + dependencies: 2636 + call-bound: 1.0.4 2637 + es-errors: 1.3.0 2638 + get-intrinsic: 1.3.0 2639 + 1971 2640 get-tsconfig@4.13.0: 1972 2641 dependencies: 1973 2642 resolve-pkg-maps: 1.0.0 ··· 1998 2667 once: 1.4.0 1999 2668 path-is-absolute: 1.0.1 2000 2669 2670 + globalthis@1.0.4: 2671 + dependencies: 2672 + define-properties: 1.2.1 2673 + gopd: 1.2.0 2674 + 2675 + gopd@1.2.0: {} 2676 + 2677 + graceful-fs@4.2.11: {} 2678 + 2679 + has-bigints@1.1.0: {} 2680 + 2001 2681 has-flag@3.0.0: {} 2002 2682 2003 2683 has-flag@4.0.0: {} 2004 2684 2685 + has-property-descriptors@1.0.2: 2686 + dependencies: 2687 + es-define-property: 1.0.1 2688 + 2689 + has-proto@1.2.0: 2690 + dependencies: 2691 + dunder-proto: 1.0.1 2692 + 2693 + has-symbols@1.1.0: {} 2694 + 2695 + has-tostringtag@1.0.2: 2696 + dependencies: 2697 + has-symbols: 1.1.0 2698 + 2005 2699 hasown@2.0.2: 2006 2700 dependencies: 2007 2701 function-bind: 1.1.2 ··· 2010 2704 2011 2705 hono@4.11.3: {} 2012 2706 2707 + hosted-git-info@2.8.9: {} 2708 + 2013 2709 ieee754@1.2.1: {} 2014 2710 2015 2711 import-fresh@3.3.1: ··· 2024 2720 2025 2721 inherits@2.0.4: {} 2026 2722 2723 + internal-slot@1.1.0: 2724 + dependencies: 2725 + es-errors: 1.3.0 2726 + hasown: 2.0.2 2727 + side-channel: 1.1.0 2728 + 2027 2729 interpret@1.4.0: {} 2028 2730 2029 2731 ipaddr.js@2.3.0: {} 2030 2732 2733 + is-array-buffer@3.0.5: 2734 + dependencies: 2735 + call-bind: 1.0.8 2736 + call-bound: 1.0.4 2737 + get-intrinsic: 1.3.0 2738 + 2031 2739 is-arrayish@0.2.1: {} 2032 2740 2741 + is-async-function@2.1.1: 2742 + dependencies: 2743 + async-function: 1.0.0 2744 + call-bound: 1.0.4 2745 + get-proto: 1.0.1 2746 + has-tostringtag: 1.0.2 2747 + safe-regex-test: 1.1.0 2748 + 2749 + is-bigint@1.1.0: 2750 + dependencies: 2751 + has-bigints: 1.1.0 2752 + 2753 + is-boolean-object@1.2.2: 2754 + dependencies: 2755 + call-bound: 1.0.4 2756 + has-tostringtag: 1.0.2 2757 + 2758 + is-callable@1.2.7: {} 2759 + 2033 2760 is-core-module@2.16.1: 2034 2761 dependencies: 2035 2762 hasown: 2.0.2 2036 2763 2764 + is-data-view@1.0.2: 2765 + dependencies: 2766 + call-bound: 1.0.4 2767 + get-intrinsic: 1.3.0 2768 + is-typed-array: 1.1.15 2769 + 2770 + is-date-object@1.1.0: 2771 + dependencies: 2772 + call-bound: 1.0.4 2773 + has-tostringtag: 1.0.2 2774 + 2775 + is-finalizationregistry@1.1.1: 2776 + dependencies: 2777 + call-bound: 1.0.4 2778 + 2779 + is-generator-function@1.1.2: 2780 + dependencies: 2781 + call-bound: 1.0.4 2782 + generator-function: 2.0.1 2783 + get-proto: 1.0.1 2784 + has-tostringtag: 1.0.2 2785 + safe-regex-test: 1.1.0 2786 + 2787 + is-map@2.0.3: {} 2788 + 2789 + is-negative-zero@2.0.3: {} 2790 + 2791 + is-number-object@1.1.1: 2792 + dependencies: 2793 + call-bound: 1.0.4 2794 + has-tostringtag: 1.0.2 2795 + 2037 2796 is-number@7.0.0: {} 2038 2797 2798 + is-regex@1.2.1: 2799 + dependencies: 2800 + call-bound: 1.0.4 2801 + gopd: 1.2.0 2802 + has-tostringtag: 1.0.2 2803 + hasown: 2.0.2 2804 + 2805 + is-set@2.0.3: {} 2806 + 2807 + is-shared-array-buffer@1.0.4: 2808 + dependencies: 2809 + call-bound: 1.0.4 2810 + 2811 + is-string@1.1.1: 2812 + dependencies: 2813 + call-bound: 1.0.4 2814 + has-tostringtag: 1.0.2 2815 + 2816 + is-symbol@1.1.1: 2817 + dependencies: 2818 + call-bound: 1.0.4 2819 + has-symbols: 1.1.0 2820 + safe-regex-test: 1.1.0 2821 + 2822 + is-typed-array@1.1.15: 2823 + dependencies: 2824 + which-typed-array: 1.1.19 2825 + 2826 + is-weakmap@2.0.2: {} 2827 + 2828 + is-weakref@1.1.1: 2829 + dependencies: 2830 + call-bound: 1.0.4 2831 + 2832 + is-weakset@2.0.4: 2833 + dependencies: 2834 + call-bound: 1.0.4 2835 + get-intrinsic: 1.3.0 2836 + 2837 + isarray@2.0.5: {} 2838 + 2839 + isexe@2.0.0: {} 2840 + 2039 2841 iso-datestring-validator@2.2.2: {} 2040 2842 2041 2843 jiti@2.6.1: {} ··· 2049 2851 js-yaml@4.1.1: 2050 2852 dependencies: 2051 2853 argparse: 2.0.1 2854 + 2855 + json-parse-better-errors@1.0.2: {} 2052 2856 2053 2857 json-parse-even-better-errors@2.3.1: {} 2054 2858 ··· 2139 2943 2140 2944 lines-and-columns@1.2.4: {} 2141 2945 2946 + load-json-file@4.0.0: 2947 + dependencies: 2948 + graceful-fs: 4.2.11 2949 + parse-json: 4.0.0 2950 + pify: 3.0.0 2951 + strip-bom: 3.0.0 2952 + 2142 2953 lodash.snakecase@4.1.1: {} 2143 2954 2144 2955 lodash@4.17.21: {} ··· 2149 2960 2150 2961 magic-bytes.js@1.12.1: {} 2151 2962 2963 + math-intrinsics@1.1.0: {} 2964 + 2965 + memorystream@0.3.1: {} 2966 + 2152 2967 micromatch@4.0.8: 2153 2968 dependencies: 2154 2969 braces: 3.0.3 ··· 2162 2977 2163 2978 multiformats@9.9.0: {} 2164 2979 2980 + nice-try@1.0.5: {} 2981 + 2165 2982 node-fetch-native@1.6.7: {} 2983 + 2984 + normalize-package-data@2.5.0: 2985 + dependencies: 2986 + hosted-git-info: 2.8.9 2987 + resolve: 1.22.11 2988 + semver: 5.7.2 2989 + validate-npm-package-license: 3.0.4 2990 + 2991 + npm-run-all@4.1.5: 2992 + dependencies: 2993 + ansi-styles: 3.2.1 2994 + chalk: 2.4.2 2995 + cross-spawn: 6.0.6 2996 + memorystream: 0.3.1 2997 + minimatch: 3.1.2 2998 + pidtree: 0.3.1 2999 + read-pkg: 3.0.0 3000 + shell-quote: 1.8.3 3001 + string.prototype.padend: 3.1.6 2166 3002 2167 3003 nypm@0.6.2: 2168 3004 dependencies: ··· 2172 3008 pkg-types: 2.3.0 2173 3009 tinyexec: 1.0.2 2174 3010 3011 + object-inspect@1.13.4: {} 3012 + 3013 + object-keys@1.1.1: {} 3014 + 3015 + object.assign@4.1.7: 3016 + dependencies: 3017 + call-bind: 1.0.8 3018 + call-bound: 1.0.4 3019 + define-properties: 1.2.1 3020 + es-object-atoms: 1.1.1 3021 + has-symbols: 1.1.0 3022 + object-keys: 1.1.1 3023 + 2175 3024 ofetch@1.5.1: 2176 3025 dependencies: 2177 3026 destr: 2.0.5 ··· 2186 3035 dependencies: 2187 3036 wrappy: 1.0.2 2188 3037 3038 + own-keys@1.0.1: 3039 + dependencies: 3040 + get-intrinsic: 1.3.0 3041 + object-keys: 1.1.1 3042 + safe-push-apply: 1.0.0 3043 + 2189 3044 oxfmt@0.20.0: 2190 3045 dependencies: 2191 3046 tinypool: 2.0.0 ··· 2214 3069 dependencies: 2215 3070 callsites: 3.1.0 2216 3071 3072 + parse-json@4.0.0: 3073 + dependencies: 3074 + error-ex: 1.3.4 3075 + json-parse-better-errors: 1.0.2 3076 + 2217 3077 parse-json@5.2.0: 2218 3078 dependencies: 2219 3079 '@babel/code-frame': 7.27.1 ··· 2223 3083 2224 3084 path-is-absolute@1.0.1: {} 2225 3085 3086 + path-key@2.0.1: {} 3087 + 2226 3088 path-parse@1.0.7: {} 2227 3089 3090 + path-type@3.0.0: 3091 + dependencies: 3092 + pify: 3.0.0 3093 + 2228 3094 pathe@2.0.3: {} 2229 3095 2230 3096 perfect-debounce@2.0.0: {} ··· 2267 3133 picocolors@1.1.1: {} 2268 3134 2269 3135 picomatch@2.3.1: {} 3136 + 3137 + pidtree@0.3.1: {} 3138 + 3139 + pify@3.0.0: {} 2270 3140 2271 3141 pino-abstract-transport@1.2.0: 2272 3142 dependencies: ··· 2343 3213 pathe: 2.0.3 2344 3214 2345 3215 pluralize@8.0.0: {} 3216 + 3217 + possible-typed-array-names@1.1.0: {} 2346 3218 2347 3219 postgres-array@2.0.0: {} 2348 3220 ··· 2372 3244 defu: 6.1.4 2373 3245 destr: 2.0.5 2374 3246 3247 + read-pkg@3.0.0: 3248 + dependencies: 3249 + load-json-file: 4.0.0 3250 + normalize-package-data: 2.5.0 3251 + path-type: 3.0.0 3252 + 2375 3253 readable-stream@4.7.0: 2376 3254 dependencies: 2377 3255 abort-controller: 3.0.0 ··· 2388 3266 dependencies: 2389 3267 resolve: 1.22.11 2390 3268 3269 + reflect.getprototypeof@1.0.10: 3270 + dependencies: 3271 + call-bind: 1.0.8 3272 + define-properties: 1.2.1 3273 + es-abstract: 1.24.1 3274 + es-errors: 1.3.0 3275 + es-object-atoms: 1.1.1 3276 + get-intrinsic: 1.3.0 3277 + get-proto: 1.0.1 3278 + which-builtin-type: 1.2.1 3279 + 3280 + regexp.prototype.flags@1.5.4: 3281 + dependencies: 3282 + call-bind: 1.0.8 3283 + define-properties: 1.2.1 3284 + es-errors: 1.3.0 3285 + get-proto: 1.0.1 3286 + gopd: 1.2.0 3287 + set-function-name: 2.0.2 3288 + 2391 3289 resolve-from@4.0.0: {} 2392 3290 2393 3291 resolve-pkg-maps@1.0.0: {} ··· 2398 3296 path-parse: 1.0.7 2399 3297 supports-preserve-symlinks-flag: 1.0.0 2400 3298 3299 + safe-array-concat@1.1.3: 3300 + dependencies: 3301 + call-bind: 1.0.8 3302 + call-bound: 1.0.4 3303 + get-intrinsic: 1.3.0 3304 + has-symbols: 1.1.0 3305 + isarray: 2.0.5 3306 + 2401 3307 safe-buffer@5.2.1: {} 2402 3308 3309 + safe-push-apply@1.0.0: 3310 + dependencies: 3311 + es-errors: 1.3.0 3312 + isarray: 2.0.5 3313 + 3314 + safe-regex-test@1.1.0: 3315 + dependencies: 3316 + call-bound: 1.0.4 3317 + es-errors: 1.3.0 3318 + is-regex: 1.2.1 3319 + 2403 3320 safe-stable-stringify@2.5.0: {} 2404 3321 2405 3322 secure-json-parse@4.1.0: {} 2406 3323 3324 + semver@5.7.2: {} 3325 + 3326 + set-function-length@1.2.2: 3327 + dependencies: 3328 + define-data-property: 1.1.4 3329 + es-errors: 1.3.0 3330 + function-bind: 1.1.2 3331 + get-intrinsic: 1.3.0 3332 + gopd: 1.2.0 3333 + has-property-descriptors: 1.0.2 3334 + 3335 + set-function-name@2.0.2: 3336 + dependencies: 3337 + define-data-property: 1.1.4 3338 + es-errors: 1.3.0 3339 + functions-have-names: 1.2.3 3340 + has-property-descriptors: 1.0.2 3341 + 3342 + set-proto@1.0.0: 3343 + dependencies: 3344 + dunder-proto: 1.0.1 3345 + es-errors: 1.3.0 3346 + es-object-atoms: 1.1.1 3347 + 3348 + shebang-command@1.2.0: 3349 + dependencies: 3350 + shebang-regex: 1.0.0 3351 + 3352 + shebang-regex@1.0.0: {} 3353 + 3354 + shell-quote@1.8.3: {} 3355 + 2407 3356 shelljs.exec@1.1.8: {} 2408 3357 2409 3358 shelljs@0.8.5: ··· 2411 3360 glob: 7.2.3 2412 3361 interpret: 1.4.0 2413 3362 rechoir: 0.6.2 3363 + 3364 + side-channel-list@1.0.0: 3365 + dependencies: 3366 + es-errors: 1.3.0 3367 + object-inspect: 1.13.4 3368 + 3369 + side-channel-map@1.0.1: 3370 + dependencies: 3371 + call-bound: 1.0.4 3372 + es-errors: 1.3.0 3373 + get-intrinsic: 1.3.0 3374 + object-inspect: 1.13.4 3375 + 3376 + side-channel-weakmap@1.0.2: 3377 + dependencies: 3378 + call-bound: 1.0.4 3379 + es-errors: 1.3.0 3380 + get-intrinsic: 1.3.0 3381 + object-inspect: 1.13.4 3382 + side-channel-map: 1.0.1 3383 + 3384 + side-channel@1.1.0: 3385 + dependencies: 3386 + es-errors: 1.3.0 3387 + object-inspect: 1.13.4 3388 + side-channel-list: 1.0.0 3389 + side-channel-map: 1.0.1 3390 + side-channel-weakmap: 1.0.2 2414 3391 2415 3392 sonic-boom@3.8.1: 2416 3393 dependencies: ··· 2420 3397 dependencies: 2421 3398 atomic-sleep: 1.0.0 2422 3399 3400 + spdx-correct@3.2.0: 3401 + dependencies: 3402 + spdx-expression-parse: 3.0.1 3403 + spdx-license-ids: 3.0.22 3404 + 3405 + spdx-exceptions@2.5.0: {} 3406 + 3407 + spdx-expression-parse@3.0.1: 3408 + dependencies: 3409 + spdx-exceptions: 2.5.0 3410 + spdx-license-ids: 3.0.22 3411 + 3412 + spdx-license-ids@3.0.22: {} 3413 + 2423 3414 split2@4.2.0: {} 2424 3415 2425 3416 std-env@3.10.0: {} 2426 3417 3418 + stop-iteration-iterator@1.1.0: 3419 + dependencies: 3420 + es-errors: 1.3.0 3421 + internal-slot: 1.1.0 3422 + 3423 + string.prototype.padend@3.1.6: 3424 + dependencies: 3425 + call-bind: 1.0.8 3426 + define-properties: 1.2.1 3427 + es-abstract: 1.24.1 3428 + es-object-atoms: 1.1.1 3429 + 3430 + string.prototype.trim@1.2.10: 3431 + dependencies: 3432 + call-bind: 1.0.8 3433 + call-bound: 1.0.4 3434 + define-data-property: 1.1.4 3435 + define-properties: 1.2.1 3436 + es-abstract: 1.24.1 3437 + es-object-atoms: 1.1.1 3438 + has-property-descriptors: 1.0.2 3439 + 3440 + string.prototype.trimend@1.0.9: 3441 + dependencies: 3442 + call-bind: 1.0.8 3443 + call-bound: 1.0.4 3444 + define-properties: 1.2.1 3445 + es-object-atoms: 1.1.1 3446 + 3447 + string.prototype.trimstart@1.0.8: 3448 + dependencies: 3449 + call-bind: 1.0.8 3450 + define-properties: 1.2.1 3451 + es-object-atoms: 1.1.1 3452 + 2427 3453 string_decoder@1.3.0: 2428 3454 dependencies: 2429 3455 safe-buffer: 5.2.1 3456 + 3457 + strip-bom@3.0.0: {} 2430 3458 2431 3459 strip-json-comments@5.0.3: {} 2432 3460 ··· 2473 3501 optionalDependencies: 2474 3502 fsevents: 2.3.3 2475 3503 3504 + typed-array-buffer@1.0.3: 3505 + dependencies: 3506 + call-bound: 1.0.4 3507 + es-errors: 1.3.0 3508 + is-typed-array: 1.1.15 3509 + 3510 + typed-array-byte-length@1.0.3: 3511 + dependencies: 3512 + call-bind: 1.0.8 3513 + for-each: 0.3.5 3514 + gopd: 1.2.0 3515 + has-proto: 1.2.0 3516 + is-typed-array: 1.1.15 3517 + 3518 + typed-array-byte-offset@1.0.4: 3519 + dependencies: 3520 + available-typed-arrays: 1.0.7 3521 + call-bind: 1.0.8 3522 + for-each: 0.3.5 3523 + gopd: 1.2.0 3524 + has-proto: 1.2.0 3525 + is-typed-array: 1.1.15 3526 + reflect.getprototypeof: 1.0.10 3527 + 3528 + typed-array-length@1.0.7: 3529 + dependencies: 3530 + call-bind: 1.0.8 3531 + for-each: 0.3.5 3532 + gopd: 1.2.0 3533 + is-typed-array: 1.1.15 3534 + possible-typed-array-names: 1.1.0 3535 + reflect.getprototypeof: 1.0.10 3536 + 2476 3537 typescript@5.9.2: {} 2477 3538 2478 3539 typescript@5.9.3: {} ··· 2483 3544 dependencies: 2484 3545 multiformats: 9.9.0 2485 3546 3547 + unbox-primitive@1.1.0: 3548 + dependencies: 3549 + call-bound: 1.0.4 3550 + has-bigints: 1.1.0 3551 + has-symbols: 1.1.0 3552 + which-boxed-primitive: 1.1.1 3553 + 2486 3554 undici-types@6.21.0: {} 2487 3555 2488 3556 undici-types@7.16.0: {} ··· 2490 3558 undici@6.21.3: {} 2491 3559 2492 3560 unicode-segmenter@0.14.4: {} 3561 + 3562 + validate-npm-package-license@3.0.4: 3563 + dependencies: 3564 + spdx-correct: 3.2.0 3565 + spdx-expression-parse: 3.0.1 3566 + 3567 + which-boxed-primitive@1.1.1: 3568 + dependencies: 3569 + is-bigint: 1.1.0 3570 + is-boolean-object: 1.2.2 3571 + is-number-object: 1.1.1 3572 + is-string: 1.1.1 3573 + is-symbol: 1.1.1 3574 + 3575 + which-builtin-type@1.2.1: 3576 + dependencies: 3577 + call-bound: 1.0.4 3578 + function.prototype.name: 1.1.8 3579 + has-tostringtag: 1.0.2 3580 + is-async-function: 2.1.1 3581 + is-date-object: 1.1.0 3582 + is-finalizationregistry: 1.1.1 3583 + is-generator-function: 1.1.2 3584 + is-regex: 1.2.1 3585 + is-weakref: 1.1.1 3586 + isarray: 2.0.5 3587 + which-boxed-primitive: 1.1.1 3588 + which-collection: 1.0.2 3589 + which-typed-array: 1.1.19 3590 + 3591 + which-collection@1.0.2: 3592 + dependencies: 3593 + is-map: 2.0.3 3594 + is-set: 2.0.3 3595 + is-weakmap: 2.0.2 3596 + is-weakset: 2.0.4 3597 + 3598 + which-typed-array@1.1.19: 3599 + dependencies: 3600 + available-typed-arrays: 1.0.7 3601 + call-bind: 1.0.8 3602 + call-bound: 1.0.4 3603 + for-each: 0.3.5 3604 + get-proto: 1.0.1 3605 + gopd: 1.2.0 3606 + has-tostringtag: 1.0.2 3607 + 3608 + which@1.3.1: 3609 + dependencies: 3610 + isexe: 2.0.0 2493 3611 2494 3612 wrappy@1.0.2: {} 2495 3613