gramobase 1.0.11 → 1.0.13
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/README.md +74 -28
- package/dist/{BotWorkerPool-9ndHQt2g.d.cts → BotWorkerPool-h_8a20dt.d.cts} +8 -3
- package/dist/{BotWorkerPool-9ndHQt2g.d.ts → BotWorkerPool-h_8a20dt.d.ts} +8 -3
- package/dist/{GramoBaseAuth-00fg0u_b.d.ts → GramoBaseAuth-DfRKq2yW.d.ts} +52 -15
- package/dist/{GramoBaseAuth-CHNn2_e5.d.cts → GramoBaseAuth-ObeOxqKj.d.cts} +52 -15
- package/dist/auth/index.d.cts +2 -2
- package/dist/auth/index.d.ts +2 -2
- package/dist/index.cjs +118 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -37
- package/dist/index.d.ts +6 -37
- package/dist/index.js +118 -26
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.cts +1 -2
- package/dist/migrations/index.d.ts +1 -2
- package/dist/studio/server.cjs +133 -26
- package/dist/studio/server.cjs.map +1 -1
- package/dist/studio/server.js +133 -26
- package/dist/studio/server.js.map +1 -1
- package/package.json +23 -23
package/dist/index.d.cts
CHANGED
|
@@ -1,40 +1,9 @@
|
|
|
1
|
-
import { B as BotWorkerPool,
|
|
2
|
-
export { b as ComparisonOperator, c as Filter, d as FindOptions, e as GramoBaseDocument,
|
|
3
|
-
import {
|
|
4
|
-
import { C as Collection, G as GramoBaseAuth } from './GramoBaseAuth-CHNn2_e5.cjs';
|
|
1
|
+
import { B as BotWorkerPool, G as GramoBaseEvent, a as GramoBaseConfig, S as SchemaLike, C as CollectionConfig, A as AuthConfig, U as UploadOptions, F as FileRecord, M as Migration, W as WorkerStats } from './BotWorkerPool-h_8a20dt.cjs';
|
|
2
|
+
export { b as ComparisonOperator, c as Filter, d as FindOptions, e as GramoBaseDocument, I as InferSchema, L as Lease, f as Session, g as UpdateOperators, h as User, i as WalEntry, j as WalOpType, k as WithId } from './BotWorkerPool-h_8a20dt.cjs';
|
|
3
|
+
import { R as Registry, C as Collection, G as GramoBaseAuth } from './GramoBaseAuth-ObeOxqKj.cjs';
|
|
5
4
|
import EventEmitter from 'eventemitter3';
|
|
6
5
|
import 'node-telegram-bot-api';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Registry uses a pinned Telegram message as a distributed lock.
|
|
10
|
-
*
|
|
11
|
-
* When a gramobase instance starts up, it reads the registry message.
|
|
12
|
-
* If no lease exists or the existing lease is expired, it writes a new
|
|
13
|
-
* lease with its own instanceId and begins sending heartbeats.
|
|
14
|
-
*
|
|
15
|
-
* This prevents multiple writer processes from corrupting the index
|
|
16
|
-
* (last-write-wins races on the pinned index message).
|
|
17
|
-
*
|
|
18
|
-
* Read-only operations are always permitted. Only index mutations
|
|
19
|
-
* require holding the write lease.
|
|
20
|
-
*/
|
|
21
|
-
declare class Registry {
|
|
22
|
-
private pool;
|
|
23
|
-
private channelId;
|
|
24
|
-
private debug;
|
|
25
|
-
private state;
|
|
26
|
-
private readonly instanceId;
|
|
27
|
-
constructor(pool: BotWorkerPool, channelId: string, debug?: boolean);
|
|
28
|
-
acquireWriteLease(): Promise<Lease>;
|
|
29
|
-
releaseWriteLease(): Promise<void>;
|
|
30
|
-
forceRelease(): Promise<void>;
|
|
31
|
-
isWriteLeaseHeld(): Promise<boolean>;
|
|
32
|
-
private heartbeat;
|
|
33
|
-
private readRegistryMessage;
|
|
34
|
-
private writeRegistryMessage;
|
|
35
|
-
getInstanceId(): string;
|
|
36
|
-
getCurrentLease(): Lease | null;
|
|
37
|
-
}
|
|
6
|
+
import 'zod';
|
|
38
7
|
|
|
39
8
|
type Unsubscribe = () => void;
|
|
40
9
|
/**
|
|
@@ -78,7 +47,7 @@ declare class GramoBase {
|
|
|
78
47
|
constructor(config: GramoBaseConfig);
|
|
79
48
|
connect(): Promise<this>;
|
|
80
49
|
disconnect(): Promise<void>;
|
|
81
|
-
collection<T extends
|
|
50
|
+
collection<T extends SchemaLike>(name: string, config: CollectionConfig<T>): Collection<T>;
|
|
82
51
|
createAuth(config: AuthConfig): GramoBaseAuth;
|
|
83
52
|
uploadFile(data: Buffer, options?: UploadOptions): Promise<FileRecord>;
|
|
84
53
|
getFileUrl(fileId: string): Promise<string>;
|
|
@@ -101,4 +70,4 @@ declare class GramoBase {
|
|
|
101
70
|
}
|
|
102
71
|
declare function createClient(config: GramoBaseConfig): GramoBase;
|
|
103
72
|
|
|
104
|
-
export { AuthConfig, Collection, CollectionConfig, FileRecord, GramoBase, GramoBaseAuth, GramoBaseConfig, GramoBaseEvent,
|
|
73
|
+
export { AuthConfig, Collection, CollectionConfig, FileRecord, GramoBase, GramoBaseAuth, GramoBaseConfig, GramoBaseEvent, Migration, RealtimeManager, SchemaLike, UploadOptions, createClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,40 +1,9 @@
|
|
|
1
|
-
import { B as BotWorkerPool,
|
|
2
|
-
export { b as ComparisonOperator, c as Filter, d as FindOptions, e as GramoBaseDocument,
|
|
3
|
-
import {
|
|
4
|
-
import { C as Collection, G as GramoBaseAuth } from './GramoBaseAuth-00fg0u_b.js';
|
|
1
|
+
import { B as BotWorkerPool, G as GramoBaseEvent, a as GramoBaseConfig, S as SchemaLike, C as CollectionConfig, A as AuthConfig, U as UploadOptions, F as FileRecord, M as Migration, W as WorkerStats } from './BotWorkerPool-h_8a20dt.js';
|
|
2
|
+
export { b as ComparisonOperator, c as Filter, d as FindOptions, e as GramoBaseDocument, I as InferSchema, L as Lease, f as Session, g as UpdateOperators, h as User, i as WalEntry, j as WalOpType, k as WithId } from './BotWorkerPool-h_8a20dt.js';
|
|
3
|
+
import { R as Registry, C as Collection, G as GramoBaseAuth } from './GramoBaseAuth-DfRKq2yW.js';
|
|
5
4
|
import EventEmitter from 'eventemitter3';
|
|
6
5
|
import 'node-telegram-bot-api';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Registry uses a pinned Telegram message as a distributed lock.
|
|
10
|
-
*
|
|
11
|
-
* When a gramobase instance starts up, it reads the registry message.
|
|
12
|
-
* If no lease exists or the existing lease is expired, it writes a new
|
|
13
|
-
* lease with its own instanceId and begins sending heartbeats.
|
|
14
|
-
*
|
|
15
|
-
* This prevents multiple writer processes from corrupting the index
|
|
16
|
-
* (last-write-wins races on the pinned index message).
|
|
17
|
-
*
|
|
18
|
-
* Read-only operations are always permitted. Only index mutations
|
|
19
|
-
* require holding the write lease.
|
|
20
|
-
*/
|
|
21
|
-
declare class Registry {
|
|
22
|
-
private pool;
|
|
23
|
-
private channelId;
|
|
24
|
-
private debug;
|
|
25
|
-
private state;
|
|
26
|
-
private readonly instanceId;
|
|
27
|
-
constructor(pool: BotWorkerPool, channelId: string, debug?: boolean);
|
|
28
|
-
acquireWriteLease(): Promise<Lease>;
|
|
29
|
-
releaseWriteLease(): Promise<void>;
|
|
30
|
-
forceRelease(): Promise<void>;
|
|
31
|
-
isWriteLeaseHeld(): Promise<boolean>;
|
|
32
|
-
private heartbeat;
|
|
33
|
-
private readRegistryMessage;
|
|
34
|
-
private writeRegistryMessage;
|
|
35
|
-
getInstanceId(): string;
|
|
36
|
-
getCurrentLease(): Lease | null;
|
|
37
|
-
}
|
|
6
|
+
import 'zod';
|
|
38
7
|
|
|
39
8
|
type Unsubscribe = () => void;
|
|
40
9
|
/**
|
|
@@ -78,7 +47,7 @@ declare class GramoBase {
|
|
|
78
47
|
constructor(config: GramoBaseConfig);
|
|
79
48
|
connect(): Promise<this>;
|
|
80
49
|
disconnect(): Promise<void>;
|
|
81
|
-
collection<T extends
|
|
50
|
+
collection<T extends SchemaLike>(name: string, config: CollectionConfig<T>): Collection<T>;
|
|
82
51
|
createAuth(config: AuthConfig): GramoBaseAuth;
|
|
83
52
|
uploadFile(data: Buffer, options?: UploadOptions): Promise<FileRecord>;
|
|
84
53
|
getFileUrl(fileId: string): Promise<string>;
|
|
@@ -101,4 +70,4 @@ declare class GramoBase {
|
|
|
101
70
|
}
|
|
102
71
|
declare function createClient(config: GramoBaseConfig): GramoBase;
|
|
103
72
|
|
|
104
|
-
export { AuthConfig, Collection, CollectionConfig, FileRecord, GramoBase, GramoBaseAuth, GramoBaseConfig, GramoBaseEvent,
|
|
73
|
+
export { AuthConfig, Collection, CollectionConfig, FileRecord, GramoBase, GramoBaseAuth, GramoBaseConfig, GramoBaseEvent, Migration, RealtimeManager, SchemaLike, UploadOptions, createClient };
|
package/dist/index.js
CHANGED
|
@@ -270,9 +270,10 @@ var INDEX_TAG = "__GRAMOBASE_INDEX__";
|
|
|
270
270
|
var DOC_TAG = "__GRAMOBASE_DOC__";
|
|
271
271
|
var MAX_MSG_BYTES = 4e3;
|
|
272
272
|
var TelegramStorage = class {
|
|
273
|
-
constructor(pool, defaultChannelId, encryptionKey, debug = false) {
|
|
273
|
+
constructor(pool, defaultChannelId, registry, encryptionKey, debug = false) {
|
|
274
274
|
this.pool = pool;
|
|
275
275
|
this.defaultChannelId = defaultChannelId;
|
|
276
|
+
this.registry = registry;
|
|
276
277
|
this.debug = debug;
|
|
277
278
|
if (encryptionKey) {
|
|
278
279
|
this.encryptionKey = createHash("sha256").update(encryptionKey).digest();
|
|
@@ -280,20 +281,52 @@ var TelegramStorage = class {
|
|
|
280
281
|
}
|
|
281
282
|
pool;
|
|
282
283
|
defaultChannelId;
|
|
284
|
+
registry;
|
|
283
285
|
debug;
|
|
284
286
|
encryptionKey = null;
|
|
285
287
|
// collection → pinned index message ID
|
|
286
288
|
indexMsgIds = /* @__PURE__ */ new Map();
|
|
287
289
|
// ─── Index management ─────────────────────────────────────────────────────
|
|
290
|
+
async readRawMessageText(msgId, channel) {
|
|
291
|
+
try {
|
|
292
|
+
const msg = await this.pool.execute(
|
|
293
|
+
(bot) => bot.forwardMessage(channel, channel, msgId)
|
|
294
|
+
);
|
|
295
|
+
if (!msg?.text) return null;
|
|
296
|
+
let text = msg.text;
|
|
297
|
+
if (this.encryptionKey && text.startsWith("ENC:")) {
|
|
298
|
+
text = this.decrypt(text);
|
|
299
|
+
}
|
|
300
|
+
return text;
|
|
301
|
+
} catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
288
305
|
async loadIndex(collection, channelId) {
|
|
289
306
|
const channel = channelId ?? this.defaultChannelId;
|
|
307
|
+
try {
|
|
308
|
+
const msgId = await this.registry.getCollectionIndexMsgId(collection);
|
|
309
|
+
if (msgId) {
|
|
310
|
+
const text = await this.readRawMessageText(msgId, channel);
|
|
311
|
+
if (text && text.startsWith(INDEX_TAG)) {
|
|
312
|
+
const json = text.replace(INDEX_TAG + "\n", "");
|
|
313
|
+
const parsed = JSON.parse(json);
|
|
314
|
+
this.indexMsgIds.set(collection, msgId);
|
|
315
|
+
return parsed;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
} catch {
|
|
319
|
+
}
|
|
290
320
|
try {
|
|
291
321
|
const chat = await this.pool.execute((bot) => bot.getChat(channel));
|
|
292
322
|
if (chat.pinned_message?.text?.startsWith(INDEX_TAG)) {
|
|
293
323
|
const json = chat.pinned_message.text.replace(INDEX_TAG + "\n", "");
|
|
294
324
|
const parsed = JSON.parse(json);
|
|
295
|
-
|
|
296
|
-
|
|
325
|
+
if (parsed.collection === collection) {
|
|
326
|
+
this.indexMsgIds.set(collection, chat.pinned_message.message_id);
|
|
327
|
+
await this.registry.setCollectionIndexMsgId(collection, chat.pinned_message.message_id);
|
|
328
|
+
return parsed;
|
|
329
|
+
}
|
|
297
330
|
}
|
|
298
331
|
} catch {
|
|
299
332
|
}
|
|
@@ -308,7 +341,7 @@ var TelegramStorage = class {
|
|
|
308
341
|
const channel = channelId ?? this.defaultChannelId;
|
|
309
342
|
const text = `${INDEX_TAG}
|
|
310
343
|
${JSON.stringify(index)}`;
|
|
311
|
-
const existingMsgId = this.indexMsgIds.get(index.collection);
|
|
344
|
+
const existingMsgId = this.indexMsgIds.get(index.collection) || await this.registry.getCollectionIndexMsgId(index.collection);
|
|
312
345
|
if (existingMsgId) {
|
|
313
346
|
try {
|
|
314
347
|
await this.pool.execute(
|
|
@@ -324,10 +357,9 @@ ${JSON.stringify(index)}`;
|
|
|
324
357
|
const msg = await this.pool.execute(
|
|
325
358
|
(bot) => bot.sendMessage(channel, text, { disable_notification: true })
|
|
326
359
|
);
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
);
|
|
360
|
+
const newMsgId = msg.message_id;
|
|
361
|
+
this.indexMsgIds.set(index.collection, newMsgId);
|
|
362
|
+
await this.registry.setCollectionIndexMsgId(index.collection, newMsgId);
|
|
331
363
|
}
|
|
332
364
|
// ─── Document CRUD ────────────────────────────────────────────────────────
|
|
333
365
|
async writeDocument(doc, channelId) {
|
|
@@ -347,10 +379,9 @@ ${JSON.stringify(index)}`;
|
|
|
347
379
|
async readDocument(msgId, channelId) {
|
|
348
380
|
const channel = channelId ?? this.defaultChannelId;
|
|
349
381
|
try {
|
|
350
|
-
const
|
|
351
|
-
(bot) => bot.
|
|
382
|
+
const msg = await this.pool.execute(
|
|
383
|
+
(bot) => bot.forwardMessage(channel, channel, msgId)
|
|
352
384
|
);
|
|
353
|
-
const msg = Array.isArray(msgs) ? msgs[0] : msgs;
|
|
354
385
|
if (!msg?.text) return null;
|
|
355
386
|
let text = msg.text;
|
|
356
387
|
if (this.encryptionKey && text.startsWith("ENC:")) {
|
|
@@ -361,6 +392,7 @@ ${JSON.stringify(index)}`;
|
|
|
361
392
|
}
|
|
362
393
|
const parsed = JSON.parse(text);
|
|
363
394
|
delete parsed[DOC_TAG];
|
|
395
|
+
parsed._msgId = msgId;
|
|
364
396
|
return parsed;
|
|
365
397
|
} catch {
|
|
366
398
|
return null;
|
|
@@ -399,10 +431,9 @@ ${JSON.stringify(index)}`;
|
|
|
399
431
|
const msgIds = JSON.parse(headerText.replace("CHUNK:", ""));
|
|
400
432
|
const parts = [];
|
|
401
433
|
for (const id of msgIds) {
|
|
402
|
-
const
|
|
403
|
-
(bot) => bot.
|
|
434
|
+
const msg = await this.pool.execute(
|
|
435
|
+
(bot) => bot.forwardMessage(channel, channel, id)
|
|
404
436
|
);
|
|
405
|
-
const msg = Array.isArray(msgs) ? msgs[0] : msgs;
|
|
406
437
|
if (msg?.text) parts.push(msg.text);
|
|
407
438
|
}
|
|
408
439
|
return parts.join("");
|
|
@@ -603,7 +634,8 @@ var Registry = class {
|
|
|
603
634
|
this.state = {
|
|
604
635
|
activeLease: null,
|
|
605
636
|
instanceId: this.instanceId,
|
|
606
|
-
registryMsgId: null
|
|
637
|
+
registryMsgId: null,
|
|
638
|
+
indexes: {}
|
|
607
639
|
};
|
|
608
640
|
}
|
|
609
641
|
pool;
|
|
@@ -611,14 +643,33 @@ var Registry = class {
|
|
|
611
643
|
debug;
|
|
612
644
|
state;
|
|
613
645
|
instanceId;
|
|
614
|
-
async acquireWriteLease() {
|
|
646
|
+
async acquireWriteLease(options = { wait: true }) {
|
|
615
647
|
const existing = await this.readRegistryMessage();
|
|
616
648
|
if (existing?.activeLease) {
|
|
617
649
|
const lease2 = existing.activeLease;
|
|
618
650
|
if (lease2.instanceId !== this.instanceId && Date.now() < lease2.expiresAt) {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
651
|
+
if (!options.wait) {
|
|
652
|
+
throw new Error(
|
|
653
|
+
`[gramobase Registry] Another instance (${lease2.instanceId}) holds the write lease until ${new Date(
|
|
654
|
+
lease2.expiresAt
|
|
655
|
+
).toISOString()}. Use Registry.forceRelease() to break a stale lease.`
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
const waitMs = lease2.expiresAt - Date.now() + 250;
|
|
659
|
+
if (this.debug) {
|
|
660
|
+
console.log(
|
|
661
|
+
`[Registry] Lease held by ${lease2.instanceId}, waiting ${waitMs}ms for it to expire...`
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
665
|
+
const recheckState = await this.readRegistryMessage();
|
|
666
|
+
if (recheckState?.activeLease && recheckState.activeLease.instanceId !== this.instanceId && Date.now() < recheckState.activeLease.expiresAt) {
|
|
667
|
+
throw new Error(
|
|
668
|
+
`[gramobase Registry] Another instance (${recheckState.activeLease.instanceId}) holds the write lease until ${new Date(
|
|
669
|
+
recheckState.activeLease.expiresAt
|
|
670
|
+
).toISOString()}. Use Registry.forceRelease() to break a stale lease.`
|
|
671
|
+
);
|
|
672
|
+
}
|
|
622
673
|
}
|
|
623
674
|
}
|
|
624
675
|
const lease = {
|
|
@@ -670,15 +721,26 @@ var Registry = class {
|
|
|
670
721
|
if (chat.pinned_message?.text?.startsWith(REGISTRY_TAG)) {
|
|
671
722
|
this.state.registryMsgId = chat.pinned_message.message_id;
|
|
672
723
|
const json = chat.pinned_message.text.replace(REGISTRY_TAG + "\n", "");
|
|
673
|
-
|
|
724
|
+
const parsed = JSON.parse(json);
|
|
725
|
+
this.state.indexes = parsed.indexes || {};
|
|
726
|
+
return parsed;
|
|
674
727
|
}
|
|
675
728
|
} catch {
|
|
676
729
|
}
|
|
677
730
|
return null;
|
|
678
731
|
}
|
|
679
732
|
async writeRegistryMessage(data) {
|
|
733
|
+
let leasePayload = null;
|
|
734
|
+
if (data.activeLease) {
|
|
735
|
+
const { heartbeatInterval, ...rest } = data.activeLease;
|
|
736
|
+
leasePayload = rest;
|
|
737
|
+
}
|
|
738
|
+
const payload = {
|
|
739
|
+
activeLease: leasePayload,
|
|
740
|
+
indexes: data.indexes || this.state.indexes || {}
|
|
741
|
+
};
|
|
680
742
|
const text = `${REGISTRY_TAG}
|
|
681
|
-
${JSON.stringify(
|
|
743
|
+
${JSON.stringify(payload, null, 0)}`;
|
|
682
744
|
if (this.state.registryMsgId) {
|
|
683
745
|
try {
|
|
684
746
|
await this.pool.execute(
|
|
@@ -701,6 +763,22 @@ ${JSON.stringify(data, null, 0)}`;
|
|
|
701
763
|
})
|
|
702
764
|
);
|
|
703
765
|
}
|
|
766
|
+
async getCollectionIndexMsgId(collection) {
|
|
767
|
+
if (!this.state.registryMsgId) {
|
|
768
|
+
await this.readRegistryMessage();
|
|
769
|
+
}
|
|
770
|
+
return this.state.indexes[collection] || null;
|
|
771
|
+
}
|
|
772
|
+
async setCollectionIndexMsgId(collection, msgId) {
|
|
773
|
+
if (!this.state.registryMsgId) {
|
|
774
|
+
await this.readRegistryMessage();
|
|
775
|
+
}
|
|
776
|
+
this.state.indexes[collection] = msgId;
|
|
777
|
+
await this.writeRegistryMessage({
|
|
778
|
+
activeLease: this.state.activeLease,
|
|
779
|
+
indexes: this.state.indexes
|
|
780
|
+
});
|
|
781
|
+
}
|
|
704
782
|
getInstanceId() {
|
|
705
783
|
return this.instanceId;
|
|
706
784
|
}
|
|
@@ -1456,9 +1534,15 @@ var GramoBase = class {
|
|
|
1456
1534
|
const tokens = Array.isArray(config.botToken) ? config.botToken : [config.botToken];
|
|
1457
1535
|
this.pool = new BotWorkerPool(tokens, config.concurrency ?? 25, config.debug ?? false);
|
|
1458
1536
|
this.cache = new HotCache(config.cacheMaxBytes, config.cacheTtlMs);
|
|
1537
|
+
this.registry = new Registry(
|
|
1538
|
+
this.pool,
|
|
1539
|
+
config.indexChannelId ?? config.channelId,
|
|
1540
|
+
config.debug ?? false
|
|
1541
|
+
);
|
|
1459
1542
|
this.storage = new TelegramStorage(
|
|
1460
1543
|
this.pool,
|
|
1461
1544
|
config.channelId,
|
|
1545
|
+
this.registry,
|
|
1462
1546
|
config.encryptionKey,
|
|
1463
1547
|
config.debug ?? false
|
|
1464
1548
|
);
|
|
@@ -1467,11 +1551,6 @@ var GramoBase = class {
|
|
|
1467
1551
|
config.walChannelId ?? config.channelId,
|
|
1468
1552
|
config.debug ?? false
|
|
1469
1553
|
);
|
|
1470
|
-
this.registry = new Registry(
|
|
1471
|
-
this.pool,
|
|
1472
|
-
config.indexChannelId ?? config.channelId,
|
|
1473
|
-
config.debug ?? false
|
|
1474
|
-
);
|
|
1475
1554
|
this.realtime = new RealtimeManager(
|
|
1476
1555
|
this.pool,
|
|
1477
1556
|
config.webhookUrl,
|
|
@@ -1602,7 +1681,20 @@ var GramoBase = class {
|
|
|
1602
1681
|
}
|
|
1603
1682
|
}
|
|
1604
1683
|
};
|
|
1684
|
+
var globalForGramo = globalThis;
|
|
1605
1685
|
function createClient(config) {
|
|
1686
|
+
if (config.global) {
|
|
1687
|
+
if (!globalForGramo.__gramobase_clients__) {
|
|
1688
|
+
globalForGramo.__gramobase_clients__ = /* @__PURE__ */ new Map();
|
|
1689
|
+
}
|
|
1690
|
+
const cacheKey = Array.isArray(config.botToken) ? `${config.channelId}:${config.botToken.join(",")}` : `${config.channelId}:${config.botToken}`;
|
|
1691
|
+
if (globalForGramo.__gramobase_clients__.has(cacheKey)) {
|
|
1692
|
+
return globalForGramo.__gramobase_clients__.get(cacheKey);
|
|
1693
|
+
}
|
|
1694
|
+
const client = new GramoBase(config);
|
|
1695
|
+
globalForGramo.__gramobase_clients__.set(cacheKey, client);
|
|
1696
|
+
return client;
|
|
1697
|
+
}
|
|
1606
1698
|
return new GramoBase(config);
|
|
1607
1699
|
}
|
|
1608
1700
|
|