hide-a-bed 5.0.5 → 5.1.1

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
@@ -40,9 +40,22 @@ A convience method to bind the config, so you dont need to pass it in.
40
40
  ```
41
41
  import { bindConfig } from 'hide-a-bed'
42
42
  const db = bindConfig(process.env)
43
- const doc = db.get('doc-123')
43
+ const doc = await db.get('doc-123')
44
44
  ```
45
45
 
46
+ ##### Config Overrides
47
+
48
+ You also can quickly change one (or more) config settings for a particular call with the db.config(options)
49
+
50
+ eg
51
+
52
+ ```
53
+ const doc = await db.config({ throwOnGetNotFound: true }).get('doc-id')
54
+ ```
55
+
56
+ You can pass any of [Config Options](#advanced-config-options) to db.config to override the original bindings.
57
+
58
+
46
59
  ### Document Operations
47
60
 
48
61
  #### get
@@ -412,6 +425,15 @@ const result = await query(config, view, options)
412
425
  // }
413
426
  ```
414
427
 
428
+ Some notes on the keys. Use native js things for arrays keys, rather then strings. Eg
429
+
430
+ - ```{ startkey: ['ryan'], endkey: ['ryan', {}] }```
431
+ - ```{ startkey: [47, null], endkey: [48, null] }```
432
+ - ```{ startkey: [customerIdVar], endkey: [customerIdVar, {}] }```
433
+ - ```{ startkey: [teamId, userId, startTimestamp], endkey: [teamId, userId, endTimestamp] }```
434
+
435
+
436
+
415
437
  #### createQuery()
416
438
  Create a query builder to help construct view queries with a fluent interface. Note we have stuck to couch naming conventions and not camel case.
417
439
 
@@ -439,6 +461,11 @@ const options = createQuery()
439
461
  const result = await query(config, view, options)
440
462
  ```
441
463
 
464
+ Again, use js types for array keys
465
+
466
+ - ```.startkey([teamId, userId]).endkey([teamId, userId, {}])```
467
+ - ```.startkey([teamId, userId, startTimestamp]).endkey([teamId, userId, endTimestamp])```
468
+
442
469
  #### queryStream
443
470
 
444
471
  Use Cases *Streaming Data*
package/cjs/index.cjs CHANGED
@@ -86,13 +86,13 @@ const schema = {
86
86
  ChangesOptions: import_changes2.ChangesOptions,
87
87
  ChangesResponse: import_changes2.ChangesResponse
88
88
  };
89
- const bindConfig = import_bind.Bind.implement((config) => {
89
+ function doBind(config) {
90
90
  const retryOptions = {
91
91
  maxRetries: config.maxRetries ?? 10,
92
92
  initialDelay: config.initialDelay ?? 1e3,
93
93
  backoffFactor: config.backoffFactor ?? 2
94
94
  };
95
- return {
95
+ const result = {
96
96
  get: config.bindWithRetry ? (0, import_retry.withRetry)(import_crud.get.bind(null, config), retryOptions) : import_crud.get.bind(null, config),
97
97
  getAtRev: config.bindWithRetry ? (0, import_retry.withRetry)(import_crud.getAtRev.bind(null, config), retryOptions) : import_crud.getAtRev.bind(null, config),
98
98
  put: config.bindWithRetry ? (0, import_retry.withRetry)(import_crud.put.bind(null, config), retryOptions) : import_crud.put.bind(null, config),
@@ -112,4 +112,15 @@ const bindConfig = import_bind.Bind.implement((config) => {
112
112
  watchDocs: import_watch.watchDocs.bind(null, config),
113
113
  changes: import_changes.changes.bind(null, config)
114
114
  };
115
+ return result;
116
+ }
117
+ const bindConfig = import_bind.Bind.implement((config) => {
118
+ const parsedConfig = import_config.CouchConfig.parse(config);
119
+ const funcs = doBind(parsedConfig);
120
+ const reconfig = (_overrides) => {
121
+ const newConfig = { ...config, ..._overrides };
122
+ return bindConfig(newConfig);
123
+ };
124
+ const all = { ...funcs, options: reconfig };
125
+ return all;
115
126
  });
@@ -18,7 +18,9 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var bind_exports = {};
20
20
  __export(bind_exports, {
21
- Bind: () => Bind
21
+ Bind: () => Bind,
22
+ BindBase: () => BindBase,
23
+ BindReturns: () => BindReturns
22
24
  });
23
25
  module.exports = __toCommonJS(bind_exports);
24
26
  var import_zod = require("zod");
@@ -31,7 +33,7 @@ var import_stream = require("./stream.cjs");
31
33
  var import_lock = require("./sugar/lock.cjs");
32
34
  var import_changes = require("./changes.cjs");
33
35
  var import_watch = require("./sugar/watch.cjs");
34
- const BindReturns = import_zod.z.object({
36
+ const BindBase = import_zod.z.object({
35
37
  bulkGet: import_bulk.BulkGetBound,
36
38
  bulkSave: import_bulk.BulkSaveBound,
37
39
  bulkRemove: import_bulk.BulkRemoveBound,
@@ -48,4 +50,8 @@ const BindReturns = import_zod.z.object({
48
50
  changes: import_changes.ChangesBound,
49
51
  watchDocs: import_watch.WatchDocsBound
50
52
  });
53
+ const RebindOptions = import_config.CouchConfig.omit({ couch: true });
54
+ const BindReturns = BindBase.extend({
55
+ options: import_zod.z.function().args(RebindOptions).returns(BindBase)
56
+ });
51
57
  const Bind = import_zod.z.function().args(import_config.CouchConfig).returns(BindReturns);
package/impl/retry.mjs CHANGED
@@ -1,39 +1,49 @@
1
1
  import { RetryableError } from './errors.mjs'
2
2
  import { sleep } from './patch.mjs'
3
3
 
4
+ /**
5
+ * Wraps a function with retry logic for RetryableError instances
6
+ * @param {Function} fn - The function to retry
7
+ * @param {Object} options - Retry options
8
+ * @param {number} [options.maxRetries=3] - Maximum number of retry attempts
9
+ * @param {number} [options.initialDelay=1000] - Initial delay in ms
10
+ * @param {number} [options.backoffFactor=2] - Multiplier for exponential backoff
11
+ * @param {number} [options.maxDelay] - Maximum delay between retries in ms
12
+ * @returns {Function} - Wrapped function with retry logic
13
+ */
4
14
  export function withRetry (fn, options = {}) {
5
15
  const {
6
16
  maxRetries = 3,
7
17
  initialDelay = 1000, // 1 second
8
- backoffFactor = 2 // exponential backoff multiplier
18
+ backoffFactor = 2, // exponential backoff multiplier
19
+ maxDelay = 30000 // 30 seconds max delay
9
20
  } = options
10
21
 
11
22
  return async (...args) => {
12
- let lastError
13
23
  let delay = initialDelay
14
24
 
15
25
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
16
26
  try {
17
- return await fn(...args)
27
+ // Clear any references to previous attempts
28
+ const result = await fn(...args)
29
+ return result
18
30
  } catch (error) {
19
- lastError = error
20
-
21
31
  // Only retry if it's a RetryableError
22
32
  if (!(error instanceof RetryableError)) {
23
33
  throw error
24
34
  }
25
35
 
26
- // If we've used all retries, throw the last error
36
+ // If we've used all retries, throw the error
27
37
  if (attempt === maxRetries) {
28
38
  throw error
29
39
  }
30
40
 
41
+ // Calculate next delay with a maximum cap
42
+ const nextDelay = Math.min(delay, maxDelay)
31
43
  // Wait with exponential backoff
32
- await sleep(delay)
44
+ await sleep(nextDelay)
33
45
  delay *= backoffFactor
34
46
  }
35
47
  }
36
-
37
- throw lastError
38
48
  }
39
49
  }
package/index.d.mts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["index.mjs"],"names":[],"mappings":"oBAEmC,iBAAiB;yBAAjB,iBAAiB;oBAAjB,iBAAiB;wBADkC,iBAAiB;yBAAjB,iBAAiB;sBAMjF,kBAAkB;4BACZ,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAJP,kBAAkB;iCAAlB,kBAAkB;2BAH4B,iBAAiB;kCAAjB,iBAAiB;oCAAjB,iBAAiB;AAkDvG,uDAAuD;AACvD,yBADY,OAAO,mBAAmB,EAAE,UAAU,CA+BhD;0BAxEwB,kBAAkB;4BADhB,yBAAyB;2BAJd,uBAAuB;2BAAvB,uBAAuB;4BAOlC,qBAAqB;gCACQ,oBAAoB;wCAApB,oBAAoB;sCAEhC,qBAAqB;sBAArB,qBAAqB;yBAJoB,mBAAmB;wBAAnB,mBAAmB;2BAAnB,mBAAmB;kCAAnB,mBAAmB;oCAAnB,mBAAmB;yBAQ3B,mBAAmB;yBAAnB,mBAAmB;yBAAnB,mBAAmB;iCAAnB,mBAAmB;sBAHzD,oBAAoB;iCAApB,oBAAoB;8BAGkB,mBAAmB;qBAC5E,mBAAmB;qBAHkB,yBAAyB;0BACzD,0BAA0B;4BADM,yBAAyB;2BAAzB,yBAAyB;2BAAzB,yBAAyB;wBAH1B,sBAAsB;+BAAtB,sBAAsB;gCAAtB,sBAAsB"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["index.mjs"],"names":[],"mappings":"oBAEmC,iBAAiB;yBAAjB,iBAAiB;oBAAjB,iBAAiB;wBADkC,iBAAiB;yBAAjB,iBAAiB;sBAMjF,kBAAkB;4BACZ,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAJP,kBAAkB;iCAAlB,kBAAkB;2BAH4B,iBAAiB;kCAAjB,iBAAiB;oCAAjB,iBAAiB;AAoFvG,uDAAuD;AACvD,yBADY,OAAO,mBAAmB,EAAE,UAAU,CAuBhD;0BAlGwB,kBAAkB;4BADhB,yBAAyB;2BAJd,uBAAuB;2BAAvB,uBAAuB;4BAOlC,qBAAqB;gCACQ,oBAAoB;wCAApB,oBAAoB;sCAEhC,qBAAqB;sBAArB,qBAAqB;yBAJoB,mBAAmB;wBAAnB,mBAAmB;2BAAnB,mBAAmB;kCAAnB,mBAAmB;oCAAnB,mBAAmB;yBAQ3B,mBAAmB;yBAAnB,mBAAmB;yBAAnB,mBAAmB;iCAAnB,mBAAmB;sBAHzD,oBAAoB;iCAApB,oBAAoB;8BAGkB,mBAAmB;qBAC5E,mBAAmB;qBAHkB,yBAAyB;0BACzD,0BAA0B;4BADM,yBAAyB;2BAAzB,yBAAyB;2BAAzB,yBAAyB;wBAH1B,sBAAsB;+BAAtB,sBAAsB;gCAAtB,sBAAsB"}
package/index.mjs CHANGED
@@ -48,12 +48,10 @@ const schema = {
48
48
  ChangesOptions,
49
49
  ChangesResponse
50
50
  }
51
-
52
- /** @type { import('./schema/bind.mjs').BindSchema } */
53
- const bindConfig = Bind.implement((
54
- /** @type { import('./schema/config.mjs').CouchConfigSchema } */
55
- config
56
- ) => {
51
+ /**
52
+ * @param {import('./schema/config.mjs').CouchConfigSchema } config
53
+ */
54
+ function doBind (config) {
57
55
  // Default retry options
58
56
  const retryOptions = {
59
57
  maxRetries: config.maxRetries ?? 10,
@@ -61,7 +59,8 @@ const bindConfig = Bind.implement((
61
59
  backoffFactor: config.backoffFactor ?? 2
62
60
  }
63
61
 
64
- return {
62
+ // Create the object without the config property first
63
+ const result = {
65
64
  get: config.bindWithRetry ? withRetry(get.bind(null, config), retryOptions) : get.bind(null, config),
66
65
  getAtRev: config.bindWithRetry ? withRetry(getAtRev.bind(null, config), retryOptions) : getAtRev.bind(null, config),
67
66
  put: config.bindWithRetry ? withRetry(put.bind(null, config), retryOptions) : put.bind(null, config),
@@ -80,6 +79,33 @@ const bindConfig = Bind.implement((
80
79
  watchDocs: watchDocs.bind(null, config),
81
80
  changes: changes.bind(null, config)
82
81
  }
82
+
83
+ return result
84
+ }
85
+
86
+ /** @type { import('./schema/bind.mjs').BindSchema } */
87
+ const bindConfig = Bind.implement((
88
+ /** @type { import('./schema/config.mjs').CouchConfigSchema } */
89
+ config
90
+ ) => {
91
+ const parsedConfig = CouchConfig.parse(config)
92
+
93
+ /** @type { import('./schema/bind.mjs').BindBaseSchema } funcs */
94
+ const funcs = doBind(parsedConfig)
95
+
96
+ // Add the options function that returns a new bound instance
97
+ // this allows the user to override some options
98
+ const reconfig = (
99
+ /** @type any */
100
+ _overrides
101
+ ) => {
102
+ // override the config and return doBind again
103
+ const newConfig = { ...config, ..._overrides }
104
+ return bindConfig(newConfig)
105
+ }
106
+ /** @type { import('./schema/bind.mjs').BindReturnsSchema } */
107
+ const all = { ...funcs, options: reconfig }
108
+ return all
83
109
  })
84
110
 
85
111
  export {
package/log.txt ADDED
@@ -0,0 +1,43 @@
1
+ [Wed, 12 Mar 2025 14:28:53 GMT] [info] [<0.000.0>] pouchdb-server has started on http://127.0.0.1:8985/
2
+ [Wed, 12 Mar 2025 14:28:53 GMT] [info] [<0.000.0>] database is in-memory; no changes will be saved.
3
+ [Wed, 12 Mar 2025 14:28:53 GMT] [info] [<0.000.0>] navigate to http://127.0.0.1:8985/_utils for the Fauxton UI.
4
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb 201
5
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/testdoc 201
6
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc 200
7
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc-not-there 404
8
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc-not-there-override 404
9
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/testdoc-not-there 404
10
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/notThereDoc 409
11
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
12
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda 201
13
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
14
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
15
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda 201
16
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-1 201
17
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
18
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-2 201
19
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
20
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
21
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-2 201
22
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-3 201
23
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
24
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/a 201
25
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
26
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_bulk_docs 201
27
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:fsda-3 201
28
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
29
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/conflict-test 201
30
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:conflict-error 201
31
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
32
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/txn:bulk-error 201
33
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - POST /testdb/_all_docs?include_docs=true 200
34
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
35
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
36
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 409
37
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
38
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
39
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 404
40
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - PUT /testdb/lock-doc-to-lock 201
41
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
42
+ [Wed, 12 Mar 2025 14:28:54 GMT] [info] [<0.000.0>] 127.0.0.1 - - GET /testdb/lock-doc-to-lock 200
43
+ [Wed, 12 Mar 2025 14:28: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.5",
3
+ "version": "5.1.1",
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",
@@ -57,4 +57,4 @@
57
57
  "node": "20.17.0",
58
58
  "npm": "10.8.2"
59
59
  }
60
- }
60
+ }