hide-a-bed 5.0.0 → 5.0.2

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 CHANGED
@@ -1,5 +1,22 @@
1
- API
2
- -------------
1
+ ### API Quick Reference
2
+
3
+ 🍭 denotes a *Sugar* api - helps makes some tasks sweet and easy, but may hide some complexities you might want to deal with.
4
+
5
+ | Document Operations | Bulk Operations | View Operations | Changes Feed |
6
+ |-------------------|-----------------|-----------------|-----------------|
7
+ | [`get()`](#get) | [`bulkGet()`](#bulkget) | [`query()`](#query) | [`changes()`](#changes) |
8
+ | [`put()`](#put) | [`bulkSave()`](#bulksave) | [`queryStream()`](#querystream) | [`watchDocs()`](#watchDocs) 🍭 |
9
+ | [`patch()`](#patch) 🍭 | [`bulkRemove()`](#bulkremove) | | |
10
+ | [`patchDangerously()`](#patchdangerously) 🍭 | [`bulkGetDictionary()`](#bulkgetdictionary) 🍭 | | |
11
+ | [`getAtRev()`](#getatrev) 🍭 | [`bulkSaveTransaction()`](#bulksavetransaction) 🍭 | | |
12
+ | [`createLock()`](#createLock) 🍭 | | | |
13
+ | [`removeLock()`](#removeLock) 🍭 | | | |
14
+
15
+ And some utility apis
16
+
17
+ - [`createQuery()`](#createquery) 🍭
18
+ - [`withRetry()`](#withretry)
19
+
3
20
 
4
21
  ### Setup
5
22
 
@@ -26,24 +43,6 @@ const db = bindConfig(process.env)
26
43
  const doc = db.get('doc-123')
27
44
  ```
28
45
 
29
- ### API Quick Reference
30
-
31
- | Document Operations | Bulk Operations | View Operations |
32
- |-------------------|-----------------|-----------------|
33
- | [`get()`](#get) | [`bulkGet()`](#bulkget) | [`query()`](#query) |
34
- | [`put()`](#put) | [`bulkSave()`](#bulksave) | [`queryStream()`](#querystream) |
35
- | [`patch()`](#patch) | [`bulkRemove()`](#bulkremove) | [`createQuery()`](#createquery) |
36
- | [`patchDangerously()`](#patchdangerously) | [`bulkGetDictionary()`](#bulkgetdictionary) | |
37
- | [`getAtRev()`](#getatrev) | [`bulkSaveTransaction()`](#bulksavetransaction) | |
38
-
39
-
40
- Some *Sugar* API helpers
41
-
42
- - [`createLock()`](#createLock)
43
- - [`removeLock()`](#removeLock)
44
- - [`changes()`](#changes)
45
- - [`watchDocs()`](#watchDocs)
46
-
47
46
  ### Document Operations
48
47
 
49
48
  #### get
@@ -284,7 +283,7 @@ const results = await bulkRemove(config, ids)
284
283
 
285
284
  #### bulkGetDictionary
286
285
 
287
- Adds some convenience to bulkGet. Found and notFound documents are separated. Both properties are records of id to result. This makes it easy to deal with the results.
286
+ Adds some convenience to bulkGet. Organizes found and notFound documents into properties that are {id:result}. This makes it easy to deal with the results.
288
287
 
289
288
  **Parameters:**
290
289
  - `config`: Object with `couch` URL string
@@ -480,79 +479,9 @@ const init = async () => {
480
479
  }
481
480
  init()
482
481
  ```
483
- Advanced Config Options
484
- =======================
485
-
486
- The config object supports the following properties:
487
-
488
- | Property | Type | Default | Description |
489
- |----------|------|---------|-------------|
490
- | couch | string | required | The URL of the CouchDB database |
491
- | throwOnGetNotFound | boolean | false | If true, throws an error when get() returns 404. If false, returns undefined |
492
- | bindWithRetry | boolean | true | When using bindConfig(), adds retry logic to bound methods |
493
- | maxRetries | number | 3 | Maximum number of retry attempts for retryable operations |
494
- | initialDelay | number | 1000 | Initial delay in milliseconds before first retry |
495
- | backoffFactor | number | 2 | Multiplier for exponential backoff between retries |
496
- | useConsoleLogger | boolean | false | If true, enables console logging when no logger is provided |
497
- | logger | object/function | undefined | Custom logging interface (winston-style object or function) |
498
-
499
- Example configuration with all options:
500
- ```javascript
501
- const config = {
502
- couch: 'http://localhost:5984/mydb',
503
- throwOnGetNotFound: true,
504
- bindWithRetry: true,
505
- maxRetries: 5,
506
- initialDelay: 2000,
507
- backoffFactor: 1.5,
508
- useConsoleLogger: true,
509
- logger: (level, ...args) => console.log(level, ...args)
510
- }
511
- ```
512
482
 
513
-
514
- Logging Support
515
- ==============
516
-
517
- The library supports flexible logging options that can be configured through the config object:
518
-
519
- ```javascript
520
- // Enable console logging (error, warn, info, debug)
521
- const config = {
522
- couch: 'http://localhost:5984/mydb',
523
- useConsoleLogger: true
524
- }
525
-
526
- // Use a custom logger object (winston-style)
527
- const config = {
528
- couch: 'http://localhost:5984/mydb',
529
- logger: {
530
- error: (msg) => console.error(msg),
531
- warn: (msg) => console.warn(msg),
532
- info: (msg) => console.info(msg),
533
- debug: (msg) => console.debug(msg)
534
- }
535
- }
536
-
537
- // Use a simple function logger
538
- const config = {
539
- couch: 'http://localhost:5984/mydb',
540
- logger: (level, ...args) => console.log(level, ...args)
541
- }
542
- ```
543
-
544
- The logger will track operations including:
545
- - Document operations (get, put, patch)
546
- - Bulk operations
547
- - View queries
548
- - Streaming operations
549
- - Retries and error handling
550
-
551
- Each operation logs appropriate information at these levels:
552
- - error: Fatal/unrecoverable errors
553
- - warn: Retryable errors, conflicts
554
- - info: Operation start/completion
555
- - debug: Detailed operation information
483
+ Want to consume this in the browser? I'd recomment https://www.npmjs.com/package/ndjson-readablestream
484
+ here is a react component that consumes it https://github.com/Azure-Samples/azure-search-openai-demo/pull/532/files#diff-506debba46b93087dc46a916384e56392808bcc02a99d9291557f3e674d4ad6c
556
485
 
557
486
  #### changes()
558
487
 
@@ -659,3 +588,77 @@ Watch specific documents for changes in real-time.
659
588
  - Triggering actions when particular documents change
660
589
  - Maintaining cached copies of frequently accessed documents
661
590
 
591
+ Advanced Config Options
592
+ =======================
593
+
594
+ The config object supports the following properties:
595
+
596
+ | Property | Type | Default | Description |
597
+ |----------|------|---------|-------------|
598
+ | couch | string | required | The URL of the CouchDB database |
599
+ | throwOnGetNotFound | boolean | false | If true, throws an error when get() returns 404. If false, returns undefined |
600
+ | bindWithRetry | boolean | true | When using bindConfig(), adds retry logic to bound methods |
601
+ | maxRetries | number | 3 | Maximum number of retry attempts for retryable operations |
602
+ | initialDelay | number | 1000 | Initial delay in milliseconds before first retry |
603
+ | backoffFactor | number | 2 | Multiplier for exponential backoff between retries |
604
+ | useConsoleLogger | boolean | false | If true, enables console logging when no logger is provided |
605
+ | logger | object/function | undefined | Custom logging interface (winston-style object or function) |
606
+
607
+ Example configuration with all options:
608
+ ```javascript
609
+ const config = {
610
+ couch: 'http://localhost:5984/mydb',
611
+ throwOnGetNotFound: true,
612
+ bindWithRetry: true,
613
+ maxRetries: 5,
614
+ initialDelay: 2000,
615
+ backoffFactor: 1.5,
616
+ useConsoleLogger: true,
617
+ logger: (level, ...args) => console.log(level, ...args)
618
+ }
619
+ ```
620
+
621
+
622
+ Logging Support
623
+ ==============
624
+
625
+ The library supports flexible logging options that can be configured through the config object:
626
+
627
+ ```javascript
628
+ // Enable console logging (error, warn, info, debug)
629
+ const config = {
630
+ couch: 'http://localhost:5984/mydb',
631
+ useConsoleLogger: true
632
+ }
633
+
634
+ // Use a custom logger object (winston-style)
635
+ const config = {
636
+ couch: 'http://localhost:5984/mydb',
637
+ logger: {
638
+ error: (msg) => console.error(msg),
639
+ warn: (msg) => console.warn(msg),
640
+ info: (msg) => console.info(msg),
641
+ debug: (msg) => console.debug(msg)
642
+ }
643
+ }
644
+
645
+ // Use a simple function logger
646
+ const config = {
647
+ couch: 'http://localhost:5984/mydb',
648
+ logger: (level, ...args) => console.log(level, ...args)
649
+ }
650
+ ```
651
+
652
+ The logger will track operations including:
653
+ - Document operations (get, put, patch)
654
+ - Bulk operations
655
+ - View queries
656
+ - Streaming operations
657
+ - Retries and error handling
658
+
659
+ Each operation logs appropriate information at these levels:
660
+ - error: Fatal/unrecoverable errors
661
+ - warn: Retryable errors, conflicts
662
+ - info: Operation start/completion
663
+ - debug: Detailed operation information
664
+
package/impl/changes.mjs CHANGED
@@ -12,15 +12,10 @@ import { Changes } from '../schema/changes.mjs'
12
12
  * }} ChangeInfo */
13
13
  // @ts-ignore
14
14
  import ChangesStream from 'changes-stream'
15
- import { createLogger } from './logger.mjs'
16
- import { sleep } from './patch.mjs'
17
-
18
- const MAX_RETRY_DELAY = 30000 // 30 seconds
19
15
 
20
16
  /** @type { import('../schema/changes.mjs').ChangesSchema } */
21
17
  export const changes = Changes.implement(async (config, onChange, options = {}) => {
22
18
  const emitter = new EventEmitter()
23
- const logger = createLogger(config)
24
19
  options.db = config.couch
25
20
  if (options.since && options.since === 'now') {
26
21
  const opts = {
@@ -37,12 +32,12 @@ export const changes = Changes.implement(async (config, onChange, options = {})
37
32
  const changes = ChangesStream(options)
38
33
 
39
34
  changes.on('readable', () => {
40
- const change = changes.read();
35
+ const change = changes.read()
41
36
  if (change.results && Array.isArray(change.results)) {
42
37
  // emit each one seperate
43
38
  change.results.forEach((/** @type {ChangeInfo} */ c) => emitter.emit('change', c))
44
39
  } else emitter.emit('change', change)
45
- });
40
+ })
46
41
 
47
42
  // Bind the provided change listener
48
43
  emitter.on('change', onChange)
package/impl/errors.mjs CHANGED
@@ -11,7 +11,7 @@ export class NotFoundError extends Error {
11
11
  * @param {string} docId - The ID of the document that wasn't found
12
12
  * @param {string} [message] - Optional error message
13
13
  */
14
- constructor(docId, message = 'Document not found') {
14
+ constructor (docId, message = 'Document not found') {
15
15
  super(message)
16
16
  this.name = 'NotFoundError'
17
17
  this.docId = docId
package/impl/query.mjs CHANGED
@@ -22,7 +22,6 @@ export const query = SimpleViewQuery.implement(async (config, view, options = {}
22
22
 
23
23
  // @ts-ignore
24
24
  let qs = queryString(options, ['key', 'startkey', 'endkey', 'reduce', 'group', 'group_level', 'stale', 'limit'])
25
- logger.debug('Generated query string:', qs)
26
25
  let method = 'GET'
27
26
  let payload = null
28
27
  const opts = {
@@ -35,21 +34,30 @@ export const query = SimpleViewQuery.implement(async (config, view, options = {}
35
34
  // If keys are supplied, issue a POST to circumvent GET query string limits
36
35
  // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options
37
36
  if (typeof options.keys !== 'undefined') {
38
- const MAX_URL_LENGTH = 2000;
37
+ const MAX_URL_LENGTH = 2000
39
38
  // according to http://stackoverflow.com/a/417184/680742,
40
39
  // the de facto URL length limit is 2000 characters
41
40
 
42
- const keysAsString = `keys=${encodeURIComponent(JSON.stringify(options.keys))}`;
41
+ const _options = structuredClone(options)
42
+ delete _options.keys
43
+ qs = queryString(_options, ['key', 'startkey', 'endkey', 'reduce', 'group', 'group_level', 'stale', 'limit'])
44
+
45
+ const keysAsString = `keys=${JSON.stringify(options.keys)}`
46
+
43
47
  if (keysAsString.length + qs.length + 1 <= MAX_URL_LENGTH) {
44
48
  // If the keys are short enough, do a GET. we do this to work around
45
49
  // Safari not understanding 304s on POSTs (see pouchdb/pouchdb#1239)
46
- qs += (qs[0] === '?' ? '&' : '?') + keysAsString;
50
+ method = 'GET'
51
+ if (qs.length > 0) qs += '&'
52
+ else qs = '?'
53
+ qs += keysAsString
47
54
  } else {
48
- method = 'POST';
49
- payload = {keys: options.keys};
55
+ method = 'POST'
56
+ payload = { keys: options.keys }
50
57
  }
51
58
  }
52
59
 
60
+ logger.debug('Generated query string:', qs)
53
61
  const url = `${config.couch}/${view}?${qs.toString()}`
54
62
  // @ts-ignore
55
63
  let results
package/impl/stream.mjs CHANGED
@@ -25,7 +25,7 @@ export const queryStream = (rawConfig, view, options, onRow) => new Promise((res
25
25
  if (typeof options.keys !== 'undefined') {
26
26
  const MAX_URL_LENGTH = 2000
27
27
  const keysAsString = `keys=${encodeURIComponent(JSON.stringify(options.keys))}`
28
-
28
+
29
29
  if (keysAsString.length + qs.length + 1 <= MAX_URL_LENGTH) {
30
30
  // If the keys are short enough, do a GET
31
31
  qs += (qs[0] === '?' ? '&' : '?') + keysAsString
@@ -70,7 +70,7 @@ export const queryStream = (rawConfig, view, options, onRow) => new Promise((res
70
70
  resolve(undefined) // all work should be done in the stream
71
71
  })
72
72
 
73
- const req = method === 'GET'
73
+ const req = method === 'GET'
74
74
  ? needle.get(url, opts)
75
75
  : needle.post(url, payload, opts)
76
76
 
@@ -5,7 +5,7 @@ import { createLogger } from '../logger.mjs'
5
5
  /** @type {import('../../schema/sugar/lock.mjs').CreateLockSchema} */
6
6
  export const createLock = CreateLock.implement(async (config, docId, options) => {
7
7
  const logger = createLogger(config)
8
-
8
+
9
9
  if (!options.enableLocking) {
10
10
  logger.debug('Locking disabled, returning true')
11
11
  return true
@@ -37,7 +37,7 @@ export const createLock = CreateLock.implement(async (config, docId, options) =>
37
37
  /** @type {import('../../schema/sugar/lock.mjs').RemoveLockSchema} */
38
38
  export const removeLock = RemoveLock.implement(async (config, docId, options) => {
39
39
  const logger = createLogger(config)
40
-
40
+
41
41
  if (!options.enableLocking) {
42
42
  logger.debug('Locking disabled, skipping unlock')
43
43
  return
@@ -50,7 +50,7 @@ export const removeLock = RemoveLock.implement(async (config, docId, options) =>
50
50
 
51
51
  const _id = `lock-${docId}`
52
52
  const existingLock = await get(config, _id)
53
-
53
+
54
54
  if (!existingLock) {
55
55
  logger.debug(`No lock found for ${docId}`)
56
56
  return
@@ -28,7 +28,7 @@ export const watchDocs = WatchDocs.implement((config, docIds, onChange, options
28
28
  const includeDocs = options.include_docs ?? false
29
29
  const ids = _docIds.join('","')
30
30
  const url = `${config.couch}/_changes?feed=${feed}&since=${lastSeq}&include_docs=${includeDocs}&filter=_doc_ids&doc_ids=["${ids}"]`
31
-
31
+
32
32
  const opts = {
33
33
  headers: { 'Content-Type': 'application/json' },
34
34
  parse_response: false
@@ -37,79 +37,79 @@ export const watchDocs = WatchDocs.implement((config, docIds, onChange, options
37
37
  let buffer = ''
38
38
  currentRequest = needle.get(url, opts)
39
39
 
40
- currentRequest.on('data', chunk => {
41
- buffer += chunk.toString()
42
- const lines = buffer.split('\n')
43
-
44
- // Keep the last partial line in the buffer
45
- buffer = lines.pop() || ''
40
+ currentRequest.on('data', chunk => {
41
+ buffer += chunk.toString()
42
+ const lines = buffer.split('\n')
46
43
 
47
- // Process complete lines
48
- for (const line of lines) {
49
- if (line.trim()) {
50
- try {
51
- const change = JSON.parse(line)
52
- if (!change.id) return null // ignore just last_seq
53
- logger.debug(`Change detected, watching [${_docIds}]`, change)
54
- lastSeq = change.seq || change.last_seq
55
- emitter.emit('change', change)
56
- } catch (err) {
57
- logger.error('Error parsing change:', err, 'Line:', line)
44
+ // Keep the last partial line in the buffer
45
+ buffer = lines.pop() || ''
46
+
47
+ // Process complete lines
48
+ for (const line of lines) {
49
+ if (line.trim()) {
50
+ try {
51
+ const change = JSON.parse(line)
52
+ if (!change.id) return null // ignore just last_seq
53
+ logger.debug(`Change detected, watching [${_docIds}]`, change)
54
+ lastSeq = change.seq || change.last_seq
55
+ emitter.emit('change', change)
56
+ } catch (err) {
57
+ logger.error('Error parsing change:', err, 'Line:', line)
58
+ }
58
59
  }
59
60
  }
60
- }
61
- })
61
+ })
62
62
 
63
- currentRequest.on('response', response => {
64
- logger.debug(`Received response with status code, watching [${_docIds}]: ${response.statusCode}`)
65
- if (RetryableError.isRetryableStatusCode(response.statusCode)) {
66
- logger.warn(`Retryable status code received: ${response.statusCode}`)
67
- currentRequest.abort()
68
- handleReconnect()
69
- } else {
70
- // Reset retry count on successful connection
71
- retryCount = 0
72
- }
73
- })
74
-
75
- currentRequest.on('error', async err => {
76
- if (stopping) {
77
- logger.info('stopping in progress, ignore stream error')
78
- return
79
- }
80
- logger.error(`Network error during stream, watching [${_docIds}]:`, err.toString())
81
- try {
82
- RetryableError.handleNetworkError(err)
83
- } catch (filteredError) {
84
- if (filteredError instanceof RetryableError) {
85
- logger.info(`Retryable error, watching [${_docIds}]:`, filteredError.toString())
63
+ currentRequest.on('response', response => {
64
+ logger.debug(`Received response with status code, watching [${_docIds}]: ${response.statusCode}`)
65
+ if (RetryableError.isRetryableStatusCode(response.statusCode)) {
66
+ logger.warn(`Retryable status code received: ${response.statusCode}`)
67
+ currentRequest.abort()
86
68
  handleReconnect()
87
69
  } else {
88
- logger.error(`Non-retryable error, watching [${_docIds}]`, nonRetryErr)
89
- emitter.emit('error', nonRetryErr)
70
+ // Reset retry count on successful connection
71
+ retryCount = 0
90
72
  }
91
- }
92
- })
73
+ })
93
74
 
94
- currentRequest.on('end', () => {
95
- // Process any remaining data in buffer
96
- if (buffer.trim()) {
75
+ currentRequest.on('error', async err => {
76
+ if (stopping) {
77
+ logger.info('stopping in progress, ignore stream error')
78
+ return
79
+ }
80
+ logger.error(`Network error during stream, watching [${_docIds}]:`, err.toString())
97
81
  try {
98
- const change = JSON.parse(buffer)
99
- logger.debug('Final change detected:', change)
100
- emitter.emit('change', change)
101
- } catch (err) {
102
- logger.error('Error parsing final change:', err)
82
+ RetryableError.handleNetworkError(err)
83
+ } catch (filteredError) {
84
+ if (filteredError instanceof RetryableError) {
85
+ logger.info(`Retryable error, watching [${_docIds}]:`, filteredError.toString())
86
+ handleReconnect()
87
+ } else {
88
+ logger.error(`Non-retryable error, watching [${_docIds}]`, filteredError.toString())
89
+ emitter.emit('error', filteredError)
90
+ }
103
91
  }
104
- }
105
- logger.info('Stream completed. Last seen seq: ', lastSeq)
106
- emitter.emit('end', { lastSeq })
107
-
108
- // If the stream ends and we're not stopping, attempt to reconnect
109
- if (!stopping) {
110
- handleReconnect()
111
- }
112
- })
92
+ })
93
+
94
+ currentRequest.on('end', () => {
95
+ // Process any remaining data in buffer
96
+ if (buffer.trim()) {
97
+ try {
98
+ const change = JSON.parse(buffer)
99
+ logger.debug('Final change detected:', change)
100
+ emitter.emit('change', change)
101
+ } catch (err) {
102
+ logger.error('Error parsing final change:', err)
103
+ }
104
+ }
105
+ logger.info('Stream completed. Last seen seq: ', lastSeq)
106
+ emitter.emit('end', { lastSeq })
107
+
108
+ // If the stream ends and we're not stopping, attempt to reconnect
109
+ if (!stopping) {
110
+ handleReconnect()
111
+ }
112
+ })
113
113
  }
114
114
 
115
115
  const handleReconnect = async () => {
@@ -123,10 +123,10 @@ export const watchDocs = WatchDocs.implement((config, docIds, onChange, options
123
123
 
124
124
  const delay = Math.min(initialDelay * Math.pow(2, retryCount), maxDelay)
125
125
  retryCount++
126
-
126
+
127
127
  logger.info(`Attempting to reconnect in ${delay}ms (attempt ${retryCount} of ${maxRetries})`)
128
128
  await sleep(delay)
129
-
129
+
130
130
  try {
131
131
  connect()
132
132
  } catch (err) {
package/log.txt ADDED
@@ -0,0 +1,84 @@
1
+ [Tue, 25 Feb 2025 02:45:58 GMT] [info] [<0.000.0>] pouchdb-server has started on http://127.0.0.1:8985/
2
+ [Tue, 25 Feb 2025 02:45:58 GMT] [info] [<0.000.0>] database is in-memory; no changes will be saved.
3
+ [Tue, 25 Feb 2025 02:45:58 GMT] [info] [<0.000.0>] navigate to http://127.0.0.1:8985/_utils for the Fauxton UI.
4
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb 201
5
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/testdoc 201
6
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc 200
7
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc-not-there 404
8
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc-not-there 404
9
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/notThereDoc 409
10
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
11
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda 201
12
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
13
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
14
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda 201
15
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-1 201
16
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
17
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-2 201
18
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
19
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
20
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-2 201
21
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-3 201
22
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
23
+ [Tue, 25 Feb 2025 02:45:59 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/a 201
24
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
25
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
26
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-3 201
27
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
28
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/conflict-test 201
29
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:conflict-error 201
30
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
31
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:bulk-error 201
32
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
33
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
34
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
35
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 409
36
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
37
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
38
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 404
39
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
40
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
41
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
42
+ [Tue, 25 Feb 2025 02:46:00 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock-2 404
43
+ [Tue, 25 Feb 2025 02:48:53 GMT] [info] [<0.000.0>] pouchdb-server has started on http://127.0.0.1:8985/
44
+ [Tue, 25 Feb 2025 02:48:53 GMT] [info] [<0.000.0>] database is in-memory; no changes will be saved.
45
+ [Tue, 25 Feb 2025 02:48:53 GMT] [info] [<0.000.0>] navigate to http://127.0.0.1:8985/_utils for the Fauxton UI.
46
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb 201
47
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/testdoc 201
48
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc 200
49
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc-not-there 404
50
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc-not-there 404
51
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/notThereDoc 409
52
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
53
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda 201
54
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
55
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
56
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda 201
57
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-1 201
58
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
59
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-2 201
60
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
61
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
62
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-2 201
63
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-3 201
64
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
65
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/a 201
66
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
67
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
68
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-3 201
69
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
70
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/conflict-test 201
71
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:conflict-error 201
72
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
73
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:bulk-error 201
74
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
75
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
76
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
77
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 409
78
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
79
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
80
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 404
81
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
82
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
83
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
84
+ [Tue, 25 Feb 2025 02:48:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock-2 404
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hide-a-bed",
3
- "version": "5.0.0",
3
+ "version": "5.0.2",
4
4
  "description": "An abstraction over couchdb calls that includes easy mock/stubs with pouchdb",
5
5
  "module": "index.mjs",
6
6
  "main": "cjs/index.cjs",
@@ -4,7 +4,7 @@ import { CouchDoc } from './crud.mjs'
4
4
 
5
5
  export const ChangesOptions = z.object({
6
6
  feed: z.enum(['continuous', 'longpoll']).default('continuous'),
7
- filter: z.any(), //z.union([z.string(), z.array()]).optional(),
7
+ filter: z.any(), // z.union([z.string(), z.array()]).optional(),
8
8
  inactivity_ms: z.number().default(60 * 60 * 1000),
9
9
  /** @type {number} */
10
10
  timeout: z.number().optional(),