@mtcute/core 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/cjs/highlevel/methods/files/upload-file.js +9 -0
- package/cjs/highlevel/methods/files/upload-file.js.map +1 -1
- package/cjs/highlevel/types/files/utils.d.ts +9 -6
- package/cjs/highlevel/types/files/utils.js.map +1 -1
- package/cjs/network/network-manager.js +1 -1
- package/cjs/storage/index.d.ts +1 -0
- package/cjs/storage/index.js +1 -0
- package/cjs/storage/index.js.map +1 -1
- package/cjs/storage/sqlite/driver.d.ts +24 -0
- package/cjs/storage/sqlite/driver.js +129 -0
- package/cjs/storage/sqlite/driver.js.map +1 -0
- package/cjs/storage/sqlite/index.d.ts +17 -0
- package/cjs/storage/sqlite/index.js +35 -0
- package/cjs/storage/sqlite/index.js.map +1 -0
- package/cjs/storage/sqlite/repository/auth-keys.d.ts +20 -0
- package/cjs/storage/sqlite/repository/auth-keys.js +68 -0
- package/cjs/storage/sqlite/repository/auth-keys.js.map +1 -0
- package/cjs/storage/sqlite/repository/kv.d.ts +14 -0
- package/cjs/storage/sqlite/repository/kv.js +96 -0
- package/cjs/storage/sqlite/repository/kv.js.map +1 -0
- package/cjs/storage/sqlite/repository/peers.d.ts +16 -0
- package/cjs/storage/sqlite/repository/peers.js +77 -0
- package/cjs/storage/sqlite/repository/peers.js.map +1 -0
- package/cjs/storage/sqlite/repository/ref-messages.d.ts +16 -0
- package/cjs/storage/sqlite/repository/ref-messages.js +49 -0
- package/cjs/storage/sqlite/repository/ref-messages.js.map +1 -0
- package/cjs/storage/sqlite/types.d.ts +18 -0
- package/cjs/storage/sqlite/types.js +3 -0
- package/cjs/storage/sqlite/types.js.map +1 -0
- package/esm/highlevel/methods/files/upload-file.js +9 -0
- package/esm/highlevel/methods/files/upload-file.js.map +1 -1
- package/esm/highlevel/types/files/utils.d.ts +9 -6
- package/esm/highlevel/types/files/utils.js.map +1 -1
- package/esm/network/network-manager.js +1 -1
- package/esm/storage/index.d.ts +1 -0
- package/esm/storage/index.js +1 -0
- package/esm/storage/index.js.map +1 -1
- package/esm/storage/sqlite/driver.d.ts +24 -0
- package/esm/storage/sqlite/driver.js +125 -0
- package/esm/storage/sqlite/driver.js.map +1 -0
- package/esm/storage/sqlite/index.d.ts +17 -0
- package/esm/storage/sqlite/index.js +17 -0
- package/esm/storage/sqlite/index.js.map +1 -0
- package/esm/storage/sqlite/repository/auth-keys.d.ts +20 -0
- package/esm/storage/sqlite/repository/auth-keys.js +64 -0
- package/esm/storage/sqlite/repository/auth-keys.js.map +1 -0
- package/esm/storage/sqlite/repository/kv.d.ts +14 -0
- package/esm/storage/sqlite/repository/kv.js +92 -0
- package/esm/storage/sqlite/repository/kv.js.map +1 -0
- package/esm/storage/sqlite/repository/peers.d.ts +16 -0
- package/esm/storage/sqlite/repository/peers.js +73 -0
- package/esm/storage/sqlite/repository/peers.js.map +1 -0
- package/esm/storage/sqlite/repository/ref-messages.d.ts +16 -0
- package/esm/storage/sqlite/repository/ref-messages.js +45 -0
- package/esm/storage/sqlite/repository/ref-messages.js.map +1 -0
- package/esm/storage/sqlite/types.d.ts +18 -0
- package/esm/storage/sqlite/types.js +2 -0
- package/esm/storage/sqlite/types.js.map +1 -0
- package/package.json +4 -4
package/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright 2023
|
|
1
|
+
Copyright 2023 alina sireneva
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
4
|
|
|
@@ -21,6 +21,8 @@ const MAX_PART_COUNT_PREMIUM = 8000; // 512 kb * 8000 = 4000 MiB
|
|
|
21
21
|
// platform-specific
|
|
22
22
|
const HAS_FILE = typeof File !== 'undefined';
|
|
23
23
|
const HAS_RESPONSE = typeof Response !== 'undefined';
|
|
24
|
+
const HAS_URL = typeof URL !== 'undefined';
|
|
25
|
+
const HAS_BLOB = typeof Blob !== 'undefined';
|
|
24
26
|
// @available=both
|
|
25
27
|
/**
|
|
26
28
|
* Upload a file to Telegram servers, without actually
|
|
@@ -57,6 +59,13 @@ async function uploadFile(client, params) {
|
|
|
57
59
|
fileSize = file.size;
|
|
58
60
|
file = file.stream();
|
|
59
61
|
}
|
|
62
|
+
if (HAS_URL && file instanceof URL) {
|
|
63
|
+
file = await fetch(file);
|
|
64
|
+
}
|
|
65
|
+
if (HAS_BLOB && file instanceof Blob) {
|
|
66
|
+
fileSize = file.size;
|
|
67
|
+
file = file.stream();
|
|
68
|
+
}
|
|
60
69
|
if (HAS_RESPONSE && file instanceof Response) {
|
|
61
70
|
const length = parseInt(file.headers.get('content-length') || '0');
|
|
62
71
|
if (!isNaN(length) && length)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-file.js","sourceRoot":"","sources":["../../../../../src/highlevel/methods/files/upload-file.ts"],"names":[],"mappings":"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","sourcesContent":["import { tl } from '@mtcute/tl'\n\nimport { getPlatform } from '../../../platform.js'\nimport { MtArgumentError } from '../../../types/errors.js'\nimport { randomLong } from '../../../utils/long-utils.js'\nimport { ITelegramClient } from '../../client.types.js'\nimport { UploadedFile, UploadFileLike } from '../../types/index.js'\nimport { guessFileMime } from '../../utils/file-type.js'\nimport { determinePartSize, isProbablyPlainText } from '../../utils/file-utils.js'\nimport { bufferToStream, createChunkedReader, streamToBuffer } from '../../utils/stream-utils.js'\n\nconst OVERRIDE_MIME: Record<string, string> = {\n // tg doesn't interpret `audio/opus` files as voice messages for some reason\n 'audio/opus': 'audio/ogg',\n}\n\n// small files (less than 128 kb) are uploaded using the current connection and not the \"upload\" pool\nconst SMALL_FILE_MAX_SIZE = 131072\nconst BIG_FILE_MIN_SIZE = 10485760 // files >10 MB are considered \"big\"\nconst DEFAULT_FILE_NAME = 'unnamed'\nconst REQUESTS_PER_CONNECTION = 3\nconst MAX_PART_COUNT = 4000 // 512 kb * 4000 = 2000 MiB\nconst MAX_PART_COUNT_PREMIUM = 8000 // 512 kb * 8000 = 4000 MiB\n\n// platform-specific\nconst HAS_FILE = typeof File !== 'undefined'\nconst HAS_RESPONSE = typeof Response !== 'undefined'\n\n// @available=both\n/**\n * Upload a file to Telegram servers, without actually\n * sending a message anywhere. Useful when an `InputFile` is required.\n *\n * This method is quite low-level, and you should use other\n * methods like {@link sendMedia} that handle this under the hood.\n *\n * @param params Upload parameters\n */\nexport async function uploadFile(\n client: ITelegramClient,\n params: {\n /**\n * Upload file source.\n */\n file: UploadFileLike\n\n /**\n * File name for the uploaded file. Is usually inferred from path,\n * but should be provided for files sent as `Buffer` or stream.\n *\n * When file name can't be inferred, it falls back to \"unnamed\"\n */\n fileName?: string\n\n /**\n * Total file size. Automatically inferred for Buffer, File and local files.\n */\n fileSize?: number\n\n /**\n * If the file size is unknown, you can provide an estimate,\n * which will be used to determine appropriate part size.\n */\n estimatedSize?: number\n\n /**\n * File MIME type. By default is automatically inferred from magic number\n * If MIME can't be inferred, it defaults to `application/octet-stream`\n */\n fileMime?: string\n\n /**\n * Upload part size (in KB).\n *\n * By default, automatically selected by file size.\n * Must not be bigger than 512 and must not be a fraction.\n */\n partSize?: number\n\n /**\n * Number of parts to be sent in parallel per connection.\n */\n requestsPerConnection?: number\n\n /**\n * Function that will be called after some part has been uploaded.\n *\n * @param uploaded Number of bytes already uploaded\n * @param total Total file size, if known\n */\n progressCallback?: (uploaded: number, total: number) => void\n\n /**\n * When using `inputMediaUploadedPhoto` (e.g. when sending an uploaded photo) require\n * the file size to be known beforehand.\n *\n * In case this is set to `true`, a stream is passed as `file` and the file size is unknown,\n * the stream will be buffered in memory and the file size will be inferred from the buffer.\n */\n requireFileSize?: boolean\n },\n): Promise<UploadedFile> {\n // normalize params\n let file = params.file\n let fileSize = -1 // unknown\n let fileName = DEFAULT_FILE_NAME\n let fileMime = params.fileMime\n\n const platform = getPlatform()\n\n if (platform.normalizeFile) {\n const res = await platform.normalizeFile(file)\n\n if (res?.file) {\n file = res.file\n if (res.fileSize) fileSize = res.fileSize\n if (res.fileName) fileName = res.fileName\n }\n }\n\n if (ArrayBuffer.isView(file)) {\n fileSize = file.length\n file = bufferToStream(file)\n }\n\n if (HAS_FILE && file instanceof File) {\n fileName = file.name\n fileSize = file.size\n file = file.stream()\n }\n\n if (HAS_RESPONSE && file instanceof Response) {\n const length = parseInt(file.headers.get('content-length') || '0')\n if (!isNaN(length) && length) fileSize = length\n\n fileMime = file.headers.get('content-type')?.split(';')[0]\n\n const disposition = file.headers.get('content-disposition')\n\n if (disposition) {\n const idx = disposition.indexOf('filename=')\n\n if (idx > -1) {\n const raw = disposition.slice(idx + 9).split(';')[0]\n fileName = JSON.parse(raw) as string\n }\n }\n\n if (fileName === DEFAULT_FILE_NAME) {\n // try to infer from url\n const url = new URL(file.url)\n const name = url.pathname.split('/').pop()\n\n if (name && name.includes('.')) {\n fileName = name\n }\n }\n\n if (!file.body) {\n throw new MtArgumentError('Fetch response contains `null` body')\n }\n\n file = file.body\n }\n\n if (!(file instanceof ReadableStream)) {\n throw new MtArgumentError('Could not convert input `file` to stream!')\n }\n\n // override file name and mime (if any)\n if (params.fileName) fileName = params.fileName\n\n // set file size if not automatically inferred\n if (fileSize === -1 && params.fileSize) fileSize = params.fileSize\n\n if (fileSize === -1 && params.requireFileSize) {\n // buffer the entire stream in memory, then convert it back to stream (bruh)\n const buffer = await streamToBuffer(file)\n fileSize = buffer.length\n file = bufferToStream(buffer)\n }\n\n let partSizeKb = params.partSize\n\n if (!partSizeKb) {\n if (fileSize === -1) {\n partSizeKb = params.estimatedSize ? determinePartSize(params.estimatedSize) : 64\n } else {\n partSizeKb = determinePartSize(fileSize)\n }\n }\n\n if (partSizeKb > 512) {\n throw new MtArgumentError(`Invalid part size: ${partSizeKb}KB`)\n }\n const partSize = partSizeKb * 1024\n\n let partCount = fileSize === -1 ? -1 : ~~((fileSize + partSize - 1) / partSize)\n const maxPartCount = client.storage.self.getCached()?.isPremium ? MAX_PART_COUNT_PREMIUM : MAX_PART_COUNT\n\n if (partCount > maxPartCount) {\n throw new MtArgumentError(`File is too large (max ${maxPartCount} parts, got ${partCount})`)\n }\n\n const isBig = fileSize === -1 || fileSize > BIG_FILE_MIN_SIZE\n const isSmall = fileSize !== -1 && fileSize < SMALL_FILE_MAX_SIZE\n const connectionKind = isSmall ? 'main' : 'upload'\n // streamed uploads must be serialized, otherwise we'll get FILE_PART_SIZE_INVALID\n const connectionPoolSize = Math.min(await client.getPoolSize(connectionKind), partCount)\n const requestsPerConnection = params.requestsPerConnection ?? REQUESTS_PER_CONNECTION\n\n client.log.debug(\n 'uploading %d bytes file in %d chunks, each %d bytes in %s connection pool of size %d',\n fileSize,\n partCount,\n partSize,\n connectionKind,\n connectionPoolSize,\n )\n\n // why is the file id generated by the client?\n // isn't the server supposed to generate it and handle collisions?\n const fileId = randomLong()\n const stream = file\n\n let pos = 0\n let idx = 0\n const reader = createChunkedReader(stream, partSize)\n\n const uploadNextPart = async (): Promise<void> => {\n const thisIdx = idx++\n\n let part = await reader.read()\n\n if (!part && fileSize !== -1) {\n throw new MtArgumentError(`Unexpected EOS (there were only ${idx - 1} parts, but expected ${partCount})`)\n }\n\n if (fileSize === -1 && (reader.ended() || !part)) {\n fileSize = pos + (part?.length ?? 0)\n partCount = ~~((fileSize + partSize - 1) / partSize)\n if (!part) part = new Uint8Array(0)\n client.log.debug('readable ended, file size = %d, part count = %d', fileSize, partCount)\n }\n\n if (!ArrayBuffer.isView(part)) {\n throw new MtArgumentError(`Part ${thisIdx} was not a Uint8Array!`)\n }\n if (part.length > partSize) {\n throw new MtArgumentError(`Part ${thisIdx} had invalid size (expected ${partSize}, got ${part.length})`)\n }\n\n if (thisIdx === 0 && fileMime === undefined) {\n const mime = guessFileMime(part)\n\n if (mime) {\n fileMime = mime\n } else {\n // either plain text or random binary gibberish\n // make an assumption based on the first 8 bytes\n // if all 8 bytes are printable ASCII characters,\n // the entire file is probably plain text\n const isPlainText = isProbablyPlainText(part.slice(0, 8))\n fileMime = isPlainText ? 'text/plain' : 'application/octet-stream'\n }\n }\n\n // why\n const request = isBig ?\n ({\n _: 'upload.saveBigFilePart',\n fileId,\n filePart: thisIdx,\n fileTotalParts: partCount,\n bytes: part,\n } satisfies tl.upload.RawSaveBigFilePartRequest) :\n ({\n _: 'upload.saveFilePart',\n fileId,\n filePart: thisIdx,\n bytes: part,\n } satisfies tl.upload.RawSaveFilePartRequest)\n\n const result = await client.call(request, { kind: connectionKind })\n if (!result) throw new Error(`Failed to upload part ${idx}`)\n\n pos += part.length\n\n params.progressCallback?.(pos, fileSize)\n\n if (idx === partCount) return\n\n return uploadNextPart()\n }\n\n let poolSize = partCount === -1 ? 1 : connectionPoolSize * requestsPerConnection\n if (partCount !== -1 && poolSize > partCount) poolSize = partCount\n\n await Promise.all(Array.from({ length: poolSize }, uploadNextPart))\n\n let inputFile: tl.TypeInputFile\n\n if (isBig) {\n inputFile = {\n _: 'inputFileBig',\n id: fileId,\n parts: partCount,\n name: fileName,\n }\n } else {\n inputFile = {\n _: 'inputFile',\n id: fileId,\n parts: partCount,\n name: fileName,\n md5Checksum: '', // tdlib doesn't do this, why should we?\n }\n }\n\n if (fileMime! in OVERRIDE_MIME) fileMime = OVERRIDE_MIME[fileMime!]\n\n return {\n inputFile,\n size: fileSize,\n mime: fileMime!,\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"upload-file.js","sourceRoot":"","sources":["../../../../../src/highlevel/methods/files/upload-file.ts"],"names":[],"mappings":"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","sourcesContent":["import { tl } from '@mtcute/tl'\n\nimport { getPlatform } from '../../../platform.js'\nimport { MtArgumentError } from '../../../types/errors.js'\nimport { randomLong } from '../../../utils/long-utils.js'\nimport { ITelegramClient } from '../../client.types.js'\nimport { UploadedFile, UploadFileLike } from '../../types/index.js'\nimport { guessFileMime } from '../../utils/file-type.js'\nimport { determinePartSize, isProbablyPlainText } from '../../utils/file-utils.js'\nimport { bufferToStream, createChunkedReader, streamToBuffer } from '../../utils/stream-utils.js'\n\nconst OVERRIDE_MIME: Record<string, string> = {\n // tg doesn't interpret `audio/opus` files as voice messages for some reason\n 'audio/opus': 'audio/ogg',\n}\n\n// small files (less than 128 kb) are uploaded using the current connection and not the \"upload\" pool\nconst SMALL_FILE_MAX_SIZE = 131072\nconst BIG_FILE_MIN_SIZE = 10485760 // files >10 MB are considered \"big\"\nconst DEFAULT_FILE_NAME = 'unnamed'\nconst REQUESTS_PER_CONNECTION = 3\nconst MAX_PART_COUNT = 4000 // 512 kb * 4000 = 2000 MiB\nconst MAX_PART_COUNT_PREMIUM = 8000 // 512 kb * 8000 = 4000 MiB\n\n// platform-specific\nconst HAS_FILE = typeof File !== 'undefined'\nconst HAS_RESPONSE = typeof Response !== 'undefined'\nconst HAS_URL = typeof URL !== 'undefined'\nconst HAS_BLOB = typeof Blob !== 'undefined'\n\n// @available=both\n/**\n * Upload a file to Telegram servers, without actually\n * sending a message anywhere. Useful when an `InputFile` is required.\n *\n * This method is quite low-level, and you should use other\n * methods like {@link sendMedia} that handle this under the hood.\n *\n * @param params Upload parameters\n */\nexport async function uploadFile(\n client: ITelegramClient,\n params: {\n /**\n * Upload file source.\n */\n file: UploadFileLike\n\n /**\n * File name for the uploaded file. Is usually inferred from path,\n * but should be provided for files sent as `Buffer` or stream.\n *\n * When file name can't be inferred, it falls back to \"unnamed\"\n */\n fileName?: string\n\n /**\n * Total file size. Automatically inferred for Buffer, File and local files.\n */\n fileSize?: number\n\n /**\n * If the file size is unknown, you can provide an estimate,\n * which will be used to determine appropriate part size.\n */\n estimatedSize?: number\n\n /**\n * File MIME type. By default is automatically inferred from magic number\n * If MIME can't be inferred, it defaults to `application/octet-stream`\n */\n fileMime?: string\n\n /**\n * Upload part size (in KB).\n *\n * By default, automatically selected by file size.\n * Must not be bigger than 512 and must not be a fraction.\n */\n partSize?: number\n\n /**\n * Number of parts to be sent in parallel per connection.\n */\n requestsPerConnection?: number\n\n /**\n * Function that will be called after some part has been uploaded.\n *\n * @param uploaded Number of bytes already uploaded\n * @param total Total file size, if known\n */\n progressCallback?: (uploaded: number, total: number) => void\n\n /**\n * When using `inputMediaUploadedPhoto` (e.g. when sending an uploaded photo) require\n * the file size to be known beforehand.\n *\n * In case this is set to `true`, a stream is passed as `file` and the file size is unknown,\n * the stream will be buffered in memory and the file size will be inferred from the buffer.\n */\n requireFileSize?: boolean\n },\n): Promise<UploadedFile> {\n // normalize params\n let file = params.file\n let fileSize = -1 // unknown\n let fileName = DEFAULT_FILE_NAME\n let fileMime = params.fileMime\n\n const platform = getPlatform()\n\n if (platform.normalizeFile) {\n const res = await platform.normalizeFile(file)\n\n if (res?.file) {\n file = res.file\n if (res.fileSize) fileSize = res.fileSize\n if (res.fileName) fileName = res.fileName\n }\n }\n\n if (ArrayBuffer.isView(file)) {\n fileSize = file.length\n file = bufferToStream(file)\n }\n\n if (HAS_FILE && file instanceof File) {\n fileName = file.name\n fileSize = file.size\n file = file.stream()\n }\n\n if (HAS_URL && file instanceof URL) {\n file = await fetch(file)\n }\n\n if (HAS_BLOB && file instanceof Blob) {\n fileSize = file.size\n file = file.stream()\n }\n\n if (HAS_RESPONSE && file instanceof Response) {\n const length = parseInt(file.headers.get('content-length') || '0')\n if (!isNaN(length) && length) fileSize = length\n\n fileMime = file.headers.get('content-type')?.split(';')[0]\n\n const disposition = file.headers.get('content-disposition')\n\n if (disposition) {\n const idx = disposition.indexOf('filename=')\n\n if (idx > -1) {\n const raw = disposition.slice(idx + 9).split(';')[0]\n fileName = JSON.parse(raw) as string\n }\n }\n\n if (fileName === DEFAULT_FILE_NAME) {\n // try to infer from url\n const url = new URL(file.url)\n const name = url.pathname.split('/').pop()\n\n if (name && name.includes('.')) {\n fileName = name\n }\n }\n\n if (!file.body) {\n throw new MtArgumentError('Fetch response contains `null` body')\n }\n\n file = file.body\n }\n\n if (!(file instanceof ReadableStream)) {\n throw new MtArgumentError('Could not convert input `file` to stream!')\n }\n\n // override file name and mime (if any)\n if (params.fileName) fileName = params.fileName\n\n // set file size if not automatically inferred\n if (fileSize === -1 && params.fileSize) fileSize = params.fileSize\n\n if (fileSize === -1 && params.requireFileSize) {\n // buffer the entire stream in memory, then convert it back to stream (bruh)\n const buffer = await streamToBuffer(file)\n fileSize = buffer.length\n file = bufferToStream(buffer)\n }\n\n let partSizeKb = params.partSize\n\n if (!partSizeKb) {\n if (fileSize === -1) {\n partSizeKb = params.estimatedSize ? determinePartSize(params.estimatedSize) : 64\n } else {\n partSizeKb = determinePartSize(fileSize)\n }\n }\n\n if (partSizeKb > 512) {\n throw new MtArgumentError(`Invalid part size: ${partSizeKb}KB`)\n }\n const partSize = partSizeKb * 1024\n\n let partCount = fileSize === -1 ? -1 : ~~((fileSize + partSize - 1) / partSize)\n const maxPartCount = client.storage.self.getCached()?.isPremium ? MAX_PART_COUNT_PREMIUM : MAX_PART_COUNT\n\n if (partCount > maxPartCount) {\n throw new MtArgumentError(`File is too large (max ${maxPartCount} parts, got ${partCount})`)\n }\n\n const isBig = fileSize === -1 || fileSize > BIG_FILE_MIN_SIZE\n const isSmall = fileSize !== -1 && fileSize < SMALL_FILE_MAX_SIZE\n const connectionKind = isSmall ? 'main' : 'upload'\n // streamed uploads must be serialized, otherwise we'll get FILE_PART_SIZE_INVALID\n const connectionPoolSize = Math.min(await client.getPoolSize(connectionKind), partCount)\n const requestsPerConnection = params.requestsPerConnection ?? REQUESTS_PER_CONNECTION\n\n client.log.debug(\n 'uploading %d bytes file in %d chunks, each %d bytes in %s connection pool of size %d',\n fileSize,\n partCount,\n partSize,\n connectionKind,\n connectionPoolSize,\n )\n\n // why is the file id generated by the client?\n // isn't the server supposed to generate it and handle collisions?\n const fileId = randomLong()\n const stream = file\n\n let pos = 0\n let idx = 0\n const reader = createChunkedReader(stream, partSize)\n\n const uploadNextPart = async (): Promise<void> => {\n const thisIdx = idx++\n\n let part = await reader.read()\n\n if (!part && fileSize !== -1) {\n throw new MtArgumentError(`Unexpected EOS (there were only ${idx - 1} parts, but expected ${partCount})`)\n }\n\n if (fileSize === -1 && (reader.ended() || !part)) {\n fileSize = pos + (part?.length ?? 0)\n partCount = ~~((fileSize + partSize - 1) / partSize)\n if (!part) part = new Uint8Array(0)\n client.log.debug('readable ended, file size = %d, part count = %d', fileSize, partCount)\n }\n\n if (!ArrayBuffer.isView(part)) {\n throw new MtArgumentError(`Part ${thisIdx} was not a Uint8Array!`)\n }\n if (part.length > partSize) {\n throw new MtArgumentError(`Part ${thisIdx} had invalid size (expected ${partSize}, got ${part.length})`)\n }\n\n if (thisIdx === 0 && fileMime === undefined) {\n const mime = guessFileMime(part)\n\n if (mime) {\n fileMime = mime\n } else {\n // either plain text or random binary gibberish\n // make an assumption based on the first 8 bytes\n // if all 8 bytes are printable ASCII characters,\n // the entire file is probably plain text\n const isPlainText = isProbablyPlainText(part.slice(0, 8))\n fileMime = isPlainText ? 'text/plain' : 'application/octet-stream'\n }\n }\n\n // why\n const request = isBig ?\n ({\n _: 'upload.saveBigFilePart',\n fileId,\n filePart: thisIdx,\n fileTotalParts: partCount,\n bytes: part,\n } satisfies tl.upload.RawSaveBigFilePartRequest) :\n ({\n _: 'upload.saveFilePart',\n fileId,\n filePart: thisIdx,\n bytes: part,\n } satisfies tl.upload.RawSaveFilePartRequest)\n\n const result = await client.call(request, { kind: connectionKind })\n if (!result) throw new Error(`Failed to upload part ${idx}`)\n\n pos += part.length\n\n params.progressCallback?.(pos, fileSize)\n\n if (idx === partCount) return\n\n return uploadNextPart()\n }\n\n let poolSize = partCount === -1 ? 1 : connectionPoolSize * requestsPerConnection\n if (partCount !== -1 && poolSize > partCount) poolSize = partCount\n\n await Promise.all(Array.from({ length: poolSize }, uploadNextPart))\n\n let inputFile: tl.TypeInputFile\n\n if (isBig) {\n inputFile = {\n _: 'inputFileBig',\n id: fileId,\n parts: partCount,\n name: fileName,\n }\n } else {\n inputFile = {\n _: 'inputFile',\n id: fileId,\n parts: partCount,\n name: fileName,\n md5Checksum: '', // tdlib doesn't do this, why should we?\n }\n }\n\n if (fileMime! in OVERRIDE_MIME) fileMime = OVERRIDE_MIME[fileMime!]\n\n return {\n inputFile,\n size: fileSize,\n mime: fileMime!,\n }\n}\n"]}
|
|
@@ -9,14 +9,16 @@ import { UploadedFile } from './uploaded-file.js';
|
|
|
9
9
|
* Describes types that can be used in {@link TelegramClient.uploadFile}
|
|
10
10
|
* method. Can be one of:
|
|
11
11
|
* - `Uint8Array`/`Buffer`, which will be interpreted as raw file contents
|
|
12
|
-
* - `File` (from the Web API)
|
|
12
|
+
* - `File`, `Blob` (from the Web API)
|
|
13
13
|
* - `string`, which will be interpreted as file path (**non-browser only!**)
|
|
14
|
-
* - `
|
|
14
|
+
* - `URL` (from the Web API, will be `fetch()`-ed; `file://` URLs are not available in browsers)
|
|
15
|
+
* - `ReadStream` (for Node.js/Bun, from the `fs` module)
|
|
16
|
+
* - `BunFile` (from `Bun.file()`)
|
|
15
17
|
* - `ReadableStream` (Web API readable stream)
|
|
16
|
-
* - `Readable` (
|
|
18
|
+
* - `Readable` (Node.js/Bun readable stream)
|
|
17
19
|
* - `Response` (from `window.fetch`)
|
|
18
20
|
*/
|
|
19
|
-
export type UploadFileLike = Uint8Array | File | string | ReadStream | ReadableStream<Uint8Array> | NodeJS.ReadableStream | Response;
|
|
21
|
+
export type UploadFileLike = URL | Uint8Array | File | Blob | string | ReadStream | ReadableStream<Uint8Array> | NodeJS.ReadableStream | Response;
|
|
20
22
|
/**
|
|
21
23
|
* Describes types that can be used as an input
|
|
22
24
|
* to any methods that send media (like {@link TelegramClient.sendPhoto})
|
|
@@ -24,14 +26,15 @@ export type UploadFileLike = Uint8Array | File | string | ReadStream | ReadableS
|
|
|
24
26
|
* Can be one of:
|
|
25
27
|
* - `Buffer`, which will be interpreted as raw file contents
|
|
26
28
|
* - `File` (from the Web API)
|
|
27
|
-
* - `ReadStream` (for
|
|
29
|
+
* - `ReadStream` (for Node.js/Bun, from the `fs` module)
|
|
28
30
|
* - `ReadableStream` (from the Web API, base readable stream)
|
|
29
|
-
* - `Readable` (for
|
|
31
|
+
* - `Readable` (for Node.js/Bun, base readable stream)
|
|
30
32
|
* - {@link UploadedFile} returned from {@link TelegramClient.uploadFile}
|
|
31
33
|
* - `tl.TypeInputFile` and `tl.TypeInputMedia` TL objects
|
|
32
34
|
* - `string` with a path to a local file prepended with `file:` (non-browser only) (e.g. `file:image.jpg`)
|
|
33
35
|
* - `string` with a URL to remote files (e.g. `https://example.com/image.jpg`)
|
|
34
36
|
* - `string` with TDLib and Bot API compatible File ID.
|
|
37
|
+
* - `URL` (from the Web API, will be `fetch()`-ed if needed; `file://` URLs are not available in browsers)
|
|
35
38
|
* - `td.RawFullRemoteFileLocation` (parsed File ID)
|
|
36
39
|
*/
|
|
37
40
|
export type InputFileLike = UploadFileLike | UploadedFile | tl.TypeInputFile | tl.TypeInputMedia | tdFileId.RawFullRemoteFileLocation;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/highlevel/types/files/utils.ts"],"names":[],"mappings":"","sourcesContent":["/* eslint-disable no-restricted-imports */\nimport type { ReadStream } from 'fs'\n\nimport { tdFileId } from '@mtcute/file-id'\nimport { tl } from '@mtcute/tl'\n\nimport { FileLocation } from './file-location.js'\nimport { UploadedFile } from './uploaded-file.js'\n\n/**\n * Describes types that can be used in {@link TelegramClient.uploadFile}\n * method. Can be one of:\n * - `Uint8Array`/`Buffer`, which will be interpreted as raw file contents\n * - `File` (from the Web API)\n * - `string`, which will be interpreted as file path (**non-browser only!**)\n * - `ReadStream` (for
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/highlevel/types/files/utils.ts"],"names":[],"mappings":"","sourcesContent":["/* eslint-disable no-restricted-imports */\nimport type { ReadStream } from 'fs'\n\nimport { tdFileId } from '@mtcute/file-id'\nimport { tl } from '@mtcute/tl'\n\nimport { FileLocation } from './file-location.js'\nimport { UploadedFile } from './uploaded-file.js'\n\n/**\n * Describes types that can be used in {@link TelegramClient.uploadFile}\n * method. Can be one of:\n * - `Uint8Array`/`Buffer`, which will be interpreted as raw file contents\n * - `File`, `Blob` (from the Web API)\n * - `string`, which will be interpreted as file path (**non-browser only!**)\n * - `URL` (from the Web API, will be `fetch()`-ed; `file://` URLs are not available in browsers)\n * - `ReadStream` (for Node.js/Bun, from the `fs` module)\n * - `BunFile` (from `Bun.file()`)\n * - `ReadableStream` (Web API readable stream)\n * - `Readable` (Node.js/Bun readable stream)\n * - `Response` (from `window.fetch`)\n */\nexport type UploadFileLike =\n | URL\n | Uint8Array\n | File\n | Blob\n | string\n | ReadStream\n | ReadableStream<Uint8Array>\n | NodeJS.ReadableStream\n | Response\n\n/**\n * Describes types that can be used as an input\n * to any methods that send media (like {@link TelegramClient.sendPhoto})\n *\n * Can be one of:\n * - `Buffer`, which will be interpreted as raw file contents\n * - `File` (from the Web API)\n * - `ReadStream` (for Node.js/Bun, from the `fs` module)\n * - `ReadableStream` (from the Web API, base readable stream)\n * - `Readable` (for Node.js/Bun, base readable stream)\n * - {@link UploadedFile} returned from {@link TelegramClient.uploadFile}\n * - `tl.TypeInputFile` and `tl.TypeInputMedia` TL objects\n * - `string` with a path to a local file prepended with `file:` (non-browser only) (e.g. `file:image.jpg`)\n * - `string` with a URL to remote files (e.g. `https://example.com/image.jpg`)\n * - `string` with TDLib and Bot API compatible File ID.\n * - `URL` (from the Web API, will be `fetch()`-ed if needed; `file://` URLs are not available in browsers)\n * - `td.RawFullRemoteFileLocation` (parsed File ID)\n */\nexport type InputFileLike =\n | UploadFileLike\n | UploadedFile\n | tl.TypeInputFile\n | tl.TypeInputMedia\n | tdFileId.RawFullRemoteFileLocation\n\n/**\n * File location which should be downloaded.\n * You can also provide TDLib and Bot API compatible File ID\n */\nexport type FileDownloadLocation = tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | FileLocation | string\n\nexport interface FileDownloadParameters {\n /**\n * Total file size, if known.\n * Used to determine upload part size.\n * In some cases can be inferred from `file` automatically.\n */\n fileSize?: number\n\n /**\n * Download part size (in KB).\n * By default, automatically selected depending on the file size\n * (or 64, if not provided). Must not be bigger than 512,\n * must not be a fraction, and must be divisible by 4.\n */\n partSize?: number\n\n /**\n * DC id from which the file will be downloaded.\n *\n * If provided DC is not the one storing the file,\n * redirection will be handled automatically.\n */\n dcId?: number\n\n /**\n * Offset in bytes. Must be divisible by 4096 (4 KB).\n */\n offset?: number\n\n /**\n * Number of bytes to be downloaded.\n * By default, downloads the entire file\n */\n limit?: number\n\n /**\n * Function that will be called after some part has been downloaded.\n *\n * @param uploaded Number of bytes already downloaded\n * @param total Total file size (`Infinity` if not available)\n */\n progressCallback?: (downloaded: number, total: number) => void\n\n /**\n * Abort signal that can be used to cancel the download.\n */\n abortSignal?: AbortSignal\n}\n"]}
|
package/cjs/storage/index.d.ts
CHANGED
package/cjs/storage/index.js
CHANGED
|
@@ -18,5 +18,6 @@ __exportStar(require("./driver.js"), exports);
|
|
|
18
18
|
__exportStar(require("./memory/index.js"), exports);
|
|
19
19
|
__exportStar(require("./provider.js"), exports);
|
|
20
20
|
__exportStar(require("./repository/index.js"), exports);
|
|
21
|
+
__exportStar(require("./sqlite/index.js"), exports);
|
|
21
22
|
__exportStar(require("./storage.js"), exports);
|
|
22
23
|
//# sourceMappingURL=index.js.map
|
package/cjs/storage/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,oDAAiC;AACjC,gDAA6B;AAC7B,wDAAqC;AACrC,+CAA4B","sourcesContent":["export * from './driver.js'\nexport * from './memory/index.js'\nexport * from './provider.js'\nexport * from './repository/index.js'\nexport * from './storage.js'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,oDAAiC;AACjC,gDAA6B;AAC7B,wDAAqC;AACrC,oDAAiC;AACjC,+CAA4B","sourcesContent":["export * from './driver.js'\nexport * from './memory/index.js'\nexport * from './provider.js'\nexport * from './repository/index.js'\nexport * from './sqlite/index.js'\nexport * from './storage.js'\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BaseStorageDriver } from '../driver.js';
|
|
2
|
+
import { ISqliteDatabase, ISqliteStatement } from './types.js';
|
|
3
|
+
type MigrationFunction = (db: ISqliteDatabase) => void;
|
|
4
|
+
export declare abstract class BaseSqliteStorageDriver extends BaseStorageDriver {
|
|
5
|
+
db: ISqliteDatabase;
|
|
6
|
+
private _pending;
|
|
7
|
+
private _runMany;
|
|
8
|
+
private _cleanup?;
|
|
9
|
+
private _migrations;
|
|
10
|
+
private _maxVersion;
|
|
11
|
+
private _legacyMigrations;
|
|
12
|
+
registerLegacyMigration(repo: string, migration: MigrationFunction): void;
|
|
13
|
+
registerMigration(repo: string, version: number, migration: MigrationFunction): void;
|
|
14
|
+
private _onLoad;
|
|
15
|
+
onLoad(cb: (db: ISqliteDatabase) => void): void;
|
|
16
|
+
_writeLater(stmt: ISqliteStatement, params: unknown[]): void;
|
|
17
|
+
private _runLegacyMigrations;
|
|
18
|
+
_initialize(): void;
|
|
19
|
+
abstract _createDatabase(): ISqliteDatabase;
|
|
20
|
+
_load(): void;
|
|
21
|
+
_save(): void;
|
|
22
|
+
_destroy(): void;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseSqliteStorageDriver = void 0;
|
|
4
|
+
const platform_js_1 = require("../../platform.js");
|
|
5
|
+
const driver_js_1 = require("../driver.js");
|
|
6
|
+
const MIGRATIONS_TABLE_NAME = 'mtcute_migrations';
|
|
7
|
+
const MIGRATIONS_TABLE_SQL = `
|
|
8
|
+
create table if not exists ${MIGRATIONS_TABLE_NAME} (
|
|
9
|
+
repo text not null primary key,
|
|
10
|
+
version integer not null
|
|
11
|
+
);
|
|
12
|
+
`.trim();
|
|
13
|
+
class BaseSqliteStorageDriver extends driver_js_1.BaseStorageDriver {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(...arguments);
|
|
16
|
+
this._pending = [];
|
|
17
|
+
this._migrations = new Map();
|
|
18
|
+
this._maxVersion = new Map();
|
|
19
|
+
// todo: remove in 1.0.0
|
|
20
|
+
this._legacyMigrations = new Map();
|
|
21
|
+
this._onLoad = new Set();
|
|
22
|
+
this._runLegacyMigrations = false;
|
|
23
|
+
}
|
|
24
|
+
registerLegacyMigration(repo, migration) {
|
|
25
|
+
if (this.loaded) {
|
|
26
|
+
throw new Error('Cannot register migrations after loading');
|
|
27
|
+
}
|
|
28
|
+
this._legacyMigrations.set(repo, migration);
|
|
29
|
+
}
|
|
30
|
+
registerMigration(repo, version, migration) {
|
|
31
|
+
if (this.loaded) {
|
|
32
|
+
throw new Error('Cannot register migrations after loading');
|
|
33
|
+
}
|
|
34
|
+
let map = this._migrations.get(repo);
|
|
35
|
+
if (!map) {
|
|
36
|
+
map = new Map();
|
|
37
|
+
this._migrations.set(repo, map);
|
|
38
|
+
}
|
|
39
|
+
if (map.has(version)) {
|
|
40
|
+
throw new Error(`Migration for ${repo} version ${version} is already registered`);
|
|
41
|
+
}
|
|
42
|
+
map.set(version, migration);
|
|
43
|
+
const prevMax = this._maxVersion.get(repo) ?? 0;
|
|
44
|
+
if (version > prevMax) {
|
|
45
|
+
this._maxVersion.set(repo, version);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
onLoad(cb) {
|
|
49
|
+
if (this.loaded) {
|
|
50
|
+
cb(this.db);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this._onLoad.add(cb);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
_writeLater(stmt, params) {
|
|
57
|
+
this._pending.push([stmt, params]);
|
|
58
|
+
}
|
|
59
|
+
_initialize() {
|
|
60
|
+
const hasLegacyTables = this.db
|
|
61
|
+
.prepare("select name from sqlite_master where type = 'table' and name = 'kv'")
|
|
62
|
+
.get();
|
|
63
|
+
if (hasLegacyTables) {
|
|
64
|
+
this._log.info('legacy tables detected, will run migrations');
|
|
65
|
+
this._runLegacyMigrations = true;
|
|
66
|
+
}
|
|
67
|
+
this.db.exec(MIGRATIONS_TABLE_SQL);
|
|
68
|
+
const writeVersion = this.db.prepare(`insert or replace into ${MIGRATIONS_TABLE_NAME} (repo, version) values (?, ?)`);
|
|
69
|
+
const getVersion = this.db.prepare(`select version from ${MIGRATIONS_TABLE_NAME} where repo = ?`);
|
|
70
|
+
const didUpgrade = new Set();
|
|
71
|
+
for (const repo of this._migrations.keys()) {
|
|
72
|
+
const res = getVersion.get(repo);
|
|
73
|
+
const startVersion = res?.version ?? 0;
|
|
74
|
+
let fromVersion = startVersion;
|
|
75
|
+
const migrations = this._migrations.get(repo);
|
|
76
|
+
const targetVer = this._maxVersion.get(repo);
|
|
77
|
+
while (fromVersion < targetVer) {
|
|
78
|
+
const nextVersion = fromVersion + 1;
|
|
79
|
+
const migration = migrations.get(nextVersion);
|
|
80
|
+
if (!migration) {
|
|
81
|
+
throw new Error(`No migration for ${repo} to version ${nextVersion}`);
|
|
82
|
+
}
|
|
83
|
+
migration(this.db);
|
|
84
|
+
fromVersion = nextVersion;
|
|
85
|
+
didUpgrade.add(repo);
|
|
86
|
+
}
|
|
87
|
+
if (fromVersion !== startVersion) {
|
|
88
|
+
writeVersion.run(repo, targetVer);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
_load() {
|
|
93
|
+
this.db = this._createDatabase();
|
|
94
|
+
this._runMany = this.db.transaction((stmts) => {
|
|
95
|
+
stmts.forEach((stmt) => {
|
|
96
|
+
stmt[0].run(stmt[1]);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
this.db.transaction(() => this._initialize())();
|
|
100
|
+
this._cleanup = (0, platform_js_1.getPlatform)().beforeExit(() => {
|
|
101
|
+
this._save();
|
|
102
|
+
this._destroy();
|
|
103
|
+
});
|
|
104
|
+
for (const cb of this._onLoad)
|
|
105
|
+
cb(this.db);
|
|
106
|
+
if (this._runLegacyMigrations) {
|
|
107
|
+
this.db.transaction(() => {
|
|
108
|
+
for (const migration of this._legacyMigrations.values()) {
|
|
109
|
+
migration(this.db);
|
|
110
|
+
}
|
|
111
|
+
// in case _writeLater was used
|
|
112
|
+
this._runMany(this._pending);
|
|
113
|
+
})();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
_save() {
|
|
117
|
+
if (!this._pending.length)
|
|
118
|
+
return;
|
|
119
|
+
this._runMany(this._pending);
|
|
120
|
+
this._pending = [];
|
|
121
|
+
}
|
|
122
|
+
_destroy() {
|
|
123
|
+
this.db.close();
|
|
124
|
+
this._cleanup?.();
|
|
125
|
+
this._cleanup = undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
exports.BaseSqliteStorageDriver = BaseSqliteStorageDriver;
|
|
129
|
+
//# sourceMappingURL=driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../../../src/storage/sqlite/driver.ts"],"names":[],"mappings":"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","sourcesContent":["import { getPlatform } from '../../platform.js'\nimport { BaseStorageDriver } from '../driver.js'\nimport { ISqliteDatabase, ISqliteStatement } from './types.js'\n\nconst MIGRATIONS_TABLE_NAME = 'mtcute_migrations'\nconst MIGRATIONS_TABLE_SQL = `\ncreate table if not exists ${MIGRATIONS_TABLE_NAME} (\n repo text not null primary key,\n version integer not null\n);\n`.trim()\n\ntype MigrationFunction = (db: ISqliteDatabase) => void\n\nexport abstract class BaseSqliteStorageDriver extends BaseStorageDriver {\n db!: ISqliteDatabase\n\n private _pending: [ISqliteStatement, unknown[]][] = []\n private _runMany!: (stmts: [ISqliteStatement, unknown[]][]) => void\n private _cleanup?: () => void\n\n private _migrations: Map<string, Map<number, MigrationFunction>> = new Map()\n private _maxVersion: Map<string, number> = new Map()\n\n // todo: remove in 1.0.0\n private _legacyMigrations: Map<string, MigrationFunction> = new Map()\n\n registerLegacyMigration(repo: string, migration: MigrationFunction): void {\n if (this.loaded) {\n throw new Error('Cannot register migrations after loading')\n }\n\n this._legacyMigrations.set(repo, migration)\n }\n\n registerMigration(repo: string, version: number, migration: MigrationFunction): void {\n if (this.loaded) {\n throw new Error('Cannot register migrations after loading')\n }\n\n let map = this._migrations.get(repo)\n\n if (!map) {\n map = new Map()\n this._migrations.set(repo, map)\n }\n\n if (map.has(version)) {\n throw new Error(`Migration for ${repo} version ${version} is already registered`)\n }\n\n map.set(version, migration)\n\n const prevMax = this._maxVersion.get(repo) ?? 0\n\n if (version > prevMax) {\n this._maxVersion.set(repo, version)\n }\n }\n\n private _onLoad = new Set<(db: ISqliteDatabase) => void>()\n\n onLoad(cb: (db: ISqliteDatabase) => void): void {\n if (this.loaded) {\n cb(this.db)\n } else {\n this._onLoad.add(cb)\n }\n }\n\n _writeLater(stmt: ISqliteStatement, params: unknown[]): void {\n this._pending.push([stmt, params])\n }\n\n private _runLegacyMigrations = false\n\n _initialize(): void {\n const hasLegacyTables = this.db\n .prepare(\"select name from sqlite_master where type = 'table' and name = 'kv'\")\n .get()\n\n if (hasLegacyTables) {\n this._log.info('legacy tables detected, will run migrations')\n this._runLegacyMigrations = true\n }\n\n this.db.exec(MIGRATIONS_TABLE_SQL)\n\n const writeVersion = this.db.prepare(\n `insert or replace into ${MIGRATIONS_TABLE_NAME} (repo, version) values (?, ?)`,\n )\n const getVersion = this.db.prepare(`select version from ${MIGRATIONS_TABLE_NAME} where repo = ?`)\n\n const didUpgrade = new Set<string>()\n\n for (const repo of this._migrations.keys()) {\n const res = getVersion.get(repo) as { version: number } | undefined\n\n const startVersion = res?.version ?? 0\n let fromVersion = startVersion\n\n const migrations = this._migrations.get(repo)!\n const targetVer = this._maxVersion.get(repo)!\n\n while (fromVersion < targetVer) {\n const nextVersion = fromVersion + 1\n const migration = migrations.get(nextVersion)\n\n if (!migration) {\n throw new Error(`No migration for ${repo} to version ${nextVersion}`)\n }\n\n migration(this.db)\n\n fromVersion = nextVersion\n didUpgrade.add(repo)\n }\n\n if (fromVersion !== startVersion) {\n writeVersion.run(repo, targetVer)\n }\n }\n }\n\n abstract _createDatabase(): ISqliteDatabase\n\n _load(): void {\n this.db = this._createDatabase()\n\n this._runMany = this.db.transaction((stmts: [ISqliteStatement, unknown[]][]) => {\n stmts.forEach((stmt) => {\n stmt[0].run(stmt[1])\n })\n })\n\n this.db.transaction(() => this._initialize())()\n\n this._cleanup = getPlatform().beforeExit(() => {\n this._save()\n this._destroy()\n })\n for (const cb of this._onLoad) cb(this.db)\n\n if (this._runLegacyMigrations) {\n this.db.transaction(() => {\n for (const migration of this._legacyMigrations.values()) {\n migration(this.db)\n }\n\n // in case _writeLater was used\n this._runMany(this._pending)\n })()\n }\n }\n\n _save(): void {\n if (!this._pending.length) return\n\n this._runMany(this._pending)\n this._pending = []\n }\n\n _destroy(): void {\n this.db.close()\n this._cleanup?.()\n this._cleanup = undefined\n }\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ITelegramStorageProvider } from '../../highlevel/storage/provider.js';
|
|
2
|
+
import { IMtStorageProvider } from '../provider.js';
|
|
3
|
+
import { BaseSqliteStorageDriver } from './driver.js';
|
|
4
|
+
import { SqliteAuthKeysRepository } from './repository/auth-keys.js';
|
|
5
|
+
import { SqliteKeyValueRepository } from './repository/kv.js';
|
|
6
|
+
import { SqlitePeersRepository } from './repository/peers.js';
|
|
7
|
+
import { SqliteRefMessagesRepository } from './repository/ref-messages.js';
|
|
8
|
+
export { BaseSqliteStorageDriver };
|
|
9
|
+
export * from './types.js';
|
|
10
|
+
export declare class BaseSqliteStorage implements IMtStorageProvider, ITelegramStorageProvider {
|
|
11
|
+
readonly driver: BaseSqliteStorageDriver;
|
|
12
|
+
constructor(driver: BaseSqliteStorageDriver);
|
|
13
|
+
readonly authKeys: SqliteAuthKeysRepository;
|
|
14
|
+
readonly kv: SqliteKeyValueRepository;
|
|
15
|
+
readonly refMessages: SqliteRefMessagesRepository;
|
|
16
|
+
readonly peers: SqlitePeersRepository;
|
|
17
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.BaseSqliteStorage = exports.BaseSqliteStorageDriver = void 0;
|
|
18
|
+
const driver_js_1 = require("./driver.js");
|
|
19
|
+
Object.defineProperty(exports, "BaseSqliteStorageDriver", { enumerable: true, get: function () { return driver_js_1.BaseSqliteStorageDriver; } });
|
|
20
|
+
const auth_keys_js_1 = require("./repository/auth-keys.js");
|
|
21
|
+
const kv_js_1 = require("./repository/kv.js");
|
|
22
|
+
const peers_js_1 = require("./repository/peers.js");
|
|
23
|
+
const ref_messages_js_1 = require("./repository/ref-messages.js");
|
|
24
|
+
__exportStar(require("./types.js"), exports);
|
|
25
|
+
class BaseSqliteStorage {
|
|
26
|
+
constructor(driver) {
|
|
27
|
+
this.driver = driver;
|
|
28
|
+
this.authKeys = new auth_keys_js_1.SqliteAuthKeysRepository(this.driver);
|
|
29
|
+
this.kv = new kv_js_1.SqliteKeyValueRepository(this.driver);
|
|
30
|
+
this.refMessages = new ref_messages_js_1.SqliteRefMessagesRepository(this.driver);
|
|
31
|
+
this.peers = new peers_js_1.SqlitePeersRepository(this.driver);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.BaseSqliteStorage = BaseSqliteStorage;
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/storage/sqlite/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAEA,2CAAqD;AAM5C,wGANA,mCAAuB,OAMA;AALhC,4DAAoE;AACpE,8CAA6D;AAC7D,oDAA6D;AAC7D,kEAA0E;AAG1E,6CAA0B;AAE1B,MAAa,iBAAiB;IAC1B,YAAqB,MAA+B;QAA/B,WAAM,GAAN,MAAM,CAAyB;QAE3C,aAAQ,GAAG,IAAI,uCAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACpD,OAAE,GAAG,IAAI,gCAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC9C,gBAAW,GAAG,IAAI,6CAA2B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1D,UAAK,GAAG,IAAI,gCAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IALA,CAAC;CAM3D;AAPD,8CAOC","sourcesContent":["import { ITelegramStorageProvider } from '../../highlevel/storage/provider.js'\nimport { IMtStorageProvider } from '../provider.js'\nimport { BaseSqliteStorageDriver } from './driver.js'\nimport { SqliteAuthKeysRepository } from './repository/auth-keys.js'\nimport { SqliteKeyValueRepository } from './repository/kv.js'\nimport { SqlitePeersRepository } from './repository/peers.js'\nimport { SqliteRefMessagesRepository } from './repository/ref-messages.js'\n\nexport { BaseSqliteStorageDriver }\nexport * from './types.js'\n\nexport class BaseSqliteStorage implements IMtStorageProvider, ITelegramStorageProvider {\n constructor(readonly driver: BaseSqliteStorageDriver) {}\n\n readonly authKeys = new SqliteAuthKeysRepository(this.driver)\n readonly kv = new SqliteKeyValueRepository(this.driver)\n readonly refMessages = new SqliteRefMessagesRepository(this.driver)\n readonly peers = new SqlitePeersRepository(this.driver)\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IAuthKeysRepository } from '../../repository/auth-keys.js';
|
|
2
|
+
import { BaseSqliteStorageDriver } from '../driver.js';
|
|
3
|
+
export declare class SqliteAuthKeysRepository implements IAuthKeysRepository {
|
|
4
|
+
readonly _driver: BaseSqliteStorageDriver;
|
|
5
|
+
constructor(_driver: BaseSqliteStorageDriver);
|
|
6
|
+
private _set;
|
|
7
|
+
private _del;
|
|
8
|
+
set(dc: number, key: Uint8Array | null): void;
|
|
9
|
+
private _get;
|
|
10
|
+
get(dc: number): Uint8Array | null;
|
|
11
|
+
private _setTemp;
|
|
12
|
+
private _delTemp;
|
|
13
|
+
setTemp(dc: number, idx: number, key: Uint8Array | null, expires: number): void;
|
|
14
|
+
private _getTemp;
|
|
15
|
+
getTemp(dc: number, idx: number, now: number): Uint8Array | null;
|
|
16
|
+
private _delTempAll;
|
|
17
|
+
deleteByDc(dc: number): void;
|
|
18
|
+
private _delAll;
|
|
19
|
+
deleteAll(): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqliteAuthKeysRepository = void 0;
|
|
4
|
+
class SqliteAuthKeysRepository {
|
|
5
|
+
constructor(_driver) {
|
|
6
|
+
this._driver = _driver;
|
|
7
|
+
_driver.registerMigration('auth_keys', 1, (db) => {
|
|
8
|
+
db.exec(`
|
|
9
|
+
create table if not exists auth_keys (
|
|
10
|
+
dc integer primary key,
|
|
11
|
+
key blob not null
|
|
12
|
+
);
|
|
13
|
+
create table if not exists temp_auth_keys (
|
|
14
|
+
dc integer not null,
|
|
15
|
+
idx integer not null,
|
|
16
|
+
key blob not null,
|
|
17
|
+
expires integer not null,
|
|
18
|
+
primary key (dc, idx)
|
|
19
|
+
);
|
|
20
|
+
`);
|
|
21
|
+
});
|
|
22
|
+
_driver.onLoad((db) => {
|
|
23
|
+
this._get = db.prepare('select key from auth_keys where dc = ?');
|
|
24
|
+
this._getTemp = db.prepare('select key from temp_auth_keys where dc = ? and idx = ? and expires > ?');
|
|
25
|
+
this._set = db.prepare('insert or replace into auth_keys (dc, key) values (?, ?)');
|
|
26
|
+
this._setTemp = this._driver.db.prepare('insert or replace into temp_auth_keys (dc, idx, key, expires) values (?, ?, ?, ?)');
|
|
27
|
+
this._del = db.prepare('delete from auth_keys where dc = ?');
|
|
28
|
+
this._delTemp = db.prepare('delete from temp_auth_keys where dc = ? and idx = ?');
|
|
29
|
+
this._delTempAll = db.prepare('delete from temp_auth_keys where dc = ?');
|
|
30
|
+
this._delAll = db.prepare('delete from auth_keys');
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
set(dc, key) {
|
|
34
|
+
if (!key) {
|
|
35
|
+
this._del.run(dc);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this._set.run(dc, key);
|
|
39
|
+
}
|
|
40
|
+
get(dc) {
|
|
41
|
+
const row = this._get.get(dc);
|
|
42
|
+
if (!row)
|
|
43
|
+
return null;
|
|
44
|
+
return row.key;
|
|
45
|
+
}
|
|
46
|
+
setTemp(dc, idx, key, expires) {
|
|
47
|
+
if (!key) {
|
|
48
|
+
this._delTemp.run(dc, idx);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this._setTemp.run(dc, idx, key, expires);
|
|
52
|
+
}
|
|
53
|
+
getTemp(dc, idx, now) {
|
|
54
|
+
const row = this._getTemp.get(dc, idx, now);
|
|
55
|
+
if (!row)
|
|
56
|
+
return null;
|
|
57
|
+
return row.key;
|
|
58
|
+
}
|
|
59
|
+
deleteByDc(dc) {
|
|
60
|
+
this._del.run(dc);
|
|
61
|
+
this._delTempAll.run(dc);
|
|
62
|
+
}
|
|
63
|
+
deleteAll() {
|
|
64
|
+
this._delAll.run();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.SqliteAuthKeysRepository = SqliteAuthKeysRepository;
|
|
68
|
+
//# sourceMappingURL=auth-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-keys.js","sourceRoot":"","sources":["../../../../../src/storage/sqlite/repository/auth-keys.ts"],"names":[],"mappings":";;;AAcA,MAAa,wBAAwB;IACjC,YAAqB,OAAgC;QAAhC,YAAO,GAAP,OAAO,CAAyB;QACjD,OAAO,CAAC,iBAAiB,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;YAC7C,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;aAYP,CAAC,CAAA;QACN,CAAC,CAAC,CAAA;QACF,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YAClB,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAA;YAChE,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,yEAAyE,CAAC,CAAA;YAErG,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,0DAA0D,CAAC,CAAA;YAClF,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CACnC,mFAAmF,CACtF,CAAA;YAED,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAA;YAC5D,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,qDAAqD,CAAC,CAAA;YACjF,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAA;YACxE,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAA;QACtD,CAAC,CAAC,CAAA;IACN,CAAC;IAID,GAAG,CAAC,EAAU,EAAE,GAAsB;QAClC,IAAI,CAAC,GAAG,EAAE;YACN,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAEjB,OAAM;SACT;QAED,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;IAC1B,CAAC;IAGD,GAAG,CAAC,EAAU;QACV,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC7B,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QAErB,OAAQ,GAAkB,CAAC,GAAG,CAAA;IAClC,CAAC;IAID,OAAO,CAAC,EAAU,EAAE,GAAW,EAAE,GAAsB,EAAE,OAAe;QACpE,IAAI,CAAC,GAAG,EAAE;YACN,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;YAE1B,OAAM;SACT;QAED,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAC5C,CAAC;IAGD,OAAO,CAAC,EAAU,EAAE,GAAW,EAAE,GAAW;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;QAC3C,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QAErB,OAAQ,GAAsB,CAAC,GAAG,CAAA;IACtC,CAAC;IAGD,UAAU,CAAC,EAAU;QACjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACjB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC5B,CAAC;IAGD,SAAS;QACL,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAA;IACtB,CAAC;CACJ;AAnFD,4DAmFC","sourcesContent":["import { IAuthKeysRepository } from '../../repository/auth-keys.js'\nimport { BaseSqliteStorageDriver } from '../driver.js'\nimport { ISqliteStatement } from '../types.js'\n\ninterface AuthKeyDto {\n dc: number\n key: Uint8Array\n}\n\ninterface TempAuthKeyDto extends AuthKeyDto {\n expires?: number\n idx?: number\n}\n\nexport class SqliteAuthKeysRepository implements IAuthKeysRepository {\n constructor(readonly _driver: BaseSqliteStorageDriver) {\n _driver.registerMigration('auth_keys', 1, (db) => {\n db.exec(`\n create table if not exists auth_keys (\n dc integer primary key,\n key blob not null\n );\n create table if not exists temp_auth_keys (\n dc integer not null,\n idx integer not null,\n key blob not null,\n expires integer not null,\n primary key (dc, idx)\n );\n `)\n })\n _driver.onLoad((db) => {\n this._get = db.prepare('select key from auth_keys where dc = ?')\n this._getTemp = db.prepare('select key from temp_auth_keys where dc = ? and idx = ? and expires > ?')\n\n this._set = db.prepare('insert or replace into auth_keys (dc, key) values (?, ?)')\n this._setTemp = this._driver.db.prepare(\n 'insert or replace into temp_auth_keys (dc, idx, key, expires) values (?, ?, ?, ?)',\n )\n\n this._del = db.prepare('delete from auth_keys where dc = ?')\n this._delTemp = db.prepare('delete from temp_auth_keys where dc = ? and idx = ?')\n this._delTempAll = db.prepare('delete from temp_auth_keys where dc = ?')\n this._delAll = db.prepare('delete from auth_keys')\n })\n }\n\n private _set!: ISqliteStatement\n private _del!: ISqliteStatement\n set(dc: number, key: Uint8Array | null): void {\n if (!key) {\n this._del.run(dc)\n\n return\n }\n\n this._set.run(dc, key)\n }\n\n private _get!: ISqliteStatement\n get(dc: number): Uint8Array | null {\n const row = this._get.get(dc)\n if (!row) return null\n\n return (row as AuthKeyDto).key\n }\n\n private _setTemp!: ISqliteStatement\n private _delTemp!: ISqliteStatement\n setTemp(dc: number, idx: number, key: Uint8Array | null, expires: number): void {\n if (!key) {\n this._delTemp.run(dc, idx)\n\n return\n }\n\n this._setTemp.run(dc, idx, key, expires)\n }\n\n private _getTemp!: ISqliteStatement\n getTemp(dc: number, idx: number, now: number): Uint8Array | null {\n const row = this._getTemp.get(dc, idx, now)\n if (!row) return null\n\n return (row as TempAuthKeyDto).key\n }\n\n private _delTempAll!: ISqliteStatement\n deleteByDc(dc: number): void {\n this._del.run(dc)\n this._delTempAll.run(dc)\n }\n\n private _delAll!: ISqliteStatement\n deleteAll(): void {\n this._delAll.run()\n }\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IKeyValueRepository } from '../../repository/key-value.js';
|
|
2
|
+
import { BaseSqliteStorageDriver } from '../driver.js';
|
|
3
|
+
export declare class SqliteKeyValueRepository implements IKeyValueRepository {
|
|
4
|
+
readonly _driver: BaseSqliteStorageDriver;
|
|
5
|
+
constructor(_driver: BaseSqliteStorageDriver);
|
|
6
|
+
private _set;
|
|
7
|
+
set(key: string, value: Uint8Array): void;
|
|
8
|
+
private _get;
|
|
9
|
+
get(key: string): Uint8Array | null;
|
|
10
|
+
private _del;
|
|
11
|
+
delete(key: string): void;
|
|
12
|
+
private _delAll;
|
|
13
|
+
deleteAll(): void;
|
|
14
|
+
}
|