@lark-sh/client 0.1.19 → 0.1.21
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/dist/{chunk-UF3SZ62Y.mjs → chunk-HHBHX2EM.mjs} +85 -121
- package/dist/chunk-HHBHX2EM.mjs.map +1 -0
- package/dist/fb-v8/index.d.mts +5 -5
- package/dist/fb-v8/index.d.ts +5 -5
- package/dist/fb-v8/index.js +88 -124
- package/dist/fb-v8/index.js.map +1 -1
- package/dist/fb-v8/index.mjs +5 -5
- package/dist/fb-v8/index.mjs.map +1 -1
- package/dist/index.d.mts +37 -24
- package/dist/index.d.ts +37 -24
- package/dist/index.js +84 -120
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-UF3SZ62Y.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1581,17 +1581,14 @@ var SubscriptionManager = class {
|
|
|
1581
1581
|
queryParamsChanged = view.updateQueryParams(queryParams);
|
|
1582
1582
|
tag = this.viewKeyToTag.get(viewKey);
|
|
1583
1583
|
}
|
|
1584
|
-
const existingEventTypes = view.getEventTypes();
|
|
1585
|
-
const isNewEventType = !existingEventTypes.includes(eventType);
|
|
1586
1584
|
const unsubscribe = view.addCallback(eventType, callback);
|
|
1587
1585
|
const wrappedUnsubscribe = () => {
|
|
1588
1586
|
this.unsubscribeCallback(normalizedPath, eventType, callback, queryId);
|
|
1589
1587
|
};
|
|
1590
|
-
if (isNewView ||
|
|
1588
|
+
if (isNewView || queryParamsChanged) {
|
|
1591
1589
|
const hasAncestorComplete = this.hasAncestorCompleteView(normalizedPath);
|
|
1592
1590
|
if (!hasAncestorComplete) {
|
|
1593
|
-
|
|
1594
|
-
this.sendSubscribe?.(normalizedPath, allEventTypes, view.queryParams ?? void 0, tag).catch((err) => {
|
|
1591
|
+
this.sendSubscribe?.(normalizedPath, view.queryParams ?? void 0, tag).catch((err) => {
|
|
1595
1592
|
console.error("Failed to subscribe:", err);
|
|
1596
1593
|
});
|
|
1597
1594
|
}
|
|
@@ -1683,11 +1680,6 @@ var SubscriptionManager = class {
|
|
|
1683
1680
|
this.sendUnsubscribe?.(normalizedPath, queryParams).catch((err) => {
|
|
1684
1681
|
console.error("Failed to unsubscribe:", err);
|
|
1685
1682
|
});
|
|
1686
|
-
} else {
|
|
1687
|
-
const remainingEventTypes = view.getEventTypes();
|
|
1688
|
-
this.sendSubscribe?.(normalizedPath, remainingEventTypes, queryParams).catch((err) => {
|
|
1689
|
-
console.error("Failed to update subscription:", err);
|
|
1690
|
-
});
|
|
1691
1683
|
}
|
|
1692
1684
|
}
|
|
1693
1685
|
if (queryIds.size === 0) {
|
|
@@ -2115,10 +2107,9 @@ var SubscriptionManager = class {
|
|
|
2115
2107
|
*/
|
|
2116
2108
|
async resubscribeAll() {
|
|
2117
2109
|
for (const view of this.views.values()) {
|
|
2118
|
-
|
|
2119
|
-
if (eventTypes.length > 0) {
|
|
2110
|
+
if (view.hasCallbacks()) {
|
|
2120
2111
|
try {
|
|
2121
|
-
await this.sendSubscribe?.(view.path,
|
|
2112
|
+
await this.sendSubscribe?.(view.path, view.queryParams ?? void 0);
|
|
2122
2113
|
} catch (err) {
|
|
2123
2114
|
console.error(`Failed to resubscribe to ${view.path}:`, err);
|
|
2124
2115
|
}
|
|
@@ -4288,21 +4279,33 @@ var ServerValue = {
|
|
|
4288
4279
|
increment: (delta) => ({ ".sv": { increment: delta } })
|
|
4289
4280
|
};
|
|
4290
4281
|
var LarkDatabase = class {
|
|
4291
|
-
|
|
4282
|
+
/**
|
|
4283
|
+
* Create a new LarkDatabase instance.
|
|
4284
|
+
*
|
|
4285
|
+
* @param databaseId - Database ID in format "project/database"
|
|
4286
|
+
* @param options - Connection options (token, anonymous, domain, transport).
|
|
4287
|
+
* Defaults to anonymous auth if not specified.
|
|
4288
|
+
*
|
|
4289
|
+
* @example
|
|
4290
|
+
* ```typescript
|
|
4291
|
+
* // Lazy connection - connects on first operation
|
|
4292
|
+
* const db = new LarkDatabase('project/database', { anonymous: true });
|
|
4293
|
+
* db.ref('/users').on('value', cb); // Auto-connects here
|
|
4294
|
+
*
|
|
4295
|
+
* // Explicit connection - for UI feedback or error handling
|
|
4296
|
+
* const db = new LarkDatabase('project/database', { anonymous: true });
|
|
4297
|
+
* await db.connect(); // Explicitly await connection
|
|
4298
|
+
* db.ref('/users').on('value', cb);
|
|
4299
|
+
* ```
|
|
4300
|
+
*/
|
|
4301
|
+
constructor(databaseId, options = {}) {
|
|
4292
4302
|
this._state = "disconnected";
|
|
4293
4303
|
this._auth = null;
|
|
4294
|
-
this._databaseId = null;
|
|
4295
|
-
this._domain = null;
|
|
4296
4304
|
this._volatilePaths = [];
|
|
4297
4305
|
this._transportType = null;
|
|
4298
|
-
// Auth state
|
|
4299
|
-
this._currentToken = null;
|
|
4300
|
-
// Token for auth (empty string = anonymous)
|
|
4301
|
-
this._isAnonymous = false;
|
|
4302
4306
|
// True if connected anonymously
|
|
4303
4307
|
// Reconnection state
|
|
4304
4308
|
this._connectionId = null;
|
|
4305
|
-
this._connectOptions = null;
|
|
4306
4309
|
this._intentionalDisconnect = false;
|
|
4307
4310
|
this._reconnectAttempt = 0;
|
|
4308
4311
|
this._reconnectTimer = null;
|
|
@@ -4315,13 +4318,26 @@ var LarkDatabase = class {
|
|
|
4315
4318
|
this.authStateChangedCallbacks = /* @__PURE__ */ new Set();
|
|
4316
4319
|
// .info path subscriptions (handled locally, not sent to server)
|
|
4317
4320
|
this.infoSubscriptions = [];
|
|
4318
|
-
//
|
|
4319
|
-
this.
|
|
4320
|
-
this.authenticationResolve = null;
|
|
4321
|
+
// Connection promise - shared by connect() and lazy operations
|
|
4322
|
+
this._connectionPromise = null;
|
|
4321
4323
|
this._serverTimeOffset = 0;
|
|
4322
4324
|
this.messageQueue = new MessageQueue();
|
|
4323
4325
|
this.subscriptionManager = new SubscriptionManager();
|
|
4324
4326
|
this.pendingWrites = new PendingWriteManager();
|
|
4327
|
+
const projectId = databaseId.split("/")[0];
|
|
4328
|
+
if (!projectId) {
|
|
4329
|
+
throw new Error('Invalid database ID: must be in format "projectId/databaseName"');
|
|
4330
|
+
}
|
|
4331
|
+
this._databaseId = databaseId;
|
|
4332
|
+
this._connectOptions = options;
|
|
4333
|
+
this._domain = options.domain || DEFAULT_LARK_DOMAIN;
|
|
4334
|
+
this._currentToken = options.token || "";
|
|
4335
|
+
this._isAnonymous = !options.token && options.anonymous !== false;
|
|
4336
|
+
this.subscriptionManager.initialize({
|
|
4337
|
+
sendSubscribe: this.sendSubscribeMessage.bind(this),
|
|
4338
|
+
sendUnsubscribe: this.sendUnsubscribeMessage.bind(this),
|
|
4339
|
+
createSnapshot: this.createSnapshot.bind(this)
|
|
4340
|
+
});
|
|
4325
4341
|
}
|
|
4326
4342
|
// ============================================
|
|
4327
4343
|
// Connection State
|
|
@@ -4406,21 +4422,38 @@ var LarkDatabase = class {
|
|
|
4406
4422
|
// Connection Management
|
|
4407
4423
|
// ============================================
|
|
4408
4424
|
/**
|
|
4409
|
-
*
|
|
4425
|
+
* Explicitly connect to the database.
|
|
4410
4426
|
*
|
|
4411
|
-
*
|
|
4412
|
-
*
|
|
4427
|
+
* This is optional - operations will auto-connect if needed.
|
|
4428
|
+
* Use this when you want to:
|
|
4429
|
+
* - Await connection completion for UI feedback
|
|
4430
|
+
* - Handle connection errors separately from operation errors
|
|
4431
|
+
* - Pre-warm the connection before first operation
|
|
4432
|
+
*
|
|
4433
|
+
* @returns Promise that resolves when fully authenticated
|
|
4413
4434
|
*/
|
|
4414
|
-
async connect(
|
|
4415
|
-
|
|
4416
|
-
|
|
4435
|
+
async connect() {
|
|
4436
|
+
return this.ensureConnected();
|
|
4437
|
+
}
|
|
4438
|
+
/**
|
|
4439
|
+
* Ensure connection is established, triggering it if needed.
|
|
4440
|
+
* Multiple concurrent calls share the same connection promise.
|
|
4441
|
+
*/
|
|
4442
|
+
async ensureConnected() {
|
|
4443
|
+
if (this._state === "authenticated") {
|
|
4444
|
+
return;
|
|
4445
|
+
}
|
|
4446
|
+
if (this._connectionPromise) {
|
|
4447
|
+
return this._connectionPromise;
|
|
4417
4448
|
}
|
|
4418
|
-
this._connectOptions = options;
|
|
4419
4449
|
this._intentionalDisconnect = false;
|
|
4420
|
-
this.
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4450
|
+
this._connectionPromise = this.performConnect(this._databaseId, this._connectOptions);
|
|
4451
|
+
try {
|
|
4452
|
+
await this._connectionPromise;
|
|
4453
|
+
} catch (error) {
|
|
4454
|
+
this._connectionPromise = null;
|
|
4455
|
+
throw error;
|
|
4456
|
+
}
|
|
4424
4457
|
}
|
|
4425
4458
|
/**
|
|
4426
4459
|
* Internal connect implementation used by both initial connect and reconnect.
|
|
@@ -4430,19 +4463,9 @@ var LarkDatabase = class {
|
|
|
4430
4463
|
* 3. Send auth (authenticates user - required even for anonymous)
|
|
4431
4464
|
*/
|
|
4432
4465
|
async performConnect(databaseId, options, isReconnect = false) {
|
|
4433
|
-
const previousState = this._state;
|
|
4434
4466
|
this._state = isReconnect ? "reconnecting" : "connecting";
|
|
4435
|
-
this._databaseId = databaseId;
|
|
4436
|
-
this._domain = options.domain || DEFAULT_LARK_DOMAIN;
|
|
4437
|
-
if (!isReconnect) {
|
|
4438
|
-
this._currentToken = options.token || "";
|
|
4439
|
-
this._isAnonymous = !options.token && options.anonymous !== false;
|
|
4440
|
-
}
|
|
4441
4467
|
try {
|
|
4442
4468
|
const projectId = databaseId.split("/")[0];
|
|
4443
|
-
if (!projectId) {
|
|
4444
|
-
throw new Error('Invalid database ID: must be in format "projectId/databaseName"');
|
|
4445
|
-
}
|
|
4446
4469
|
const wsUrl = `wss://${projectId}.${this._domain}/ws`;
|
|
4447
4470
|
const transportResult = await createTransport(
|
|
4448
4471
|
wsUrl,
|
|
@@ -4495,18 +4518,7 @@ var LarkDatabase = class {
|
|
|
4495
4518
|
};
|
|
4496
4519
|
this._state = "authenticated";
|
|
4497
4520
|
this._reconnectAttempt = 0;
|
|
4498
|
-
if (this.authenticationResolve) {
|
|
4499
|
-
this.authenticationResolve();
|
|
4500
|
-
this.authenticationResolve = null;
|
|
4501
|
-
}
|
|
4502
4521
|
this.fireConnectionStateChange();
|
|
4503
|
-
if (!isReconnect) {
|
|
4504
|
-
this.subscriptionManager.initialize({
|
|
4505
|
-
sendSubscribe: this.sendSubscribeMessage.bind(this),
|
|
4506
|
-
sendUnsubscribe: this.sendUnsubscribeMessage.bind(this),
|
|
4507
|
-
createSnapshot: this.createSnapshot.bind(this)
|
|
4508
|
-
});
|
|
4509
|
-
}
|
|
4510
4522
|
if (isReconnect) {
|
|
4511
4523
|
await this.restoreAfterReconnect();
|
|
4512
4524
|
}
|
|
@@ -4520,12 +4532,8 @@ var LarkDatabase = class {
|
|
|
4520
4532
|
}
|
|
4521
4533
|
this._state = "disconnected";
|
|
4522
4534
|
this._auth = null;
|
|
4523
|
-
this._databaseId = null;
|
|
4524
|
-
this._connectOptions = null;
|
|
4525
4535
|
this._connectionId = null;
|
|
4526
4536
|
this._transportType = null;
|
|
4527
|
-
this._currentToken = null;
|
|
4528
|
-
this._isAnonymous = false;
|
|
4529
4537
|
this.transport?.close();
|
|
4530
4538
|
this.transport = null;
|
|
4531
4539
|
throw error;
|
|
@@ -4593,8 +4601,9 @@ var LarkDatabase = class {
|
|
|
4593
4601
|
}
|
|
4594
4602
|
}
|
|
4595
4603
|
/**
|
|
4596
|
-
* Full cleanup - clears
|
|
4604
|
+
* Full cleanup - clears connection state including subscriptions.
|
|
4597
4605
|
* Used for intentional disconnect.
|
|
4606
|
+
* Preserves config (databaseId, domain, token) so connect() can be called again.
|
|
4598
4607
|
*/
|
|
4599
4608
|
cleanupFull() {
|
|
4600
4609
|
const wasAuthenticated = this._state === "authenticated";
|
|
@@ -4602,17 +4611,11 @@ var LarkDatabase = class {
|
|
|
4602
4611
|
this.transport = null;
|
|
4603
4612
|
this._state = "disconnected";
|
|
4604
4613
|
this._auth = null;
|
|
4605
|
-
this._databaseId = null;
|
|
4606
4614
|
this._volatilePaths = [];
|
|
4607
|
-
this._domain = null;
|
|
4608
4615
|
this._connectionId = null;
|
|
4609
|
-
this._connectOptions = null;
|
|
4610
4616
|
this._transportType = null;
|
|
4611
|
-
this._currentToken = null;
|
|
4612
|
-
this._isAnonymous = false;
|
|
4613
4617
|
this._reconnectAttempt = 0;
|
|
4614
|
-
this.
|
|
4615
|
-
this.authenticationResolve = null;
|
|
4618
|
+
this._connectionPromise = null;
|
|
4616
4619
|
this.subscriptionManager.clear();
|
|
4617
4620
|
this.messageQueue.rejectAll(new Error("Connection closed"));
|
|
4618
4621
|
this.pendingWrites.clear();
|
|
@@ -4713,15 +4716,14 @@ var LarkDatabase = class {
|
|
|
4713
4716
|
* Attempt to reconnect to the database.
|
|
4714
4717
|
*/
|
|
4715
4718
|
async attemptReconnect() {
|
|
4716
|
-
if (this._intentionalDisconnect
|
|
4719
|
+
if (this._intentionalDisconnect) {
|
|
4717
4720
|
return;
|
|
4718
4721
|
}
|
|
4719
|
-
this.
|
|
4720
|
-
this.authenticationResolve = resolve;
|
|
4721
|
-
});
|
|
4722
|
+
this._connectionPromise = this.performConnect(this._databaseId, this._connectOptions, true);
|
|
4722
4723
|
try {
|
|
4723
|
-
await this.
|
|
4724
|
+
await this._connectionPromise;
|
|
4724
4725
|
} catch {
|
|
4726
|
+
this._connectionPromise = null;
|
|
4725
4727
|
}
|
|
4726
4728
|
}
|
|
4727
4729
|
/**
|
|
@@ -4885,9 +4887,7 @@ var LarkDatabase = class {
|
|
|
4885
4887
|
* @internal Send a transaction to the server.
|
|
4886
4888
|
*/
|
|
4887
4889
|
async _sendTransaction(ops) {
|
|
4888
|
-
if (
|
|
4889
|
-
if (!this.isAuthenticatedOrThrow()) await this.waitForAuthenticated();
|
|
4890
|
-
}
|
|
4890
|
+
if (this._state !== "authenticated") await this.ensureConnected();
|
|
4891
4891
|
const requestId = this.messageQueue.nextRequestId();
|
|
4892
4892
|
this.pendingWrites.trackWrite(requestId, "transaction", "/", ops);
|
|
4893
4893
|
const message = {
|
|
@@ -5081,41 +5081,6 @@ var LarkDatabase = class {
|
|
|
5081
5081
|
// ============================================
|
|
5082
5082
|
// Internal: Sending Messages
|
|
5083
5083
|
// ============================================
|
|
5084
|
-
/**
|
|
5085
|
-
* Check if authenticated synchronously.
|
|
5086
|
-
* Returns true if authenticated, false if connecting (should wait), throws if disconnected.
|
|
5087
|
-
*/
|
|
5088
|
-
isAuthenticatedOrThrow() {
|
|
5089
|
-
if (this._state === "authenticated") {
|
|
5090
|
-
return true;
|
|
5091
|
-
}
|
|
5092
|
-
if (this._state === "connecting" || this._state === "connected" || this._state === "joined" || this._state === "reconnecting") {
|
|
5093
|
-
return false;
|
|
5094
|
-
}
|
|
5095
|
-
throw new LarkError("not_connected", "Not connected - call connect() first");
|
|
5096
|
-
}
|
|
5097
|
-
/**
|
|
5098
|
-
* Wait for authentication to complete before performing an operation.
|
|
5099
|
-
* If already authenticated, returns immediately (synchronously).
|
|
5100
|
-
* If connecting/reconnecting, waits for auth to complete.
|
|
5101
|
-
* If disconnected and no connect in progress, throws.
|
|
5102
|
-
*
|
|
5103
|
-
* IMPORTANT: This returns a Promise only if waiting is needed.
|
|
5104
|
-
* Callers should use: `if (!this.isAuthenticatedOrThrow()) if (!this.isAuthenticatedOrThrow()) await this.waitForAuthenticated();`
|
|
5105
|
-
* to preserve synchronous execution when already authenticated.
|
|
5106
|
-
*/
|
|
5107
|
-
async waitForAuthenticated() {
|
|
5108
|
-
if (this._state === "authenticated") {
|
|
5109
|
-
return;
|
|
5110
|
-
}
|
|
5111
|
-
if (this._state === "connecting" || this._state === "connected" || this._state === "joined" || this._state === "reconnecting") {
|
|
5112
|
-
if (this.authenticationPromise) {
|
|
5113
|
-
await this.authenticationPromise;
|
|
5114
|
-
return;
|
|
5115
|
-
}
|
|
5116
|
-
}
|
|
5117
|
-
throw new LarkError("not_connected", "Not connected - call connect() first");
|
|
5118
|
-
}
|
|
5119
5084
|
send(message) {
|
|
5120
5085
|
if (!this.transport || !this.transport.connected) {
|
|
5121
5086
|
throw new LarkError("not_connected", "Not connected to database");
|
|
@@ -5130,7 +5095,7 @@ var LarkDatabase = class {
|
|
|
5130
5095
|
* Note: Priority is now part of the value (as .priority), not a separate field.
|
|
5131
5096
|
*/
|
|
5132
5097
|
async _sendSet(path, value) {
|
|
5133
|
-
if (
|
|
5098
|
+
if (this._state !== "authenticated") await this.ensureConnected();
|
|
5134
5099
|
const normalizedPath = normalizePath(path) || "/";
|
|
5135
5100
|
validateWriteData(value, normalizedPath);
|
|
5136
5101
|
validateWriteSize(value, normalizedPath);
|
|
@@ -5156,7 +5121,7 @@ var LarkDatabase = class {
|
|
|
5156
5121
|
* @internal Send an update operation.
|
|
5157
5122
|
*/
|
|
5158
5123
|
async _sendUpdate(path, values) {
|
|
5159
|
-
if (
|
|
5124
|
+
if (this._state !== "authenticated") await this.ensureConnected();
|
|
5160
5125
|
const normalizedPath = normalizePath(path) || "/";
|
|
5161
5126
|
for (const [key, value] of Object.entries(values)) {
|
|
5162
5127
|
const fullPath = key.startsWith("/") ? key : `${normalizedPath}/${key}`;
|
|
@@ -5189,7 +5154,7 @@ var LarkDatabase = class {
|
|
|
5189
5154
|
* @internal Send a delete operation.
|
|
5190
5155
|
*/
|
|
5191
5156
|
async _sendDelete(path) {
|
|
5192
|
-
if (
|
|
5157
|
+
if (this._state !== "authenticated") await this.ensureConnected();
|
|
5193
5158
|
const normalizedPath = normalizePath(path) || "/";
|
|
5194
5159
|
const requestId = this.messageQueue.nextRequestId();
|
|
5195
5160
|
const pendingWriteIds = this.subscriptionManager.getPendingWriteIdsForPath(normalizedPath);
|
|
@@ -5298,7 +5263,7 @@ var LarkDatabase = class {
|
|
|
5298
5263
|
return new DataSnapshot(cached.value, path, this);
|
|
5299
5264
|
}
|
|
5300
5265
|
}
|
|
5301
|
-
if (
|
|
5266
|
+
if (this._state !== "authenticated") await this.ensureConnected();
|
|
5302
5267
|
const requestId = this.messageQueue.nextRequestId();
|
|
5303
5268
|
const message = {
|
|
5304
5269
|
o: "o",
|
|
@@ -5315,7 +5280,7 @@ var LarkDatabase = class {
|
|
|
5315
5280
|
* @internal Send an onDisconnect operation.
|
|
5316
5281
|
*/
|
|
5317
5282
|
async _sendOnDisconnect(path, action, value) {
|
|
5318
|
-
if (
|
|
5283
|
+
if (this._state !== "authenticated") await this.ensureConnected();
|
|
5319
5284
|
const requestId = this.messageQueue.nextRequestId();
|
|
5320
5285
|
const message = {
|
|
5321
5286
|
o: "od",
|
|
@@ -5341,13 +5306,12 @@ var LarkDatabase = class {
|
|
|
5341
5306
|
* @internal Send a subscribe message to server.
|
|
5342
5307
|
* Includes tag for non-default queries to enable proper event routing.
|
|
5343
5308
|
*/
|
|
5344
|
-
async sendSubscribeMessage(path,
|
|
5345
|
-
if (
|
|
5309
|
+
async sendSubscribeMessage(path, queryParams, tag) {
|
|
5310
|
+
if (this._state !== "authenticated") await this.ensureConnected();
|
|
5346
5311
|
const requestId = this.messageQueue.nextRequestId();
|
|
5347
5312
|
const message = {
|
|
5348
5313
|
o: "sb",
|
|
5349
5314
|
p: normalizePath(path) || "/",
|
|
5350
|
-
e: eventTypes,
|
|
5351
5315
|
r: requestId,
|
|
5352
5316
|
...queryParams,
|
|
5353
5317
|
...tag !== void 0 ? { tag } : {}
|
|
@@ -5360,7 +5324,7 @@ var LarkDatabase = class {
|
|
|
5360
5324
|
* Includes query params and tag so server can identify which specific subscription to remove.
|
|
5361
5325
|
*/
|
|
5362
5326
|
async sendUnsubscribeMessage(path, queryParams, tag) {
|
|
5363
|
-
if (
|
|
5327
|
+
if (this._state !== "authenticated") await this.ensureConnected();
|
|
5364
5328
|
const requestId = this.messageQueue.nextRequestId();
|
|
5365
5329
|
const message = {
|
|
5366
5330
|
o: "us",
|