feat(client): allow implicit storage usage

This commit is contained in:
alina 🌸 2023-11-30 23:39:53 +03:00
parent 93ddc6a58c
commit c42c629475
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
12 changed files with 91 additions and 13 deletions

View file

@ -30,7 +30,8 @@
}, },
"browser": { "browser": {
"./src/methods/files/_platform.js": "./src/methods/files/_platform.web.js", "./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": { "dependencies": {
"@mtcute/core": "workspace:^", "@mtcute/core": "workspace:^",

View file

@ -258,6 +258,7 @@ async function addSingleMethod(state, fileName) {
const isExported = (stmt.modifiers || []).find((mod) => mod.kind === ts.SyntaxKind.ExportKeyword) const isExported = (stmt.modifiers || []).find((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)
const isInitialize = checkForFlag(stmt, '@initialize') const isInitialize = checkForFlag(stmt, '@initialize')
const isInitializeSuper = isInitialize === 'super'
const aliases = (function () { const aliases = (function () {
const flag = checkForFlag(stmt, '@alias') const flag = checkForFlag(stmt, '@alias')
if (!flag) return [] if (!flag) return []
@ -295,8 +296,12 @@ async function addSingleMethod(state, fileName) {
while (code[code.length - 1] !== '}') code = code.slice(0, -1) while (code[code.length - 1] !== '}') code = code.slice(0, -1)
code = code.slice(1, -1).trim() code = code.slice(1, -1).trim()
if (isInitializeSuper) {
state.init.unshift(code)
} else {
state.init.push(code) state.init.push(code)
} }
}
if (!isExported) continue 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`)) state.fields.forEach(({ code }) => output.write(`protected ${code}\n`))
output.write('constructor(opts: TelegramClientOptions) {\n') output.write('constructor(opts: TelegramClientOptions) {\n')
output.write('super(opts)\n')
state.init.forEach((code) => { state.init.forEach((code) => {
output.write(code + '\n') output.write(code + '\n')
}) })

View file

@ -3,6 +3,7 @@
import { import {
BaseTelegramClient, BaseTelegramClient,
BaseTelegramClientOptions, BaseTelegramClientOptions,
ITelegramStorage,
Long, Long,
MaybeArray, MaybeArray,
MaybeAsync, MaybeAsync,
@ -10,6 +11,7 @@ import {
PartialOnly, PartialOnly,
tl, tl,
} from '@mtcute/core' } from '@mtcute/core'
import { MemoryStorage } from '@mtcute/core/src/storage/memory.js'
import { tdFileId } from '@mtcute/file-id' import { tdFileId } from '@mtcute/file-id'
import { AuthState, getAuthState } from './methods/auth/_state.js' import { AuthState, getAuthState } from './methods/auth/_state.js'
@ -317,9 +319,21 @@ import {
UserStatusUpdate, UserStatusUpdate,
UserTypingUpdate, UserTypingUpdate,
} from './types/index.js' } from './types/index.js'
import { _defaultStorageFactory } from './utils/platform/storage.js'
// from methods/_init.ts // from methods/_init.ts
interface TelegramClientOptions extends BaseTelegramClientOptions { interface TelegramClientOptions extends Omit<BaseTelegramClientOptions, 'storage'> {
/**
* 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. * Parameters for updates manager.
*/ */
@ -5079,8 +5093,17 @@ export type { TelegramClientOptions }
export class TelegramClient extends BaseTelegramClient { export class TelegramClient extends BaseTelegramClient {
constructor(opts: TelegramClientOptions) { 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) super(opts)
/* eslint-enable @typescript-eslint/no-unsafe-call */
if (!opts.disableUpdates) { if (!opts.disableUpdates) {
const { messageGroupingInterval, ...managerParams } = opts.updates ?? {} const { messageGroupingInterval, ...managerParams } = opts.updates ?? {}

View file

@ -3,6 +3,7 @@
import { import {
BaseTelegramClient, BaseTelegramClient,
BaseTelegramClientOptions, BaseTelegramClientOptions,
ITelegramStorage,
Long, Long,
MaybeArray, MaybeArray,
MaybeAsync, MaybeAsync,

View file

@ -1,12 +1,14 @@
/* eslint-disable @typescript-eslint/no-unused-vars */ /* 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' import { TelegramClient } from '../client.js'
// @copy // @copy
import { Conversation } from '../types/conversation.js' import { Conversation } from '../types/conversation.js'
// @copy // @copy
import { logOut } from './auth/log-out.js' import { _defaultStorageFactory } from '../utils/platform/storage.js'
// @copy // @copy
import { start } from './auth/start.js' import { start } from './auth/start.js'
// @copy // @copy
@ -18,13 +20,39 @@ import {
} from './updates/index.js' } from './updates/index.js'
// @copy // @copy
interface TelegramClientOptions extends BaseTelegramClientOptions { interface TelegramClientOptions extends Omit<BaseTelegramClientOptions, 'storage'> {
/**
* 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. * Parameters for updates manager.
*/ */
updates?: Omit<ParsedUpdateHandlerParams & UpdatesManagerParams, 'onUpdate' | 'onRawUpdate'> updates?: Omit<ParsedUpdateHandlerParams & UpdatesManagerParams, 'onUpdate' | 'onRawUpdate'>
} }
// @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 // @initialize
/** @internal */ /** @internal */
function _initializeClient(this: TelegramClient, opts: TelegramClientOptions) { function _initializeClient(this: TelegramClient, opts: TelegramClientOptions) {

View file

@ -0,0 +1,6 @@
import { JsonFileStorage } from '@mtcute/core/src/storage/json-file.js'
/** @internal */
export const _defaultStorageFactory = (name: string) => {
return new JsonFileStorage(name)
}

View file

@ -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!')
}

View file

@ -34,6 +34,10 @@
"./network/transports/*.js": { "./network/transports/*.js": {
"import": "./esm/network/transports/*.js", "import": "./esm/network/transports/*.js",
"require": "./cjs/network/transports/*.js" "require": "./cjs/network/transports/*.js"
},
"./storage/*.js": {
"import": "./esm/storage/*.js",
"require": "./cjs/storage/*.js"
} }
} }
}, },

View file

@ -42,7 +42,7 @@ export interface BaseTelegramClientOptions {
apiHash: string apiHash: string
/** /**
* Telegram storage to use. * Storage to use for this client.
*/ */
storage: ITelegramStorage storage: ITelegramStorage

View file

@ -1,5 +1 @@
export * from './abstract.js' export * from './abstract.js'
export * from './json.js'
export * from './json-file.js'
export * from './localstorage.js'
export * from './memory.js'

View file

@ -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' import { createAesIgeForMessage, ICryptoProvider } from '@mtcute/core/utils.js'
export class StubMemoryTelegramStorage extends MemoryStorage implements ITelegramStorage { export class StubMemoryTelegramStorage extends MemoryStorage implements ITelegramStorage {

View file

@ -1,6 +1,7 @@
import { describe, expect, it } from 'vitest' import { describe, expect, it } from 'vitest'
import { BaseTelegramClient } from '@mtcute/core' import { BaseTelegramClient } from '@mtcute/core'
import { MemoryStorage } from '@mtcute/core/src/storage/memory.js'
import { createStub } from './stub.js' import { createStub } from './stub.js'
import { StubTelegramTransport } from './transport.js' import { StubTelegramTransport } from './transport.js'
@ -17,6 +18,7 @@ describe('transport stub', () => {
main: createStub('dcOption', { ipAddress: '1.2.3.4', port: 1234 }), main: createStub('dcOption', { ipAddress: '1.2.3.4', port: 1234 }),
media: createStub('dcOption', { ipAddress: '1.2.3.4', port: 5678 }), media: createStub('dcOption', { ipAddress: '1.2.3.4', port: 5678 }),
}, },
storage: new MemoryStorage(),
transport: () => transport: () =>
new StubTelegramTransport({ new StubTelegramTransport({
onConnect: (dc, testMode) => { onConnect: (dc, testMode) => {