refactor!: cleanup platform support (#306)

* refactor!: cleanup platform support

* chore: lint

* fix: web platform

* feat: provide UniversalCache

Provide UniversalCache as a wrapper around Platform.shim.Cache.

* fix: invalid import

* refactor: remove isolated-vm support

* fix: type info

* refactor: cleanup exports

* fix: mark jintr as external dependency

In the bundled CJS node build, mark jintr as external.

* chore: add additional exports

web exports provide a way to select web implementation manually without
relying on the bundler to select it correctly from the "exports" field

web points to src/platform/web.js
web.bundle points to bundle/browser.js
web.bundle.browser points to bundle/browser.min.js

agnostic exports provide users of the library to provide their own
platform implementation without first importing the default one.

agnostic points to src/platform/lib.ts

* fix: toDash on web

* revert: eval is synchronous

* fix: use serializeDOM in FormatUtils

* ci: automate releases with `release-please`

* chore: clean up workflow files

* ci: fix NPM publish action

---------

Co-authored-by: LuanRT <luan.lrt4@gmail.com>
This commit is contained in:
Daniel Wykerd
2023-02-12 09:21:44 +02:00
committed by GitHub
parent a69e43bf3a
commit 2ccbe2ce62
504 changed files with 11184 additions and 6279 deletions

View File

@@ -1,8 +1,19 @@
import package_json from '../../package.json';
import { Memo } from '../parser/helpers';
import { FetchFunction } from './HTTPClient';
import userAgents from './user-agents.json';
import { Memo } from '../parser/helpers.js';
import PlatformShim, { FetchFunction } from '../types/PlatformShim.js';
import userAgents from './user-agents.js';
export class Platform {
static #shim: PlatformShim | undefined;
static load(platform: PlatformShim): void {
Platform.#shim = platform;
}
static get shim(): PlatformShim {
if (!Platform.#shim) {
throw new Error('Platform is not loaded');
}
return Platform.#shim;
}
}
export class InnertubeError extends Error {
date: Date;
version: string;
@@ -16,7 +27,7 @@ export class InnertubeError extends Error {
}
this.date = new Date();
this.version = package_json.version;
this.version = Platform.shim.info.version;
}
}
@@ -70,40 +81,8 @@ export function getRandomUserAgent(type: DeviceCategory): string {
return available_agents[random_index];
}
export async function sha1Hash(str: string): Promise<string> {
const SubtleCrypto = getRuntime() === 'node' ? (Reflect.get(module, 'require')('crypto').webcrypto as unknown as Crypto).subtle : window.crypto.subtle;
const byteToHex = [
'00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f',
'10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f',
'20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f',
'30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f',
'40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f',
'50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f',
'60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f',
'70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f',
'80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f',
'90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f',
'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af',
'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf',
'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf',
'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df',
'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef',
'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff'
];
function hex(arrayBuffer: ArrayBuffer): string {
const buff = new Uint8Array(arrayBuffer);
const hexOctets = [];
for (let i = 0; i < buff.length; ++i)
hexOctets.push(byteToHex[buff[i]]);
return hexOctets.join('');
}
return hex(await SubtleCrypto.digest('SHA-1', new TextEncoder().encode(str)));
}
/**
* Generates an authentication token from a cookies' sid.
* Generates an authentication token from a cookies' sid..js
* @param sid - Sid extracted from cookies
*/
export async function generateSidAuth(sid: string): Promise<string> {
@@ -111,7 +90,7 @@ export async function generateSidAuth(sid: string): Promise<string> {
const timestamp = Math.floor(new Date().getTime() / 1000);
const input = [ timestamp, sid, youtube ].join(' ');
const gen_hash = await sha1Hash(input);
const gen_hash = await Platform.shim.sha1Hash(input);
return [ 'SAPISIDHASH', [ timestamp, gen_hash ].join('_') ].join(' ');
}
@@ -177,36 +156,6 @@ export function hasKeys<T extends object, R extends (keyof T)[]>(params: T, ...k
return true;
}
export function uuidv4(): string {
if (getRuntime() === 'node') {
return Reflect.get(module, 'require')('crypto').webcrypto.randomUUID();
}
if (globalThis.crypto?.randomUUID()) {
return globalThis.crypto.randomUUID();
}
// See https://stackoverflow.com/a/2117523
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (cc) => {
const c = parseInt(cc);
return (c ^ window.crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16);
});
}
export type Runtime = 'node' | 'deno' | 'browser';
export function getRuntime(): Runtime {
if ((typeof process !== 'undefined') && (process?.versions?.node))
return 'node';
if (Reflect.has(globalThis, 'Deno'))
return 'deno';
return 'browser';
}
export function isServer(): boolean {
return [ 'node', 'deno' ].includes(getRuntime());
}
export async function* streamToIterable(stream: ReadableStream<Uint8Array>) {
const reader = stream.getReader();
@@ -262,7 +211,7 @@ export const debugFetch: FetchFunction = (input, init) => {
' body:\n${body_contents}`
);
return globalThis.fetch(input, init);
return Platform.shim.fetch(input, init);
};
export function u8ToBase64(u8: Uint8Array): string {