@lark-sh/client 0.1.15 → 0.1.17
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-EK7OYLDG.mjs → chunk-VLAAYUVX.mjs} +190 -127
- package/dist/chunk-VLAAYUVX.mjs.map +1 -0
- package/dist/fb-v8/index.js +189 -126
- package/dist/fb-v8/index.js.map +1 -1
- package/dist/fb-v8/index.mjs +1 -1
- package/dist/index.d.mts +16 -22
- package/dist/index.d.ts +16 -22
- package/dist/index.js +189 -126
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-EK7OYLDG.mjs.map +0 -1
|
@@ -1,67 +1,3 @@
|
|
|
1
|
-
// src/protocol/constants.ts
|
|
2
|
-
var OnDisconnectAction = {
|
|
3
|
-
SET: "s",
|
|
4
|
-
UPDATE: "u",
|
|
5
|
-
DELETE: "d",
|
|
6
|
-
CANCEL: "c"
|
|
7
|
-
};
|
|
8
|
-
var ErrorCode = {
|
|
9
|
-
PERMISSION_DENIED: "permission_denied",
|
|
10
|
-
INVALID_DATA: "invalid_data",
|
|
11
|
-
NOT_FOUND: "not_found",
|
|
12
|
-
INVALID_PATH: "invalid_path",
|
|
13
|
-
INVALID_OPERATION: "invalid_operation",
|
|
14
|
-
INTERNAL_ERROR: "internal_error",
|
|
15
|
-
CONDITION_FAILED: "condition_failed",
|
|
16
|
-
INVALID_QUERY: "invalid_query",
|
|
17
|
-
AUTH_REQUIRED: "auth_required"
|
|
18
|
-
};
|
|
19
|
-
var DEFAULT_COORDINATOR_URL = "https://db.lark.sh";
|
|
20
|
-
|
|
21
|
-
// src/connection/Coordinator.ts
|
|
22
|
-
var Coordinator = class {
|
|
23
|
-
constructor(baseUrl = DEFAULT_COORDINATOR_URL) {
|
|
24
|
-
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Request connection details from the coordinator.
|
|
28
|
-
*
|
|
29
|
-
* @param database - Database ID in format "project/database"
|
|
30
|
-
* @param options - Either a user token or anonymous flag
|
|
31
|
-
* @returns Connection details including host, port, and connection token
|
|
32
|
-
*/
|
|
33
|
-
async connect(database, options = {}) {
|
|
34
|
-
const body = { database };
|
|
35
|
-
if (options.token) {
|
|
36
|
-
body.token = options.token;
|
|
37
|
-
} else if (options.anonymous) {
|
|
38
|
-
body.anonymous = true;
|
|
39
|
-
} else {
|
|
40
|
-
body.anonymous = true;
|
|
41
|
-
}
|
|
42
|
-
const response = await fetch(`${this.baseUrl}/connect`, {
|
|
43
|
-
method: "POST",
|
|
44
|
-
headers: {
|
|
45
|
-
"Content-Type": "application/json"
|
|
46
|
-
},
|
|
47
|
-
body: JSON.stringify(body)
|
|
48
|
-
});
|
|
49
|
-
if (!response.ok) {
|
|
50
|
-
let errorMessage = `Coordinator request failed: ${response.status}`;
|
|
51
|
-
try {
|
|
52
|
-
const errorBody = await response.json();
|
|
53
|
-
if (errorBody.message) {
|
|
54
|
-
errorMessage = errorBody.message;
|
|
55
|
-
}
|
|
56
|
-
} catch {
|
|
57
|
-
}
|
|
58
|
-
throw new Error(errorMessage);
|
|
59
|
-
}
|
|
60
|
-
const data = await response.json();
|
|
61
|
-
return data;
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
1
|
// src/connection/WebSocketTransport.ts
|
|
66
2
|
import WebSocketNode from "ws";
|
|
67
3
|
var WebSocketImpl = typeof WebSocket !== "undefined" ? WebSocket : WebSocketNode;
|
|
@@ -1428,7 +1364,6 @@ var View = class {
|
|
|
1428
1364
|
/**
|
|
1429
1365
|
* Check if this View loads all data (no limits, no range filters).
|
|
1430
1366
|
* A View that loads all data can serve as a "complete" cache for child paths.
|
|
1431
|
-
* This matches Firebase's loadsAllData() semantics.
|
|
1432
1367
|
*/
|
|
1433
1368
|
loadsAllData() {
|
|
1434
1369
|
if (!this.queryParams) return true;
|
|
@@ -1844,8 +1779,8 @@ var SubscriptionManager = class {
|
|
|
1844
1779
|
/**
|
|
1845
1780
|
* Detect and fire child_moved events for children that changed position OR sort value.
|
|
1846
1781
|
*
|
|
1847
|
-
*
|
|
1848
|
-
* the position actually changes.
|
|
1782
|
+
* child_moved fires for ANY priority/sort value change, regardless of whether
|
|
1783
|
+
* the position actually changes.
|
|
1849
1784
|
*
|
|
1850
1785
|
* IMPORTANT: child_moved should only fire for children whose VALUE or PRIORITY changed.
|
|
1851
1786
|
* Children that are merely "displaced" by another child moving should NOT fire child_moved.
|
|
@@ -2048,9 +1983,6 @@ var SubscriptionManager = class {
|
|
|
2048
1983
|
* A complete View has no limits and no range filters, so it contains all data
|
|
2049
1984
|
* for its subtree. Child subscriptions can use the ancestor's data instead
|
|
2050
1985
|
* of creating their own server subscription.
|
|
2051
|
-
*
|
|
2052
|
-
* This matches Firebase's behavior where child listeners don't need their own
|
|
2053
|
-
* server subscription if an ancestor has an unlimited listener.
|
|
2054
1986
|
*/
|
|
2055
1987
|
hasAncestorCompleteView(path) {
|
|
2056
1988
|
const normalized = normalizePath(path);
|
|
@@ -2176,8 +2108,8 @@ var SubscriptionManager = class {
|
|
|
2176
2108
|
/**
|
|
2177
2109
|
* Recursively sort object keys for consistent comparison.
|
|
2178
2110
|
* This ensures {a:1, b:2} and {b:2, a:1} compare as equal.
|
|
2179
|
-
* Uses simple alphabetical sorting
|
|
2180
|
-
*
|
|
2111
|
+
* Uses simple alphabetical sorting since we're just checking data equality,
|
|
2112
|
+
* not display order.
|
|
2181
2113
|
*/
|
|
2182
2114
|
sortKeysForComparison(value) {
|
|
2183
2115
|
if (value === null || typeof value !== "object") {
|
|
@@ -2771,6 +2703,26 @@ var SubscriptionManager = class {
|
|
|
2771
2703
|
}
|
|
2772
2704
|
};
|
|
2773
2705
|
|
|
2706
|
+
// src/protocol/constants.ts
|
|
2707
|
+
var OnDisconnectAction = {
|
|
2708
|
+
SET: "s",
|
|
2709
|
+
UPDATE: "u",
|
|
2710
|
+
DELETE: "d",
|
|
2711
|
+
CANCEL: "c"
|
|
2712
|
+
};
|
|
2713
|
+
var ErrorCode = {
|
|
2714
|
+
PERMISSION_DENIED: "permission_denied",
|
|
2715
|
+
INVALID_DATA: "invalid_data",
|
|
2716
|
+
NOT_FOUND: "not_found",
|
|
2717
|
+
INVALID_PATH: "invalid_path",
|
|
2718
|
+
INVALID_OPERATION: "invalid_operation",
|
|
2719
|
+
INTERNAL_ERROR: "internal_error",
|
|
2720
|
+
CONDITION_FAILED: "condition_failed",
|
|
2721
|
+
INVALID_QUERY: "invalid_query",
|
|
2722
|
+
AUTH_REQUIRED: "auth_required"
|
|
2723
|
+
};
|
|
2724
|
+
var DEFAULT_LARK_DOMAIN = "larkdb.net";
|
|
2725
|
+
|
|
2774
2726
|
// src/OnDisconnect.ts
|
|
2775
2727
|
var OnDisconnect = class {
|
|
2776
2728
|
constructor(db, path) {
|
|
@@ -2874,6 +2826,125 @@ function generatePushId() {
|
|
|
2874
2826
|
return id;
|
|
2875
2827
|
}
|
|
2876
2828
|
|
|
2829
|
+
// src/utils/validation.ts
|
|
2830
|
+
var MAX_KEY_BYTES = 768;
|
|
2831
|
+
var INVALID_KEY_CHARS = /[.#$\[\]\/]/;
|
|
2832
|
+
var CONTROL_CHARS = /[\x00-\x1f\x7f]/;
|
|
2833
|
+
function hasControlChars(str) {
|
|
2834
|
+
return CONTROL_CHARS.test(str);
|
|
2835
|
+
}
|
|
2836
|
+
function getByteLength(str) {
|
|
2837
|
+
if (typeof TextEncoder !== "undefined") {
|
|
2838
|
+
return new TextEncoder().encode(str).length;
|
|
2839
|
+
}
|
|
2840
|
+
return Buffer.byteLength(str, "utf8");
|
|
2841
|
+
}
|
|
2842
|
+
function validateKey(key, context) {
|
|
2843
|
+
const prefix = context ? `${context}: ` : "";
|
|
2844
|
+
if (typeof key !== "string") {
|
|
2845
|
+
throw new LarkError(
|
|
2846
|
+
ErrorCode.INVALID_DATA,
|
|
2847
|
+
`${prefix}key must be a string`
|
|
2848
|
+
);
|
|
2849
|
+
}
|
|
2850
|
+
if (key.length === 0) {
|
|
2851
|
+
throw new LarkError(
|
|
2852
|
+
ErrorCode.INVALID_DATA,
|
|
2853
|
+
`${prefix}key cannot be empty`
|
|
2854
|
+
);
|
|
2855
|
+
}
|
|
2856
|
+
if (INVALID_KEY_CHARS.test(key)) {
|
|
2857
|
+
throw new LarkError(
|
|
2858
|
+
ErrorCode.INVALID_DATA,
|
|
2859
|
+
`${prefix}key "${key}" contains invalid characters (. $ # [ ] / are not allowed)`
|
|
2860
|
+
);
|
|
2861
|
+
}
|
|
2862
|
+
if (hasControlChars(key)) {
|
|
2863
|
+
throw new LarkError(
|
|
2864
|
+
ErrorCode.INVALID_DATA,
|
|
2865
|
+
`${prefix}key "${key}" contains control characters (ASCII 0-31, 127 are not allowed)`
|
|
2866
|
+
);
|
|
2867
|
+
}
|
|
2868
|
+
const byteLength = getByteLength(key);
|
|
2869
|
+
if (byteLength > MAX_KEY_BYTES) {
|
|
2870
|
+
throw new LarkError(
|
|
2871
|
+
ErrorCode.INVALID_DATA,
|
|
2872
|
+
`${prefix}key "${key.substring(0, 50)}..." exceeds maximum size of ${MAX_KEY_BYTES} bytes (got ${byteLength})`
|
|
2873
|
+
);
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
function validatePath(path, context) {
|
|
2877
|
+
if (typeof path !== "string") {
|
|
2878
|
+
throw new LarkError(
|
|
2879
|
+
ErrorCode.INVALID_PATH,
|
|
2880
|
+
`${context ? `${context}: ` : ""}path must be a string`
|
|
2881
|
+
);
|
|
2882
|
+
}
|
|
2883
|
+
if (path === "" || path === "/") {
|
|
2884
|
+
return;
|
|
2885
|
+
}
|
|
2886
|
+
const segments = path.split("/").filter((s) => s.length > 0);
|
|
2887
|
+
for (const segment of segments) {
|
|
2888
|
+
if (segment === ".priority" || segment === ".value" || segment === ".sv" || segment === ".info") {
|
|
2889
|
+
continue;
|
|
2890
|
+
}
|
|
2891
|
+
validateKey(segment, context);
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2894
|
+
function validateValue(value, context, path = "") {
|
|
2895
|
+
const prefix = context ? `${context}: ` : "";
|
|
2896
|
+
const location = path ? ` at "${path}"` : "";
|
|
2897
|
+
if (value === null || value === void 0) {
|
|
2898
|
+
return;
|
|
2899
|
+
}
|
|
2900
|
+
if (typeof value === "string") {
|
|
2901
|
+
if (hasControlChars(value)) {
|
|
2902
|
+
throw new LarkError(
|
|
2903
|
+
ErrorCode.INVALID_DATA,
|
|
2904
|
+
`${prefix}string value${location} contains control characters (ASCII 0-31, 127 are not allowed)`
|
|
2905
|
+
);
|
|
2906
|
+
}
|
|
2907
|
+
return;
|
|
2908
|
+
}
|
|
2909
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
2910
|
+
return;
|
|
2911
|
+
}
|
|
2912
|
+
if (Array.isArray(value)) {
|
|
2913
|
+
for (let i = 0; i < value.length; i++) {
|
|
2914
|
+
validateValue(value[i], context, path ? `${path}/${i}` : String(i));
|
|
2915
|
+
}
|
|
2916
|
+
return;
|
|
2917
|
+
}
|
|
2918
|
+
if (typeof value === "object") {
|
|
2919
|
+
const obj = value;
|
|
2920
|
+
const keys = Object.keys(obj);
|
|
2921
|
+
if (".value" in obj) {
|
|
2922
|
+
const otherKeys = keys.filter((k) => k !== ".value" && k !== ".priority");
|
|
2923
|
+
if (otherKeys.length > 0) {
|
|
2924
|
+
const loc = path || "/";
|
|
2925
|
+
throw new LarkError(
|
|
2926
|
+
ErrorCode.INVALID_DATA,
|
|
2927
|
+
`${prefix}data at ${loc} contains ".value" alongside other children (${otherKeys.join(", ")}). ".value" can only be used with ".priority" for primitives with priority.`
|
|
2928
|
+
);
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
for (const [key, childValue] of Object.entries(obj)) {
|
|
2932
|
+
if (key !== ".priority" && key !== ".value" && key !== ".sv") {
|
|
2933
|
+
validateKey(key, context);
|
|
2934
|
+
}
|
|
2935
|
+
validateValue(childValue, context, path ? `${path}/${key}` : key);
|
|
2936
|
+
}
|
|
2937
|
+
return;
|
|
2938
|
+
}
|
|
2939
|
+
throw new LarkError(
|
|
2940
|
+
ErrorCode.INVALID_DATA,
|
|
2941
|
+
`${prefix}invalid value type${location}: ${typeof value}`
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
function validateWriteData(value, context) {
|
|
2945
|
+
validateValue(value, context);
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2877
2948
|
// src/DatabaseReference.ts
|
|
2878
2949
|
function isInfoPath(path) {
|
|
2879
2950
|
return path === "/.info" || path.startsWith("/.info/");
|
|
@@ -2949,7 +3020,6 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
2949
3020
|
* For queries (created via orderBy*, limitTo*, startAt, etc.), this returns
|
|
2950
3021
|
* a reference to the same path without query constraints.
|
|
2951
3022
|
* For non-query references, this returns the reference itself.
|
|
2952
|
-
* This matches Firebase's Query.ref behavior.
|
|
2953
3023
|
*/
|
|
2954
3024
|
get ref() {
|
|
2955
3025
|
if (Object.keys(this._query).length === 0) {
|
|
@@ -2974,7 +3044,7 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
2974
3044
|
* Returns "default" for non-query references (no constraints).
|
|
2975
3045
|
* Returns a sorted JSON string of wire-format params for queries.
|
|
2976
3046
|
*
|
|
2977
|
-
*
|
|
3047
|
+
* Used for wire protocol and subscription deduplication.
|
|
2978
3048
|
*/
|
|
2979
3049
|
get queryIdentifier() {
|
|
2980
3050
|
const queryObj = {};
|
|
@@ -3033,7 +3103,7 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
3033
3103
|
}
|
|
3034
3104
|
/**
|
|
3035
3105
|
* Get the data at this location. Alias for once('value').
|
|
3036
|
-
*
|
|
3106
|
+
* Alternative to once('value') for reading data.
|
|
3037
3107
|
*/
|
|
3038
3108
|
async get() {
|
|
3039
3109
|
return this.once("value");
|
|
@@ -3045,6 +3115,7 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
3045
3115
|
* Get a reference to a child path.
|
|
3046
3116
|
*/
|
|
3047
3117
|
child(path) {
|
|
3118
|
+
validatePath(path, "child");
|
|
3048
3119
|
const childPath = joinPath(this._path, path);
|
|
3049
3120
|
return new _DatabaseReference(this._db, childPath);
|
|
3050
3121
|
}
|
|
@@ -3061,6 +3132,7 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
3061
3132
|
*/
|
|
3062
3133
|
async set(value) {
|
|
3063
3134
|
validateNotInfoPath(this._path, "set");
|
|
3135
|
+
validateWriteData(value, "set");
|
|
3064
3136
|
if (this._db.isVolatilePath(this._path)) {
|
|
3065
3137
|
this._db._sendVolatileSet(this._path, value);
|
|
3066
3138
|
return;
|
|
@@ -3070,7 +3142,7 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
3070
3142
|
/**
|
|
3071
3143
|
* Update specific children at this location without overwriting other children.
|
|
3072
3144
|
*
|
|
3073
|
-
* Also supports
|
|
3145
|
+
* Also supports multi-path updates when keys look like paths
|
|
3074
3146
|
* (start with '/'). In this mode, each path is written atomically as a transaction.
|
|
3075
3147
|
*
|
|
3076
3148
|
* @example
|
|
@@ -3090,6 +3162,16 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
3090
3162
|
*/
|
|
3091
3163
|
async update(values) {
|
|
3092
3164
|
validateNotInfoPath(this._path, "update");
|
|
3165
|
+
for (const [key, value] of Object.entries(values)) {
|
|
3166
|
+
if (key.includes("/")) {
|
|
3167
|
+
validatePath(key, "update");
|
|
3168
|
+
} else {
|
|
3169
|
+
validateKey(key, "update");
|
|
3170
|
+
}
|
|
3171
|
+
if (value !== null) {
|
|
3172
|
+
validateWriteData(value, "update");
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3093
3175
|
const hasPathKeys = Object.keys(values).some((key) => key.startsWith("/"));
|
|
3094
3176
|
if (hasPathKeys) {
|
|
3095
3177
|
const ops = [];
|
|
@@ -3141,13 +3223,17 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
3141
3223
|
* For objects: injects `.priority` into the value object.
|
|
3142
3224
|
* For primitives: wraps as `{ '.value': primitive, '.priority': priority }`.
|
|
3143
3225
|
*
|
|
3144
|
-
*
|
|
3226
|
+
* Uses { '.value': value, '.priority': priority } format for the wire protocol.
|
|
3145
3227
|
*
|
|
3146
3228
|
* @param value - The value to write
|
|
3147
3229
|
* @param priority - The priority for ordering
|
|
3148
3230
|
*/
|
|
3149
3231
|
async setWithPriority(value, priority) {
|
|
3150
3232
|
validateNotInfoPath(this._path, "setWithPriority");
|
|
3233
|
+
validateWriteData(value, "setWithPriority");
|
|
3234
|
+
if (typeof priority === "string") {
|
|
3235
|
+
validateWriteData(priority, "setWithPriority (priority)");
|
|
3236
|
+
}
|
|
3151
3237
|
if (value === null || value === void 0) {
|
|
3152
3238
|
await this._db._sendSet(this._path, value);
|
|
3153
3239
|
return;
|
|
@@ -3689,17 +3775,11 @@ var DatabaseReference = class _DatabaseReference {
|
|
|
3689
3775
|
}
|
|
3690
3776
|
}
|
|
3691
3777
|
/**
|
|
3692
|
-
* Validate that a key is a valid
|
|
3693
|
-
*
|
|
3694
|
-
* Also cannot start or end with .
|
|
3778
|
+
* Validate that a key is a valid key format.
|
|
3779
|
+
* Delegates to the shared validation utility.
|
|
3695
3780
|
*/
|
|
3696
3781
|
_validateKeyFormat(methodName, key) {
|
|
3697
|
-
|
|
3698
|
-
throw new LarkError(
|
|
3699
|
-
ErrorCode.INVALID_QUERY,
|
|
3700
|
-
`Query.${methodName}: invalid key "${key}" - keys cannot contain . # $ [ ] /`
|
|
3701
|
-
);
|
|
3702
|
-
}
|
|
3782
|
+
validateKey(key, `Query.${methodName}`);
|
|
3703
3783
|
}
|
|
3704
3784
|
// ============================================
|
|
3705
3785
|
// Internal Helpers
|
|
@@ -3903,9 +3983,9 @@ var DataSnapshot = class _DataSnapshot {
|
|
|
3903
3983
|
* Get a child snapshot at the specified path.
|
|
3904
3984
|
*
|
|
3905
3985
|
* Special handling:
|
|
3906
|
-
* - `.priority` returns the priority value
|
|
3986
|
+
* - `.priority` returns the priority value
|
|
3907
3987
|
* - For wrapped primitives, only `.priority` returns data; other paths return null
|
|
3908
|
-
* - Non-existent paths return a snapshot with val() === null
|
|
3988
|
+
* - Non-existent paths return a snapshot with val() === null
|
|
3909
3989
|
*/
|
|
3910
3990
|
child(path) {
|
|
3911
3991
|
const childPath = joinPath(this._path, path);
|
|
@@ -4009,7 +4089,6 @@ var DataSnapshot = class _DataSnapshot {
|
|
|
4009
4089
|
}
|
|
4010
4090
|
/**
|
|
4011
4091
|
* Check if this snapshot was from a volatile (high-frequency) update.
|
|
4012
|
-
* This is a Lark extension not present in Firebase.
|
|
4013
4092
|
*/
|
|
4014
4093
|
isVolatile() {
|
|
4015
4094
|
return this._volatile;
|
|
@@ -4018,7 +4097,6 @@ var DataSnapshot = class _DataSnapshot {
|
|
|
4018
4097
|
* Get the server timestamp for this snapshot (milliseconds since Unix epoch).
|
|
4019
4098
|
* Only present on volatile value events. Use deltas between timestamps for
|
|
4020
4099
|
* interpolation rather than absolute times to avoid clock sync issues.
|
|
4021
|
-
* This is a Lark extension not present in Firebase.
|
|
4022
4100
|
*/
|
|
4023
4101
|
getServerTimestamp() {
|
|
4024
4102
|
return this._serverTimestamp;
|
|
@@ -4067,28 +4145,6 @@ function isVolatilePath(path, patterns) {
|
|
|
4067
4145
|
}
|
|
4068
4146
|
|
|
4069
4147
|
// src/LarkDatabase.ts
|
|
4070
|
-
function validateWriteData(data, path = "") {
|
|
4071
|
-
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
4072
|
-
return;
|
|
4073
|
-
}
|
|
4074
|
-
const obj = data;
|
|
4075
|
-
const keys = Object.keys(obj);
|
|
4076
|
-
if (".value" in obj) {
|
|
4077
|
-
const otherKeys = keys.filter((k) => k !== ".value" && k !== ".priority");
|
|
4078
|
-
if (otherKeys.length > 0) {
|
|
4079
|
-
const location = path || "/";
|
|
4080
|
-
throw new LarkError(
|
|
4081
|
-
"invalid_data",
|
|
4082
|
-
`Data at ${location} contains ".value" alongside other children (${otherKeys.join(", ")}). ".value" can only be used with ".priority" for primitives with priority.`
|
|
4083
|
-
);
|
|
4084
|
-
}
|
|
4085
|
-
}
|
|
4086
|
-
for (const key of keys) {
|
|
4087
|
-
if (key !== ".priority" && key !== ".value") {
|
|
4088
|
-
validateWriteData(obj[key], path ? `${path}/${key}` : `/${key}`);
|
|
4089
|
-
}
|
|
4090
|
-
}
|
|
4091
|
-
}
|
|
4092
4148
|
var RECONNECT_BASE_DELAY_MS = 1e3;
|
|
4093
4149
|
var RECONNECT_MAX_DELAY_MS = 3e4;
|
|
4094
4150
|
var RECONNECT_JITTER_FACTOR = 0.5;
|
|
@@ -4163,7 +4219,7 @@ var LarkDatabase = class {
|
|
|
4163
4219
|
this._state = "disconnected";
|
|
4164
4220
|
this._auth = null;
|
|
4165
4221
|
this._databaseId = null;
|
|
4166
|
-
this.
|
|
4222
|
+
this._domain = null;
|
|
4167
4223
|
this._volatilePaths = [];
|
|
4168
4224
|
this._transportType = null;
|
|
4169
4225
|
// Auth state
|
|
@@ -4226,8 +4282,9 @@ var LarkDatabase = class {
|
|
|
4226
4282
|
* @internal Get the base URL for reference toString().
|
|
4227
4283
|
*/
|
|
4228
4284
|
_getBaseUrl() {
|
|
4229
|
-
if (this.
|
|
4230
|
-
|
|
4285
|
+
if (this._domain && this._databaseId) {
|
|
4286
|
+
const projectId = this._databaseId.split("/")[0];
|
|
4287
|
+
return `https://${projectId}.${this._domain}`;
|
|
4231
4288
|
}
|
|
4232
4289
|
return "lark://";
|
|
4233
4290
|
}
|
|
@@ -4279,7 +4336,7 @@ var LarkDatabase = class {
|
|
|
4279
4336
|
* Connect to a database.
|
|
4280
4337
|
*
|
|
4281
4338
|
* @param databaseId - Database ID in format "project/database"
|
|
4282
|
-
* @param options - Connection options (token, anonymous,
|
|
4339
|
+
* @param options - Connection options (token, anonymous, domain)
|
|
4283
4340
|
*/
|
|
4284
4341
|
async connect(databaseId, options = {}) {
|
|
4285
4342
|
if (this._state !== "disconnected") {
|
|
@@ -4303,19 +4360,17 @@ var LarkDatabase = class {
|
|
|
4303
4360
|
const previousState = this._state;
|
|
4304
4361
|
this._state = isReconnect ? "reconnecting" : "connecting";
|
|
4305
4362
|
this._databaseId = databaseId;
|
|
4306
|
-
this.
|
|
4363
|
+
this._domain = options.domain || DEFAULT_LARK_DOMAIN;
|
|
4307
4364
|
if (!isReconnect) {
|
|
4308
4365
|
this._currentToken = options.token || "";
|
|
4309
4366
|
this._isAnonymous = !options.token && options.anonymous !== false;
|
|
4310
4367
|
}
|
|
4311
4368
|
try {
|
|
4312
|
-
const
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
});
|
|
4318
|
-
const wsUrl = connectResponse.ws_url;
|
|
4369
|
+
const projectId = databaseId.split("/")[0];
|
|
4370
|
+
if (!projectId) {
|
|
4371
|
+
throw new Error('Invalid database ID: must be in format "projectId/databaseName"');
|
|
4372
|
+
}
|
|
4373
|
+
const wsUrl = `wss://${projectId}.${this._domain}/ws`;
|
|
4319
4374
|
const transportResult = await createTransport(
|
|
4320
4375
|
wsUrl,
|
|
4321
4376
|
{
|
|
@@ -4476,7 +4531,7 @@ var LarkDatabase = class {
|
|
|
4476
4531
|
this._auth = null;
|
|
4477
4532
|
this._databaseId = null;
|
|
4478
4533
|
this._volatilePaths = [];
|
|
4479
|
-
this.
|
|
4534
|
+
this._domain = null;
|
|
4480
4535
|
this._connectionId = null;
|
|
4481
4536
|
this._connectOptions = null;
|
|
4482
4537
|
this._transportType = null;
|
|
@@ -4673,7 +4728,7 @@ var LarkDatabase = class {
|
|
|
4673
4728
|
*
|
|
4674
4729
|
* Supports two syntaxes:
|
|
4675
4730
|
*
|
|
4676
|
-
* **Object syntax** (
|
|
4731
|
+
* **Object syntax** (multi-path update):
|
|
4677
4732
|
* ```javascript
|
|
4678
4733
|
* await db.transaction({
|
|
4679
4734
|
* '/users/alice/name': 'Alice',
|
|
@@ -4711,14 +4766,20 @@ var LarkDatabase = class {
|
|
|
4711
4766
|
*/
|
|
4712
4767
|
async convertToTxOp(op) {
|
|
4713
4768
|
const path = normalizePath(op.path) || "/";
|
|
4769
|
+
validatePath(op.path, "transaction");
|
|
4714
4770
|
switch (op.op) {
|
|
4715
4771
|
case "set":
|
|
4772
|
+
validateWriteData(op.value, "transaction");
|
|
4716
4773
|
return { o: "s", p: path, v: op.value };
|
|
4717
4774
|
case "update":
|
|
4775
|
+
validateWriteData(op.value, "transaction");
|
|
4718
4776
|
return { o: "u", p: path, v: op.value };
|
|
4719
4777
|
case "delete":
|
|
4720
4778
|
return { o: "d", p: path };
|
|
4721
4779
|
case "condition":
|
|
4780
|
+
if (op.value !== void 0 && op.value !== null) {
|
|
4781
|
+
validateWriteData(op.value, "transaction condition");
|
|
4782
|
+
}
|
|
4722
4783
|
if (isPrimitive(op.value)) {
|
|
4723
4784
|
return { o: "c", p: path, v: op.value };
|
|
4724
4785
|
} else {
|
|
@@ -4736,10 +4797,12 @@ var LarkDatabase = class {
|
|
|
4736
4797
|
convertObjectToTxOps(obj) {
|
|
4737
4798
|
const ops = [];
|
|
4738
4799
|
for (const [path, value] of Object.entries(obj)) {
|
|
4800
|
+
validatePath(path, "transaction");
|
|
4739
4801
|
const normalizedPath = normalizePath(path) || "/";
|
|
4740
4802
|
if (value === null) {
|
|
4741
4803
|
ops.push({ o: "d", p: normalizedPath });
|
|
4742
4804
|
} else {
|
|
4805
|
+
validateWriteData(value, "transaction");
|
|
4743
4806
|
ops.push({ o: "s", p: normalizedPath, v: value });
|
|
4744
4807
|
}
|
|
4745
4808
|
}
|
|
@@ -5285,4 +5348,4 @@ export {
|
|
|
5285
5348
|
ServerValue,
|
|
5286
5349
|
LarkDatabase
|
|
5287
5350
|
};
|
|
5288
|
-
//# sourceMappingURL=chunk-
|
|
5351
|
+
//# sourceMappingURL=chunk-VLAAYUVX.mjs.map
|