@yuuko1410/feishu-bitable 0.0.2 → 0.0.3
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 +464 -0
- package/lib/client.d.ts +8 -1
- package/lib/index.cjs +302 -126
- package/lib/index.d.ts +1 -1
- package/lib/index.js +302 -126
- package/lib/types.d.ts +6 -0
- package/package.json +1 -1
package/lib/index.cjs
CHANGED
|
@@ -170,7 +170,8 @@ function normalizeRecordFields(fields) {
|
|
|
170
170
|
}
|
|
171
171
|
function splitUpdateRecord(record) {
|
|
172
172
|
const { record_id: recordId, ...fields } = record;
|
|
173
|
-
|
|
173
|
+
const normalizedFields = Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));
|
|
174
|
+
return { recordId, fields: normalizedFields };
|
|
174
175
|
}
|
|
175
176
|
async function toBuffer(file) {
|
|
176
177
|
if (typeof file === "string") {
|
|
@@ -223,18 +224,44 @@ function isFileLike(value) {
|
|
|
223
224
|
}
|
|
224
225
|
|
|
225
226
|
// src/client.ts
|
|
227
|
+
var DEFAULT_LOGGER = {
|
|
228
|
+
info(message, meta) {
|
|
229
|
+
if (meta) {
|
|
230
|
+
console.info(`[feishu-bitable] ${message}`, meta);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
console.info(`[feishu-bitable] ${message}`);
|
|
234
|
+
},
|
|
235
|
+
warn(message, meta) {
|
|
236
|
+
if (meta) {
|
|
237
|
+
console.warn(`[feishu-bitable] ${message}`, meta);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
console.warn(`[feishu-bitable] ${message}`);
|
|
241
|
+
},
|
|
242
|
+
error(message, meta) {
|
|
243
|
+
if (meta) {
|
|
244
|
+
console.error(`[feishu-bitable] ${message}`, meta);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
console.error(`[feishu-bitable] ${message}`);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
226
251
|
class Bitable {
|
|
227
252
|
client;
|
|
228
253
|
defaultAppToken;
|
|
229
254
|
maxRetries;
|
|
230
255
|
retryDelayMs;
|
|
231
256
|
defaultConcurrency;
|
|
257
|
+
logger;
|
|
232
258
|
constructor(optionsOrToken, appId, appSecret) {
|
|
233
259
|
const options = this.resolveConstructorOptions(optionsOrToken, appId, appSecret);
|
|
234
260
|
this.defaultAppToken = options.defaultAppToken;
|
|
235
261
|
this.maxRetries = Math.max(1, options.maxRetries ?? 5);
|
|
236
262
|
this.retryDelayMs = Math.max(100, options.retryDelayMs ?? 1000);
|
|
237
263
|
this.defaultConcurrency = Math.max(1, options.defaultConcurrency ?? 1);
|
|
264
|
+
this.logger = options.logger === null ? null : options.logger ?? DEFAULT_LOGGER;
|
|
238
265
|
this.client = options.sdkClient ?? new lark.Client({
|
|
239
266
|
appId: options.appId,
|
|
240
267
|
appSecret: options.appSecret,
|
|
@@ -250,159 +277,251 @@ class Bitable {
|
|
|
250
277
|
});
|
|
251
278
|
}
|
|
252
279
|
async fetchAllRecords(tableId, options = {}, appToken) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
280
|
+
return this.runLogged("fetchAllRecords", {
|
|
281
|
+
tableId,
|
|
282
|
+
pageSize: options.pageSize ?? FEISHU_BATCH_LIMIT,
|
|
283
|
+
hasViewId: Boolean(options.viewId),
|
|
284
|
+
fieldCount: options.fieldNames?.length ?? 0
|
|
285
|
+
}, async () => {
|
|
286
|
+
const token = this.resolveAppToken(appToken);
|
|
287
|
+
const pageSize = Math.max(1, Math.min(options.pageSize ?? FEISHU_BATCH_LIMIT, FEISHU_BATCH_LIMIT));
|
|
288
|
+
const iterator = await this.client.bitable.v1.appTableRecord.searchWithIterator({
|
|
289
|
+
path: {
|
|
290
|
+
app_token: token,
|
|
291
|
+
table_id: tableId
|
|
292
|
+
},
|
|
293
|
+
params: {
|
|
294
|
+
page_size: pageSize,
|
|
295
|
+
user_id_type: "open_id"
|
|
296
|
+
},
|
|
297
|
+
data: {
|
|
298
|
+
view_id: options.viewId,
|
|
299
|
+
field_names: options.fieldNames,
|
|
300
|
+
filter: options.filter,
|
|
301
|
+
sort: options.sort,
|
|
302
|
+
automatic_fields: options.automaticFields
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
const allRecords = [];
|
|
306
|
+
for await (const page of iterator) {
|
|
307
|
+
const items = page?.items ?? [];
|
|
308
|
+
allRecords.push(...items.map((item) => normalizeRecord(item.record_id, item.fields, options.normalizeFields !== false)));
|
|
270
309
|
}
|
|
310
|
+
this.logInfo("fetchAllRecords completed", {
|
|
311
|
+
tableId,
|
|
312
|
+
recordCount: allRecords.length
|
|
313
|
+
});
|
|
314
|
+
return allRecords;
|
|
271
315
|
});
|
|
272
|
-
const allRecords = [];
|
|
273
|
-
for await (const page of iterator) {
|
|
274
|
-
const items = page?.items ?? [];
|
|
275
|
-
allRecords.push(...items.map((item) => normalizeRecord(item.record_id, item.fields, options.normalizeFields !== false)));
|
|
276
|
-
}
|
|
277
|
-
return allRecords;
|
|
278
316
|
}
|
|
279
317
|
async insertList(tableId, records, options = {}) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
records: chunk.map((fields) => ({ fields }))
|
|
318
|
+
return this.runLogged("insertList", {
|
|
319
|
+
tableId,
|
|
320
|
+
recordCount: records.length,
|
|
321
|
+
chunkSize: options.chunkSize ?? FEISHU_BATCH_LIMIT,
|
|
322
|
+
concurrency: options.concurrency ?? this.defaultConcurrency
|
|
323
|
+
}, async () => {
|
|
324
|
+
if (records.length === 0) {
|
|
325
|
+
return [];
|
|
289
326
|
}
|
|
290
|
-
|
|
327
|
+
const token = this.resolveAppToken(options.appToken);
|
|
328
|
+
const chunks = chunkArray(records, options.chunkSize ?? FEISHU_BATCH_LIMIT);
|
|
329
|
+
const responses = await runWithConcurrency(chunks, options.concurrency ?? this.defaultConcurrency, async (chunk) => this.withRetry("insert records", async () => assertFeishuResponse(await this.client.bitable.v1.appTableRecord.batchCreate({
|
|
330
|
+
path: { app_token: token, table_id: tableId },
|
|
331
|
+
data: {
|
|
332
|
+
records: chunk.map((fields) => ({ fields }))
|
|
333
|
+
}
|
|
334
|
+
}), "insert records")));
|
|
335
|
+
this.logInfo("insertList completed", {
|
|
336
|
+
tableId,
|
|
337
|
+
chunkCount: chunks.length
|
|
338
|
+
});
|
|
339
|
+
return responses;
|
|
340
|
+
});
|
|
291
341
|
}
|
|
292
342
|
async batchUpdateRecords(payload) {
|
|
293
|
-
return this.
|
|
343
|
+
return this.runLogged("batchUpdateRecords", {
|
|
344
|
+
tableId: payload.path.table_id,
|
|
345
|
+
recordCount: payload.data.records.length
|
|
346
|
+
}, async () => this.executeBatchUpdateRecords(payload));
|
|
294
347
|
}
|
|
295
348
|
async updateRecords(tableId, records, options = {}) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
349
|
+
return this.runLogged("updateRecords", {
|
|
350
|
+
tableId,
|
|
351
|
+
inputRecordCount: records.length,
|
|
352
|
+
chunkSize: options.chunkSize ?? FEISHU_BATCH_LIMIT,
|
|
353
|
+
concurrency: options.concurrency ?? this.defaultConcurrency
|
|
354
|
+
}, async () => {
|
|
355
|
+
if (records.length === 0) {
|
|
356
|
+
return [];
|
|
357
|
+
}
|
|
358
|
+
const token = this.resolveAppToken(options.appToken);
|
|
359
|
+
const chunks = chunkArray(records, options.chunkSize ?? FEISHU_BATCH_LIMIT);
|
|
360
|
+
const responses = await runWithConcurrency(chunks, options.concurrency ?? this.defaultConcurrency, async (chunk, index) => {
|
|
361
|
+
const batchRecords = chunk.map((record) => {
|
|
362
|
+
const { recordId, fields } = splitUpdateRecord(record);
|
|
363
|
+
if (Object.keys(fields).length === 0) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
record_id: recordId,
|
|
368
|
+
fields
|
|
369
|
+
};
|
|
370
|
+
}).filter((record) => Boolean(record));
|
|
371
|
+
if (batchRecords.length === 0) {
|
|
372
|
+
this.logInfo("updateRecords skipped empty chunk", {
|
|
373
|
+
tableId,
|
|
374
|
+
chunkIndex: index,
|
|
375
|
+
inputChunkSize: chunk.length
|
|
376
|
+
});
|
|
377
|
+
return {
|
|
378
|
+
code: 0,
|
|
379
|
+
msg: "ok",
|
|
380
|
+
data: {
|
|
381
|
+
records: []
|
|
382
|
+
}
|
|
383
|
+
};
|
|
315
384
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
385
|
+
const payload = {
|
|
386
|
+
path: {
|
|
387
|
+
app_token: token,
|
|
388
|
+
table_id: tableId
|
|
389
|
+
},
|
|
390
|
+
data: {
|
|
391
|
+
records: batchRecords
|
|
392
|
+
}
|
|
321
393
|
};
|
|
322
|
-
|
|
323
|
-
|
|
394
|
+
if (options.userIdType || options.ignoreConsistencyCheck !== undefined) {
|
|
395
|
+
payload.params = {
|
|
396
|
+
user_id_type: options.userIdType,
|
|
397
|
+
ignore_consistency_check: options.ignoreConsistencyCheck
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
return this.executeBatchUpdateRecords(payload);
|
|
401
|
+
});
|
|
402
|
+
this.logInfo("updateRecords completed", {
|
|
403
|
+
tableId,
|
|
404
|
+
chunkCount: chunks.length
|
|
405
|
+
});
|
|
406
|
+
return responses;
|
|
324
407
|
});
|
|
325
408
|
}
|
|
326
409
|
async deleteList(tableId, recordIds, options = {}) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
records: chunk
|
|
410
|
+
return this.runLogged("deleteList", {
|
|
411
|
+
tableId,
|
|
412
|
+
recordCount: recordIds.length,
|
|
413
|
+
chunkSize: options.chunkSize ?? FEISHU_BATCH_LIMIT,
|
|
414
|
+
concurrency: options.concurrency ?? this.defaultConcurrency
|
|
415
|
+
}, async () => {
|
|
416
|
+
if (recordIds.length === 0) {
|
|
417
|
+
return [];
|
|
336
418
|
}
|
|
337
|
-
|
|
419
|
+
const token = this.resolveAppToken(options.appToken);
|
|
420
|
+
const chunks = chunkArray(recordIds, options.chunkSize ?? FEISHU_BATCH_LIMIT);
|
|
421
|
+
const responses = await runWithConcurrency(chunks, options.concurrency ?? this.defaultConcurrency, async (chunk) => this.withRetry("delete records", async () => assertFeishuResponse(await this.client.bitable.v1.appTableRecord.batchDelete({
|
|
422
|
+
path: { app_token: token, table_id: tableId },
|
|
423
|
+
data: {
|
|
424
|
+
records: chunk
|
|
425
|
+
}
|
|
426
|
+
}), "delete records")));
|
|
427
|
+
this.logInfo("deleteList completed", {
|
|
428
|
+
tableId,
|
|
429
|
+
chunkCount: chunks.length
|
|
430
|
+
});
|
|
431
|
+
return responses;
|
|
432
|
+
});
|
|
338
433
|
}
|
|
339
434
|
async uploadFile(options) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
435
|
+
return this.runLogged("uploadFile", {
|
|
436
|
+
parentType: options.parentType,
|
|
437
|
+
parentNode: options.parentNode,
|
|
438
|
+
hasExtra: Boolean(options.extra)
|
|
439
|
+
}, async () => {
|
|
440
|
+
const buffer = await toBuffer(options.file);
|
|
441
|
+
const fileName = options.fileName ?? inferFileName(options.file);
|
|
442
|
+
this.logInfo("uploadFile resolved input", {
|
|
443
|
+
fileName,
|
|
444
|
+
size: buffer.byteLength,
|
|
445
|
+
mode: buffer.byteLength <= FEISHU_SIMPLE_UPLOAD_LIMIT ? "simple" : "multipart"
|
|
446
|
+
});
|
|
447
|
+
if (buffer.byteLength <= FEISHU_SIMPLE_UPLOAD_LIMIT) {
|
|
448
|
+
return await this.withRetry("upload file", async () => this.client.drive.v1.media.uploadAll({
|
|
449
|
+
data: {
|
|
450
|
+
file_name: fileName,
|
|
451
|
+
parent_type: options.parentType,
|
|
452
|
+
parent_node: options.parentNode,
|
|
453
|
+
size: buffer.byteLength,
|
|
454
|
+
extra: options.extra,
|
|
455
|
+
file: buffer
|
|
456
|
+
}
|
|
457
|
+
})) ?? {};
|
|
458
|
+
}
|
|
459
|
+
const prepare = assertFeishuResponse(await this.withRetry("prepare multipart upload", async () => this.client.drive.v1.media.uploadPrepare({
|
|
344
460
|
data: {
|
|
345
461
|
file_name: fileName,
|
|
346
462
|
parent_type: options.parentType,
|
|
347
463
|
parent_node: options.parentNode,
|
|
348
|
-
size: buffer.byteLength
|
|
349
|
-
extra: options.extra,
|
|
350
|
-
file: buffer
|
|
464
|
+
size: buffer.byteLength
|
|
351
465
|
}
|
|
352
|
-
}))
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
data
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
466
|
+
})), "prepare multipart upload");
|
|
467
|
+
const uploadId = prepare.data?.upload_id;
|
|
468
|
+
const blockSize = prepare.data?.block_size;
|
|
469
|
+
const blockNum = prepare.data?.block_num;
|
|
470
|
+
if (!uploadId || !blockSize || !blockNum) {
|
|
471
|
+
throw new FeishuBitableError("prepare multipart upload failed: missing upload metadata", {
|
|
472
|
+
details: prepare
|
|
473
|
+
});
|
|
360
474
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
await this.withRetry(
|
|
475
|
+
for (let index = 0;index < blockNum; index++) {
|
|
476
|
+
const start = index * blockSize;
|
|
477
|
+
const end = Math.min(start + blockSize, buffer.byteLength);
|
|
478
|
+
const chunk = buffer.subarray(start, end);
|
|
479
|
+
await this.withRetry(`upload file chunk ${index + 1}/${blockNum}`, async () => this.client.drive.v1.media.uploadPart({
|
|
480
|
+
data: {
|
|
481
|
+
upload_id: uploadId,
|
|
482
|
+
seq: index,
|
|
483
|
+
size: chunk.byteLength,
|
|
484
|
+
file: chunk
|
|
485
|
+
}
|
|
486
|
+
}));
|
|
487
|
+
}
|
|
488
|
+
const finish = assertFeishuResponse(await this.withRetry("finish multipart upload", async () => this.client.drive.v1.media.uploadFinish({
|
|
375
489
|
data: {
|
|
376
490
|
upload_id: uploadId,
|
|
377
|
-
|
|
378
|
-
size: chunk.byteLength,
|
|
379
|
-
file: chunk
|
|
491
|
+
block_num: blockNum
|
|
380
492
|
}
|
|
381
|
-
}));
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
block_num: blockNum
|
|
387
|
-
}
|
|
388
|
-
})), "finish multipart upload");
|
|
389
|
-
return {
|
|
390
|
-
file_token: finish.data?.file_token
|
|
391
|
-
};
|
|
493
|
+
})), "finish multipart upload");
|
|
494
|
+
return {
|
|
495
|
+
file_token: finish.data?.file_token
|
|
496
|
+
};
|
|
497
|
+
});
|
|
392
498
|
}
|
|
393
499
|
async downloadFile(fileToken, extra) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
500
|
+
return this.runLogged("downloadFile", {
|
|
501
|
+
fileToken,
|
|
502
|
+
hasExtra: Boolean(extra)
|
|
503
|
+
}, async () => {
|
|
504
|
+
const response = await this.withRetry("download file", async () => this.client.drive.v1.media.download({
|
|
505
|
+
path: {
|
|
506
|
+
file_token: fileToken
|
|
507
|
+
},
|
|
508
|
+
params: {
|
|
509
|
+
extra
|
|
510
|
+
}
|
|
511
|
+
}));
|
|
512
|
+
const buffer = await readableToBuffer(response.getReadableStream());
|
|
513
|
+
this.logInfo("downloadFile completed", {
|
|
514
|
+
fileToken,
|
|
515
|
+
size: buffer.byteLength
|
|
516
|
+
});
|
|
517
|
+
return buffer;
|
|
518
|
+
});
|
|
403
519
|
}
|
|
404
520
|
async downLoadFile(fileToken, extra) {
|
|
405
|
-
return this.
|
|
521
|
+
return this.runLogged("downLoadFile", {
|
|
522
|
+
fileToken,
|
|
523
|
+
hasExtra: Boolean(extra)
|
|
524
|
+
}, async () => this.downloadFile(fileToken, extra));
|
|
406
525
|
}
|
|
407
526
|
resolveConstructorOptions(optionsOrToken, appIdArg, appSecretArg) {
|
|
408
527
|
const objectMode = typeof optionsOrToken === "object" && optionsOrToken !== null && !Array.isArray(optionsOrToken);
|
|
@@ -430,6 +549,9 @@ class Bitable {
|
|
|
430
549
|
}
|
|
431
550
|
return token;
|
|
432
551
|
}
|
|
552
|
+
async executeBatchUpdateRecords(payload) {
|
|
553
|
+
return this.withRetry("batch update records", async () => assertFeishuResponse(await this.client.bitable.v1.appTableRecord.batchUpdate(payload), "batch update records"));
|
|
554
|
+
}
|
|
433
555
|
async withRetry(label, task) {
|
|
434
556
|
let lastError;
|
|
435
557
|
for (let attempt = 1;attempt <= this.maxRetries; attempt++) {
|
|
@@ -437,16 +559,70 @@ class Bitable {
|
|
|
437
559
|
return await task();
|
|
438
560
|
} catch (error) {
|
|
439
561
|
lastError = error;
|
|
562
|
+
const meta = {
|
|
563
|
+
label,
|
|
564
|
+
attempt,
|
|
565
|
+
maxRetries: this.maxRetries,
|
|
566
|
+
retryDelayMs: this.retryDelayMs,
|
|
567
|
+
...this.getErrorMeta(error)
|
|
568
|
+
};
|
|
440
569
|
if (attempt === this.maxRetries) {
|
|
570
|
+
this.logError("request exhausted retries", meta);
|
|
441
571
|
break;
|
|
442
572
|
}
|
|
573
|
+
this.logWarn("request attempt failed, retrying", meta);
|
|
443
574
|
await sleep(this.retryDelayMs * attempt);
|
|
444
575
|
}
|
|
445
576
|
}
|
|
446
|
-
|
|
447
|
-
|
|
577
|
+
const causeMessage = lastError instanceof Error ? `: ${lastError.message}` : "";
|
|
578
|
+
throw new FeishuBitableError(`${label} failed after ${this.maxRetries} attempts${causeMessage}`, {
|
|
579
|
+
cause: lastError,
|
|
580
|
+
code: lastError instanceof FeishuBitableError ? lastError.code : undefined,
|
|
581
|
+
details: lastError instanceof FeishuBitableError ? lastError.details : undefined
|
|
448
582
|
});
|
|
449
583
|
}
|
|
584
|
+
async runLogged(action, meta, task) {
|
|
585
|
+
this.logInfo(`${action} started`, meta);
|
|
586
|
+
try {
|
|
587
|
+
const result = await task();
|
|
588
|
+
this.logInfo(`${action} succeeded`, meta);
|
|
589
|
+
return result;
|
|
590
|
+
} catch (error) {
|
|
591
|
+
this.logError(`${action} failed`, {
|
|
592
|
+
...meta,
|
|
593
|
+
...this.getErrorMeta(error)
|
|
594
|
+
});
|
|
595
|
+
throw error;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
logInfo(message, meta) {
|
|
599
|
+
this.logger?.info(message, meta);
|
|
600
|
+
}
|
|
601
|
+
logWarn(message, meta) {
|
|
602
|
+
this.logger?.warn?.(message, meta);
|
|
603
|
+
}
|
|
604
|
+
logError(message, meta) {
|
|
605
|
+
this.logger?.error?.(message, meta);
|
|
606
|
+
}
|
|
607
|
+
getErrorMeta(error) {
|
|
608
|
+
if (error instanceof FeishuBitableError) {
|
|
609
|
+
return {
|
|
610
|
+
errorName: error.name,
|
|
611
|
+
errorMessage: error.message,
|
|
612
|
+
errorCode: error.code,
|
|
613
|
+
errorDetails: error.details
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (error instanceof Error) {
|
|
617
|
+
return {
|
|
618
|
+
errorName: error.name,
|
|
619
|
+
errorMessage: error.message
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
errorMessage: String(error)
|
|
624
|
+
};
|
|
625
|
+
}
|
|
450
626
|
}
|
|
451
627
|
|
|
452
628
|
// src/index.ts
|
package/lib/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ import { Bitable } from "./client";
|
|
|
2
2
|
export { Bitable };
|
|
3
3
|
export { FeishuBitableError } from "./errors";
|
|
4
4
|
export { AppType, Domain, LoggerLevel } from "@larksuiteoapi/node-sdk";
|
|
5
|
-
export type { BatchOperationOptions, BitableBatchUpdatePayload, BitableBatchUpdateResponse, BitableConstructorOptions, BitableFieldValue, BitableFilterCondition, BitableFilterGroup, BitableInsertRecord, BitableLocationValue, BitableMemberValue, BitableRecord, BitableRecordFields, BitableSort, BitableTextValue, BitableUpdateRecord, FetchAllRecordsOptions, MediaParentType, UpdateRecordsOptions, UploadFileOptions, UploadableFile, } from "./types";
|
|
5
|
+
export type { BatchOperationOptions, BitableBatchUpdatePayload, BitableBatchUpdateResponse, BitableConstructorOptions, BitableFieldValue, BitableFilterCondition, BitableFilterGroup, BitableInsertRecord, BitableLocationValue, BitableLogger, BitableMemberValue, BitableRecord, BitableRecordFields, BitableSort, BitableTextValue, BitableUpdateRecord, FetchAllRecordsOptions, MediaParentType, UpdateRecordsOptions, UploadFileOptions, UploadableFile, } from "./types";
|
|
6
6
|
export default Bitable;
|