From 3162aea5a5cce56d6fa94582731030c8f5989b0a Mon Sep 17 00:00:00 2001 From: ayoubqrt Date: Sun, 11 Feb 2024 10:34:38 +0100 Subject: [PATCH] feat: add support of cloudflare workers --- examples/cloudflare-worker/package.json | 18 ++++++ examples/cloudflare-worker/src/index.ts | 19 +++++++ examples/cloudflare-worker/tsconfig.json | 19 +++++++ examples/cloudflare-worker/wrangler.toml | 3 + package.json | 10 +++- src/platform/cf-worker.ts | 71 ++++++++++++++++++++++++ src/types/PlatformShim.ts | 2 +- src/utils/HTTPClient.ts | 4 +- 8 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 examples/cloudflare-worker/package.json create mode 100644 examples/cloudflare-worker/src/index.ts create mode 100644 examples/cloudflare-worker/tsconfig.json create mode 100644 examples/cloudflare-worker/wrangler.toml create mode 100644 src/platform/cf-worker.ts diff --git a/examples/cloudflare-worker/package.json b/examples/cloudflare-worker/package.json new file mode 100644 index 000000000..54758ae57 --- /dev/null +++ b/examples/cloudflare-worker/package.json @@ -0,0 +1,18 @@ +{ + "name": "cf-worker", + "version": "0.0.0", + "private": true, + "scripts": { + "deploy": "wrangler deploy", + "dev": "wrangler dev", + "start": "wrangler dev" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20240208.0", + "typescript": "^5.0.4", + "wrangler": "^3.0.0" + }, + "dependencies": { + "youtubei.js": "latest" + } +} diff --git a/examples/cloudflare-worker/src/index.ts b/examples/cloudflare-worker/src/index.ts new file mode 100644 index 000000000..c8436dc46 --- /dev/null +++ b/examples/cloudflare-worker/src/index.ts @@ -0,0 +1,19 @@ +import { Innertube } from "youtubei.js/cf-worker"; + +export interface Env {} + +export default { + async fetch( + request: Request, + env: Env, + ctx: ExecutionContext + ): Promise { + // cannot initialize Innertube in global scope as it makes fetch requests + const yt = await Innertube.create(); + + const video = await yt.getInfo("jNQXAC9IVRw"); + console.log("Video title is", video.basic_info.title); + + return new Response("Hello World!"); + }, +}; diff --git a/examples/cloudflare-worker/tsconfig.json b/examples/cloudflare-worker/tsconfig.json new file mode 100644 index 000000000..ba13ec8d3 --- /dev/null +++ b/examples/cloudflare-worker/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es2021", + "lib": ["es2021"], + "jsx": "react", + "module": "es2022", + "moduleResolution": "node", + "types": ["@cloudflare/workers-types/2023-07-01"], + "resolveJsonModule": true, + "allowJs": true, + "checkJs": false, + "noEmit": true, + "isolatedModules": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + } +} diff --git a/examples/cloudflare-worker/wrangler.toml b/examples/cloudflare-worker/wrangler.toml new file mode 100644 index 000000000..e937d8c48 --- /dev/null +++ b/examples/cloudflare-worker/wrangler.toml @@ -0,0 +1,3 @@ +name = "cf-worker-youtubei" +main = "src/index.ts" +compatibility_date = "2024-02-08" \ No newline at end of file diff --git a/package.json b/package.json index e7914e138..10cdd2be5 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,9 @@ ], "web.bundle.min": [ "./dist/src/platform/lib.d.ts" + ], + "cf-worker": [ + "./dist/src/platform/lib.d.ts" ] } }, @@ -46,6 +49,10 @@ "./web.bundle.min": { "types": "./dist/src/platform/lib.d.ts", "default": "./bundle/browser.min.js" + }, + "./cf-worker": { + "types": "./dist/src/platform/lib.d.ts", + "default": "./dist/src/platform/cf-worker.js" } }, "author": "LuanRT (https://github.com/LuanRT)", @@ -68,7 +75,7 @@ "test": "npx jest --verbose", "lint": "npx eslint ./src", "lint:fix": "npx eslint --fix ./src", - "build": "npm run build:parser-map && npm run build:proto && npm run build:esm && npm run bundle:node && npm run bundle:browser && npm run bundle:browser:prod", + "build": "npm run build:parser-map && npm run build:proto && npm run build:esm && npm run bundle:node && npm run bundle:browser && npm run bundle:browser:prod && npm run bundle:cf-worker", "build:parser-map": "node ./scripts/gen-parser-map.mjs", "build:proto": "npx pb-gen-ts --entry-path=\"src/proto\" --out-dir=\"src/proto/generated\" --ext-in-import=\".js\"", "build:esm": "npx tspc", @@ -76,6 +83,7 @@ "bundle:node": "npx esbuild ./dist/src/platform/node.js --bundle --target=node10 --keep-names --format=cjs --platform=node --outfile=./bundle/node.cjs --external:jintr --external:undici --external:linkedom --external:tslib --sourcemap --banner:js=\"/* eslint-disable */\"", "bundle:browser": "npx esbuild ./dist/src/platform/web.js --banner:js=\"/* eslint-disable */\" --bundle --target=chrome58 --keep-names --format=esm --sourcemap --define:global=globalThis --conditions=module --outfile=./bundle/browser.js --platform=browser", "bundle:browser:prod": "npm run bundle:browser -- --outfile=./bundle/browser.min.js --minify", + "bundle:cf-worker": "npx esbuild ./dist/src/platform/cf-worker.js --banner:js=\"/* eslint-disable */\" --bundle --target=es2020 --keep-names --format=esm --sourcemap --define:global=globalThis --conditions=module --outfile=./bundle/cf-worker.js --platform=node", "prepare": "npm run build", "watch": "npx tsc --watch" }, diff --git a/src/platform/cf-worker.ts b/src/platform/cf-worker.ts new file mode 100644 index 000000000..e16d0bd14 --- /dev/null +++ b/src/platform/cf-worker.ts @@ -0,0 +1,71 @@ +import type { ICache } from '../types/Cache.js'; +import { Platform } from '../utils/Utils.js'; +import evaluate from './jsruntime/jinter.js'; +import { $INLINE_JSON } from 'ts-transformer-inline-file'; +import sha1Hash from './polyfills/web-crypto.js'; + +const { homepage, version, bugs } = $INLINE_JSON('../../package.json'); +const repo_url = homepage?.split('#')[0]; + +class Cache implements ICache { + #persistent_directory: string; + #persistent: boolean; + + constructor(persistent = false, persistent_directory?: string) { + this.#persistent_directory = persistent_directory || ''; + this.#persistent = persistent; + } + + get cache_dir() { + return this.#persistent ? this.#persistent_directory : ''; + } + + async get(key: string) { + const cache = await caches.open('yt-api'); + + const response = await cache.match(key); + if (!response) return undefined; + + return response.arrayBuffer(); + } + + async set(key: string, value: ArrayBuffer) { + + const cache = await caches.open('yt-api'); + cache.put(key, new Response(value)); + } + + async remove(key: string) { + const cache = await caches.open('yt-api'); + + await cache.delete(key); + } +} + +Platform.load({ + runtime: 'cf-worker', + info: { + version: version, + bugs_url: bugs?.url || `${repo_url}/issues`, + repo_url + }, + server: true, + Cache: Cache, + sha1Hash, + uuidv4() { + return crypto.randomUUID(); + }, + eval: evaluate, + fetch: fetch.bind(globalThis), + Request: Request, + Response: Response, + Headers: Headers, + FormData: FormData, + File: File, + ReadableStream: ReadableStream, + CustomEvent: CustomEvent +}); + +export * from './lib.js'; +import Innertube from './lib.js'; +export default Innertube; diff --git a/src/types/PlatformShim.ts b/src/types/PlatformShim.ts index 38e6f9b98..cae070517 100644 --- a/src/types/PlatformShim.ts +++ b/src/types/PlatformShim.ts @@ -1,6 +1,6 @@ import type { ICacheConstructor } from './Cache.js'; -export type Runtime = 'deno' | 'node' | 'browser' | 'unknown'; +export type Runtime = 'deno' | 'node' | 'browser' | 'cf-worker' | 'unknown'; export type FetchFunction = typeof fetch; diff --git a/src/utils/HTTPClient.ts b/src/utils/HTTPClient.ts index f954f5d4e..9d8b880a6 100644 --- a/src/utils/HTTPClient.ts +++ b/src/utils/HTTPClient.ts @@ -135,8 +135,8 @@ export default class HTTPClient { const response = await this.#fetch(request, { body: request_body, headers: request_headers, - credentials: 'include', - redirect: input instanceof Platform.shim.Request ? input.redirect : init?.redirect || 'follow' + redirect: input instanceof Platform.shim.Request ? input.redirect : init?.redirect || 'follow', + ...(Platform.shim.runtime !== 'cf-worker' ? { credentials: 'include' } : {}) }); // Check if 2xx