diff --git a/.cspell.json b/.cspell.json index cf5a4b1..05b52fe 100644 --- a/.cspell.json +++ b/.cspell.json @@ -30,6 +30,7 @@ "Libsodium", "ciphertext", "tweetnacl", - "typeguards" + "typeguards", + "Numberish" ] } diff --git a/.env.example b/.env.example index 77ecc40..5083073 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ X25519_PRIVATE_KEY= NFT_MINTER_PRIVATE_KEY= SUPABASE_URL= -SUPABASE_ANON_KEY= \ No newline at end of file +SUPABASE_KEY= diff --git a/.eslintrc b/.eslintrc index 5996f04..0251eb5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -6,7 +6,7 @@ }, "plugins": ["@typescript-eslint", "sonarjs"], "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:sonarjs/recommended"], - "ignorePatterns": ["**/*.js"], + "ignorePatterns": ["**/*.js", "src/adapters/supabase/types/database.ts"], "rules": { "prefer-arrow-callback": ["warn", { "allowNamedFunctions": true }], "func-style": ["warn", "declaration", { "allowArrowFunctions": false }], diff --git a/.github/workflows/jest-testing.yml b/.github/workflows/jest-testing.yml index e86b3bc..1641a4d 100644 --- a/.github/workflows/jest-testing.yml +++ b/.github/workflows/jest-testing.yml @@ -1,7 +1,7 @@ name: Run Jest testing suite on: workflow_dispatch: - pull_request_target: + pull_request: types: [opened, synchronize] env: diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml new file mode 100644 index 0000000..7a94477 --- /dev/null +++ b/.github/workflows/publish-package.yml @@ -0,0 +1,28 @@ +name: Publish Package + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: google-github-actions/release-please-action@v4 + with: + release-type: node + package-name: "@ubiquibot/permit-generation" + default-branch: main + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20.10.0' + registry-url: https://registry.npmjs.org/ + - run: | + yarn install --immutable --immutable-cache --check-cache + yarn pack + yarn publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 3bd776e..10bea97 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ node_modules .env static/dist /coverage -junit.xml \ No newline at end of file +junit.xml +dist diff --git a/knip.ts b/knip.ts index 8588dea..4712f46 100644 --- a/knip.ts +++ b/knip.ts @@ -1,9 +1,10 @@ import type { KnipConfig } from "knip"; const config: KnipConfig = { - entry: ["build/index.ts"], + entry: ["src/main.ts"], project: ["src/**/*.ts"], ignore: [], + ignoreBinaries: ["publish"], ignoreExportsUsedInFile: true, ignoreDependencies: ["ts-node"], jest: { diff --git a/package.json b/package.json index 13724db..a8947e0 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,7 @@ { "name": "@ubiquibot/permit-generation", - "version": "1.0.0", - "description": "Template repository with TypeScript support.", - "main": "src/index.ts", + "version": "1.0.2", + "description": "ECR20 / ECR721 permit generation for automated payments.", "author": "Ubiquity DAO", "license": "MIT", "engines": { @@ -16,7 +15,8 @@ "knip": "knip", "knip-ci": "knip --no-exit-code --reporter json", "prepare": "husky install", - "test": "jest" + "test": "jest", + "build": "rollup -c" }, "keywords": [ "typescript", @@ -31,7 +31,7 @@ "@octokit/rest": "^20.0.2", "@octokit/webhooks": "^13.1.0", "@sinclair/typebox": "^0.32.5", - "@supabase/supabase-js": "^2.39.7", + "@supabase/supabase-js": "2.42.0", "@uniswap/permit2-sdk": "^1.2.0", "dotenv": "^16.4.4", "ethers": "6.11.1", @@ -43,6 +43,13 @@ "@cspell/dict-node": "^4.0.3", "@cspell/dict-software-terms": "^3.3.18", "@cspell/dict-typescript": "^3.1.2", + "@jest/globals": "29.7.0", + "@jest/types": "29.6.3", + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-json": "6.1.0", + "@rollup/plugin-node-resolve": "15.2.3", + "@rollup/plugin-terser": "0.4.4", + "@rollup/plugin-yaml": "4.1.2", "@types/libsodium-wrappers": "^0.7.8", "@types/node": "^20.11.19", "@typescript-eslint/eslint-plugin": "^7.0.1", @@ -57,6 +64,9 @@ "lint-staged": "^15.2.2", "npm-run-all": "^4.1.5", "prettier": "^3.2.5", + "rollup": "4.14.0", + "rollup-plugin-dts-bundle-generator": "1.4.0", + "rollup-plugin-typescript2": "0.36.0", "ts-jest": "29.1.2", "ts-node": "10.9.2", "tsx": "^4.7.1", @@ -75,5 +85,13 @@ "extends": [ "@commitlint/config-conventional" ] - } + }, + "files": [ + "dist/*", + "README.md", + "package.json" + ], + "module": "dist/index.esm.js", + "main": "dist/index.js", + "typings": "dist/index.d.ts" } diff --git a/rollup.config.mjs b/rollup.config.mjs new file mode 100644 index 0000000..6fb6356 --- /dev/null +++ b/rollup.config.mjs @@ -0,0 +1,16 @@ +import typescript from "rollup-plugin-typescript2"; +import yaml from "@rollup/plugin-yaml"; +import { generateDtsBundle } from "rollup-plugin-dts-bundle-generator"; +import nodeResolve from "@rollup/plugin-node-resolve"; +import commonjs from "@rollup/plugin-commonjs"; +import json from "@rollup/plugin-json"; +import terser from "@rollup/plugin-terser"; + +export default { + input: "src/index.ts", + output: { + dir: "dist", + format: "cjs", + }, + plugins: [nodeResolve(), commonjs(), typescript(), yaml(), json(), generateDtsBundle(), terser()], +}; diff --git a/src/adapters/supabase/helpers/user.ts b/src/adapters/supabase/helpers/user.ts index 817ac25..54bf03f 100644 --- a/src/adapters/supabase/helpers/user.ts +++ b/src/adapters/supabase/helpers/user.ts @@ -8,41 +8,30 @@ export class User extends Super { super(supabase, context); } - async getUsernameById(userId: number) { - const { data, error } = await this.supabase.from("users").select("username").eq("user_id", userId).single(); + async getUserById(userId: number) { + const { data, error } = await this.supabase.from("users").select("*").eq("id", userId).single(); if (error) { console.error(FAILED_TO_GET_USER, { userId, error }); throw error; } - console.log(SUCCESSFULLY_FETCHED_USER, { userId, username: data?.username }); - return data?.username; - } - - async getUserIdByUsername(username: string) { - const { data, error } = await this.supabase.from("users").select("user_id").eq("username", username).single(); - if (error) { - console.error(FAILED_TO_GET_USER, { username, error }); - throw error; - } - - console.log(SUCCESSFULLY_FETCHED_USER, { username, userId: data?.user_id }); - return data?.user_id; + console.log(SUCCESSFULLY_FETCHED_USER, { userId, ...data }); + return data; } async getUserIdByWallet(wallet: string) { - const { data, error } = await this.supabase.from("wallets").select("user_id").eq("address", wallet).single(); + const { data, error } = await this.supabase.from("wallets").select("id").eq("address", wallet).single(); if (error) { console.error(FAILED_TO_GET_USER, { wallet, error }); throw error; } - console.log(SUCCESSFULLY_FETCHED_USER, { wallet, userId: data?.user_id }); - return data?.user_id; + console.log(SUCCESSFULLY_FETCHED_USER, { wallet, userId: data?.id }); + return data?.id.toString(); } async upsertUser(userId: number, username: string) { - const { error } = await this.supabase.from("users").upsert({ user_id: userId, username }).select(); + const { error } = await this.supabase.from("users").upsert({ id: userId, username }).select(); if (error) { console.error("Failed to upsert user", { userId, username, error }); throw error; diff --git a/src/adapters/supabase/helpers/wallet.ts b/src/adapters/supabase/helpers/wallet.ts index a915e9a..f94af08 100644 --- a/src/adapters/supabase/helpers/wallet.ts +++ b/src/adapters/supabase/helpers/wallet.ts @@ -9,49 +9,31 @@ export class Wallet extends Super { } async getWalletByUserId(userId: number) { - const { data, error } = await this.supabase.from("wallets").select("address").eq("user_id", userId).single(); + const { data, error } = await this.supabase.from("users").select("wallets(*)").eq("id", userId).single(); if (error) { console.error("Failed to get wallet", { userId, error }); throw error; } - console.info("Successfully fetched wallet", { userId, address: data.address }); - return data.address; + console.info("Successfully fetched wallet", { userId, address: data.wallets?.address }); + return data.wallets?.address; } - async getWalletByUsername(username: string) { - const { data, error } = await this.supabase.from("users").select("id").eq("username", username).single(); - if (error) { - console.error("Failed to get user", { username, error }); - throw error; - } - - const userId = data?.id; - - if (!userId) { - console.error("Failed to get user", { username }); - throw new Error("User not found"); - } - - const { data: walletData, error: walletError } = await this.supabase.from("wallets").select("address").eq("user_id", userId).single(); + async upsertWallet(userId: number, address: string) { + const { error: walletError, data } = await this.supabase.from("wallets").upsert([{ address }]).select().single(); if (walletError) { - console.error("Failed to get wallet", { userId, error }); + console.error("Failed to upsert wallet", { userId, address, walletError }); throw walletError; } - console.info("Successfully fetched wallet", { userId, address: walletData?.address }); - - return walletData?.address as `0x${string}` | undefined; - } + const { error: userError } = await this.supabase.from("users").upsert([{ id: userId, wallet_id: data.id }]); - async upsertWallet(userId: number, address: string) { - const { error } = await this.supabase.from("wallets").upsert([{ user_id: userId.toString(), address }]); - if (error) { - console.error("Failed to upsert wallet", { userId, address, error }); - throw error; + if (userError) { + console.error("Failed to upsert user with new wallet", { userId, address, userError }); + throw userError; } - console.info("Successfully upserted wallet", { userId, address }); + console.info("Successfully upsert wallet", { userId, address }); } } diff --git a/src/adapters/supabase/types/database.ts b/src/adapters/supabase/types/database.ts index 2f63668..39d0b33 100644 --- a/src/adapters/supabase/types/database.ts +++ b/src/adapters/supabase/types/database.ts @@ -1,62 +1,847 @@ -/* eslint-disable @typescript-eslint/naming-convention */ - export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[]; export type Database = { + graphql_public: { + Tables: { + [_ in never]: never; + }; + Views: { + [_ in never]: never; + }; + Functions: { + graphql: { + Args: { + operationName?: string; + query?: string; + variables?: Json; + extensions?: Json; + }; + Returns: Json; + }; + }; + Enums: { + [_ in never]: never; + }; + CompositeTypes: { + [_ in never]: never; + }; + }; public: { Tables: { + access: { + Row: { + created: string; + id: number; + labels: Json | null; + location_id: number | null; + multiplier: number; + multiplier_reason: string | null; + updated: string | null; + user_id: number; + }; + Insert: { + created?: string; + id?: number; + labels?: Json | null; + location_id?: number | null; + multiplier?: number; + multiplier_reason?: string | null; + updated?: string | null; + user_id: number; + }; + Update: { + created?: string; + id?: number; + labels?: Json | null; + location_id?: number | null; + multiplier?: number; + multiplier_reason?: string | null; + updated?: string | null; + user_id?: number; + }; + Relationships: [ + { + foreignKeyName: "access_user_id_fkey"; + columns: ["user_id"]; + isOneToOne: false; + referencedRelation: "users"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "fk_access_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "fk_access_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + ]; + }; + credits: { + Row: { + amount: number; + created: string; + id: number; + location_id: number | null; + permit_id: number | null; + updated: string | null; + }; + Insert: { + amount: number; + created?: string; + id?: number; + location_id?: number | null; + permit_id?: number | null; + updated?: string | null; + }; + Update: { + amount?: number; + created?: string; + id?: number; + location_id?: number | null; + permit_id?: number | null; + updated?: string | null; + }; + Relationships: [ + { + foreignKeyName: "credits_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "credits_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "credits_permit_id_fkey"; + columns: ["permit_id"]; + isOneToOne: false; + referencedRelation: "permits"; + referencedColumns: ["id"]; + }, + ]; + }; + debits: { + Row: { + amount: number; + created: string; + id: number; + location_id: number | null; + token_id: number | null; + updated: string | null; + }; + Insert: { + amount: number; + created?: string; + id?: number; + location_id?: number | null; + token_id?: number | null; + updated?: string | null; + }; + Update: { + amount?: number; + created?: string; + id?: number; + location_id?: number | null; + token_id?: number | null; + updated?: string | null; + }; + Relationships: [ + { + foreignKeyName: "debits_token_id_fkey"; + columns: ["token_id"]; + isOneToOne: false; + referencedRelation: "tokens"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "fk_debits_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "fk_debits_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + ]; + }; + labels: { + Row: { + authorized: boolean | null; + created: string; + id: number; + label_from: string | null; + label_to: string | null; + location_id: number | null; + updated: string | null; + }; + Insert: { + authorized?: boolean | null; + created?: string; + id?: number; + label_from?: string | null; + label_to?: string | null; + location_id?: number | null; + updated?: string | null; + }; + Update: { + authorized?: boolean | null; + created?: string; + id?: number; + label_from?: string | null; + label_to?: string | null; + location_id?: number | null; + updated?: string | null; + }; + Relationships: [ + { + foreignKeyName: "labels_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "labels_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + ]; + }; + locations: { + Row: { + comment_id: number | null; + created: string; + id: number; + issue_id: number | null; + node_id: string | null; + node_type: string | null; + node_url: string | null; + organization_id: number | null; + repository_id: number | null; + updated: string | null; + user_id: number | null; + }; + Insert: { + comment_id?: number | null; + created?: string; + id?: number; + issue_id?: number | null; + node_id?: string | null; + node_type?: string | null; + node_url?: string | null; + organization_id?: number | null; + repository_id?: number | null; + updated?: string | null; + user_id?: number | null; + }; + Update: { + comment_id?: number | null; + created?: string; + id?: number; + issue_id?: number | null; + node_id?: string | null; + node_type?: string | null; + node_url?: string | null; + organization_id?: number | null; + repository_id?: number | null; + updated?: string | null; + user_id?: number | null; + }; + Relationships: []; + }; + logs: { + Row: { + created: string; + id: number; + level: string | null; + location_id: number | null; + log: string; + metadata: Json | null; + updated: string | null; + }; + Insert: { + created?: string; + id?: number; + level?: string | null; + location_id?: number | null; + log: string; + metadata?: Json | null; + updated?: string | null; + }; + Update: { + created?: string; + id?: number; + level?: string | null; + location_id?: number | null; + log?: string; + metadata?: Json | null; + updated?: string | null; + }; + Relationships: [ + { + foreignKeyName: "fk_logs_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "fk_logs_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + ]; + }; + partners: { + Row: { + created: string; + id: number; + location_id: number | null; + updated: string | null; + wallet_id: number | null; + }; + Insert: { + created?: string; + id?: number; + location_id?: number | null; + updated?: string | null; + wallet_id?: number | null; + }; + Update: { + created?: string; + id?: number; + location_id?: number | null; + updated?: string | null; + wallet_id?: number | null; + }; + Relationships: [ + { + foreignKeyName: "fk_partners_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "fk_partners_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "partners_wallet_id_fkey"; + columns: ["wallet_id"]; + isOneToOne: true; + referencedRelation: "wallets"; + referencedColumns: ["id"]; + }, + ]; + }; + permits: { + Row: { + amount: string; + beneficiary_id: number; + created: string; + deadline: string; + id: number; + location_id: number | null; + nonce: string; + partner_id: number | null; + signature: string; + token_id: number | null; + transaction: string | null; + updated: string | null; + }; + Insert: { + amount: string; + beneficiary_id: number; + created?: string; + deadline: string; + id?: number; + location_id?: number | null; + nonce: string; + partner_id?: number | null; + signature: string; + token_id?: number | null; + transaction?: string | null; + updated?: string | null; + }; + Update: { + amount?: string; + beneficiary_id?: number; + created?: string; + deadline?: string; + id?: number; + location_id?: number | null; + nonce?: string; + partner_id?: number | null; + signature?: string; + token_id?: number | null; + transaction?: string | null; + updated?: string | null; + }; + Relationships: [ + { + foreignKeyName: "fk_permits_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "fk_permits_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "permits_beneficiary_id_fkey"; + columns: ["beneficiary_id"]; + isOneToOne: false; + referencedRelation: "users"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "permits_partner_id_fkey"; + columns: ["partner_id"]; + isOneToOne: false; + referencedRelation: "partners"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "permits_token_fkey"; + columns: ["token_id"]; + isOneToOne: false; + referencedRelation: "tokens"; + referencedColumns: ["id"]; + }, + ]; + }; + settlements: { + Row: { + created: string; + credit_id: number | null; + debit_id: number | null; + id: number; + location_id: number | null; + updated: string | null; + user_id: number; + }; + Insert: { + created?: string; + credit_id?: number | null; + debit_id?: number | null; + id?: number; + location_id?: number | null; + updated?: string | null; + user_id: number; + }; + Update: { + created?: string; + credit_id?: number | null; + debit_id?: number | null; + id?: number; + location_id?: number | null; + updated?: string | null; + user_id?: number; + }; + Relationships: [ + { + foreignKeyName: "fk_settlements_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "fk_settlements_location"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "settlements_credit_id_fkey"; + columns: ["credit_id"]; + isOneToOne: false; + referencedRelation: "credits"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "settlements_debit_id_fkey"; + columns: ["debit_id"]; + isOneToOne: false; + referencedRelation: "debits"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "settlements_user_id_fkey"; + columns: ["user_id"]; + isOneToOne: false; + referencedRelation: "users"; + referencedColumns: ["id"]; + }, + ]; + }; + tokens: { + Row: { + address: string; + created: string; + id: number; + location_id: number | null; + network: number; + updated: string | null; + }; + Insert: { + address: string; + created?: string; + id?: number; + location_id?: number | null; + network?: number; + updated?: string | null; + }; + Update: { + address?: string; + created?: string; + id?: number; + location_id?: number | null; + network?: number; + updated?: string | null; + }; + Relationships: [ + { + foreignKeyName: "tokens_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "tokens_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + ]; + }; users: { Row: { + created: string; + id: number; + location_id: number | null; + updated: string | null; + wallet_id: number | null; + }; + Insert: { + created?: string; + id: number; + location_id?: number | null; + updated?: string | null; + wallet_id?: number | null; + }; + Update: { + created?: string; + id?: number; + location_id?: number | null; + updated?: string | null; + wallet_id?: number | null; + }; + Relationships: [ + { + foreignKeyName: "users_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "users_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "users_wallet_id_fkey"; + columns: ["wallet_id"]; + isOneToOne: false; + referencedRelation: "wallets"; + referencedColumns: ["id"]; + }, + ]; + }; + wallets: { + Row: { + address: string | null; + created: string; + id: number; + location_id: number | null; + updated: string | null; + }; + Insert: { + address?: string | null; + created?: string; + id?: number; + location_id?: number | null; + updated?: string | null; + }; + Update: { + address?: string | null; + created?: string; + id?: number; + location_id?: number | null; + updated?: string | null; + }; + Relationships: [ + { + foreignKeyName: "wallets_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "issues_view"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "wallets_location_id_fkey"; + columns: ["location_id"]; + isOneToOne: false; + referencedRelation: "locations"; + referencedColumns: ["id"]; + }, + ]; + }; + }; + Views: { + issues_view: { + Row: { + comment_id: number | null; + created: string | null; + id: number | null; + issue_id: number | null; + node_id: string | null; + node_type: string | null; + node_url: string | null; + organization_id: number | null; + repository_id: number | null; + updated: string | null; + user_id: number | null; + }; + Relationships: []; + }; + }; + Functions: { + insert_with_exception_handling: { + Args: Record; + Returns: undefined; + }; + read_secret: { + Args: { + secret_name: string; + }; + Returns: string; + }; + }; + Enums: { + github_node_type: + | "App" + | "Bot" + | "CheckRun" + | "CheckSuite" + | "ClosedEvent" + | "CodeOfConduct" + | "Commit" + | "CommitComment" + | "CommitContributionsByRepository" + | "ContributingGuidelines" + | "ConvertToDraftEvent" + | "CreatedCommitContribution" + | "CreatedIssueContribution" + | "CreatedPullRequestContribution" + | "CreatedPullRequestReviewContribution" + | "CreatedRepositoryContribution" + | "CrossReferencedEvent" + | "Discussion" + | "DiscussionComment" + | "Enterprise" + | "EnterpriseUserAccount" + | "FundingLink" + | "Gist" + | "Issue" + | "IssueComment" + | "JoinedGitHubContribution" + | "Label" + | "License" + | "Mannequin" + | "MarketplaceCategory" + | "MarketplaceListing" + | "MergeQueue" + | "MergedEvent" + | "MigrationSource" + | "Milestone" + | "Organization" + | "PackageFile" + | "Project" + | "ProjectCard" + | "ProjectColumn" + | "ProjectV2" + | "PullRequest" + | "PullRequestCommit" + | "PullRequestReview" + | "PullRequestReviewComment" + | "ReadyForReviewEvent" + | "Release" + | "ReleaseAsset" + | "Repository" + | "RepositoryContactLink" + | "RepositoryTopic" + | "RestrictedContribution" + | "ReviewDismissedEvent" + | "SecurityAdvisoryReference" + | "SocialAccount" + | "SponsorsListing" + | "Team" + | "TeamDiscussion" + | "TeamDiscussionComment" + | "User" + | "Workflow" + | "WorkflowRun" + | "WorkflowRunFile"; + }; + CompositeTypes: { + [_ in never]: never; + }; + }; + storage: { + Tables: { + buckets: { + Row: { + allowed_mime_types: string[] | null; + avif_autodetection: boolean | null; created_at: string | null; + file_size_limit: number | null; id: string; + name: string; + owner: string | null; + owner_id: string | null; + public: boolean | null; updated_at: string | null; - user_id: number; - username: string; }; Insert: { + allowed_mime_types?: string[] | null; + avif_autodetection?: boolean | null; created_at?: string | null; - id?: string; + file_size_limit?: number | null; + id: string; + name: string; + owner?: string | null; + owner_id?: string | null; + public?: boolean | null; updated_at?: string | null; - user_id: number; - username: string; }; Update: { + allowed_mime_types?: string[] | null; + avif_autodetection?: boolean | null; created_at?: string | null; + file_size_limit?: number | null; id?: string; + name?: string; + owner?: string | null; + owner_id?: string | null; + public?: boolean | null; updated_at?: string | null; - user_id?: number; - username?: string; }; Relationships: []; }; - wallets: { + migrations: { Row: { - address: string; + executed_at: string | null; + hash: string; + id: number; + name: string; + }; + Insert: { + executed_at?: string | null; + hash: string; + id: number; + name: string; + }; + Update: { + executed_at?: string | null; + hash?: string; + id?: number; + name?: string; + }; + Relationships: []; + }; + objects: { + Row: { + bucket_id: string | null; created_at: string | null; id: string; + last_accessed_at: string | null; + metadata: Json | null; + name: string | null; + owner: string | null; + owner_id: string | null; + path_tokens: string[] | null; updated_at: string | null; - user_id: string; + version: string | null; }; Insert: { - address: string; + bucket_id?: string | null; created_at?: string | null; id?: string; + last_accessed_at?: string | null; + metadata?: Json | null; + name?: string | null; + owner?: string | null; + owner_id?: string | null; + path_tokens?: string[] | null; updated_at?: string | null; - user_id: string; + version?: string | null; }; Update: { - address?: string; + bucket_id?: string | null; created_at?: string | null; id?: string; + last_accessed_at?: string | null; + metadata?: Json | null; + name?: string | null; + owner?: string | null; + owner_id?: string | null; + path_tokens?: string[] | null; updated_at?: string | null; - user_id?: string; + version?: string | null; }; Relationships: [ { - foreignKeyName: "wallets_user_id_fkey"; - columns: ["user_id"]; + foreignKeyName: "objects_bucketId_fkey"; + columns: ["bucket_id"]; isOneToOne: false; - referencedRelation: "users"; + referencedRelation: "buckets"; referencedColumns: ["id"]; }, ]; @@ -66,7 +851,60 @@ export type Database = { [_ in never]: never; }; Functions: { - [_ in never]: never; + can_insert_object: { + Args: { + bucketid: string; + name: string; + owner: string; + metadata: Json; + }; + Returns: undefined; + }; + extension: { + Args: { + name: string; + }; + Returns: string; + }; + filename: { + Args: { + name: string; + }; + Returns: string; + }; + foldername: { + Args: { + name: string; + }; + Returns: string[]; + }; + get_size_by_bucket: { + Args: Record; + Returns: { + size: number; + bucket_id: string; + }[]; + }; + search: { + Args: { + prefix: string; + bucketname: string; + limits?: number; + levels?: number; + offsets?: number; + search?: string; + sortcolumn?: string; + sortorder?: string; + }; + Returns: { + name: string; + id: string; + updated_at: string; + created_at: string; + last_accessed_at: string; + metadata: Json; + }[]; + }; }; Enums: { [_ in never]: never; diff --git a/src/generate-permits-from-context.ts b/src/generate-permits-from-context.ts new file mode 100644 index 0000000..b4918ff --- /dev/null +++ b/src/generate-permits-from-context.ts @@ -0,0 +1,104 @@ +import * as github from "@actions/github"; +import { Octokit } from "@octokit/rest"; +import { Value } from "@sinclair/typebox/value"; +import { createClient } from "@supabase/supabase-js"; +import { createAdapters } from "./adapters"; +import { Database } from "./adapters/supabase/types/database"; +import { generatePayoutPermit } from "./handlers"; +import { registerWallet } from "./handlers/register-wallet"; +import { Context } from "./types/context"; +import { envSchema } from "./types/env"; +import { permitGenerationSettingsSchema, PluginInputs } from "./types/plugin-input"; + +/** + * Generates all the permits based on the currently populated context. + */ +export async function generatePermitsFromContext() { + const webhookPayload = github.context.payload.inputs; + + const env = Value.Decode(envSchema, process.env); + const settings = Value.Decode(permitGenerationSettingsSchema, JSON.parse(webhookPayload.settings)); + + const inputs: PluginInputs = { + stateId: webhookPayload.stateId, + eventName: webhookPayload.eventName, + eventPayload: JSON.parse(webhookPayload.eventPayload), + settings: settings, + authToken: webhookPayload.authToken, + ref: webhookPayload.ref, + }; + const octokit = new Octokit({ auth: inputs.authToken }); + const supabaseClient = createClient(env.SUPABASE_URL, env.SUPABASE_KEY); + + const context: Context = { + eventName: inputs.eventName, + payload: inputs.eventPayload, + config: inputs.settings, + octokit, + env, + logger: { + debug(message: unknown, ...optionalParams: unknown[]) { + console.debug(message, ...optionalParams); + }, + info(message: unknown, ...optionalParams: unknown[]) { + console.log(message, ...optionalParams); + }, + warn(message: unknown, ...optionalParams: unknown[]) { + console.warn(message, ...optionalParams); + }, + error(message: unknown, ...optionalParams: unknown[]) { + console.error(message, ...optionalParams); + }, + fatal(message: unknown, ...optionalParams: unknown[]) { + console.error(message, ...optionalParams); + }, + }, + adapters: {} as ReturnType, + }; + + context.adapters = createAdapters(supabaseClient, context); + + if (context.eventName === "issue_comment.created") { + await handleSlashCommands(context, octokit); + } else { + const permits = await generatePayoutPermit(context, settings.permitRequests); + await returnDataToKernel(env.GITHUB_TOKEN, inputs.stateId, permits); + return JSON.stringify(permits); + } + + return null; +} + +async function returnDataToKernel(repoToken: string, stateId: string, output: object) { + const octokit = new Octokit({ auth: repoToken }); + await octokit.repos.createDispatchEvent({ + owner: github.context.repo.owner, + repo: github.context.repo.repo, + event_type: "return_data_to_ubiquibot_kernel", + client_payload: { + state_id: stateId, + output: JSON.stringify(output), + }, + }); +} + +async function handleSlashCommands(context: Context, octokit: Octokit) { + const payload = context.payload as Context<"issue_comment.created">["payload"]; + const body = payload.comment.body; + + const registrationRegex = /\/wallet (0x[a-fA-F0-9]{40})/g; + const matches = body.match(registrationRegex); + + if (matches) { + const address = matches[0]; + // try registering wallet, if it fails, notify the user + if (!(await registerWallet(context, address))) { + await octokit.issues.createComment({ + owner: github.context.repo.owner, + repo: github.context.repo.repo, + issue_number: payload.issue.number, + body: `Failed to register wallet: ${address}`, + }); + } + } +} diff --git a/src/handlers/encode-decode.ts b/src/handlers/encode-decode.ts new file mode 100644 index 0000000..fad6ec4 --- /dev/null +++ b/src/handlers/encode-decode.ts @@ -0,0 +1,107 @@ +import { Permit, TokenType } from "../types"; +import { RewardPermit } from "./permit-type"; + +/** + * Returns a base64 encoded string containing all the permit data + */ +export function encodePermits(permits: Permit[]) { + const permitsDto = permits + .map((permit) => { + if (permit.tokenType === TokenType.ERC20) { + return { + type: "erc20-permit", + permit: { + permitted: { + token: permit.tokenAddress, + amount: permit.amount, + }, + nonce: permit.nonce, + deadline: permit.deadline, + }, + transferDetails: { + to: permit.beneficiary, + requestedAmount: permit.amount, + }, + owner: permit.owner, + signature: permit.signature, + networkId: permit.networkId, + }; + } else { + if (permit.erc721Request) { + return { + type: "erc721-permit", + permit: { + permitted: { + token: permit.tokenAddress, + amount: permit.amount, + }, + nonce: permit.nonce, + deadline: permit.deadline, + }, + transferDetails: { + to: permit.beneficiary, + requestedAmount: permit.amount, + }, + owner: permit.owner, + signature: permit.signature, + networkId: permit.networkId, + nftMetadata: permit.erc721Request.metadata, + request: { + beneficiary: permit.beneficiary, + deadline: permit.deadline, + keys: permit.erc721Request?.keys, + nonce: permit.nonce, + values: permit.erc721Request?.values, + }, + }; + } else { + return null; + } + } + }) + .filter((o) => o) as RewardPermit[]; + return Buffer.from(JSON.stringify(permitsDto)).toString("base64"); +} + +export function decodePermits(base64: string) { + const decoded = atob(base64); + const objs: Array = JSON.parse(decoded); + const result: Permit[] = []; + for (const obj of objs) { + const tokenType = obj.type === "erc20-permit" ? TokenType.ERC20 : TokenType.ERC721; + if (tokenType === TokenType.ERC721) { + result.push({ + amount: obj.permit.permitted.amount as "0" | "1", + beneficiary: obj.transferDetails.to, + deadline: obj.permit.deadline, + networkId: obj.networkId, + nonce: obj.permit.nonce, + owner: obj.owner, + signature: obj.signature, + tokenAddress: obj.permit.permitted.token, + tokenType, + ...(obj.type === "erc721-permit" && + obj.nftMetadata && { + erc721Request: { + metadata: obj.nftMetadata, + keys: obj.request?.keys ?? [], + values: obj.request?.values ?? [], + }, + }), + }); + } else { + result.push({ + amount: obj.permit.permitted.amount, + beneficiary: obj.transferDetails.to, + deadline: obj.permit.deadline, + networkId: obj.networkId, + nonce: obj.permit.nonce, + owner: obj.owner, + signature: obj.signature, + tokenAddress: obj.permit.permitted.token, + tokenType, + }); + } + } + return result; +} diff --git a/src/handlers/generate-erc20-permit.ts b/src/handlers/generate-erc20-permit.ts index bddee04..e88ee9f 100644 --- a/src/handlers/generate-erc20-permit.ts +++ b/src/handlers/generate-erc20-permit.ts @@ -1,41 +1,73 @@ import { PERMIT2_ADDRESS, PermitTransferFrom, SignatureTransfer } from "@uniswap/permit2-sdk"; import { ethers, keccak256, MaxInt256, parseUnits, toUtf8Bytes } from "ethers"; -import { Context } from "../types/context"; -import { Permit } from "../types/permits"; +import { Context, Logger } from "../types/context"; +import { Permit, TokenType } from "../types"; import { decryptKeys } from "../utils/keys"; import { getPayoutConfigByNetworkId } from "../utils/payoutConfigByNetworkId"; -export async function generateErc20PermitSignature(context: Context, username: string, amount: number): Promise { - const config = context.config; - const logger = context.logger; - const { evmNetworkId, evmPrivateEncrypted } = config; - const { user, wallet } = context.adapters.supabase; +export interface Payload { + evmNetworkId: number; + evmPrivateEncrypted: string; + walletAddress: string; + issueId: number; + logger: Logger; + userId: number; +} + +export async function generateErc20PermitSignature(payload: Payload, username: string, amount: number): Promise; +export async function generateErc20PermitSignature(context: Context, username: string, amount: number): Promise; +export async function generateErc20PermitSignature(contextOrPayload: Context | Payload, username: string, amount: number): Promise { + let _logger: Logger; + const _username = username; + let _walletAddress: string | null | undefined; + let _issueId: number; + let _evmNetworkId: number; + let _evmPrivateEncrypted: string; + let _userId: number; - const userId = await user.getUserIdByUsername(username); - const walletAddress = await wallet.getWalletByUserId(userId); - let issueId: string; - if ("issue" in context.payload) { - issueId = context.payload.issue.id.toString(); - } else if ("pull_request" in context.payload) { - issueId = context.payload.pull_request.id.toString(); + if ("issueId" in contextOrPayload) { + _logger = contextOrPayload.logger as Logger; + _walletAddress = contextOrPayload.walletAddress; + _evmNetworkId = contextOrPayload.evmNetworkId; + _evmPrivateEncrypted = contextOrPayload.evmPrivateEncrypted; + _issueId = contextOrPayload.issueId; + _userId = contextOrPayload.userId; } else { - throw new Error("Issue Id is missing"); + const config = contextOrPayload.config; + _logger = contextOrPayload.logger; + const { evmNetworkId, evmPrivateEncrypted } = config; + const { data: userData } = await contextOrPayload.octokit.users.getByUsername({ username: _username }); + if (!userData) { + throw new Error(`GitHub user was not found for id ${_username}`); + } + _userId = userData.id; + const { wallet } = contextOrPayload.adapters.supabase; + _walletAddress = await wallet.getWalletByUserId(_userId); + _evmNetworkId = evmNetworkId; + _evmPrivateEncrypted = evmPrivateEncrypted; + if ("issue" in contextOrPayload.payload) { + _issueId = contextOrPayload.payload.issue.id; + } else if ("pull_request" in contextOrPayload.payload) { + _issueId = contextOrPayload.payload.pull_request.id; + } else { + throw new Error("Issue Id is missing"); + } } - if (!userId) { + if (!_username) { throw new Error("User was not found"); } - if (!walletAddress) { + if (!_walletAddress) { const errorMessage = "ERC20 Permit generation error: Wallet not found"; - logger.error(errorMessage); + _logger.error(errorMessage); throw new Error(errorMessage); } - const { rpc, token, decimals } = getPayoutConfigByNetworkId(evmNetworkId); - const { privateKey } = await decryptKeys(evmPrivateEncrypted); + const { rpc, token, decimals } = getPayoutConfigByNetworkId(_evmNetworkId); + const { privateKey } = await decryptKeys(_evmPrivateEncrypted); if (!privateKey) { const errorMessage = "Private key is not defined"; - logger.fatal(errorMessage); + _logger.fatal(errorMessage); throw new Error(errorMessage); } @@ -44,13 +76,17 @@ export async function generateErc20PermitSignature(context: Context, username: s try { provider = new ethers.JsonRpcProvider(rpc); } catch (error) { - throw logger.debug("Failed to instantiate provider", error); + const errorMessage = `Failed to instantiate provider: ${error}`; + _logger.debug(errorMessage); + throw new Error(errorMessage); } try { adminWallet = new ethers.Wallet(privateKey, provider); } catch (error) { - throw logger.debug("Failed to instantiate wallet", error); + const errorMessage = `Failed to instantiate wallet: ${error}`; + _logger.debug(errorMessage); + throw new Error(errorMessage); } const permitTransferFromData: PermitTransferFrom = { @@ -58,12 +94,12 @@ export async function generateErc20PermitSignature(context: Context, username: s token: token, amount: parseUnits(amount.toString(), decimals), }, - spender: walletAddress, - nonce: BigInt(keccak256(toUtf8Bytes(`${userId}-${issueId}`))), + spender: _walletAddress, + nonce: BigInt(keccak256(toUtf8Bytes(`${_userId}-${_issueId}`))), deadline: MaxInt256, }; - const { domain, types, values } = SignatureTransfer.getPermitData(permitTransferFromData, PERMIT2_ADDRESS, evmNetworkId); + const { domain, types, values } = SignatureTransfer.getPermitData(permitTransferFromData, PERMIT2_ADDRESS, _evmNetworkId); const signature = await adminWallet .signTypedData( @@ -79,12 +115,12 @@ export async function generateErc20PermitSignature(context: Context, username: s ) .catch((error) => { const errorMessage = `Failed to sign typed data ${error}`; - logger.error(errorMessage); + _logger.error(errorMessage); throw new Error(errorMessage); }); const erc20Permit: Permit = { - tokenType: "ERC20", + tokenType: TokenType.ERC20, tokenAddress: permitTransferFromData.permitted.token, beneficiary: permitTransferFromData.spender, nonce: permitTransferFromData.nonce.toString(), @@ -92,10 +128,10 @@ export async function generateErc20PermitSignature(context: Context, username: s amount: permitTransferFromData.permitted.amount.toString(), owner: adminWallet.address, signature: signature, - networkId: evmNetworkId, + networkId: _evmNetworkId, }; - logger.info("Generated ERC20 permit2 signature", erc20Permit); + _logger.info("Generated ERC20 permit2 signature", erc20Permit); return erc20Permit; } diff --git a/src/handlers/generate-erc721-permit.ts b/src/handlers/generate-erc721-permit.ts index 82f0d5c..2ec3499 100644 --- a/src/handlers/generate-erc721-permit.ts +++ b/src/handlers/generate-erc721-permit.ts @@ -1,10 +1,9 @@ -import { getPayoutConfigByNetworkId } from "../utils/payoutConfigByNetworkId"; -import { ethers } from "ethers"; import { MaxUint256 } from "@uniswap/permit2-sdk"; -import { keccak256, toUtf8Bytes } from "ethers"; -import { Permit } from "../types/permits"; -import { Context } from "../types/context"; +import { ethers, keccak256, toUtf8Bytes } from "ethers"; +import { Context, Logger } from "../types/context"; +import { Permit, TokenType } from "../types"; import { isIssueEvent } from "../types/typeguards"; +import { getPayoutConfigByNetworkId } from "../utils/payoutConfigByNetworkId"; interface Erc721PermitSignatureData { beneficiary: string; @@ -27,95 +26,143 @@ const types = { ], }; -export async function generateErc721PermitSignature(context: Context, username: string, contributionType: string): Promise { - const { NFT_MINTER_PRIVATE_KEY, NFT_CONTRACT_ADDRESS } = context.env; - const { evmNetworkId } = context.config; - const adapters = context.adapters; - const logger = context.logger; +export interface PermitPayload { + evmNetworkId: number; + nftMinterPrivateKey: string; + nftContractAddress: string; + walletAddress: string; + logger: Logger; + issueId: string; + organizationName: string; + repositoryName: string; + userId: number; +} + +export async function generateErc721PermitSignature(permitPayload: PermitPayload, username: string, contributionType: string): Promise; +export async function generateErc721PermitSignature(context: Context, username: string, contributionType: string): Promise; +export async function generateErc721PermitSignature( + contextOrPermitPayload: Context | PermitPayload, + username: string, + contributionType: string +): Promise { + let _logger: Logger; + let _nftContractAddress: string; + let _evmNetworkId: number; + let _nftMinterPrivateKey: string; + let _userId: number; + let _walletAddress: string; + let _issueId: string; + let _organizationName: string; + let _repositoryName: string; + let _username = username; + + if ("evmNetworkId" in contextOrPermitPayload) { + _logger = contextOrPermitPayload.logger; + _nftContractAddress = contextOrPermitPayload.nftContractAddress; + _nftMinterPrivateKey = contextOrPermitPayload.nftMinterPrivateKey; + _evmNetworkId = contextOrPermitPayload.evmNetworkId; + _walletAddress = contextOrPermitPayload.walletAddress; + _issueId = contextOrPermitPayload.issueId; + _organizationName = contextOrPermitPayload.organizationName; + _repositoryName = contextOrPermitPayload.repositoryName; + _userId = contextOrPermitPayload.userId; + } else { + const { NFT_MINTER_PRIVATE_KEY, NFT_CONTRACT_ADDRESS } = contextOrPermitPayload.env; + const { evmNetworkId } = contextOrPermitPayload.config; + const adapters = contextOrPermitPayload.adapters; + _logger = contextOrPermitPayload.logger; + _nftContractAddress = NFT_CONTRACT_ADDRESS; + _evmNetworkId = evmNetworkId; + _nftMinterPrivateKey = NFT_MINTER_PRIVATE_KEY; + _username = username; + if (isIssueEvent(contextOrPermitPayload)) { + _issueId = contextOrPermitPayload.payload.issue.id.toString(); + } else { + throw new Error("Issue Id is missing."); + } + _organizationName = contextOrPermitPayload.payload.repository.owner.login; + _repositoryName = contextOrPermitPayload.payload.repository.name; + const { data: userData } = await contextOrPermitPayload.octokit.users.getByUsername({ username: _username }); + if (!userData) { + throw new Error(`GitHub user was not found for id ${_username}`); + } + _userId = userData.id; + const walletAddress = await adapters.supabase.wallet.getWalletByUserId(_userId); + if (!walletAddress) { + _logger.error("No wallet found for user"); + throw new Error("No wallet found for user"); + } + _walletAddress = walletAddress; + } - const { rpc } = getPayoutConfigByNetworkId(evmNetworkId); + const { rpc } = getPayoutConfigByNetworkId(_evmNetworkId); if (!rpc) { - logger.error("RPC is not defined"); + _logger.error("RPC is not defined"); throw new Error("RPC is not defined"); } - if (!NFT_CONTRACT_ADDRESS) { + if (!_nftContractAddress) { const errorMessage = "NFT contract address is not defined"; - logger.error(errorMessage); + _logger.error(errorMessage); throw new Error(errorMessage); } - const beneficiary = await adapters.supabase.wallet.getWalletByUsername(username); - if (!beneficiary) { - logger.error("No wallet found for user"); - throw new Error("No wallet found for user"); - } - - const userId = await adapters.supabase.user.getUserIdByWallet(beneficiary); - - const organizationName = context.payload.repository.owner.login; - const repositoryName = context.payload.repository.name; - let issueId = ""; - if (isIssueEvent(context)) { - issueId = context.payload.issue.id.toString(); - } - let provider; let adminWallet; try { provider = new ethers.JsonRpcProvider(rpc); } catch (error) { - logger.error("Failed to instantiate provider", error); + _logger.error("Failed to instantiate provider", error); throw new Error("Failed to instantiate provider"); } try { - adminWallet = new ethers.Wallet(NFT_MINTER_PRIVATE_KEY, provider); + adminWallet = new ethers.Wallet(_nftMinterPrivateKey, provider); } catch (error) { - logger.error("Failed to instantiate wallet", error); + _logger.error("Failed to instantiate wallet", error); throw new Error("Failed to instantiate wallet"); } const erc721Metadata = { - GITHUB_ORGANIZATION_NAME: organizationName, - GITHUB_REPOSITORY_NAME: repositoryName, - GITHUB_ISSUE_ID: issueId, - GITHUB_USERNAME: username, + GITHUB_ORGANIZATION_NAME: _organizationName, + GITHUB_REPOSITORY_NAME: _repositoryName, + GITHUB_ISSUE_ID: _issueId, + GITHUB_USERNAME: _username, GITHUB_CONTRIBUTION_TYPE: contributionType, }; const metadata = Object.entries(erc721Metadata); const erc721SignatureData: Erc721PermitSignatureData = { - beneficiary: beneficiary, + beneficiary: _walletAddress, deadline: MaxUint256.toBigInt(), keys: metadata.map(([key]) => keccak256(toUtf8Bytes(key))), - nonce: BigInt(keccak256(toUtf8Bytes(`${userId}-${issueId}`))), + nonce: BigInt(keccak256(toUtf8Bytes(`${_userId}-${_issueId}`))), values: metadata.map(([, value]) => value), }; const domain = { name: SIGNING_DOMAIN_NAME, version: SIGNING_DOMAIN_VERSION, - verifyingContract: NFT_CONTRACT_ADDRESS, - chainId: evmNetworkId, + verifyingContract: _nftContractAddress, + chainId: _evmNetworkId, }; const signature = await adminWallet.signTypedData(domain, types, erc721SignatureData).catch((error: unknown) => { - logger.error("Failed to sign typed data", error); - throw new Error("Failed to sign typed data"); + _logger.error("Failed to sign typed data", error); + throw new Error(`Failed to sign typed data: ${error}`); }); const erc721Permit: Permit = { - tokenType: "ERC721", - tokenAddress: NFT_CONTRACT_ADDRESS, - beneficiary: beneficiary, + tokenType: TokenType.ERC721, + tokenAddress: _nftContractAddress, + beneficiary: _walletAddress, amount: "1", nonce: erc721SignatureData.nonce.toString(), deadline: erc721SignatureData.deadline.toString(), signature: signature, owner: adminWallet.address, - networkId: evmNetworkId, + networkId: _evmNetworkId, erc721Request: { keys: erc721SignatureData.keys.map((key) => key.toString()), values: erc721SignatureData.values, diff --git a/src/handlers/generate-payout-permit.ts b/src/handlers/generate-payout-permit.ts index 08ede78..61a5e24 100644 --- a/src/handlers/generate-payout-permit.ts +++ b/src/handlers/generate-payout-permit.ts @@ -1,4 +1,4 @@ -import { Permit } from "../types/permits"; +import { Permit } from "../types"; import { Context } from "../types/context"; import { generateErc20PermitSignature } from "./generate-erc20-permit"; import { generateErc721PermitSignature } from "./generate-erc721-permit"; diff --git a/src/handlers/index.ts b/src/handlers/index.ts new file mode 100644 index 0000000..e97af25 --- /dev/null +++ b/src/handlers/index.ts @@ -0,0 +1,4 @@ +export * from "./generate-erc20-permit"; +export * from "./generate-erc721-permit"; +export * from "./generate-payout-permit"; +export * from "./encode-decode"; diff --git a/src/handlers/permit-type.ts b/src/handlers/permit-type.ts new file mode 100644 index 0000000..7ac4300 --- /dev/null +++ b/src/handlers/permit-type.ts @@ -0,0 +1,72 @@ +import { StaticDecode, Type as T } from "@sinclair/typebox"; +import { BigNumberish } from "ethers"; + +const bigNumberT = T.Transform(T.Union([T.RegExp(/^\d+$/), T.Number()])) + .Decode((value) => BigInt(value) as BigNumberish) + .Encode((value) => value.toString()); + +const networkIdT = T.Number(); + +const addressT = T.Transform(T.RegExp(/^0x[a-fA-F0-9]{40}$/)) + .Decode((value) => value.toLowerCase()) + .Encode((value) => value); + +const signatureT = T.Transform(T.RegExp(/^0x[a-fA-F0-9]+$/)) + .Decode((value) => value.toLowerCase()) + .Encode((value) => value); + +const erc20PermitT = T.Object({ + type: T.Literal("erc20-permit"), + permit: T.Object({ + permitted: T.Object({ + token: addressT, + amount: bigNumberT, + }), + nonce: bigNumberT, + deadline: bigNumberT, + }), + transferDetails: T.Object({ + to: addressT, + requestedAmount: bigNumberT, + }), + owner: addressT, + signature: signatureT, + networkId: T.Number(), +}); + +const erc721PermitT = T.Object({ + type: T.Literal("erc721-permit"), + permit: T.Object({ + permitted: T.Object({ + token: addressT, + amount: bigNumberT, + }), + nonce: bigNumberT, + deadline: bigNumberT, + }), + transferDetails: T.Object({ + to: addressT, + requestedAmount: bigNumberT, + }), + owner: addressT, + signature: signatureT, + networkId: networkIdT, + nftMetadata: T.Object({ + GITHUB_ORGANIZATION_NAME: T.String(), + GITHUB_REPOSITORY_NAME: T.String(), + GITHUB_ISSUE_ID: T.String(), + GITHUB_USERNAME: T.String(), + GITHUB_CONTRIBUTION_TYPE: T.String(), + }), + request: T.Object({ + beneficiary: addressT, + deadline: bigNumberT, + keys: T.Array(T.String()), + nonce: bigNumberT, + values: T.Array(T.String()), + }), +}); + +export const claimTxT = T.Union([erc20PermitT, erc721PermitT]); + +export type RewardPermit = StaticDecode; diff --git a/src/handlers/register-wallet.ts b/src/handlers/register-wallet.ts index 915d5fd..6e653c8 100644 --- a/src/handlers/register-wallet.ts +++ b/src/handlers/register-wallet.ts @@ -33,10 +33,10 @@ export async function registerWallet(context: Context, address: string | null) { if (address && senderID) { const { wallet, user } = adapters.supabase; - const userRecord = await user.getUsernameById(senderID); + const userRecord = await user.getUserById(senderID); try { - if (!userRecord || userRecord.length === 0) { + if (!userRecord) { await user.upsertUser(senderID, sender); await wallet.upsertWallet(senderID, address); } else { diff --git a/src/index.ts b/src/index.ts index 9d9b039..69c6f60 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,111 +1,4 @@ -import * as core from "@actions/core"; -import * as github from "@actions/github"; -import { Octokit } from "@octokit/rest"; -import { PluginInputs, permitGenerationSettingsSchema } from "./types/plugin-input"; -import { Context } from "./types/context"; -import { createClient } from "@supabase/supabase-js"; -import { createAdapters } from "./adapters"; -import { Database } from "./adapters/supabase/types/database"; -import { registerWallet } from "./handlers/register-wallet"; -import { generatePayoutPermit } from "./handlers/generate-payout-permit"; -import { Value } from "@sinclair/typebox/value"; -import { envSchema } from "./types/env"; - -async function run() { - const webhookPayload = github.context.payload.inputs; - - const env = Value.Decode(envSchema, process.env); - const settings = Value.Decode(permitGenerationSettingsSchema, JSON.parse(webhookPayload.settings)); - - const inputs: PluginInputs = { - stateId: webhookPayload.stateId, - eventName: webhookPayload.eventName, - eventPayload: JSON.parse(webhookPayload.eventPayload), - settings: settings, - authToken: webhookPayload.authToken, - ref: webhookPayload.ref, - }; - const octokit = new Octokit({ auth: inputs.authToken }); - const supabaseClient = createClient(env.SUPABASE_URL, env.SUPABASE_KEY); - - const context: Context = { - eventName: inputs.eventName, - payload: inputs.eventPayload, - config: inputs.settings, - octokit, - env, - logger: { - debug(message: unknown, ...optionalParams: unknown[]) { - console.debug(message, ...optionalParams); - }, - info(message: unknown, ...optionalParams: unknown[]) { - console.log(message, ...optionalParams); - }, - warn(message: unknown, ...optionalParams: unknown[]) { - console.warn(message, ...optionalParams); - }, - error(message: unknown, ...optionalParams: unknown[]) { - console.error(message, ...optionalParams); - }, - fatal(message: unknown, ...optionalParams: unknown[]) { - console.error(message, ...optionalParams); - }, - }, - adapters: {} as ReturnType, - }; - - context.adapters = createAdapters(supabaseClient, context); - - if (context.eventName === "issue_comment.created") { - await handleSlashCommands(context, octokit); - } else { - const permits = await generatePayoutPermit(context, settings.permitRequests); - await returnDataToKernel(env.GITHUB_TOKEN, inputs.stateId, permits); - return JSON.stringify(permits); - } - - return "No permit generated"; -} - -async function returnDataToKernel(repoToken: string, stateId: string, output: object) { - const octokit = new Octokit({ auth: repoToken }); - await octokit.repos.createDispatchEvent({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - event_type: "return_data_to_ubiquibot_kernel", - client_payload: { - state_id: stateId, - output: JSON.stringify(output), - }, - }); -} - -async function handleSlashCommands(context: Context, octokit: Octokit) { - const payload = context.payload as Context<"issue_comment.created">["payload"]; - const body = payload.comment.body; - - const registrationRegex = /\/wallet (0x[a-fA-F0-9]{40})/g; - const matches = body.match(registrationRegex); - - if (matches) { - const address = matches[0]; - // try registering wallet, if it fails, notify the user - if (!(await registerWallet(context, address))) { - await octokit.issues.createComment({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - issue_number: payload.issue.number, - body: `Failed to register wallet: ${address}`, - }); - } - } -} - -run() - .then((result) => { - core.setOutput("result", result); - }) - .catch((error) => { - console.error(error); - core.setFailed(error); - }); +export * from "./handlers"; +export * from "./adapters"; +export * from "./generate-permits-from-context"; +export * from "./types"; diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..abcb776 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,11 @@ +import * as core from "@actions/core"; +import { generatePermitsFromContext } from "./generate-permits-from-context"; + +generatePermitsFromContext() + .then((result) => { + core.setOutput("result", result); + }) + .catch((error) => { + console.error(error); + core.setFailed(error); + }); diff --git a/src/types/context.ts b/src/types/context.ts index 6a16c90..17d773f 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -6,6 +6,14 @@ import { Env } from "./env"; export type SupportedEvents = "issue_comment.created" | "workflow_dispatch" | "pull_request.closed" | "issues.closed"; +export interface Logger { + fatal: (message: unknown, ...optionalParams: unknown[]) => void; + error: (message: unknown, ...optionalParams: unknown[]) => void; + warn: (message: unknown, ...optionalParams: unknown[]) => void; + info: (message: unknown, ...optionalParams: unknown[]) => void; + debug: (message: unknown, ...optionalParams: unknown[]) => void; +} + export interface Context { eventName: T; payload: WebhookEvent["payload"]; @@ -13,11 +21,5 @@ export interface Context { adapters: ReturnType; config: PermitGenerationSettings; env: Env; - logger: { - fatal: (message: unknown, ...optionalParams: unknown[]) => void; - error: (message: unknown, ...optionalParams: unknown[]) => void; - warn: (message: unknown, ...optionalParams: unknown[]) => void; - info: (message: unknown, ...optionalParams: unknown[]) => void; - debug: (message: unknown, ...optionalParams: unknown[]) => void; - }; + logger: Logger; } diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..96fa5c7 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1 @@ +export * from "./permits"; diff --git a/src/types/permits.ts b/src/types/permits.ts index f7bc151..1eb8be2 100644 --- a/src/types/permits.ts +++ b/src/types/permits.ts @@ -1,15 +1,30 @@ -type TokenType = "ERC20" | "ERC721"; +import { BigNumberish } from "ethers"; -export interface Permit { +export enum TokenType { + ERC20 = "ERC20", + ERC721 = "ERC721", +} + +interface CommonFields { tokenType: TokenType; tokenAddress: string; beneficiary: string; - amount: string; - nonce: string; - deadline: string; + nonce: BigNumberish; + deadline: BigNumberish; owner: string; signature: string; networkId: number; +} + +interface ERC20Permit extends CommonFields { + tokenType: TokenType.ERC20; + amount: BigNumberish; + erc721Request?: never; +} + +interface ERC721Permit extends CommonFields { + tokenType: TokenType.ERC721; + amount: "0" | "1"; erc721Request?: { keys: string[]; values: string[]; @@ -22,3 +37,5 @@ export interface Permit { }; }; } + +export type Permit = ERC20Permit | ERC721Permit; diff --git a/tests/constants.ts b/tests/constants.ts index b08ee93..2f7749c 100644 --- a/tests/constants.ts +++ b/tests/constants.ts @@ -1,7 +1,8 @@ import { Context } from "../src/types/context"; +import { jest } from "@jest/globals"; export const NFT_CONTRACT_ADDRESS = "0x0000000000000000000000000000000000000003"; -export const SPENDER = "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d"; +export const SPENDER = "123"; export const WALLET_ADDRESS = "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd"; @@ -44,7 +45,7 @@ export const mockContext = { upsertUser: jest.fn(), getUserIdByWallet: jest.fn().mockReturnValue(123), getUserIdByUsername: jest.fn().mockReturnValue(1), - getUsernameById: jest.fn(), + getUserById: jest.fn(), }, wallet: { upsertWallet: jest.fn().mockImplementation(() => Promise.resolve()), diff --git a/tests/encode-decode.test.ts b/tests/encode-decode.test.ts new file mode 100644 index 0000000..afc0798 --- /dev/null +++ b/tests/encode-decode.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from "@jest/globals"; +import { decodePermits, encodePermits, Permit, TokenType } from "../src"; + +describe("Encoding / Decoding tests", () => { + it("Should properly encode and decode a list of permits", () => { + const permitErc20: Permit = { + beneficiary: "ubiquity", + deadline: "1", + networkId: 100, + nonce: "0x1", + owner: "0x1", + signature: "0x1", + tokenAddress: "0x1", + tokenType: TokenType.ERC20, + amount: 100, + }; + const permitErc721: Permit = { + beneficiary: "ubiquity2", + deadline: "2", + networkId: 101, + nonce: "0x2", + owner: "0x2", + signature: "0x2", + tokenAddress: "0x2", + tokenType: TokenType.ERC721, + amount: "1", + erc721Request: { + metadata: { + GITHUB_ORGANIZATION_NAME: "", + GITHUB_REPOSITORY_NAME: "", + GITHUB_ISSUE_ID: "", + GITHUB_USERNAME: "", + GITHUB_CONTRIBUTION_TYPE: "", + }, + keys: ["a", "b"], + values: ["c", "d"], + }, + }; + const encoded = encodePermits([permitErc20, permitErc721]); + const decoded = decodePermits(encoded); + expect(decoded).toEqual([permitErc20, permitErc721]); + }); +}); diff --git a/tests/generate-erc20-permit.test.ts b/tests/generate-erc20-permit.test.ts index cb20546..40718c3 100644 --- a/tests/generate-erc20-permit.test.ts +++ b/tests/generate-erc20-permit.test.ts @@ -1,6 +1,7 @@ -import { generateErc20PermitSignature } from "../src/handlers/generate-erc20-permit"; +import { generateErc20PermitSignature } from "../src"; import { Context } from "../src/types/context"; import { SPENDER, mockContext } from "./constants"; +import { describe, expect, it, beforeEach, jest } from "@jest/globals"; describe("generateErc20PermitSignature", () => { let context: Context; @@ -25,7 +26,7 @@ describe("generateErc20PermitSignature", () => { eq: jest.fn().mockReturnValue({ select: jest.fn().mockReturnValue({ eq: jest.fn().mockReturnValue({ - single: jest.fn().mockResolvedValue({ id: 123 }), + single: jest.fn().mockReturnValue({ id: 123 }), }), }), }), @@ -49,6 +50,14 @@ describe("generateErc20PermitSignature", () => { config: { evmNetworkId: 100, }, + octokit: { + request() { + return { data: { id: 1, login: "123" } }; + }, + users: { + getByUsername: jest.fn().mockReturnValue({ data: { id: 123 } }), + }, + }, } as unknown as Context; }); diff --git a/tests/generate-erc721-permit.test.ts b/tests/generate-erc721-permit.test.ts index f834417..da4be8b 100644 --- a/tests/generate-erc721-permit.test.ts +++ b/tests/generate-erc721-permit.test.ts @@ -1,9 +1,10 @@ import { MaxUint256 } from "@uniswap/permit2-sdk"; -import { keccak256, toUtf8Bytes } from "ethers"; -import { generateErc721PermitSignature } from "../src/handlers/generate-erc721-permit"; +import { BaseWallet, keccak256, toUtf8Bytes, TypedDataDomain, TypedDataField } from "ethers"; +import { generateErc721PermitSignature } from "../src"; import { Context } from "../src/types/context"; import { Env } from "../src/types/env"; import { cypherText, mockContext, NFT_CONTRACT_ADDRESS, SPENDER } from "./constants"; +import { describe, expect, it, beforeEach, afterEach, jest } from "@jest/globals"; describe("generateErc721PermitSignature", () => { let context: Context; @@ -35,9 +36,16 @@ describe("generateErc721PermitSignature", () => { // nft specific inputs contribution_type: "contribution", - username: "tester", issueID: 123, }, + octokit: { + request() { + return { data: { id: 1, login: "123" } }; + }, + users: { + getByUsername: jest.fn().mockReturnValue({ data: { id: userId } }), + }, + }, } as unknown as Context; context.env = process.env as Env; context.eventName = "issues.closed"; @@ -49,7 +57,7 @@ describe("generateErc721PermitSignature", () => { eq: jest.fn().mockReturnValue({ select: jest.fn().mockReturnValue({ eq: jest.fn().mockReturnValue({ - single: jest.fn().mockResolvedValue({ id: 123 }), + single: jest.fn().mockReturnValue({ id: 123 }), }), }), }), @@ -58,8 +66,14 @@ describe("generateErc721PermitSignature", () => { }), }; }); - (context.adapters.supabase.wallet.getWalletByUsername as jest.Mock).mockReturnValue(SPENDER); + (context.adapters.supabase.wallet.getWalletByUserId as jest.Mock).mockReturnValue(SPENDER); (context.adapters.supabase.user.getUserIdByWallet as jest.Mock).mockReturnValue(userId); + jest + .spyOn(BaseWallet.prototype, "signTypedData") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .mockImplementation((domain: TypedDataDomain, types: Record, value: Record) => { + return Promise.resolve("0x0"); + }); }); afterEach(() => { @@ -69,9 +83,9 @@ describe("generateErc721PermitSignature", () => { it("should generate ERC721 permit signature", async () => { const issueId = 123; const contributionType = "contribution"; - const username = "tester"; + const userId = "123"; - const result = await generateErc721PermitSignature(context, username, contributionType); + const result = await generateErc721PermitSignature(context, userId, contributionType); const organizationName = "test"; const repositoryName = "test"; @@ -87,7 +101,7 @@ describe("generateErc721PermitSignature", () => { expect(result.beneficiary).toBe(SPENDER); expect(result.deadline).toBe(MaxUint256.toString()); expect(result.nonce).toBe(BigInt(keccak256(toUtf8Bytes(`${userId}-${issueId}`))).toString()); - expect(result.erc721Request?.values).toEqual([organizationName, repositoryName, issueNumber, username, contributionType]); + expect(result.erc721Request?.values).toEqual([organizationName, repositoryName, issueNumber, userId, contributionType]); expect(result.networkId).toBe(context.config.evmNetworkId); const keysHashed = keys.map((key) => keccak256(toUtf8Bytes(key))); expect(result.erc721Request?.keys).toEqual(keysHashed); @@ -98,30 +112,30 @@ describe("generateErc721PermitSignature", () => { it("should throw an error if RPC is not defined", async () => { context.config.evmNetworkId = 123; - await expect(generateErc721PermitSignature(context, "tester", "contribution")).rejects.toThrow("No config setup for evmNetworkId: 123"); + await expect(generateErc721PermitSignature(context, "123", "contribution")).rejects.toThrow("No config" + " setup for evmNetworkId: 123"); }); it("should throw an error if NFT minter private key is not defined", async () => { delete process.env.NFT_MINTER_PRIVATE_KEY; - await expect(generateErc721PermitSignature(context, "tester", "contribution")).rejects.toThrow("Failed to instantiate wallet"); + await expect(generateErc721PermitSignature(context, "123", "contribution")).rejects.toThrow("Failed to" + " instantiate wallet"); expect(context.logger.error).toHaveBeenCalled(); }); it("should throw an error if NFT contract address is not defined", async () => { delete process.env.NFT_CONTRACT_ADDRESS; - await expect(generateErc721PermitSignature(context, "tester", "contribution")).rejects.toThrow("NFT contract address is not defined"); + await expect(generateErc721PermitSignature(context, "123", "contribution")).rejects.toThrow("NFT contract" + " address" + " is not defined"); expect(context.logger.error).toHaveBeenCalled(); }); it("should throw an error if no wallet found for user", async () => { (context.adapters.supabase.user.getUserIdByWallet as jest.Mock).mockReturnValue(null); - (context.adapters.supabase.wallet.getWalletByUsername as jest.Mock).mockReturnValue(null); + (context.adapters.supabase.wallet.getWalletByUserId as jest.Mock).mockReturnValue(null); context.config.evmPrivateEncrypted = cypherText; (context.adapters.supabase.user.getUserIdByWallet as jest.Mock).mockReturnValue(null); - await expect(generateErc721PermitSignature(context, "tester", "contribution")).rejects.toThrow("No wallet found for user"); + await expect(generateErc721PermitSignature(context, "123", "contribution")).rejects.toThrow("No wallet" + " found" + " for" + " user"); expect(context.logger.error).toHaveBeenCalledWith("No wallet found for user"); }); }); diff --git a/tests/generate-payout-permit.test.ts b/tests/generate-payout-permit.test.ts index d175e7e..ab7c95e 100644 --- a/tests/generate-payout-permit.test.ts +++ b/tests/generate-payout-permit.test.ts @@ -1,9 +1,10 @@ // import { generateErc20PermitSignature } from "../src/handlers/generate-erc20-permit"; -import { generateErc20PermitSignature } from "../src/handlers/generate-erc20-permit"; +import { generateErc20PermitSignature } from "../src"; // import { generateErc721PermitSignature } from "../src/handlers/generate-erc721-permit"; -import { generatePayoutPermit } from "../src/handlers/generate-payout-permit"; +import { generatePayoutPermit } from "../src"; import { Context } from "../src/types/context"; import { cypherText, mockContext, SPENDER } from "./constants"; +import { describe, expect, it, beforeEach, afterEach, jest } from "@jest/globals"; jest.mock("../src/handlers/generate-erc20-permit"); jest.mock("../src/handlers/generate-erc721-permit"); @@ -57,13 +58,13 @@ describe("generatePayoutPermit", () => { { type: "ERC20", amount: 100, - username: "username", + username: "123", contributionType: "ISSUE", }, { type: "ERC20", amount: 100, - username: "username", + username: "123", contributionType: "ISSUE", }, ]); diff --git a/tests/register-wallet.test.ts b/tests/register-wallet.test.ts index f1b8179..04b047b 100644 --- a/tests/register-wallet.test.ts +++ b/tests/register-wallet.test.ts @@ -1,6 +1,7 @@ import { registerWallet } from "../src/handlers/register-wallet"; import { Context } from "../src/types/context"; import { mockContext } from "./constants"; +import { describe, expect, it, beforeEach, afterEach, jest } from "@jest/globals"; describe("registerWallet", () => { let context: Context; @@ -31,7 +32,6 @@ describe("registerWallet", () => { }); it("should skip registration when address is null address", async () => { - context.payload.sender; expect(await registerWallet(context, "0x0000000000000000000000000000000000000000")).toBe(false); expect(context.logger.error).toHaveBeenCalledWith("Skipping to register a wallet address because user is trying to set their address to null address"); expect(context.adapters.supabase.wallet.upsertWallet).not.toHaveBeenCalled(); @@ -39,8 +39,8 @@ describe("registerWallet", () => { it("should handle error while registering wallet address", async () => { const address = "0x1234567890abcdef"; - const error = new Error("An error"); - (context.adapters.supabase.wallet.upsertWallet as jest.Mock).mockRejectedValue(error); + const error: Error = new Error("An error"); + (context.adapters.supabase.wallet.upsertWallet as jest.Mock).mockRejectedValue(error as never); expect(await registerWallet(context, address)).toBe(false); expect(context.logger.error).toHaveBeenCalledWith("Error while registering wallet address", { diff --git a/tsconfig.json b/tsconfig.json index cff607a..283242e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "ES2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ @@ -25,9 +25,9 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "commonjs" /* Specify what module code is generated. */, + "module": "ES2022" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "Node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ diff --git a/yarn.lock b/yarn.lock index 694635f..332742f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1507,7 +1507,7 @@ jest-mock "^29.7.0" jest-util "^29.7.0" -"@jest/globals@^29.7.0": +"@jest/globals@29.7.0", "@jest/globals@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== @@ -1604,7 +1604,7 @@ slash "^3.0.0" write-file-atomic "^4.0.2" -"@jest/types@^29.6.3": +"@jest/types@29.6.3", "@jest/types@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== @@ -1635,7 +1635,15 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -1993,6 +2001,147 @@ "@pnpm/resolve-workspace-range" "5.0.1" ramda "npm:@pnpm/ramda@0.28.1" +"@rollup/plugin-commonjs@25.0.7": + version "25.0.7" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz#145cec7589ad952171aeb6a585bbeabd0fd3b4cf" + integrity sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + commondir "^1.0.1" + estree-walker "^2.0.2" + glob "^8.0.3" + is-reference "1.2.1" + magic-string "^0.30.3" + +"@rollup/plugin-json@6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-6.1.0.tgz#fbe784e29682e9bb6dee28ea75a1a83702e7b805" + integrity sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA== + dependencies: + "@rollup/pluginutils" "^5.1.0" + +"@rollup/plugin-node-resolve@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz#e5e0b059bd85ca57489492f295ce88c2d4b0daf9" + integrity sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + "@types/resolve" "1.20.2" + deepmerge "^4.2.2" + is-builtin-module "^3.2.1" + is-module "^1.0.0" + resolve "^1.22.1" + +"@rollup/plugin-terser@0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz#15dffdb3f73f121aa4fbb37e7ca6be9aeea91962" + integrity sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A== + dependencies: + serialize-javascript "^6.0.1" + smob "^1.0.0" + terser "^5.17.4" + +"@rollup/plugin-yaml@4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-yaml/-/plugin-yaml-4.1.2.tgz#a3b4cd5793dfd374b815c60183f5adf21bf1ff66" + integrity sha512-RpupciIeZMUqhgFE97ba0s98mOFS7CWzN3EJNhJkqSv9XLlWYtwVdtE6cDw6ASOF/sZVFS7kRJXftaqM2Vakdw== + dependencies: + "@rollup/pluginutils" "^5.0.1" + js-yaml "^4.1.0" + tosource "^2.0.0-alpha.3" + +"@rollup/pluginutils@^4.1.2": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" + integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + +"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" + integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + +"@rollup/rollup-android-arm-eabi@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.0.tgz#57936f50d0335e2e7bfac496d209606fa516add4" + integrity sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w== + +"@rollup/rollup-android-arm64@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.0.tgz#81bba83b37382a2d0e30ceced06c8d3d85138054" + integrity sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q== + +"@rollup/rollup-darwin-arm64@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.0.tgz#a371bd723a5c4c4a33376da72abfc3938066842b" + integrity sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA== + +"@rollup/rollup-darwin-x64@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.0.tgz#8baf2fda277c9729125017c65651296282412886" + integrity sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ== + +"@rollup/rollup-linux-arm-gnueabihf@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.0.tgz#822830a8f7388d5b81d04c69415408d3bab1079b" + integrity sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA== + +"@rollup/rollup-linux-arm64-gnu@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.0.tgz#e20fbe1bd4414c7119f9e0bba8ad17a6666c8365" + integrity sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A== + +"@rollup/rollup-linux-arm64-musl@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.0.tgz#13f475596a62e1924f13fe1c8cf2c40e09a99b47" + integrity sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA== + +"@rollup/rollup-linux-powerpc64le-gnu@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.0.tgz#6a431c441420d1c510a205e08c6673355a0a2ea9" + integrity sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA== + +"@rollup/rollup-linux-riscv64-gnu@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.0.tgz#53d9448962c3f9ed7a1672269655476ea2d67567" + integrity sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw== + +"@rollup/rollup-linux-s390x-gnu@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.0.tgz#95f0c133b324da3e7e5c7d12855e0eb71d21a946" + integrity sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA== + +"@rollup/rollup-linux-x64-gnu@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.0.tgz#820ada75c68ead1acc486e41238ca0d8f8531478" + integrity sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg== + +"@rollup/rollup-linux-x64-musl@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.0.tgz#ca74f22e125efbe94c1148d989ef93329b464443" + integrity sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg== + +"@rollup/rollup-win32-arm64-msvc@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.0.tgz#269023332297051d037a9593dcba92c10fef726b" + integrity sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ== + +"@rollup/rollup-win32-ia32-msvc@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.0.tgz#d7701438daf964011fd7ca33e3f13f3ff5129e7b" + integrity sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw== + +"@rollup/rollup-win32-x64-msvc@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz#0bb7ac3cd1c3292db1f39afdabfd03ccea3a3d34" + integrity sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -2026,17 +2175,17 @@ ignore "^5.1.8" p-map "^4.0.0" -"@supabase/functions-js@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.1.5.tgz#ed1b85f499dfda21d40fe39b86ab923117cb572b" - integrity sha512-BNzC5XhCzzCaggJ8s53DP+WeHHGT/NfTsx2wUSSGKR2/ikLFQTBCDzMvGz/PxYMqRko/LwncQtKXGOYp1PkPaw== +"@supabase/auth-js@2.63.0": + version "2.63.0" + resolved "https://registry.yarnpkg.com/@supabase/auth-js/-/auth-js-2.63.0.tgz#41ff746a50a916208c1f2c6898deacf92c6d0b91" + integrity sha512-yIgcHnlgv24GxHtVGUhwGqAFDyJkPIC/xjx7HostN08A8yCy8HIfl4JEkTKyBqD1v1L05jNEJOUke4Lf4O1+Qg== dependencies: "@supabase/node-fetch" "^2.6.14" -"@supabase/gotrue-js@2.62.2": - version "2.62.2" - resolved "https://registry.yarnpkg.com/@supabase/gotrue-js/-/gotrue-js-2.62.2.tgz#9f15a451559d71475c953aa0027e1248b0210196" - integrity sha512-AP6e6W9rQXFTEJ7sTTNYQrNf0LCcnt1hUW+RIgUK+Uh3jbWvcIST7wAlYyNZiMlS9+PYyymWQ+Ykz/rOYSO0+A== +"@supabase/functions-js@2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.2.2.tgz#53a22d9f1fc770d96c9ad8c9dba5eda339b305f5" + integrity sha512-sJGq1nludmi7pY/fdtCpyY/pYonx7MfHdN408bqb736guWcVI1AChYVbI4kUM978EuOE4Ci6l7bUudfGg07QRw== dependencies: "@supabase/node-fetch" "^2.6.14" @@ -2047,10 +2196,10 @@ dependencies: whatwg-url "^5.0.0" -"@supabase/postgrest-js@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.9.2.tgz#39c839022ce73f4eb5da6fb7724fb6a6392150c7" - integrity sha512-I6yHo8CC9cxhOo6DouDMy9uOfW7hjdsnCxZiaJuIVZm1dBGTFiQPgfMa9zXCamEWzNyWRjZvupAUuX+tqcl5Sw== +"@supabase/postgrest-js@1.15.0": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.15.0.tgz#2218c8885a596835b85971f09ea87d1d8353c0c5" + integrity sha512-U4bwBOrhsXWqDjZiYNbVqMBtRGgIIYE0kE5ZNSwsIbeBWfr/UxOMrnkIQUBGIZRhpYW/tw1WnTdRl1AGNyaxcw== dependencies: "@supabase/node-fetch" "^2.6.14" @@ -2071,22 +2220,22 @@ dependencies: "@supabase/node-fetch" "^2.6.14" -"@supabase/supabase-js@^2.39.7": - version "2.39.8" - resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.39.8.tgz#2d8935438bdd6add82484ecd46edb0cd5b3f8c38" - integrity sha512-WpiawHjseIRcCQTZbMJtHUSOepz5+M9qE1jP9BDmg8X7ehALFwgEkiKyHAu59qm/pKP2ryyQXLtu2XZNRbUarw== +"@supabase/supabase-js@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.42.0.tgz#9e739cd96989acb0cbaab16da3717400b2ac92fa" + integrity sha512-1PDqJiA4iG45w3AAu6xkccJ3wPqlGJUoz9CPhScRLLTStxhewYhz0mjryTpXz1kgtNHdUAsirALreezn8UZMjA== dependencies: - "@supabase/functions-js" "2.1.5" - "@supabase/gotrue-js" "2.62.2" + "@supabase/auth-js" "2.63.0" + "@supabase/functions-js" "2.2.2" "@supabase/node-fetch" "2.6.15" - "@supabase/postgrest-js" "1.9.2" + "@supabase/postgrest-js" "1.15.0" "@supabase/realtime-js" "2.9.3" "@supabase/storage-js" "2.5.5" "@tsconfig/node10@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== "@tsconfig/node12@^1.0.7": version "1.0.11" @@ -2136,6 +2285,11 @@ dependencies: "@babel/types" "^7.20.7" +"@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== + "@types/graceful-fs@^4.1.3": version "4.1.9" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" @@ -2211,6 +2365,11 @@ resolved "https://registry.yarnpkg.com/@types/picomatch/-/picomatch-2.3.3.tgz#be60498568c19e989e43fb39aa84be1ed3655e92" integrity sha512-Yll76ZHikRFCyz/pffKGjrCwe/le2CDwOP5F210KQo27kpRE46U2rDnzikNlVn6/ezH3Mhn46bJMTfeVTtcYMg== +"@types/resolve@1.20.2": + version "1.20.2" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" + integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== + "@types/semver@^7.5.0": version "7.5.7" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.7.tgz#326f5fdda70d13580777bcaa1bc6fa772a5aef0e" @@ -2369,7 +2528,7 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^8.4.1, acorn@^8.9.0: +acorn@^8.4.1, acorn@^8.8.2, acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -2706,6 +2865,11 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +builtin-modules@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + builtins@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" @@ -2895,6 +3059,11 @@ commander@^12.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-12.0.0.tgz#b929db6df8546080adfd004ab215ed48cf6f2592" integrity sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA== +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" @@ -2911,6 +3080,11 @@ comment-json@^4.2.3: has-own-prop "^2.0.0" repeat-string "^1.6.1" +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + compare-func@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" @@ -3281,6 +3455,14 @@ dotenv@^16.4.4: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.4.tgz#a26e7bb95ebd36272ebb56edb80b826aecf224c1" integrity sha512-XvPXc8XAQThSjAbY6cQ/9PcBXmFoWuw1sQ3b8HqUCR6ziGXjkTi//kB9SWa2UwqlgdAIuRqAa/9hVljzPehbYg== +dts-bundle-generator@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/dts-bundle-generator/-/dts-bundle-generator-7.2.0.tgz#1a06f621e33399e38c8968bbd71d65ab577e5327" + integrity sha512-pHjRo52hvvLDRijzIYRTS9eJR7vAOs3gd/7jx+7YVnLU8ay3yPUWGtHXPtuMBSlJYk/s4nq1SvXObDCZVguYMg== + dependencies: + typescript ">=4.5.2" + yargs "^17.6.0" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -3578,6 +3760,11 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^2.0.1, estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -3769,6 +3956,15 @@ filter-obj@^1.1.0: resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== +find-cache-dir@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + find-up-simple@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/find-up-simple/-/find-up-simple-1.0.0.tgz#21d035fde9fdbd56c8f4d2f63f32fd93a1cfc368" @@ -3828,7 +4024,7 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" -fs-extra@10.1.0: +fs-extra@10.1.0, fs-extra@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== @@ -3842,7 +4038,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2, fsevents@~2.3.3: +fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -3982,6 +4178,17 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + global-directory@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-4.0.1.tgz#4d7ac7cfd2cb73f304c53b8810891748df5e361e" @@ -4272,6 +4479,13 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-builtin-module@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" + integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== + dependencies: + builtin-modules "^3.3.0" + is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" @@ -4330,6 +4544,11 @@ is-iterable@^1.1.0: resolved "https://registry.yarnpkg.com/is-iterable/-/is-iterable-1.1.1.tgz#71f9aa6f113e1d968ebe1d41cff4c8fb23a817bc" integrity sha512-EdOZCr0NsGE00Pot+x1ZFx9MJK3C6wy91geZpXwvwexDLJvA4nzYyZf7r+EIwSeVsOLDdBz7ATg9NqKTzuNYuQ== +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -4367,6 +4586,13 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== +is-reference@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -5221,6 +5447,20 @@ magic-string@^0.16.0: dependencies: vlq "^0.2.1" +magic-string@^0.30.3: + version "0.30.8" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.8.tgz#14e8624246d2bedba70d5462aa99ac9681844613" + integrity sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + +make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + make-dir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -5367,6 +5607,13 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -5758,7 +6005,7 @@ picomatch@4.0.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.1.tgz#68c26c8837399e5819edce48590412ea07f17a07" integrity sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg== -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -5783,7 +6030,7 @@ pirates@^4.0.4: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== -pkg-dir@^4.2.0: +pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -5867,6 +6114,13 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/@pnpm/ramda/-/ramda-0.28.1.tgz#0f32abc5275d586a03e0dc1dd90a009ac668ff33" integrity sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw== +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + react-is@^18.0.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" @@ -5992,7 +6246,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.10.0, resolve@^1.20.0: +resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.1: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -6043,6 +6297,56 @@ rimraf@^5.0.5: dependencies: glob "^10.3.7" +rollup-plugin-dts-bundle-generator@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-dts-bundle-generator/-/rollup-plugin-dts-bundle-generator-1.4.0.tgz#533fd3a003094a1c46a93628f3c824bd4e69fd79" + integrity sha512-++Vax6N0iFiH6/hqbKvdnVvyz48grMqAos6TqW4wajQE0AgDzbQK0hbsyDgKTTQoz1BjanC0omOJc/RnQoYajQ== + dependencies: + dts-bundle-generator "^7.0.0" + rollup "^2.75.5" + +rollup-plugin-typescript2@0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.36.0.tgz#309564eb70d710412f5901344ca92045e180ed53" + integrity sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw== + dependencies: + "@rollup/pluginutils" "^4.1.2" + find-cache-dir "^3.3.2" + fs-extra "^10.0.0" + semver "^7.5.4" + tslib "^2.6.2" + +rollup@4.14.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.14.0.tgz#c3e2cd479f1b2358b65c1f810fa05b51603d7be8" + integrity sha512-Qe7w62TyawbDzB4yt32R0+AbIo6m1/sqO7UPzFS8Z/ksL5mrfhA0v4CavfdmFav3D+ub4QeAgsGEe84DoWe/nQ== + dependencies: + "@types/estree" "1.0.5" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.14.0" + "@rollup/rollup-android-arm64" "4.14.0" + "@rollup/rollup-darwin-arm64" "4.14.0" + "@rollup/rollup-darwin-x64" "4.14.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.14.0" + "@rollup/rollup-linux-arm64-gnu" "4.14.0" + "@rollup/rollup-linux-arm64-musl" "4.14.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.14.0" + "@rollup/rollup-linux-riscv64-gnu" "4.14.0" + "@rollup/rollup-linux-s390x-gnu" "4.14.0" + "@rollup/rollup-linux-x64-gnu" "4.14.0" + "@rollup/rollup-linux-x64-musl" "4.14.0" + "@rollup/rollup-win32-arm64-msvc" "4.14.0" + "@rollup/rollup-win32-ia32-msvc" "4.14.0" + "@rollup/rollup-win32-x64-msvc" "4.14.0" + fsevents "~2.3.2" + +rollup@^2.75.5: + version "2.79.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" + integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== + optionalDependencies: + fsevents "~2.3.2" + run-parallel@^1.1.9, run-parallel@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -6060,7 +6364,7 @@ safe-array-concat@^1.1.0: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@~5.2.0: +safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -6091,11 +6395,18 @@ semver@7.6.0, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver dependencies: lru-cache "^6.0.0" -semver@^6.1.0, semver@^6.3.0, semver@^6.3.1: +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + set-function-length@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.1.tgz#47cc5945f2c771e2cf261c6737cf9684a2a5e425" @@ -6197,6 +6508,11 @@ slice-ansi@^7.0.0: ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" +smob@^1.0.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/smob/-/smob-1.5.0.tgz#85d79a1403abf128d24d3ebc1cdc5e1a9548d3ab" + integrity sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig== + smol-toml@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.1.4.tgz#08c23b105f56f17e57b0a77c7edcb10b75a62c5c" @@ -6210,6 +6526,14 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -6285,7 +6609,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6360,7 +6693,14 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -6442,6 +6782,16 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +terser@^5.17.4: + version "5.30.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.3.tgz#f1bb68ded42408c316b548e3ec2526d7dd03f4d2" + integrity sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -6514,6 +6864,11 @@ to-space-case@^1.0.0: dependencies: to-no-case "^1.0.0" +tosource@^2.0.0-alpha.3: + version "2.0.0-alpha.3" + resolved "https://registry.yarnpkg.com/tosource/-/tosource-2.0.0-alpha.3.tgz#ef385dac9092e009bf25c018838ddaae436daeb6" + integrity sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug== + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -6567,6 +6922,11 @@ tslib@2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tsx@^4.7.1: version "4.7.1" resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.7.1.tgz#27af6cbf4e1cdfcb9b5425b1c61bb7e668eb5e84" @@ -6675,6 +7035,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typescript@>=4.5.2: + version "5.4.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" + integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== + typescript@^5.3.3: version "5.3.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" @@ -6886,7 +7251,16 @@ which@^4.0.0: dependencies: isexe "^3.1.1" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -6991,7 +7365,7 @@ yargs-parser@^21.0.1, yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.0.0, yargs@^17.3.1: +yargs@^17.0.0, yargs@^17.3.1, yargs@^17.6.0: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==