From c42c629475ff0fbc5ae01d72f4143f2689c4d772 Mon Sep 17 00:00:00 2001 From: Alina Sireneva Date: Thu, 30 Nov 2023 23:39:53 +0300 Subject: [PATCH] feat(client): allow implicit storage usage --- packages/client/package.json | 3 +- packages/client/scripts/generate-client.cjs | 8 +++-- packages/client/src/client.ts | 25 +++++++++++++- packages/client/src/methods/_imports.ts | 1 + packages/client/src/methods/_init.ts | 34 +++++++++++++++++-- packages/client/src/utils/platform/storage.ts | 6 ++++ .../client/src/utils/platform/storage.web.ts | 12 +++++++ packages/core/package.json | 4 +++ packages/core/src/base-client.ts | 2 +- packages/core/src/storage/index.ts | 4 --- packages/test/src/storage.ts | 3 +- packages/test/src/transport.test.ts | 2 ++ 12 files changed, 91 insertions(+), 13 deletions(-) create mode 100644 packages/client/src/utils/platform/storage.ts create mode 100644 packages/client/src/utils/platform/storage.web.ts diff --git a/packages/client/package.json b/packages/client/package.json index f8215ecf..79a0b71d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -30,7 +30,8 @@ }, "browser": { "./src/methods/files/_platform.js": "./src/methods/files/_platform.web.js", - "./src/methods/files/download-file.js": "./src/methods/files/download-file.web.js" + "./src/methods/files/download-file.js": "./src/methods/files/download-file.web.js", + "./src/utils/platform/storage.js": "./src/utils/platform/storage.web.js" }, "dependencies": { "@mtcute/core": "workspace:^", diff --git a/packages/client/scripts/generate-client.cjs b/packages/client/scripts/generate-client.cjs index e4bf48b7..02f59749 100644 --- a/packages/client/scripts/generate-client.cjs +++ b/packages/client/scripts/generate-client.cjs @@ -258,6 +258,7 @@ async function addSingleMethod(state, fileName) { const isExported = (stmt.modifiers || []).find((mod) => mod.kind === ts.SyntaxKind.ExportKeyword) const isInitialize = checkForFlag(stmt, '@initialize') + const isInitializeSuper = isInitialize === 'super' const aliases = (function () { const flag = checkForFlag(stmt, '@alias') if (!flag) return [] @@ -295,7 +296,11 @@ async function addSingleMethod(state, fileName) { while (code[code.length - 1] !== '}') code = code.slice(0, -1) code = code.slice(1, -1).trim() - state.init.push(code) + if (isInitializeSuper) { + state.init.unshift(code) + } else { + state.init.push(code) + } } if (!isExported) continue @@ -638,7 +643,6 @@ on(name: string, handler: (...args: any[]) => void): this\n`) state.fields.forEach(({ code }) => output.write(`protected ${code}\n`)) output.write('constructor(opts: TelegramClientOptions) {\n') - output.write('super(opts)\n') state.init.forEach((code) => { output.write(code + '\n') }) diff --git a/packages/client/src/client.ts b/packages/client/src/client.ts index a8ef31c0..ac6b6324 100644 --- a/packages/client/src/client.ts +++ b/packages/client/src/client.ts @@ -3,6 +3,7 @@ import { BaseTelegramClient, BaseTelegramClientOptions, + ITelegramStorage, Long, MaybeArray, MaybeAsync, @@ -10,6 +11,7 @@ import { PartialOnly, tl, } from '@mtcute/core' +import { MemoryStorage } from '@mtcute/core/src/storage/memory.js' import { tdFileId } from '@mtcute/file-id' import { AuthState, getAuthState } from './methods/auth/_state.js' @@ -317,9 +319,21 @@ import { UserStatusUpdate, UserTypingUpdate, } from './types/index.js' +import { _defaultStorageFactory } from './utils/platform/storage.js' // from methods/_init.ts -interface TelegramClientOptions extends BaseTelegramClientOptions { +interface TelegramClientOptions extends Omit { + /** + * Storage to use for this client. + * + * If a string is passed, it will be used as: + * - a path to a JSON file for Node.js + * - IndexedDB database name for browsers + * + * If omitted, {@link MemoryStorage} is used + */ + storage?: string | ITelegramStorage + /** * Parameters for updates manager. */ @@ -5079,8 +5093,17 @@ export type { TelegramClientOptions } export class TelegramClient extends BaseTelegramClient { constructor(opts: TelegramClientOptions) { + if (typeof opts.storage === 'string') { + opts.storage = _defaultStorageFactory(opts.storage) + } else if (!opts.storage) { + opts.storage = new MemoryStorage() + } + + /* eslint-disable @typescript-eslint/no-unsafe-call */ + // @ts-expect-error codegen super(opts) + /* eslint-enable @typescript-eslint/no-unsafe-call */ if (!opts.disableUpdates) { const { messageGroupingInterval, ...managerParams } = opts.updates ?? {} diff --git a/packages/client/src/methods/_imports.ts b/packages/client/src/methods/_imports.ts index ff779334..e5c3ca70 100644 --- a/packages/client/src/methods/_imports.ts +++ b/packages/client/src/methods/_imports.ts @@ -3,6 +3,7 @@ import { BaseTelegramClient, BaseTelegramClientOptions, + ITelegramStorage, Long, MaybeArray, MaybeAsync, diff --git a/packages/client/src/methods/_init.ts b/packages/client/src/methods/_init.ts index 9cca5bc0..89fb93df 100644 --- a/packages/client/src/methods/_init.ts +++ b/packages/client/src/methods/_init.ts @@ -1,12 +1,14 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { BaseTelegramClientOptions } from '@mtcute/core' +import { BaseTelegramClientOptions, ITelegramStorage } from '@mtcute/core' +// @copy +import { MemoryStorage } from '@mtcute/core/src/storage/memory.js' import { TelegramClient } from '../client.js' // @copy import { Conversation } from '../types/conversation.js' // @copy -import { logOut } from './auth/log-out.js' +import { _defaultStorageFactory } from '../utils/platform/storage.js' // @copy import { start } from './auth/start.js' // @copy @@ -18,13 +20,39 @@ import { } from './updates/index.js' // @copy -interface TelegramClientOptions extends BaseTelegramClientOptions { +interface TelegramClientOptions extends Omit { + /** + * Storage to use for this client. + * + * If a string is passed, it will be used as: + * - a path to a JSON file for Node.js + * - IndexedDB database name for browsers + * + * If omitted, {@link MemoryStorage} is used + */ + storage?: string | ITelegramStorage + /** * Parameters for updates manager. */ updates?: Omit } +// @initialize=super +/** @internal */ +function _initializeClientSuper(this: TelegramClient, opts: TelegramClientOptions) { + if (typeof opts.storage === 'string') { + opts.storage = _defaultStorageFactory(opts.storage) + } else if (!opts.storage) { + opts.storage = new MemoryStorage() + } + + /* eslint-disable @typescript-eslint/no-unsafe-call */ + // @ts-expect-error codegen + super(opts) + /* eslint-enable @typescript-eslint/no-unsafe-call */ +} + // @initialize /** @internal */ function _initializeClient(this: TelegramClient, opts: TelegramClientOptions) { diff --git a/packages/client/src/utils/platform/storage.ts b/packages/client/src/utils/platform/storage.ts new file mode 100644 index 00000000..3d580e99 --- /dev/null +++ b/packages/client/src/utils/platform/storage.ts @@ -0,0 +1,6 @@ +import { JsonFileStorage } from '@mtcute/core/src/storage/json-file.js' + +/** @internal */ +export const _defaultStorageFactory = (name: string) => { + return new JsonFileStorage(name) +} diff --git a/packages/client/src/utils/platform/storage.web.ts b/packages/client/src/utils/platform/storage.web.ts new file mode 100644 index 00000000..135f0b8c --- /dev/null +++ b/packages/client/src/utils/platform/storage.web.ts @@ -0,0 +1,12 @@ +import { IdbStorage } from '@mtcute/core/src/storage/idb.js' + +import { MtUnsupportedError } from '../../index.js' + +/** @internal */ +export const _defaultStorageFactory = (name: string) => { + if (typeof indexedDB !== 'undefined') { + return new IdbStorage(name) + } + + throw new MtUnsupportedError('No storage available!') +} diff --git a/packages/core/package.json b/packages/core/package.json index eb1924d1..0cf80661 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -34,6 +34,10 @@ "./network/transports/*.js": { "import": "./esm/network/transports/*.js", "require": "./cjs/network/transports/*.js" + }, + "./storage/*.js": { + "import": "./esm/storage/*.js", + "require": "./cjs/storage/*.js" } } }, diff --git a/packages/core/src/base-client.ts b/packages/core/src/base-client.ts index a044f0ac..ef258e8c 100644 --- a/packages/core/src/base-client.ts +++ b/packages/core/src/base-client.ts @@ -42,7 +42,7 @@ export interface BaseTelegramClientOptions { apiHash: string /** - * Telegram storage to use. + * Storage to use for this client. */ storage: ITelegramStorage diff --git a/packages/core/src/storage/index.ts b/packages/core/src/storage/index.ts index 29b3f9c7..2e9bd6cc 100644 --- a/packages/core/src/storage/index.ts +++ b/packages/core/src/storage/index.ts @@ -1,5 +1 @@ export * from './abstract.js' -export * from './json.js' -export * from './json-file.js' -export * from './localstorage.js' -export * from './memory.js' diff --git a/packages/test/src/storage.ts b/packages/test/src/storage.ts index 0d94796a..b4395dcb 100644 --- a/packages/test/src/storage.ts +++ b/packages/test/src/storage.ts @@ -1,4 +1,5 @@ -import { ITelegramStorage, MemoryStorage, MtArgumentError } from '@mtcute/core' +import { ITelegramStorage, MtArgumentError } from '@mtcute/core' +import { MemoryStorage } from '@mtcute/core/src/storage/memory.js' import { createAesIgeForMessage, ICryptoProvider } from '@mtcute/core/utils.js' export class StubMemoryTelegramStorage extends MemoryStorage implements ITelegramStorage { diff --git a/packages/test/src/transport.test.ts b/packages/test/src/transport.test.ts index 1e4a131a..5a42a15c 100644 --- a/packages/test/src/transport.test.ts +++ b/packages/test/src/transport.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest' import { BaseTelegramClient } from '@mtcute/core' +import { MemoryStorage } from '@mtcute/core/src/storage/memory.js' import { createStub } from './stub.js' import { StubTelegramTransport } from './transport.js' @@ -17,6 +18,7 @@ describe('transport stub', () => { main: createStub('dcOption', { ipAddress: '1.2.3.4', port: 1234 }), media: createStub('dcOption', { ipAddress: '1.2.3.4', port: 5678 }), }, + storage: new MemoryStorage(), transport: () => new StubTelegramTransport({ onConnect: (dc, testMode) => {