hide-a-bed 7.0.1 → 7.1.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/README.md +167 -145
- package/dist/cjs/index.cjs +47 -0
- package/dist/esm/index.mjs +47 -1
- package/impl/bindConfig.mts +72 -60
- package/impl/headDB.mts +55 -0
- package/impl/utils/errors.mts +189 -158
- package/impl/utils/fetch.mts +102 -93
- package/index.mts +56 -41
- package/package.json +1 -1
- package/types/output/impl/bindConfig.d.mts +16 -14
- package/types/output/impl/bindConfig.d.mts.map +1 -1
- package/types/output/impl/headDB.d.mts +13 -0
- package/types/output/impl/headDB.d.mts.map +1 -0
- package/types/output/impl/headDB.test.d.mts +2 -0
- package/types/output/impl/headDB.test.d.mts.map +1 -0
- package/types/output/impl/utils/errors.d.mts +12 -12
- package/types/output/impl/utils/errors.d.mts.map +1 -1
- package/types/output/impl/utils/fetch.d.mts +4 -4
- package/types/output/impl/utils/fetch.d.mts.map +1 -1
- package/types/output/index.d.mts +35 -34
- package/types/output/index.d.mts.map +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
And some utility APIs
|
|
16
16
|
|
|
17
17
|
- [`getDBInfo()`](#getdbinfo)
|
|
18
|
+
- [`headDB()`](#headdb)
|
|
18
19
|
- [`createQuery()`](#createquery) 🍭
|
|
19
20
|
- [`withRetry()`](#withretry)
|
|
20
21
|
|
|
@@ -48,25 +49,25 @@ If your CouchDB requires basic auth, pass `auth` on the config:
|
|
|
48
49
|
|
|
49
50
|
```javascript
|
|
50
51
|
const config = {
|
|
51
|
-
couch:
|
|
52
|
+
couch: "https://the.couch.url.com:5984/mydb",
|
|
52
53
|
auth: {
|
|
53
54
|
username: process.env.COUCHDB_USER,
|
|
54
|
-
password: process.env.COUCHDB_PASSWORD
|
|
55
|
-
}
|
|
56
|
-
}
|
|
55
|
+
password: process.env.COUCHDB_PASSWORD,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
57
58
|
```
|
|
58
59
|
|
|
59
60
|
You can also set default request controls on the config:
|
|
60
61
|
|
|
61
62
|
```javascript
|
|
62
63
|
const config = {
|
|
63
|
-
couch:
|
|
64
|
+
couch: "https://the.couch.url.com:5984/mydb",
|
|
64
65
|
request: {
|
|
65
66
|
timeout: 5000,
|
|
66
67
|
signal: abortController.signal,
|
|
67
|
-
dispatcher
|
|
68
|
-
}
|
|
69
|
-
}
|
|
68
|
+
dispatcher,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
70
71
|
```
|
|
71
72
|
|
|
72
73
|
See [Advanced Config Options](#advanced-config-options) for more advanced settings.
|
|
@@ -113,19 +114,19 @@ Get a single document by ID.
|
|
|
113
114
|
- Throws: `NotFoundError` when the document does not exist and `throwOnGetNotFound` is true
|
|
114
115
|
|
|
115
116
|
```javascript
|
|
116
|
-
const config = { couch:
|
|
117
|
-
const doc = await get(config,
|
|
118
|
-
console.log(doc._id, doc._rev)
|
|
117
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
118
|
+
const doc = await get(config, "doc-123");
|
|
119
|
+
console.log(doc._id, doc._rev);
|
|
119
120
|
|
|
120
|
-
const missing = await get(config,
|
|
121
|
-
console.log(missing) // null
|
|
121
|
+
const missing = await get(config, "notFound");
|
|
122
|
+
console.log(missing); // null
|
|
122
123
|
|
|
123
124
|
try {
|
|
124
|
-
await get({ ...config, throwOnGetNotFound: true },
|
|
125
|
+
await get({ ...config, throwOnGetNotFound: true }, "notFound");
|
|
125
126
|
} catch (err) {
|
|
126
|
-
if (err.name ===
|
|
127
|
-
console.log(err.statusCode) // 404
|
|
128
|
-
console.log(err.docId) // notFound
|
|
127
|
+
if (err.name === "NotFoundError") {
|
|
128
|
+
console.log(err.statusCode); // 404
|
|
129
|
+
console.log(err.docId); // notFound
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
```
|
|
@@ -142,21 +143,21 @@ Save a document.
|
|
|
142
143
|
- Throws: `ConflictError` when CouchDB returns a 409 for a single-document write
|
|
143
144
|
|
|
144
145
|
```javascript
|
|
145
|
-
const config = { couch:
|
|
146
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
146
147
|
const doc = {
|
|
147
|
-
_id:
|
|
148
|
-
type:
|
|
149
|
-
name:
|
|
150
|
-
}
|
|
151
|
-
const result = await put(config, doc)
|
|
148
|
+
_id: "doc-123",
|
|
149
|
+
type: "user",
|
|
150
|
+
name: "Alice",
|
|
151
|
+
};
|
|
152
|
+
const result = await put(config, doc);
|
|
152
153
|
// result: { ok: true, id: 'doc-123', rev: '1-abc123' }
|
|
153
154
|
|
|
154
155
|
try {
|
|
155
|
-
await put(config, { _id:
|
|
156
|
+
await put(config, { _id: "notThereDoc", _rev: "32-does-not-compute" });
|
|
156
157
|
} catch (err) {
|
|
157
|
-
if (err.name ===
|
|
158
|
-
console.log(err.statusCode) // 409
|
|
159
|
-
console.log(err.docId) // notThereDoc
|
|
158
|
+
if (err.name === "ConflictError") {
|
|
159
|
+
console.log(err.statusCode); // 409
|
|
160
|
+
console.log(err.docId); // notThereDoc
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
163
|
```
|
|
@@ -174,15 +175,15 @@ The patch function lets you update specific properties of a document. The \_rev
|
|
|
174
175
|
|
|
175
176
|
```javascript
|
|
176
177
|
const config = {
|
|
177
|
-
couch:
|
|
178
|
-
retries: 3
|
|
179
|
-
}
|
|
178
|
+
couch: "http://localhost:5984/mydb",
|
|
179
|
+
retries: 3,
|
|
180
|
+
};
|
|
180
181
|
const properties = {
|
|
181
|
-
_rev:
|
|
182
|
-
name:
|
|
183
|
-
updated: true
|
|
184
|
-
}
|
|
185
|
-
const result = await patch(config,
|
|
182
|
+
_rev: "3-fdskjhfsdkjhfsd",
|
|
183
|
+
name: "Alice Smith",
|
|
184
|
+
updated: true,
|
|
185
|
+
};
|
|
186
|
+
const result = await patch(config, "doc-123", properties);
|
|
186
187
|
// result: { ok: true, id: 'doc-123', rev: '2-xyz789' }
|
|
187
188
|
```
|
|
188
189
|
|
|
@@ -204,14 +205,14 @@ _Warning_: patchDangerously can clobber data. It will retry even if a conflict h
|
|
|
204
205
|
|
|
205
206
|
```javascript
|
|
206
207
|
const config = {
|
|
207
|
-
couch:
|
|
208
|
-
retries: 3
|
|
209
|
-
}
|
|
208
|
+
couch: "http://localhost:5984/mydb",
|
|
209
|
+
retries: 3,
|
|
210
|
+
};
|
|
210
211
|
const properties = {
|
|
211
|
-
name:
|
|
212
|
-
updated: true
|
|
213
|
-
}
|
|
214
|
-
const result = await patchDangerously(config,
|
|
212
|
+
name: "Alice Smith",
|
|
213
|
+
updated: true,
|
|
214
|
+
};
|
|
215
|
+
const result = await patchDangerously(config, "doc-123", properties);
|
|
215
216
|
// result: { ok: true, id: 'doc-123', rev: '2-xyz789' }
|
|
216
217
|
```
|
|
217
218
|
|
|
@@ -228,9 +229,9 @@ Return a document at the rev specified.
|
|
|
228
229
|
_CouchDB_ is not a version control db. This is a special function for unique situations. The \_rev might not be around as couch cleans up old revs.
|
|
229
230
|
|
|
230
231
|
```javascript
|
|
231
|
-
const config = { couch:
|
|
232
|
-
const doc = await getAtRev(config,
|
|
233
|
-
console.log(doc._id, doc._rev)
|
|
232
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
233
|
+
const doc = await getAtRev(config, "doc-123", "2-fsdjfsdakljfsajlksd");
|
|
234
|
+
console.log(doc._id, doc._rev);
|
|
234
235
|
```
|
|
235
236
|
|
|
236
237
|
#### createLock
|
|
@@ -266,17 +267,17 @@ Remove a lock from a document.
|
|
|
266
267
|
Only the user who created the lock can remove it.
|
|
267
268
|
|
|
268
269
|
```javascript
|
|
269
|
-
const config = { couch:
|
|
270
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
270
271
|
const options = {
|
|
271
272
|
enableLocking: true,
|
|
272
|
-
username:
|
|
273
|
-
}
|
|
273
|
+
username: "alice",
|
|
274
|
+
};
|
|
274
275
|
|
|
275
|
-
const locked = await createLock(config,
|
|
276
|
+
const locked = await createLock(config, "doc-123", options);
|
|
276
277
|
if (locked) {
|
|
277
278
|
// Document is now locked for exclusive access
|
|
278
279
|
// Perform your updates here
|
|
279
|
-
await removeLock(config,
|
|
280
|
+
await removeLock(config, "doc-123", options);
|
|
280
281
|
}
|
|
281
282
|
// Lock is now removed if it existed and was owned by 'alice'
|
|
282
283
|
```
|
|
@@ -294,12 +295,12 @@ Save multiple documents in one request.
|
|
|
294
295
|
- Returns: Promise resolving to array of results with `ok`, `id`, `rev` for each doc
|
|
295
296
|
|
|
296
297
|
```javascript
|
|
297
|
-
const config = { couch:
|
|
298
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
298
299
|
const docs = [
|
|
299
|
-
{ _id:
|
|
300
|
-
{ _id:
|
|
301
|
-
]
|
|
302
|
-
const results = await bulkSave(config, docs)
|
|
300
|
+
{ _id: "doc1", type: "user", name: "Alice" },
|
|
301
|
+
{ _id: "doc2", type: "user", name: "Bob" },
|
|
302
|
+
];
|
|
303
|
+
const results = await bulkSave(config, docs);
|
|
303
304
|
// [
|
|
304
305
|
// { ok: true, id: 'doc1', rev: '1-abc123' },
|
|
305
306
|
// { ok: true, id: 'doc2', rev: '1-def456' }
|
|
@@ -321,17 +322,17 @@ Get multiple documents by ID.
|
|
|
321
322
|
Warning: documents that are not found will still have a row in the results. The doc property will be null, and the error property will be set.
|
|
322
323
|
|
|
323
324
|
```javascript
|
|
324
|
-
import z from
|
|
325
|
+
import z from "zod";
|
|
325
326
|
|
|
326
|
-
const config = { couch:
|
|
327
|
-
const ids = [
|
|
327
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
328
|
+
const ids = ["doc1", "doc2", "doesNotExist"];
|
|
328
329
|
const docs = await bulkGet(config, ids, {
|
|
329
330
|
docSchema: z.looseObject({
|
|
330
331
|
_id: z.string(),
|
|
331
332
|
type: z.string(),
|
|
332
|
-
name: z.string()
|
|
333
|
-
})
|
|
334
|
-
})
|
|
333
|
+
name: z.string(),
|
|
334
|
+
}),
|
|
335
|
+
});
|
|
335
336
|
// rows: [
|
|
336
337
|
// { id: 'doc1', doc: { _id: 'doc1', type: 'user', name: 'Alice' } },
|
|
337
338
|
// { id: 'doc2', doc: { _id: 'doc2', type: 'user', name: 'Bob' } },
|
|
@@ -351,9 +352,9 @@ Delete multiple documents in one request.
|
|
|
351
352
|
- Throws: `RetryableError` or `OperationError` only for request-level failures. Missing documents remain item-level outcomes.
|
|
352
353
|
|
|
353
354
|
```javascript
|
|
354
|
-
const config = { couch:
|
|
355
|
-
const ids = [
|
|
356
|
-
const results = await bulkRemove(config, ids)
|
|
355
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
356
|
+
const ids = ["doc1", "doc2"];
|
|
357
|
+
const results = await bulkRemove(config, ids);
|
|
357
358
|
// results: [
|
|
358
359
|
// { ok: true, id: 'doc1', rev: '2-ghi789' },
|
|
359
360
|
// { ok: true, id: 'doc2', rev: '2-jkl012' }
|
|
@@ -375,10 +376,10 @@ Allows more efficient deletion of document by providing only id and rev. This is
|
|
|
375
376
|
- Throws: `NotFoundError` when the document does not exist
|
|
376
377
|
|
|
377
378
|
```javascript
|
|
378
|
-
const config = { couch:
|
|
379
|
-
const id =
|
|
380
|
-
const rev =
|
|
381
|
-
const result = await remove(config, id, rev)
|
|
379
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
380
|
+
const id = "doc1";
|
|
381
|
+
const rev = "2-ghi789";
|
|
382
|
+
const result = await remove(config, id, rev);
|
|
382
383
|
// result:
|
|
383
384
|
// { ok: true, id: 'doc1', rev: '2-ghi789' }
|
|
384
385
|
```
|
|
@@ -395,9 +396,9 @@ Delete multiple documents in one request. Same inputs and outputs as [bulkRemove
|
|
|
395
396
|
- Throws: `RetryableError` or `OperationError` only for request-level failures while deleting an item. Missing or otherwise unremovable items are skipped.
|
|
396
397
|
|
|
397
398
|
```javascript
|
|
398
|
-
const config = { couch:
|
|
399
|
-
const ids = [
|
|
400
|
-
const results = await bulkRemoveMap(config, ids)
|
|
399
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
400
|
+
const ids = ["doc1", "doc2"];
|
|
401
|
+
const results = await bulkRemoveMap(config, ids);
|
|
401
402
|
// results: [
|
|
402
403
|
// { ok: true, id: 'doc1', rev: '2-ghi789' },
|
|
403
404
|
// { ok: true, id: 'doc2', rev: '2-jkl012' }
|
|
@@ -434,16 +435,16 @@ _notFound_ looks like
|
|
|
434
435
|
```
|
|
435
436
|
|
|
436
437
|
```javascript
|
|
437
|
-
import z from
|
|
438
|
+
import z from "zod";
|
|
438
439
|
|
|
439
|
-
const config = { couch:
|
|
440
|
-
const ids = [
|
|
440
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
441
|
+
const ids = ["doc1", "doc2", "doesNotExist"];
|
|
441
442
|
const results = await bulkGetDictionary(config, ids, {
|
|
442
443
|
docSchema: z.looseObject({
|
|
443
444
|
_id: z.string(),
|
|
444
|
-
data: z.record(z.any())
|
|
445
|
-
})
|
|
446
|
-
})
|
|
445
|
+
data: z.record(z.any()),
|
|
446
|
+
}),
|
|
447
|
+
});
|
|
447
448
|
// results: {
|
|
448
449
|
// found: {
|
|
449
450
|
// doc1: { _id: 'doc2', _rev: '1-221', data: {} },
|
|
@@ -478,28 +479,28 @@ Exceptions to handle:
|
|
|
478
479
|
- `TransactionRollbackError`: Thrown if the rollback operation fails after a transaction failure.
|
|
479
480
|
|
|
480
481
|
```javascript
|
|
481
|
-
const config = { couch:
|
|
482
|
-
const transactionId =
|
|
482
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
483
|
+
const transactionId = "txn-123";
|
|
483
484
|
const docs = [
|
|
484
|
-
{ _id:
|
|
485
|
-
{ _id:
|
|
486
|
-
]
|
|
485
|
+
{ _id: "doc1", type: "user", name: "Alice", _rev: "1-abc123" },
|
|
486
|
+
{ _id: "doc2", type: "user", name: "Bob", _rev: "1-def456" },
|
|
487
|
+
];
|
|
487
488
|
|
|
488
489
|
try {
|
|
489
|
-
const results = await bulkSaveTransaction(config, transactionId, docs)
|
|
490
|
-
console.log(
|
|
490
|
+
const results = await bulkSaveTransaction(config, transactionId, docs);
|
|
491
|
+
console.log("Transaction successful:", results);
|
|
491
492
|
} catch (error) {
|
|
492
493
|
if (error instanceof TransactionSetupError) {
|
|
493
494
|
// the transaction could not start - usually an existing transaction with the same id
|
|
494
|
-
console.error(
|
|
495
|
+
console.error("Transaction setup failed:", error);
|
|
495
496
|
} else if (error instanceof TransactionVersionConflictError) {
|
|
496
497
|
// one or more of the versions of the docs provided dont match with what is currently in the db
|
|
497
|
-
console.error(
|
|
498
|
+
console.error("Version conflict error:", error);
|
|
498
499
|
} else if (error instanceof TransactionRollbackError) {
|
|
499
500
|
// the transaction was rolled back - so the 'or none' condition occured
|
|
500
|
-
console.error(
|
|
501
|
+
console.error("Rollback error:", error);
|
|
501
502
|
} else {
|
|
502
|
-
console.error(
|
|
503
|
+
console.error("Unexpected error:", error);
|
|
503
504
|
}
|
|
504
505
|
}
|
|
505
506
|
```
|
|
@@ -517,6 +518,19 @@ const result = await getDBInfo({
|
|
|
517
518
|
// result: { db_name: 'test', doc_count: 3232 }
|
|
518
519
|
```
|
|
519
520
|
|
|
521
|
+
#### headDB()
|
|
522
|
+
|
|
523
|
+
Run a lightweight database health check using CouchDB's `HEAD /{db}` route.
|
|
524
|
+
|
|
525
|
+
```javascript
|
|
526
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
527
|
+
const healthy = await headDB({
|
|
528
|
+
...config,
|
|
529
|
+
request: { timeout: 2000 },
|
|
530
|
+
});
|
|
531
|
+
// healthy: true
|
|
532
|
+
```
|
|
533
|
+
|
|
520
534
|
### View Queries
|
|
521
535
|
|
|
522
536
|
#### query
|
|
@@ -541,15 +555,15 @@ Query a view with options.
|
|
|
541
555
|
- Returns: Promise resolving to response with `rows` array
|
|
542
556
|
|
|
543
557
|
```javascript
|
|
544
|
-
const config = { couch:
|
|
545
|
-
const view =
|
|
558
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
559
|
+
const view = "_design/users/_view/by_name";
|
|
546
560
|
const options = {
|
|
547
|
-
startkey:
|
|
548
|
-
endkey:
|
|
561
|
+
startkey: "A",
|
|
562
|
+
endkey: "B",
|
|
549
563
|
include_docs: true,
|
|
550
|
-
limit: 10
|
|
551
|
-
}
|
|
552
|
-
const result = await query(config, view, options)
|
|
564
|
+
limit: 10,
|
|
565
|
+
};
|
|
566
|
+
const result = await query(config, view, options);
|
|
553
567
|
// result: {
|
|
554
568
|
// rows: [
|
|
555
569
|
// {
|
|
@@ -588,9 +602,14 @@ Create a query builder to help construct view queries with a fluent interface. N
|
|
|
588
602
|
- `build()`: Return the constructed query options object
|
|
589
603
|
|
|
590
604
|
```javascript
|
|
591
|
-
const options = createQuery()
|
|
605
|
+
const options = createQuery()
|
|
606
|
+
.startkey("A")
|
|
607
|
+
.endkey("B")
|
|
608
|
+
.include_docs(true)
|
|
609
|
+
.limit(10)
|
|
610
|
+
.build();
|
|
592
611
|
|
|
593
|
-
const result = await query(config, view, options)
|
|
612
|
+
const result = await query(config, view, options);
|
|
594
613
|
```
|
|
595
614
|
|
|
596
615
|
Again, use js types for array keys
|
|
@@ -656,22 +675,22 @@ npm install hide-a-bed-changes
|
|
|
656
675
|
Usage mirrors the original API:
|
|
657
676
|
|
|
658
677
|
```javascript
|
|
659
|
-
import { changes } from
|
|
678
|
+
import { changes } from "hide-a-bed-changes";
|
|
660
679
|
|
|
661
|
-
const config = { couch:
|
|
680
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
662
681
|
|
|
663
682
|
const feed = await changes(
|
|
664
683
|
config,
|
|
665
|
-
change => {
|
|
666
|
-
console.log(
|
|
684
|
+
(change) => {
|
|
685
|
+
console.log("Document changed:", change.id);
|
|
667
686
|
},
|
|
668
|
-
{ since:
|
|
669
|
-
)
|
|
687
|
+
{ since: "now", include_docs: true },
|
|
688
|
+
);
|
|
670
689
|
|
|
671
|
-
feed.on(
|
|
690
|
+
feed.on("error", console.error);
|
|
672
691
|
|
|
673
692
|
// later
|
|
674
|
-
feed.stop()
|
|
693
|
+
feed.stop();
|
|
675
694
|
```
|
|
676
695
|
|
|
677
696
|
`hide-a-bed-changes` reuses the same config structure and resolves `since: 'now'` to the current `update_seq` before starting the feed.
|
|
@@ -700,38 +719,38 @@ Returns an EventEmitter that emits:
|
|
|
700
719
|
- 'end' events with last sequence number.
|
|
701
720
|
|
|
702
721
|
```javascript
|
|
703
|
-
const config = { couch:
|
|
722
|
+
const config = { couch: "http://localhost:5984/mydb" };
|
|
704
723
|
|
|
705
724
|
// Watch a single document
|
|
706
|
-
const feed = await watchDocs(config,
|
|
707
|
-
console.log(
|
|
708
|
-
console.log(
|
|
709
|
-
})
|
|
725
|
+
const feed = await watchDocs(config, "doc123", (change) => {
|
|
726
|
+
console.log("Document changed:", change.id);
|
|
727
|
+
console.log("New revision:", change.changes[0].rev);
|
|
728
|
+
});
|
|
710
729
|
|
|
711
730
|
// Watch multiple documents with full doc content
|
|
712
731
|
const feed = await watchDocs(
|
|
713
732
|
config,
|
|
714
|
-
[
|
|
715
|
-
change => {
|
|
733
|
+
["doc1", "doc2", "doc3"],
|
|
734
|
+
(change) => {
|
|
716
735
|
if (change.doc) {
|
|
717
|
-
console.log(
|
|
736
|
+
console.log("Updated document:", change.doc);
|
|
718
737
|
}
|
|
719
738
|
},
|
|
720
|
-
{ include_docs: true }
|
|
721
|
-
)
|
|
739
|
+
{ include_docs: true },
|
|
740
|
+
);
|
|
722
741
|
|
|
723
742
|
// Handle errors
|
|
724
|
-
feed.on(
|
|
725
|
-
console.error(
|
|
726
|
-
})
|
|
743
|
+
feed.on("error", (error) => {
|
|
744
|
+
console.error("Watch error:", error);
|
|
745
|
+
});
|
|
727
746
|
|
|
728
747
|
// Handle end of feed
|
|
729
|
-
feed.on(
|
|
730
|
-
console.log(
|
|
731
|
-
})
|
|
748
|
+
feed.on("end", ({ lastSeq }) => {
|
|
749
|
+
console.log("Feed ended at sequence:", lastSeq);
|
|
750
|
+
});
|
|
732
751
|
|
|
733
752
|
// Stop watching
|
|
734
|
-
feed.stop()
|
|
753
|
+
feed.stop();
|
|
735
754
|
```
|
|
736
755
|
|
|
737
756
|
The watchDocs feed is useful for:
|
|
@@ -761,13 +780,13 @@ Example configuration with all options:
|
|
|
761
780
|
|
|
762
781
|
```javascript
|
|
763
782
|
const config = {
|
|
764
|
-
couch:
|
|
783
|
+
couch: "http://localhost:5984/mydb",
|
|
765
784
|
auth: {
|
|
766
785
|
username: process.env.COUCHDB_USER,
|
|
767
|
-
password: process.env.COUCHDB_PASSWORD
|
|
786
|
+
password: process.env.COUCHDB_PASSWORD,
|
|
768
787
|
},
|
|
769
788
|
request: {
|
|
770
|
-
timeout: 5000
|
|
789
|
+
timeout: 5000,
|
|
771
790
|
},
|
|
772
791
|
throwOnGetNotFound: true,
|
|
773
792
|
bindWithRetry: true,
|
|
@@ -775,8 +794,8 @@ const config = {
|
|
|
775
794
|
initialDelay: 2000,
|
|
776
795
|
backoffFactor: 1.5,
|
|
777
796
|
useConsoleLogger: true,
|
|
778
|
-
logger: (level, ...args) => console.log(level, ...args)
|
|
779
|
-
}
|
|
797
|
+
logger: (level, ...args) => console.log(level, ...args),
|
|
798
|
+
};
|
|
780
799
|
```
|
|
781
800
|
|
|
782
801
|
`bindConfig()` and `withRetry()` now perform a single built-in retry for transient `401` and `403` responses before surfacing the error.
|
|
@@ -786,12 +805,15 @@ const config = {
|
|
|
786
805
|
`withRetry(fn, options)` wraps an async function and retries based on the built-in retry rules.
|
|
787
806
|
|
|
788
807
|
```javascript
|
|
789
|
-
import { withRetry, get } from
|
|
808
|
+
import { withRetry, get } from "hide-a-bed";
|
|
790
809
|
|
|
791
|
-
const getWithCustomRetry = withRetry(
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
810
|
+
const getWithCustomRetry = withRetry(
|
|
811
|
+
(id) => get({ couch: "http://localhost:5984/mydb" }, id),
|
|
812
|
+
{
|
|
813
|
+
maxRetries: 2,
|
|
814
|
+
initialDelay: 250,
|
|
815
|
+
},
|
|
816
|
+
);
|
|
795
817
|
```
|
|
796
818
|
|
|
797
819
|
### Migration Note
|
|
@@ -809,26 +831,26 @@ The library supports flexible logging options that can be configured through the
|
|
|
809
831
|
```javascript
|
|
810
832
|
// Enable console logging (error, warn, info, debug)
|
|
811
833
|
const config = {
|
|
812
|
-
couch:
|
|
813
|
-
useConsoleLogger: true
|
|
814
|
-
}
|
|
834
|
+
couch: "http://localhost:5984/mydb",
|
|
835
|
+
useConsoleLogger: true,
|
|
836
|
+
};
|
|
815
837
|
|
|
816
838
|
// Use a custom logger object (winston-style)
|
|
817
839
|
const config = {
|
|
818
|
-
couch:
|
|
840
|
+
couch: "http://localhost:5984/mydb",
|
|
819
841
|
logger: {
|
|
820
|
-
error: msg => console.error(msg),
|
|
821
|
-
warn: msg => console.warn(msg),
|
|
822
|
-
info: msg => console.info(msg),
|
|
823
|
-
debug: msg => console.debug(msg)
|
|
824
|
-
}
|
|
825
|
-
}
|
|
842
|
+
error: (msg) => console.error(msg),
|
|
843
|
+
warn: (msg) => console.warn(msg),
|
|
844
|
+
info: (msg) => console.info(msg),
|
|
845
|
+
debug: (msg) => console.debug(msg),
|
|
846
|
+
},
|
|
847
|
+
};
|
|
826
848
|
|
|
827
849
|
// Use a simple function logger
|
|
828
850
|
const config = {
|
|
829
|
-
couch:
|
|
830
|
-
logger: (level, ...args) => console.log(level, ...args)
|
|
831
|
-
}
|
|
851
|
+
couch: "http://localhost:5984/mydb",
|
|
852
|
+
logger: (level, ...args) => console.log(level, ...args),
|
|
853
|
+
};
|
|
832
854
|
```
|
|
833
855
|
|
|
834
856
|
The logger will track operations including:
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -2070,6 +2070,51 @@ const getDBInfo = async (configInput) => {
|
|
|
2070
2070
|
return CouchDBInfo.parse(resp.body);
|
|
2071
2071
|
};
|
|
2072
2072
|
|
|
2073
|
+
//#endregion
|
|
2074
|
+
//#region impl/headDB.mts
|
|
2075
|
+
/**
|
|
2076
|
+
* Performs a health check against the target CouchDB database using `HEAD /{db}`.
|
|
2077
|
+
*
|
|
2078
|
+
* @see {@link https://docs.couchdb.org/en/stable/api/database/common.html#head--db | CouchDB API Documentation}
|
|
2079
|
+
*
|
|
2080
|
+
* @param configInput - The CouchDB configuration input.
|
|
2081
|
+
* @returns A promise that resolves to `true` when the database responds successfully.
|
|
2082
|
+
* @throws {RetryableError} `RetryableError` If a retryable error occurs during the request.
|
|
2083
|
+
* @throws {OperationError} For other non-retryable response failures.
|
|
2084
|
+
*/
|
|
2085
|
+
const headDB = async (configInput) => {
|
|
2086
|
+
const config = CouchConfig.parse(configInput);
|
|
2087
|
+
const logger = createLogger(config);
|
|
2088
|
+
const url = createCouchDbUrl(config.couch);
|
|
2089
|
+
let resp;
|
|
2090
|
+
try {
|
|
2091
|
+
resp = await fetchCouchJson({
|
|
2092
|
+
auth: config.auth,
|
|
2093
|
+
method: "HEAD",
|
|
2094
|
+
operation: "headDB",
|
|
2095
|
+
request: config.request,
|
|
2096
|
+
url
|
|
2097
|
+
});
|
|
2098
|
+
if (!isSuccessStatusCode("database", resp.statusCode)) {
|
|
2099
|
+
logger.error(`Non-success status code received: ${resp.statusCode}`);
|
|
2100
|
+
throw createResponseError({
|
|
2101
|
+
body: resp.body,
|
|
2102
|
+
defaultMessage: "Database health check failed",
|
|
2103
|
+
operation: "headDB",
|
|
2104
|
+
statusCode: resp.statusCode
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
} catch (err) {
|
|
2108
|
+
logger.error("Error during head operation:", err);
|
|
2109
|
+
RetryableError.handleNetworkError(err, "headDB");
|
|
2110
|
+
}
|
|
2111
|
+
if (!resp) {
|
|
2112
|
+
logger.error("No response received from head request");
|
|
2113
|
+
throw new RetryableError("Database health check failed", 503, { operation: "headDB" });
|
|
2114
|
+
}
|
|
2115
|
+
return true;
|
|
2116
|
+
};
|
|
2117
|
+
|
|
2073
2118
|
//#endregion
|
|
2074
2119
|
//#region schema/sugar/lock.mts
|
|
2075
2120
|
const LockDoc = CouchDoc.extend({
|
|
@@ -2403,6 +2448,7 @@ function doBind(config) {
|
|
|
2403
2448
|
bulkSave: config.bindWithRetry ? withRetry(bulkSave.bind(null, config), retryOptions) : bulkSave.bind(null, config),
|
|
2404
2449
|
bulkSaveTransaction: bulkSaveTransaction.bind(null, config),
|
|
2405
2450
|
getDBInfo: config.bindWithRetry ? withRetry(getDBInfo.bind(null, config), retryOptions) : getDBInfo.bind(null, config),
|
|
2451
|
+
headDB: config.bindWithRetry ? withRetry(headDB.bind(null, config), retryOptions) : headDB.bind(null, config),
|
|
2406
2452
|
patch: config.bindWithRetry ? withRetry(patch.bind(null, config), retryOptions) : patch.bind(null, config),
|
|
2407
2453
|
patchDangerously: patchDangerously.bind(null, config),
|
|
2408
2454
|
put: config.bindWithRetry ? withRetry(put.bind(null, config), retryOptions) : put.bind(null, config),
|
|
@@ -2434,6 +2480,7 @@ exports.createQuery = createQuery;
|
|
|
2434
2480
|
exports.get = get;
|
|
2435
2481
|
exports.getAtRev = getAtRev;
|
|
2436
2482
|
exports.getDBInfo = getDBInfo;
|
|
2483
|
+
exports.headDB = headDB;
|
|
2437
2484
|
exports.patch = patch;
|
|
2438
2485
|
exports.patchDangerously = patchDangerously;
|
|
2439
2486
|
exports.put = put;
|