diff --git a/drizzle.config.js b/drizzle.config.js new file mode 100644 index 0000000..7dafe4b --- /dev/null +++ b/drizzle.config.js @@ -0,0 +1,12 @@ +import * as dotenv from 'dotenv' +dotenv.config() + + +export default { + "out": "./src/db/migrations", + "schema": "./src/db/schemas.js", + "driver": "pg", + "dbCredentials": { + "connectionString": process.env.DATABASE_URL + } +} diff --git a/drizzle.config.json b/drizzle.config.json deleted file mode 100644 index 1310bfa..0000000 --- a/drizzle.config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "out": "./src/db/migrations", - "schema": "./src/db/schemas.ts" -} diff --git a/package.json b/package.json index c792fcb..077fa96 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,9 @@ "license": "none", "scripts": { "lint": "xo", - "dev": "tsx watch --clear-screen=false src/index.ts", + "dev": "tsx watch --clear-screen=false src/index.js", "prettier": "prettier --write .", "migrate": "drizzle-kit generate:pg", - "build": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json", "start": "node src/index.js" }, "devDependencies": { @@ -30,11 +29,14 @@ }, "dependencies": { "@fastify/cors": "^8.4.2", + "@fastify/oauth2": "^7.8.0", "drizzle-orm": "^0.29.1", "fastify": "^4.25.0", "fastify-plugin": "^4.5.1", + "googleapis": "^134.0.0", "pg": "^8.11.3", "redis": "^4.6.11", + "simple-get": "^4.0.1", "tsc": "^2.0.4", "zod": "^3.22.4" }, diff --git a/src/db/index.js b/src/db/index.js index e1e60b0..203dbd7 100644 --- a/src/db/index.js +++ b/src/db/index.js @@ -11,6 +11,7 @@ export let db; export const initDb = async () => { const pool = await new Pool({ connectionString: env.DATABASE_URL, + idleTimeoutMillis: 20000 }) .connect() .then((client) => { @@ -27,14 +28,14 @@ export const initDb = async () => { schema, }); - await migrate(db, { - migrationsFolder: "./src/db/migrations", - }) - .then(() => { - Logger.info("INIT", "Migrated database"); - }) - .catch((error) => { - Logger.error("INIT", `Failed to migrate database ${String(error)}`); - throw new Error(`Failed to migrate database ${String(error)}`); - }); + // await migrate(db, { + // migrationsFolder: "./src/db/migrations", + // }) + // .then(() => { + // Logger.info("INIT", "Migrated database"); + // }) + // .catch((error) => { + // Logger.error("INIT", `Failed to migrate database ${String(error)}`); + // throw new Error(`Failed to migrate database ${String(error)}`); + // }); }; diff --git a/src/db/migrations/0000_huge_ares.sql b/src/db/migrations/0000_huge_ares.sql new file mode 100644 index 0000000..370a6ac --- /dev/null +++ b/src/db/migrations/0000_huge_ares.sql @@ -0,0 +1,43 @@ +CREATE TABLE IF NOT EXISTS "articles" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "site_id" uuid, + "content" text, + "source_video_id" text +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "sessions" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "user_id" uuid, + "google_code" text +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "sites" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "user_id" uuid, + "name" text +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "users" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "google_id" text, + "name" text, + "email" text +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "articles" ADD CONSTRAINT "articles_site_id_sites_id_fk" FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "sites" ADD CONSTRAINT "sites_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/src/db/migrations/0000_plain_killmonger.sql b/src/db/migrations/0000_plain_killmonger.sql deleted file mode 100644 index b75c273..0000000 --- a/src/db/migrations/0000_plain_killmonger.sql +++ /dev/null @@ -1,5 +0,0 @@ -CREATE TABLE IF NOT EXISTS "users" ( - "id" serial PRIMARY KEY NOT NULL, - "full_name" text, - "phone" varchar(256) -); diff --git a/src/db/migrations/0001_slim_xavin.sql b/src/db/migrations/0001_slim_xavin.sql new file mode 100644 index 0000000..9a59c34 --- /dev/null +++ b/src/db/migrations/0001_slim_xavin.sql @@ -0,0 +1,6 @@ +ALTER TABLE "sessions" ADD COLUMN "google_access_token" text;--> statement-breakpoint +ALTER TABLE "sessions" ADD COLUMN "google_refresh_token" text;--> statement-breakpoint +ALTER TABLE "sessions" ADD COLUMN "expires_at" date;--> statement-breakpoint +ALTER TABLE "users" ADD COLUMN "google_refresh_token" text;--> statement-breakpoint +ALTER TABLE "sessions" DROP COLUMN IF EXISTS "google_code";--> statement-breakpoint +ALTER TABLE "users" DROP COLUMN IF EXISTS "google_id"; \ No newline at end of file diff --git a/src/db/migrations/0002_small_forge.sql b/src/db/migrations/0002_small_forge.sql new file mode 100644 index 0000000..bae96de --- /dev/null +++ b/src/db/migrations/0002_small_forge.sql @@ -0,0 +1 @@ +ALTER TABLE "users" ADD COLUMN "channel_id" text; \ No newline at end of file diff --git a/src/db/migrations/0003_elite_falcon.sql b/src/db/migrations/0003_elite_falcon.sql new file mode 100644 index 0000000..0a7abc4 --- /dev/null +++ b/src/db/migrations/0003_elite_falcon.sql @@ -0,0 +1 @@ +ALTER TABLE "users" DROP COLUMN IF EXISTS "google_refresh_token"; \ No newline at end of file diff --git a/src/db/migrations/0004_daffy_ironclad.sql b/src/db/migrations/0004_daffy_ironclad.sql new file mode 100644 index 0000000..b005c4d --- /dev/null +++ b/src/db/migrations/0004_daffy_ironclad.sql @@ -0,0 +1 @@ +ALTER TABLE "users" ADD COLUMN "google_id" text; \ No newline at end of file diff --git a/src/db/migrations/0005_tricky_sheva_callister.sql b/src/db/migrations/0005_tricky_sheva_callister.sql new file mode 100644 index 0000000..d8fe0ac --- /dev/null +++ b/src/db/migrations/0005_tricky_sheva_callister.sql @@ -0,0 +1 @@ +ALTER TABLE "users" ADD COLUMN "uploads_playlist_id" text; \ No newline at end of file diff --git a/src/db/migrations/0006_wide_the_hunter.sql b/src/db/migrations/0006_wide_the_hunter.sql new file mode 100644 index 0000000..c880d56 --- /dev/null +++ b/src/db/migrations/0006_wide_the_hunter.sql @@ -0,0 +1 @@ +ALTER TABLE "sessions" ALTER COLUMN "expires_at" SET DATA TYPE timestamp; \ No newline at end of file diff --git a/src/db/migrations/meta/0000_snapshot.json b/src/db/migrations/meta/0000_snapshot.json index 1a5afc0..9e806b8 100644 --- a/src/db/migrations/meta/0000_snapshot.json +++ b/src/db/migrations/meta/0000_snapshot.json @@ -1,35 +1,178 @@ { + "id": "b6cb5336-be20-4e96-861f-fff166b013c7", + "prevId": "00000000-0000-0000-0000-000000000000", "version": "5", "dialect": "pg", - "id": "478200dd-a614-41dd-9cd1-f6368405417e", - "prevId": "00000000-0000-0000-0000-000000000000", "tables": { + "articles": { + "name": "articles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "site_id": { + "name": "site_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_video_id": { + "name": "source_video_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "articles_site_id_sites_id_fk": { + "name": "articles_site_id_sites_id_fk", + "tableFrom": "articles", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "google_code": { + "name": "google_code", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sites": { + "name": "sites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sites_user_id_users_id_fk": { + "name": "sites_user_id_users_id_fk", + "tableFrom": "sites", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, "users": { "name": "users", "schema": "", "columns": { "id": { "name": "id", - "type": "serial", + "type": "uuid", "primaryKey": true, - "notNull": true + "notNull": true, + "default": "gen_random_uuid()" }, - "full_name": { - "name": "full_name", + "google_id": { + "name": "google_id", "type": "text", "primaryKey": false, "notNull": false }, - "phone": { - "name": "phone", - "type": "varchar(256)", + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", "primaryKey": false, "notNull": false } }, "indexes": {}, "foreignKeys": {}, - "compositePrimaryKeys": {} + "compositePrimaryKeys": {}, + "uniqueConstraints": {} } }, "enums": {}, diff --git a/src/db/migrations/meta/0001_snapshot.json b/src/db/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..fc081b4 --- /dev/null +++ b/src/db/migrations/meta/0001_snapshot.json @@ -0,0 +1,197 @@ +{ + "id": "de9d771e-4272-49d2-bcc7-6eb5291bcd51", + "prevId": "b6cb5336-be20-4e96-861f-fff166b013c7", + "version": "5", + "dialect": "pg", + "tables": { + "articles": { + "name": "articles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "site_id": { + "name": "site_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_video_id": { + "name": "source_video_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "articles_site_id_sites_id_fk": { + "name": "articles_site_id_sites_id_fk", + "tableFrom": "articles", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "google_access_token": { + "name": "google_access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "google_refresh_token": { + "name": "google_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "date", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sites": { + "name": "sites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sites_user_id_users_id_fk": { + "name": "sites_user_id_users_id_fk", + "tableFrom": "sites", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "google_refresh_token": { + "name": "google_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/db/migrations/meta/0002_snapshot.json b/src/db/migrations/meta/0002_snapshot.json new file mode 100644 index 0000000..7e8c9eb --- /dev/null +++ b/src/db/migrations/meta/0002_snapshot.json @@ -0,0 +1,203 @@ +{ + "id": "ef238b19-05f5-4be9-90f8-56f4a08bb576", + "prevId": "de9d771e-4272-49d2-bcc7-6eb5291bcd51", + "version": "5", + "dialect": "pg", + "tables": { + "articles": { + "name": "articles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "site_id": { + "name": "site_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_video_id": { + "name": "source_video_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "articles_site_id_sites_id_fk": { + "name": "articles_site_id_sites_id_fk", + "tableFrom": "articles", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "google_access_token": { + "name": "google_access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "google_refresh_token": { + "name": "google_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "date", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sites": { + "name": "sites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sites_user_id_users_id_fk": { + "name": "sites_user_id_users_id_fk", + "tableFrom": "sites", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "google_refresh_token": { + "name": "google_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/db/migrations/meta/0003_snapshot.json b/src/db/migrations/meta/0003_snapshot.json new file mode 100644 index 0000000..fb3f4da --- /dev/null +++ b/src/db/migrations/meta/0003_snapshot.json @@ -0,0 +1,197 @@ +{ + "id": "d7ae7ea1-7218-4141-a9a9-35395e42e9bd", + "prevId": "ef238b19-05f5-4be9-90f8-56f4a08bb576", + "version": "5", + "dialect": "pg", + "tables": { + "articles": { + "name": "articles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "site_id": { + "name": "site_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_video_id": { + "name": "source_video_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "articles_site_id_sites_id_fk": { + "name": "articles_site_id_sites_id_fk", + "tableFrom": "articles", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "google_access_token": { + "name": "google_access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "google_refresh_token": { + "name": "google_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "date", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sites": { + "name": "sites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sites_user_id_users_id_fk": { + "name": "sites_user_id_users_id_fk", + "tableFrom": "sites", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/db/migrations/meta/0004_snapshot.json b/src/db/migrations/meta/0004_snapshot.json new file mode 100644 index 0000000..40662b0 --- /dev/null +++ b/src/db/migrations/meta/0004_snapshot.json @@ -0,0 +1,203 @@ +{ + "id": "130129fa-d718-4be8-8ffe-f285dce85195", + "prevId": "d7ae7ea1-7218-4141-a9a9-35395e42e9bd", + "version": "5", + "dialect": "pg", + "tables": { + "articles": { + "name": "articles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "site_id": { + "name": "site_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_video_id": { + "name": "source_video_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "articles_site_id_sites_id_fk": { + "name": "articles_site_id_sites_id_fk", + "tableFrom": "articles", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "google_access_token": { + "name": "google_access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "google_refresh_token": { + "name": "google_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "date", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sites": { + "name": "sites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sites_user_id_users_id_fk": { + "name": "sites_user_id_users_id_fk", + "tableFrom": "sites", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "google_id": { + "name": "google_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/db/migrations/meta/0005_snapshot.json b/src/db/migrations/meta/0005_snapshot.json new file mode 100644 index 0000000..fa591a1 --- /dev/null +++ b/src/db/migrations/meta/0005_snapshot.json @@ -0,0 +1,209 @@ +{ + "id": "4c4cea1e-1ffe-4736-b045-7dadd7e22244", + "prevId": "130129fa-d718-4be8-8ffe-f285dce85195", + "version": "5", + "dialect": "pg", + "tables": { + "articles": { + "name": "articles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "site_id": { + "name": "site_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_video_id": { + "name": "source_video_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "articles_site_id_sites_id_fk": { + "name": "articles_site_id_sites_id_fk", + "tableFrom": "articles", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "google_access_token": { + "name": "google_access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "google_refresh_token": { + "name": "google_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "date", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sites": { + "name": "sites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sites_user_id_users_id_fk": { + "name": "sites_user_id_users_id_fk", + "tableFrom": "sites", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "google_id": { + "name": "google_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uploads_playlist_id": { + "name": "uploads_playlist_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/db/migrations/meta/0006_snapshot.json b/src/db/migrations/meta/0006_snapshot.json new file mode 100644 index 0000000..b090d42 --- /dev/null +++ b/src/db/migrations/meta/0006_snapshot.json @@ -0,0 +1,209 @@ +{ + "id": "3ec0762e-c27b-4b7f-b4a6-4db07400a5ae", + "prevId": "4c4cea1e-1ffe-4736-b045-7dadd7e22244", + "version": "5", + "dialect": "pg", + "tables": { + "articles": { + "name": "articles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "site_id": { + "name": "site_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_video_id": { + "name": "source_video_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "articles_site_id_sites_id_fk": { + "name": "articles_site_id_sites_id_fk", + "tableFrom": "articles", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "google_access_token": { + "name": "google_access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "google_refresh_token": { + "name": "google_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sites": { + "name": "sites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sites_user_id_users_id_fk": { + "name": "sites_user_id_users_id_fk", + "tableFrom": "sites", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "google_id": { + "name": "google_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uploads_playlist_id": { + "name": "uploads_playlist_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/db/migrations/meta/_journal.json b/src/db/migrations/meta/_journal.json index 16da2ec..eae1bdd 100644 --- a/src/db/migrations/meta/_journal.json +++ b/src/db/migrations/meta/_journal.json @@ -5,9 +5,51 @@ { "idx": 0, "version": "5", - "when": 1686356934306, - "tag": "0000_plain_killmonger", - "breakpoints": false + "when": 1713532681066, + "tag": "0000_huge_ares", + "breakpoints": true + }, + { + "idx": 1, + "version": "5", + "when": 1713547912112, + "tag": "0001_slim_xavin", + "breakpoints": true + }, + { + "idx": 2, + "version": "5", + "when": 1713549800799, + "tag": "0002_small_forge", + "breakpoints": true + }, + { + "idx": 3, + "version": "5", + "when": 1713550262815, + "tag": "0003_elite_falcon", + "breakpoints": true + }, + { + "idx": 4, + "version": "5", + "when": 1713550343102, + "tag": "0004_daffy_ironclad", + "breakpoints": true + }, + { + "idx": 5, + "version": "5", + "when": 1713551541682, + "tag": "0005_tricky_sheva_callister", + "breakpoints": true + }, + { + "idx": 6, + "version": "5", + "when": 1713614011867, + "tag": "0006_wide_the_hunter", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/db/schemas.js b/src/db/schemas.js index a1de64c..770008f 100644 --- a/src/db/schemas.js +++ b/src/db/schemas.js @@ -1,7 +1,31 @@ -import { pgTable, serial, text, varchar } from "drizzle-orm/pg-core"; +import { date, foreignKey, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"; export const users = pgTable("users", { - id: serial("id").primaryKey(), - fullName: text("full_name"), - phone: varchar("phone", { length: 256 }), + id: uuid("id").defaultRandom().primaryKey(), + google_id: text("google_id"), + name: text("name"), + email: text("email"), + channel_id: text("channel_id"), + uploads_playlist_id: text("uploads_playlist_id") }); + +export const sessions = pgTable("sessions", { + id: uuid("id").defaultRandom().primaryKey(), + user_id: uuid("user_id").references(() => users.id), + access_token: text("google_access_token"), + refresh_token: text("google_refresh_token"), + expires_at: timestamp("expires_at") +}) + +export const site = pgTable("sites", { + id: uuid("id").defaultRandom().primaryKey(), + user_id: uuid("user_id").references(() => users.id), + name: text("name") +}) + +export const article = pgTable("articles", { + id: uuid("id").defaultRandom().primaryKey(), + site_id: uuid("site_id").references(() => site.id), + content: text("content"), + source_video_id: text("source_video_id") +}) \ No newline at end of file diff --git a/src/fastify.d.ts b/src/fastify.d.ts index ba01b9e..5053446 100644 --- a/src/fastify.d.ts +++ b/src/fastify.d.ts @@ -1,10 +1,21 @@ +import {OAuth2Namespace} from "@fastify/oauth2"; import type { db } from "./db"; import type { Redis } from "./utils"; declare module "fastify" { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions interface FastifyRequest { - db: typeof db; - redis: typeof Redis; + // db: typeof db; + // redis: typeof Redis; + session?: { + id: string, + user_id: string, + google_access_token: string, + google_refresh_token: string, + expires_at: Date + } + } + interface FastifyInstance { + googleOAuth2: OAuth2Namespace } } diff --git a/src/index.js b/src/index.js index 22e9a6b..97c8a11 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,10 @@ import { initDb } from "./db/index.js"; -import { testRoutes } from "./routes/index.js"; +import { channelRoutes, authRoutes } from "./routes/index.js"; import { env, Logger, Redis } from "./utils/index.js"; import fastify from "fastify"; import { middleware } from "./modules/middleware.js"; +import oauth from '@fastify/oauth2'; +import { videoRoutes } from "./routes/videos.js"; const API_VERSION = "v1"; @@ -13,7 +15,7 @@ export const main = async () => { }); await initDb(); - await Redis.initialize(); + // await Redis.initialize(); server.register(middleware); server.register(import("@fastify/cors"), { @@ -21,12 +23,45 @@ export const main = async () => { origin: true, credentials: true, }); + server.register(oauth, { + name: 'googleOAuth2', + scope: ['https://www.googleapis.com/auth/youtube.readonly', 'https://www.googleapis.com/auth/youtube.force-ssl', "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"], + credentials: { + client: { + id: '103003963446-6m80lqbe4bkgjv1nq5ihmju0bb6agkkg.apps.googleusercontent.com', + secret: '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' + }, + auth: oauth.GOOGLE_CONFIGURATION + }, + callbackUriParams: { + // custom query param that will be passed to callbackUri + access_type: 'offline', // will tell Google to send a refreshToken too + }, + pkce: 'S256', + // register a fastify url to start the redirect flow + startRedirectPath: '/auth/google', + // facebook redirect here after the user login + callbackUri: 'http://localhost:3000/auth/google/callback' + }) + // Routes - server.register(testRoutes, { - prefix: `/${API_VERSION}/test`, + server.register(channelRoutes, { + prefix: `/`, }); + server.register(videoRoutes, { + prefix: `/videos`, + }); + + server.register(authRoutes, { + prefix: `/auth`, + }); + + server.get("/hello", (req, res) => { + res.send("world"); + }) + server.listen({ host: env.HOST, port: env.PORT }, (error, address) => { if (error) { Logger.error("INIT", error.message); diff --git a/src/modules/middleware.js b/src/modules/middleware.js index 23700ba..83bab5b 100644 --- a/src/modules/middleware.js +++ b/src/modules/middleware.js @@ -2,6 +2,8 @@ import fp from "fastify-plugin"; import { Redis } from "../utils/index.js"; import { db } from "../db/index.js"; +import { sessions } from "../db/schemas.js"; +import { eq } from "drizzle-orm"; const middleware = fp( /** @@ -9,10 +11,34 @@ const middleware = fp( * @param {unknown} _options */ async (fastify, _options) => { - fastify.addHook("onRequest", async (request) => { - request.redis = Redis; - request.db = db; + fastify.addHook("onRequest", async (request) => { + // request.redis = Redis; + // request.db = db; + }); }); -}); -export { middleware }; +const authMiddleware = fp( + async (fastify, _options) => { + fastify.addHook("preValidation", async (request, response) => { + try { + if (!request.headers.authorization || !request.headers.authorization.startsWith("Bearer")) { + response.status(401).send("Missing authentication token"); + return; + } + const token = request.headers.authorization.split(" ")[1]; + const session = await db.select().from(sessions).where(eq(sessions.id, token)); + if(session.length == 0) { + response.status(401).send("Invalid authentication token"); + return; + } + // console.log(token); + // console.log(session); + request.session = session[0]; + } catch (e) { + console.log(e); + } + }); + } +) + +export { middleware, authMiddleware }; diff --git a/src/routes/auth.js b/src/routes/auth.js new file mode 100644 index 0000000..c88cb7d --- /dev/null +++ b/src/routes/auth.js @@ -0,0 +1,68 @@ +import sget from 'simple-get'; +import { createAuthToken as createSession } from '../utils/token.js'; +import { google } from 'googleapis'; +import { getChannelInfo, getUserInfo } from '../utils/youtube.js'; +import { db } from '../db/index.js'; +import { users as usersTable } from '../db/schemas.js'; +import { userInfo } from 'os'; +import { eq } from 'drizzle-orm'; + +/** @typedef {import("fastify").FastifyInstance} FastifyInstance */ +/** + * + * @param {FastifyInstance} fastify + * @param {unknown} _ + * @param {() => void} done + */ +export const authRoutes = (fastify, _, done) => { + fastify.get("/google/callback", async (request, response) => { + try { + const { token } = await fastify.googleOAuth2.getAccessTokenFromAuthorizationCodeFlow(request); + + const user_info = await getUserInfo(token.access_token); + if (!user_info.verified_email) { + response.status(400).send({ success: false, message: "Provider email is not verified" }); + return; + } + const channel_info = await getChannelInfo(token.access_token); + + const existing_user = await db.select().from(usersTable).where(eq(usersTable.google_id, user_info.id)).then(x=>x[0]); + let user; + + if (existing_user) { + user = existing_user; + } + else { + user = await db.insert(usersTable).values({ + name: user_info.name, + google_id: user_info.id, + email: user_info.email, + channel_id: channel_info.id, + uploads_playlist_id: channel_info.contentDetails.relatedPlaylists.uploads + }).returning({ id: usersTable.id }).then(x=>x[0]); + + if (user.length == 0) { + response.status(400).send({ success: false, message: "Problem when creating user account" }); + return; + } + } + + const session = await createSession(user.id, { + access_token: token.access_token, + refresh_token: token.refresh_token, + expires_at: new Date(token.expires_at) + }); + + response.send({ + token: session.session_id + }) + return; + } catch (e) { + console.log(e); + response.send({ success: false, message: e.message }); + return; + } + }); + + done(); +}; diff --git a/src/routes/channels.js b/src/routes/channels.js new file mode 100644 index 0000000..01433df --- /dev/null +++ b/src/routes/channels.js @@ -0,0 +1,36 @@ +/** @typedef {import("fastify").FastifyInstance} FastifyInstance */ + +import { authMiddleware } from "../modules/middleware.js"; +import { getChannelInfo } from "../utils/youtube.js"; + +/** + * + * @param {FastifyInstance} fastify + * @param {unknown} _ + * @param {() => void} done + */ +export const channelRoutes = (fastify, _, done) => { + fastify.register(authMiddleware); + + fastify.get("/", async (request, response) => { + try { + console.log(request.session); + + const { token } = await fastify.googleOAuth2.getNewAccessTokenUsingRefreshToken({ + refresh_token: request.session.google_refresh_token, + expires_at: request.session.expires_at + }); + console.log(token); + const channel = await getChannelInfo(token.access_token); + + response.send({ + success: true, + channel + }) + } catch (e) { + console.log(e); + } + }); + + done(); +}; diff --git a/src/routes/index.js b/src/routes/index.js index 22111de..b25e9f2 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1 +1,2 @@ -export * from "./test.js"; +export * from "./channels.js"; +export * from "./auth.js"; \ No newline at end of file diff --git a/src/routes/test.js b/src/routes/test.js deleted file mode 100644 index 0fa1f83..0000000 --- a/src/routes/test.js +++ /dev/null @@ -1,21 +0,0 @@ -/** @typedef {import("fastify").FastifyInstance} FastifyInstance */ - -/** - * - * @param {FastifyInstance} fastify - * @param {unknown} _ - * @param {() => void} done - */ -export const testRoutes = (fastify, _, done) => { - fastify.get("/", async (request, response) => { - const visits = Number(await request.redis.get("visits")); - - request.redis.incr("visits"); - response.send({ - hello: "world", - visits, - }); - }); - - done(); -}; diff --git a/src/routes/videos.js b/src/routes/videos.js new file mode 100644 index 0000000..804c7b7 --- /dev/null +++ b/src/routes/videos.js @@ -0,0 +1,61 @@ +/** @typedef {import("fastify").FastifyInstance} FastifyInstance */ + +import { eq } from "drizzle-orm"; +import { db } from "../db/index.js"; +import { users } from "../db/schemas.js"; +import { authMiddleware } from "../modules/middleware.js"; +import { getCaptionText, getNewToken, getVideoCaptions, getVideosFromPlaylist } from "../utils/youtube.js"; + +/** + * + * @param {FastifyInstance} fastify + * @param {unknown} _ + * @param {() => void} done + */ +export const videoRoutes = (fastify, _, done) => { + fastify.register(authMiddleware); + + fastify.get("/", async (request, response) => { + try { + const token = await getNewToken(fastify.googleOAuth2, request.session, {}); + const [user] = await db.select().from(users).where(eq(users.id, request.session.user_id)); + const videos = await getVideosFromPlaylist(token.access_token, user.uploads_playlist_id); + + response.send({ + success: true, + videos + }) + } catch (e) { + console.log(e); + } + }); + + fastify.get("/captions/:video_id", async (request, response) => { + try { + + const token = await getNewToken(fastify.googleOAuth2, request.session, {}); + const captions_list = await getVideoCaptions(token.access_token, request.params.video_id); + + const caption = captions_list.filter(x => x.snippet.language === "en"); + + if (caption.length === 0) { + response.send({ + success: false, + message: "Couldn't find caption" + }); + return; + } + + const caption_text = await getCaptionText(token.access_token, caption[0].id); + + response.send({ + captions_info: caption, + captions: caption_text + }); + } catch (e) { + console.log(e); + } + }) + + done(); +}; diff --git a/src/utils/token.js b/src/utils/token.js new file mode 100644 index 0000000..faa7aa1 --- /dev/null +++ b/src/utils/token.js @@ -0,0 +1,29 @@ +import { db } from "../db/index.js"; +import { sessions } from "../db/schemas.js"; + +/** + * + * @param {string} user_id User to assign the auth token to + * @param {{access_token: string, refresh_token: string, expires_at: Date}} googleAuth + * + * @returns {Promise<{session_id: string}>} Auth token + */ +export async function createAuthToken(user_id, { + access_token, + refresh_token, + expires_at +}) { + const token = await db.insert(sessions).values({ + user_id, + google_access_token: access_token, + google_refresh_token: refresh_token, + expires_at + }).returning({ id: sessions.id }); + if(token.length == 0) { + throw new Error("Error creating auth token"); + } + + return { + session_id: token[0].id + } +} \ No newline at end of file diff --git a/src/utils/youtube.js b/src/utils/youtube.js new file mode 100644 index 0000000..6535712 --- /dev/null +++ b/src/utils/youtube.js @@ -0,0 +1,112 @@ +import { db } from '../db/index.js'; +import { sessions } from '../db/schemas.js'; +import { google } from 'googleapis'; +const service = google.youtube("v3"); + + +/** + * + * @param {string} access_token + * @param {string} video_id + * + * @returns {Promise} + */ +export async function getVideoCaptions(access_token, video_id) { + const captions = await service.captions.list({ + access_token, + videoId: video_id, + part: "id,snippet" + }).then(x=>x.data.items); + + return captions; +} + +/** + * + * @param {string} access_token + * @param {string} caption_id + * + * @returns {Promise} + */ +export async function getCaptionText(access_token, caption_id) { + const caption_text = await service.captions.download({ + id: caption_id, + part: "snippet", + tfmt: "srt", + tlang: "en", + headers: { + "Authorization": "Bearer " + access_token + } + }).then(res=>res.data).then(x=>x.text()); + console.log(caption_text) + return caption_text; +} + +/** + * + * @param {string} access_token + * @param {string} playlist_id + * + * @returns {Promise} + */ +export async function getVideosFromPlaylist(access_token, playlist_id) { + const videos = await service.playlistItems.list({ + access_token, + part: "id,snippet", + playlistId: playlist_id, + maxResults: 10 + }).then(res => res); + + return videos.data.items; +} + +/** + * + * @param {string} access_token + * + * @returns {Promise} + */ +export async function getChannelInfo(access_token) { + const channel = await service.channels.list({ + access_token, + part: "id,contentDetails,snippet", + mine: true, + maxResults: 1 + }).then(res => res); + + return channel.data.items[0]; +} + +/** @typedef {{name: string, email: string, isVerified: boolean}} UserInfo */ + +/** + * + * @param {string} access_token + * + * @returns {Promise} + */ +export async function getUserInfo(access_token) { + const url = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json"; + // const url = "https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses"; + const response = await fetch(url, { + headers: { + "Authorization": `Bearer ${access_token}` + } + }) + const data = await response.json(); + + return data +} + +/** + * + * @param {import('@fastify/oauth2').OAuth2Namespace} oauth + * @param {import('@fastify/oauth2').Token} session + * + * @returns {Promise} + */ +export async function getNewToken(oauth, session) { + const {token} = await oauth.getNewAccessTokenUsingRefreshToken(session, {}); + + return token; +} \ No newline at end of file diff --git a/test.md b/test.md new file mode 100644 index 0000000..b32b2f8 --- /dev/null +++ b/test.md @@ -0,0 +1,240 @@ +last week AMD launched their new +graphics cards and I already reviewed +the RX 7900 XTX so today I'm going to +talk about this RX 7900 XT now I did not +have a chance to test the reference card +but I do have this tough gaming model +from Asus and while I do think that AMD +has done a great job at creating +high-end graphics cards and bringing +some well needed competition to the +market I also think that there are +plenty of things that still need a bit +of work and that should be improved so +I'm going to take a bit of a different +approach today and I'm going to talk +about my issues with this 7900 XT let's +go this video is brought to you by +Corsair and their brand new Dominator +Platinum RGB memory these super fast +ddr5 6000 Hertz memory kits are +specifically made for ryzen 7000 series +CPUs they feature a stylish aluminum +heat spreader with dhx technology that +keeps them nice and cool under load +offering a smooth and stable performance +with a lot out of room for overclocking +and they come with 12 customizable +kapelix LEDs that you can control with +their IQ software and easily sync up +with your other coarser components check +them out using the links in the +description below one of the first and +most obvious issues I had with this card +is its name the RX 7900 XT sounds very +similar to the 7900 XTX even though when +we look at the specs you can see that +they are vastly different the XCX has +more cores higher clock speeds more +memory and a bigger memory bus than the +XT and I don't think that removing One X +at the end of the product name is enough +to distinguish and obviously lower tier +card from a higher tier one it just +causes a lot of confusion especially for +the less informed consumers that might +think that they are buying a very +similar product for a hundred dollars +less which is definitely not the case +here now Nvidia received a lot of +criticism for their 4086 16 gig and 4080 +12 gig cards and AMD here is pretty much +doing the same thing the XT is more than +15 slower than the xdx and they should +have called it a 7800 XT or at least a +7900 without any X's just to make it a +bit more obvious to everyone and that +brings me to my next issue the relative +performance because the XT is priced so +closely to the XTX its performance +should also be at a close distance +compared to the xdx and that is +definitely not the case here so the xt's +recommended price is only 10 lower than +the xdx but when it comes to Performance +the XTX is 16 faster than the XD and +keep in mind I was using the relatively +fast third-party version of the XT so +for 100 more you can get a card that is +16 faster and if you already decided to +spend 900 on a GPU upgrading to dxdx for +a hundred dollars more just seems like a +logical choice and that pressure from +the relative performance is a bit of a +shame because in absolute terms the XT +is a pretty powerful chip at 1440p +resolution it shows a great High refresh +rate experience in every game I've +tested and most games will easily run at +144 FPS or above but even the heaviest +titles like Dying Light 2 and cyberpunk +2077 for example will get pretty close +to that at 4K resolution the XC does +well offering that 4K 120 experience in +lighter titles and 60-ish FPS or above +in heavier games amd's FSR has also been +adopted by a lot of game developers so +for the titles that do support it this +7900 XT is actually a very capable 4K +gaming card as well but should you buy a +much stronger XTX for 100 more +absolutely now the next issue I had was +performance inconsistency when testing +Call of Duty Modern Warfare we were +getting really inconsistent results so +one moment the XT would be running at +around 2400 megahertz showing FPS +numbers that kind of fall in line with +other cards but during some other runs +it would suddenly boost much higher +somewhere closer to 2 900 megahertz +which would result in a much higher +average FPS and which would put it above +the RTX 4090 and the 7900 XDS and there +was absolutely no logic behind it so it +was the same system same settings no +updates in between the CPU wasn't +throttling or anything else that we can +think of actually so every time we +reboot the PC it would act differently +for no clear reason now in this +particular game it doesn't really matter +as much because in the worst case +scenario it was close to an RTX 4090 and +in the best case scenario it was +actually beating it which is definitely +not bad for a GPU that costs half as +much but seeing this inconsistent +Behavior always causes doubt whether +everything is working well as it should +and what kind of an impact does it have +in titles where this card was not doing +as well but AMD has been on top of this +since I mentioned it and they are trying +to figure it out but there are no clear +answers just yet now hopefully they will +come up with a driver update that will +stabilize this situation a bit more now +my next issue is a really noticeable one +coil line in my review of the XTX I +mentioned that my reference card had +some coil line now coil wine is mostly +sample specific and then it is often +specific to certain games or super high +FPS gameplay but the XT here had a +noticeable amount of coal wine regularly +and since the launch a lot of reviewers +as well as people who bought their cards +frequently mentioned coil wine too both +in reference cards as well as third +party cards so this tough gaming from +Asus doesn't always whine but it does +sit pretty frequently and since the +sound often changes depending on what's +going on with your PC it is way more +noticeable than if it was just a +consistent tone I did manage to test the +thermal and noise performance at one +point where it wasn't whining and this +oversized tough cooler performed +extremely well barely going over 50 +degrees with almost no noise at all and +even though this should be a great +cooler design it is only quiet sometimes +the other times it is just super whiny +and given the fact that these reports +are so widespread with all sorts of +Radeon cards it just feels like this is +something that AMD really needs to work +on my next issue is the power +consumption especially in idle when +having multiple monitors connected to +your cart if I just connect a single +monitor power consumption is completely +fine with a single watt of a difference +between the 4080 and this 7900 XD but +when connecting two monitors so I had +one 4K 120 hertz one and one 4K 60hz one +the power consumption on the XT went up +by a lot it was 15 watts higher than the +4080 and I would say that is a +significant change now depending on how +much you pay for your electricity and +how many hours you have your monitors on +per day this could really add up quickly +now supposedly this should get fixed +with the next driver so I will put an +update in the comment under this video +once I learn more about this +but perhaps the biggest issue right now +is the supply and pricing before these +cards launch there were plenty of posts +saying that there should be plenty of +stock and that the prices should be as +promised but in reality the supply so +far hasn't been as good it will vary per +region but if I look at the Netherlands +I haven't seen a single xdx listed at +any reputable retailer and even the XT +which had more critical reviews overall +has been really hard to find most shops +I spoke to told me that they have no +clear indication of stock on any Radeon +cards at this point and the couple shops +that did list the XT seem to have very +limited stock and they're selling them +at very high prices so right now the +cheapest one I can find is at 1300 Euros +which is 250 euros over the MSRP and +only about 150 Euros less than a 4080 +and a 4080 is faster has stronger Ray +tracing performance and it is more power +efficient and I think all this was much +worse because of the hype that followed +the AMD launch and the belief that there +might actually be some stock or that the +prices might actually stay down anyway +the launch was definitely a bit shaky +but it is important to remember that +most of the things I mentioned today are +absolutely fixable and that was the +reason of making this video because I +know know that AMD cares about criticism +and that they do want to fix things for +the end users at least the things that +can be fixed because as I said before +the absolute performance of this 7900 XT +is quite good and the only way to fix +their relative performance is to lower +the price because if it gets +significantly cheaper I'm sure that most +of us just would not care about the +confusing name business or the fact that +it is boosting a bit higher one day and +then a bit lower the next now the coil +wine is a bit more complicated to fix +especially for the cars that already +love the factory but for future batches +that too is definitely fixable and they +definitely should fix it because the GPU +Market is so competitive and even a +single downside like coil wine for +example can make a big difference at the +end of the day now that is all I have +for today I hope this video was +interesting enough let me know in the +comments down below what are your +thoughts about the XD and if you want to +make sure not to miss any of my future +videos try to click that subscribe +button bye guys and see in the next one \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 22cdd89..f24dfc5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -371,6 +371,14 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.0.tgz#0709e9f4cb252351c609c6e6d8d6779a8d25edff" integrity sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA== +"@fastify/cookie@^9.0.4": + version "9.3.1" + resolved "https://registry.yarnpkg.com/@fastify/cookie/-/cookie-9.3.1.tgz#48b89a356a23860c666e2fe522a084cc5c943d33" + integrity sha512-h1NAEhB266+ZbZ0e9qUE6NnNR07i7DnNXWG9VbbZ8uC6O/hxHpl+Zoe5sw1yfdZ2U6XhToUGDnzQtWJdCaPwfg== + dependencies: + cookie-signature "^1.1.0" + fastify-plugin "^4.0.0" + "@fastify/cors@^8.4.2": version "8.4.2" resolved "https://registry.yarnpkg.com/@fastify/cors/-/cors-8.4.2.tgz#5a3af71a356def991d49d78fe9982fba504d3d0a" @@ -396,6 +404,58 @@ dependencies: fast-json-stringify "^5.7.0" +"@fastify/oauth2@^7.8.0": + version "7.8.0" + resolved "https://registry.yarnpkg.com/@fastify/oauth2/-/oauth2-7.8.0.tgz#0b35351aceec375baf9621cc6b14e388fbef8260" + integrity sha512-piQldGFUfAH0+SXM7Cw6hlanFmYnTWYtDC3EcbxNiQedAbr9SbGNxJynTHsvyKzRO7dupdxIdWA81k1egxKftQ== + dependencies: + "@fastify/cookie" "^9.0.4" + fastify-plugin "^4.5.1" + simple-oauth2 "^5.0.0" + +"@hapi/boom@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-10.0.1.tgz#ebb14688275ae150aa6af788dbe482e6a6062685" + integrity sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA== + dependencies: + "@hapi/hoek" "^11.0.2" + +"@hapi/bourne@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-3.0.0.tgz#f11fdf7dda62fe8e336fa7c6642d9041f30356d7" + integrity sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w== + +"@hapi/hoek@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-10.0.1.tgz#ee9da297fabc557e1c040a0f44ee89c266ccc306" + integrity sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw== + +"@hapi/hoek@^11.0.2": + version "11.0.4" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-11.0.4.tgz#42a7f244fd3dd777792bfb74b8c6340ae9182f37" + integrity sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ== + +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@hapi/wreck@^18.0.0": + version "18.1.0" + resolved "https://registry.yarnpkg.com/@hapi/wreck/-/wreck-18.1.0.tgz#68e631fc7568ebefc6252d5b86cb804466c8dbe6" + integrity sha512-0z6ZRCmFEfV/MQqkQomJ7sl/hyxvcZM7LtuVqN3vdAO4vM9eBbowl0kaqQj9EJJQab+3Uuh1GxbGIBFy4NfJ4w== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/bourne" "^3.0.0" + "@hapi/hoek" "^11.0.2" + "@humanwhocodes/config-array@^0.11.13": version "0.11.13" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" @@ -482,6 +542,23 @@ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.5.tgz#a6d70ef7a0e71e083ea09b967df0a0ed742bc6ad" integrity sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg== +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@types/cli-color@^2.0.6": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/cli-color/-/cli-color-2.0.6.tgz#becc4b0c8509bbc938e7c3b2b7a0a8dd64691d08" @@ -670,6 +747,13 @@ acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== +agent-base@^7.0.2: + version "7.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -844,7 +928,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.3.1: +base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -854,6 +938,11 @@ big-integer@^1.6.44: resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== +bignumber.js@^9.0.0: + version "9.1.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" + integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -893,6 +982,11 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -939,6 +1033,17 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: get-intrinsic "^1.2.1" set-function-length "^1.1.1" +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -1066,6 +1171,11 @@ confusing-browser-globals@1.0.11: resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== +cookie-signature@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.1.tgz#790dea2cce64638c7ae04d9fabed193bd7ccf3b4" + integrity sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw== + cookie@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" @@ -1110,6 +1220,13 @@ data-uri-to-buffer@^2.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz#d296973d5a4897a5dbe31716d118211921f04770" integrity sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA== +debug@4, debug@^4.0.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1117,12 +1234,12 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.0.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: - ms "2.1.2" + mimic-response "^3.1.0" deep-is@^0.1.3: version "0.1.4" @@ -1156,6 +1273,15 @@ define-data-property@^1.0.1, define-data-property@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -1240,6 +1366,13 @@ drizzle-orm@^0.29.1: resolved "https://registry.yarnpkg.com/drizzle-orm/-/drizzle-orm-0.29.1.tgz#0c93efed19718a851d97d23d9ff2dd8b788faf2d" integrity sha512-yItc4unfHnk8XkDD3/bdC63vdboTY7e7I03lCF1OJYABXSIfQYU9BFTQJXMMovVeb3T1/OJWwfW/70T1XPnuUA== +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1318,6 +1451,18 @@ es-abstract@^1.22.1: unbox-primitive "^1.0.2" which-typed-array "^1.1.13" +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-set-tostringtag@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" @@ -1813,6 +1958,11 @@ ext@^1.1.2: dependencies: type "^2.7.2" +extend@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + fast-content-type-parse@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz#4087162bf5af3294d4726ff29b334f72e3a1092c" @@ -2062,6 +2212,25 @@ functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gaxios@^6.0.0, gaxios@^6.0.3, gaxios@^6.1.1: + version "6.5.0" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-6.5.0.tgz#21bc20e24f21189ce8907079b56205ff9fd2c0d7" + integrity sha512-R9QGdv8j4/dlNoQbX3hSaK/S0rkMijqjVvW3YM06CoBdbU/VdKd159j4hePpng0KuE6Lh6JJ7UdmVGJZFcAG1w== + dependencies: + extend "^3.0.2" + https-proxy-agent "^7.0.1" + is-stream "^2.0.0" + node-fetch "^2.6.9" + uuid "^9.0.1" + +gcp-metadata@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-6.1.0.tgz#9b0dd2b2445258e7597f2024332d20611cbd6b8c" + integrity sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg== + dependencies: + gaxios "^6.0.0" + json-bigint "^1.0.0" + generic-pool@3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4" @@ -2077,6 +2246,17 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" +get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-set-props@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-set-props/-/get-set-props-0.1.0.tgz#998475c178445686d0b32246da5df8dbcfbe8ea3" @@ -2201,6 +2381,38 @@ globby@^13.2.2: merge2 "^1.4.1" slash "^4.0.0" +google-auth-library@^9.0.0, google-auth-library@^9.7.0: + version "9.8.0" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.8.0.tgz#43ae0f72dd72f49fd6a4a46d8eeffe2236691b20" + integrity sha512-TJJXFzMlVGRlIH27gYZ6XXyPf5Y3OItsKFfefsDAafNNywYRTkei83nEO29IrYj8GtdHWU78YnW+YZdaZaXIJA== + dependencies: + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + gaxios "^6.1.1" + gcp-metadata "^6.1.0" + gtoken "^7.0.0" + jws "^4.0.0" + +googleapis-common@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/googleapis-common/-/googleapis-common-7.1.0.tgz#e97e468a7ef2f230df8255c0f66701cf7e28947c" + integrity sha512-p3KHiWDBBWJEXk6SYauBEvxw5+UmRy7k2scxGtsNv9eHsTbpopJ3/7If4OrNnzJ9XMLg3IlyQXpVp8YPQsStiw== + dependencies: + extend "^3.0.2" + gaxios "^6.0.3" + google-auth-library "^9.7.0" + qs "^6.7.0" + url-template "^2.0.8" + uuid "^9.0.0" + +googleapis@^134.0.0: + version "134.0.0" + resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-134.0.0.tgz#1cde101a00916c677384b76bcd0eea57cf3f80bd" + integrity sha512-o8LhD1754W6MHWtpwAPeP1WUHgNxuMxCnLMDFlMKAA5kCMTNqX9/eaTXnkkAIv6YRfoKMQ6D1vyR6/biXuhE9g== + dependencies: + google-auth-library "^9.0.0" + googleapis-common "^7.0.0" + gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -2218,6 +2430,14 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +gtoken@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-7.1.0.tgz#d61b4ebd10132222817f7222b1e6064bd463fc26" + integrity sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw== + dependencies: + gaxios "^6.0.0" + jws "^4.0.0" + hanji@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/hanji/-/hanji-0.0.5.tgz#22a5092e53b2a83ed6172c488ae0d68eb3119213" @@ -2248,6 +2468,13 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.2.2" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + has-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" @@ -2287,6 +2514,14 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== +https-proxy-agent@^7.0.1: + version "7.0.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" + integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -2643,6 +2878,17 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +joi@^17.6.4: + version "17.12.3" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.12.3.tgz#944646979cd3b460178547b12ba37aca8482f63d" + integrity sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g== + dependencies: + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -2670,6 +2916,13 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -2718,6 +2971,23 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -2891,6 +3161,11 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + min-indent@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -2982,6 +3257,13 @@ next-tick@1, next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -3065,7 +3347,7 @@ on-exit-leak-free@^2.1.0: resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w== -once@^1.3.0: +once@^1.3.0, once@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -3489,6 +3771,13 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +qs@^6.7.0: + version "6.12.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a" + integrity sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ== + dependencies: + side-channel "^1.0.6" + queue-lit@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/queue-lit/-/queue-lit-1.5.0.tgz#8197fdafda1edd615c8a0fc14c48353626e5160a" @@ -3690,6 +3979,11 @@ safe-array-concat@^1.0.1: has-symbols "^1.0.3" isarray "^2.0.5" +safe-buffer@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -3756,6 +4050,18 @@ set-function-length@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + set-function-name@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" @@ -3786,11 +4092,45 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-oauth2@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/simple-oauth2/-/simple-oauth2-5.0.0.tgz#3b7d85700944b26f8f5451c017426292f330460c" + integrity sha512-8291lo/z5ZdpmiOFzOs1kF3cxn22bMj5FFH+DNUppLJrpoIlM1QnFiE7KpshHu3J3i21TVcx4yW+gXYjdCKDLQ== + dependencies: + "@hapi/hoek" "^10.0.1" + "@hapi/wreck" "^18.0.0" + debug "^4.3.4" + joi "^17.6.4" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -4042,6 +4382,11 @@ toad-cache@^3.3.0: resolved "https://registry.yarnpkg.com/toad-cache/-/toad-cache-3.4.1.tgz#a3506a9e0f877d751832083e2ee4ed8fb151b3e5" integrity sha512-T0m3MxP3wcqW0LaV3dF1mHBU294sgYSm4FOpa5eEJaYO7PqJZBOjZEQI1y4YaKNnih1FXCEYTWDS9osCoTUefg== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-api-utils@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" @@ -4220,6 +4565,16 @@ url-or-path@^2.1.0: resolved "https://registry.yarnpkg.com/url-or-path/-/url-or-path-2.3.0.tgz#61a49523b96cec6764c9c37ba4762946f9c39dba" integrity sha512-5g9xpEJKjbAY8ikLU3XFpEg3hRLGt6SbCQmDElb1AL7JTW6vMi5Na5e3dMvONHisIu9VHgMAADLHJ8EznYR2ow== +url-template@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" + integrity sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw== + +uuid@^9.0.0, uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -4228,6 +4583,19 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"