hide-a-bed 7.1.0 → 7.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 +148 -156
- package/impl/bindConfig.mts +62 -69
- package/impl/headDB.mts +28 -28
- package/impl/utils/errors.mts +159 -189
- package/impl/utils/fetch.mts +94 -102
- package/index.mts +42 -55
- package/package.json +2 -2
- package/types/output/impl/bindConfig.d.mts +15 -15
- package/types/output/impl/bindConfig.d.mts.map +1 -1
- package/types/output/impl/headDB.d.mts +1 -1
- package/types/output/impl/headDB.d.mts.map +1 -1
- 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 -35
- package/types/output/index.d.mts.map +1 -1
package/impl/bindConfig.mts
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
1
|
// oxlint-disable typescript/no-explicit-any
|
|
2
|
-
import type z from
|
|
3
|
-
import { CouchConfig, type CouchConfigInput } from
|
|
4
|
-
import { withRetry } from
|
|
2
|
+
import type z from 'zod'
|
|
3
|
+
import { CouchConfig, type CouchConfigInput } from '../schema/config.mts'
|
|
4
|
+
import { withRetry } from './retry.mts'
|
|
5
5
|
import {
|
|
6
6
|
type BulkGetBound,
|
|
7
7
|
bulkGet,
|
|
8
8
|
type BulkGetDictionaryBound,
|
|
9
|
-
bulkGetDictionary
|
|
10
|
-
} from
|
|
11
|
-
import { type GetBound, type GetAtRevBound, getAtRev, get } from
|
|
12
|
-
import { queryStream } from
|
|
13
|
-
import { patch, patchDangerously } from
|
|
14
|
-
import { put } from
|
|
15
|
-
import type { QueryBound } from
|
|
16
|
-
import { query } from
|
|
17
|
-
import { bulkRemove, bulkRemoveMap } from
|
|
18
|
-
import { bulkSave, bulkSaveTransaction } from
|
|
19
|
-
import { getDBInfo } from
|
|
20
|
-
import { headDB } from
|
|
21
|
-
import { remove } from
|
|
22
|
-
import { createLock, removeLock } from
|
|
23
|
-
import { watchDocs } from
|
|
9
|
+
bulkGetDictionary
|
|
10
|
+
} from './bulkGet.mts'
|
|
11
|
+
import { type GetBound, type GetAtRevBound, getAtRev, get } from './get.mts'
|
|
12
|
+
import { queryStream } from './stream.mts'
|
|
13
|
+
import { patch, patchDangerously } from './patch.mts'
|
|
14
|
+
import { put } from './put.mts'
|
|
15
|
+
import type { QueryBound } from './query.mts'
|
|
16
|
+
import { query } from './query.mts'
|
|
17
|
+
import { bulkRemove, bulkRemoveMap } from './bulkRemove.mts'
|
|
18
|
+
import { bulkSave, bulkSaveTransaction } from './bulkSave.mts'
|
|
19
|
+
import { getDBInfo } from './getDBInfo.mts'
|
|
20
|
+
import { headDB } from './headDB.mts'
|
|
21
|
+
import { remove } from './remove.mts'
|
|
22
|
+
import { createLock, removeLock } from './sugar/lock.mts'
|
|
23
|
+
import { watchDocs } from './sugar/watch.mts'
|
|
24
24
|
|
|
25
25
|
type BoundConfigMethod<T> = T extends (...args: infer Args) => infer Result
|
|
26
26
|
? Args extends [unknown, ...infer Rest]
|
|
27
27
|
? (...args: Rest) => Result
|
|
28
28
|
: never
|
|
29
|
-
: never
|
|
29
|
+
: never
|
|
30
30
|
|
|
31
31
|
type BoundMethods = {
|
|
32
|
-
bulkGet: BulkGetBound
|
|
33
|
-
bulkGetDictionary: BulkGetDictionaryBound
|
|
34
|
-
get: GetBound
|
|
35
|
-
getAtRev: GetAtRevBound
|
|
36
|
-
query: QueryBound
|
|
37
|
-
bulkRemove: BoundConfigMethod<typeof bulkRemove
|
|
38
|
-
bulkRemoveMap: BoundConfigMethod<typeof bulkRemoveMap
|
|
39
|
-
bulkSave: BoundConfigMethod<typeof bulkSave
|
|
40
|
-
bulkSaveTransaction: BoundConfigMethod<typeof bulkSaveTransaction
|
|
41
|
-
getDBInfo: BoundConfigMethod<typeof getDBInfo
|
|
42
|
-
headDB: BoundConfigMethod<typeof headDB
|
|
43
|
-
patch: BoundConfigMethod<typeof patch
|
|
44
|
-
patchDangerously: BoundConfigMethod<typeof patchDangerously
|
|
45
|
-
put: BoundConfigMethod<typeof put
|
|
46
|
-
queryStream: BoundConfigMethod<typeof queryStream
|
|
47
|
-
remove: BoundConfigMethod<typeof remove
|
|
48
|
-
createLock: BoundConfigMethod<typeof createLock
|
|
49
|
-
removeLock: BoundConfigMethod<typeof removeLock
|
|
50
|
-
watchDocs: BoundConfigMethod<typeof watchDocs
|
|
51
|
-
}
|
|
32
|
+
bulkGet: BulkGetBound
|
|
33
|
+
bulkGetDictionary: BulkGetDictionaryBound
|
|
34
|
+
get: GetBound
|
|
35
|
+
getAtRev: GetAtRevBound
|
|
36
|
+
query: QueryBound
|
|
37
|
+
bulkRemove: BoundConfigMethod<typeof bulkRemove>
|
|
38
|
+
bulkRemoveMap: BoundConfigMethod<typeof bulkRemoveMap>
|
|
39
|
+
bulkSave: BoundConfigMethod<typeof bulkSave>
|
|
40
|
+
bulkSaveTransaction: BoundConfigMethod<typeof bulkSaveTransaction>
|
|
41
|
+
getDBInfo: BoundConfigMethod<typeof getDBInfo>
|
|
42
|
+
headDB: BoundConfigMethod<typeof headDB>
|
|
43
|
+
patch: BoundConfigMethod<typeof patch>
|
|
44
|
+
patchDangerously: BoundConfigMethod<typeof patchDangerously>
|
|
45
|
+
put: BoundConfigMethod<typeof put>
|
|
46
|
+
queryStream: BoundConfigMethod<typeof queryStream>
|
|
47
|
+
remove: BoundConfigMethod<typeof remove>
|
|
48
|
+
createLock: BoundConfigMethod<typeof createLock>
|
|
49
|
+
removeLock: BoundConfigMethod<typeof removeLock>
|
|
50
|
+
watchDocs: BoundConfigMethod<typeof watchDocs>
|
|
51
|
+
}
|
|
52
52
|
|
|
53
53
|
export type BoundInstance = BoundMethods & {
|
|
54
|
-
options(overrides: Partial<z.input<typeof CouchConfig>>): BoundInstance
|
|
55
|
-
}
|
|
54
|
+
options(overrides: Partial<z.input<typeof CouchConfig>>): BoundInstance
|
|
55
|
+
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
58
|
* Build a validated binding that exposes CouchDB helpers plus an options() helper for overrides.
|
|
@@ -60,22 +60,20 @@ export type BoundInstance = BoundMethods & {
|
|
|
60
60
|
* @returns A bound instance with CouchDB operations and an options() method for overrides
|
|
61
61
|
*/
|
|
62
62
|
export const bindConfig = (config: CouchConfigInput): BoundInstance => {
|
|
63
|
-
const parsedConfig = CouchConfig.parse(config)
|
|
63
|
+
const parsedConfig = CouchConfig.parse(config)
|
|
64
64
|
|
|
65
|
-
const funcs = doBind(parsedConfig)
|
|
65
|
+
const funcs = doBind(parsedConfig)
|
|
66
66
|
|
|
67
67
|
// Add the options function that returns a new bound instance
|
|
68
68
|
// this allows the user to override some options
|
|
69
|
-
const reconfigure: BoundInstance[
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return bindConfig(newConfig);
|
|
74
|
-
};
|
|
69
|
+
const reconfigure: BoundInstance['options'] = (overrides: Partial<CouchConfigInput>) => {
|
|
70
|
+
const newConfig: z.input<typeof CouchConfig> = { ...config, ...overrides }
|
|
71
|
+
return bindConfig(newConfig)
|
|
72
|
+
}
|
|
75
73
|
|
|
76
|
-
const bound: BoundInstance = { ...funcs, options: reconfigure }
|
|
77
|
-
return bound
|
|
78
|
-
}
|
|
74
|
+
const bound: BoundInstance = { ...funcs, options: reconfigure }
|
|
75
|
+
return bound
|
|
76
|
+
}
|
|
79
77
|
|
|
80
78
|
/**
|
|
81
79
|
* @internal
|
|
@@ -86,21 +84,19 @@ export const bindConfig = (config: CouchConfigInput): BoundInstance => {
|
|
|
86
84
|
* @param config The CouchDB configuration
|
|
87
85
|
* @returns The bound function, possibly wrapped with retry logic
|
|
88
86
|
*/
|
|
89
|
-
export function getBoundWithRetry<
|
|
90
|
-
TBound extends (...args: any[]) => Promise<any>,
|
|
91
|
-
>(
|
|
87
|
+
export function getBoundWithRetry<TBound extends (...args: any[]) => Promise<any>>(
|
|
92
88
|
func: (config: CouchConfig, ...args: any[]) => Promise<any>,
|
|
93
|
-
config: CouchConfig
|
|
89
|
+
config: CouchConfig
|
|
94
90
|
) {
|
|
95
|
-
const bound = func.bind(null, config)
|
|
91
|
+
const bound = func.bind(null, config)
|
|
96
92
|
if (config.bindWithRetry) {
|
|
97
93
|
return withRetry(bound, {
|
|
98
94
|
maxRetries: config.maxRetries ?? 10,
|
|
99
95
|
initialDelay: config.initialDelay ?? 1000,
|
|
100
|
-
backoffFactor: config.backoffFactor ?? 2
|
|
101
|
-
}) as TBound
|
|
96
|
+
backoffFactor: config.backoffFactor ?? 2
|
|
97
|
+
}) as TBound
|
|
102
98
|
} else {
|
|
103
|
-
return bound as TBound
|
|
99
|
+
return bound as TBound
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
102
|
|
|
@@ -116,8 +112,8 @@ function doBind(config: CouchConfig): BoundMethods {
|
|
|
116
112
|
const retryOptions = {
|
|
117
113
|
maxRetries: config.maxRetries ?? 10,
|
|
118
114
|
initialDelay: config.initialDelay ?? 1000,
|
|
119
|
-
backoffFactor: config.backoffFactor ?? 2
|
|
120
|
-
}
|
|
115
|
+
backoffFactor: config.backoffFactor ?? 2
|
|
116
|
+
}
|
|
121
117
|
|
|
122
118
|
// Create the object without the config property first
|
|
123
119
|
const result: BoundMethods = {
|
|
@@ -126,10 +122,7 @@ function doBind(config: CouchConfig): BoundMethods {
|
|
|
126
122
|
* To preserve the overloads we need dedicated Bound types
|
|
127
123
|
*/
|
|
128
124
|
bulkGet: getBoundWithRetry<BulkGetBound>(bulkGet, config),
|
|
129
|
-
bulkGetDictionary: getBoundWithRetry<BulkGetDictionaryBound>(
|
|
130
|
-
bulkGetDictionary,
|
|
131
|
-
config,
|
|
132
|
-
),
|
|
125
|
+
bulkGetDictionary: getBoundWithRetry<BulkGetDictionaryBound>(bulkGetDictionary, config),
|
|
133
126
|
get: getBoundWithRetry<GetBound>(get, config),
|
|
134
127
|
getAtRev: getBoundWithRetry<GetAtRevBound>(getAtRev, config),
|
|
135
128
|
query: getBoundWithRetry<QueryBound>(query, config),
|
|
@@ -169,8 +162,8 @@ function doBind(config: CouchConfig): BoundMethods {
|
|
|
169
162
|
|
|
170
163
|
createLock: createLock.bind(null, config),
|
|
171
164
|
removeLock: removeLock.bind(null, config),
|
|
172
|
-
watchDocs: watchDocs.bind(null, config)
|
|
173
|
-
}
|
|
165
|
+
watchDocs: watchDocs.bind(null, config)
|
|
166
|
+
}
|
|
174
167
|
|
|
175
|
-
return result
|
|
168
|
+
return result
|
|
176
169
|
}
|
package/impl/headDB.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { RetryableError, createResponseError } from
|
|
2
|
-
import { createLogger } from
|
|
3
|
-
import { CouchConfig, type CouchConfigInput } from
|
|
4
|
-
import { fetchCouchJson } from
|
|
5
|
-
import { isSuccessStatusCode } from
|
|
6
|
-
import { createCouchDbUrl } from
|
|
1
|
+
import { RetryableError, createResponseError } from './utils/errors.mts'
|
|
2
|
+
import { createLogger } from './utils/logger.mts'
|
|
3
|
+
import { CouchConfig, type CouchConfigInput } from '../schema/config.mts'
|
|
4
|
+
import { fetchCouchJson } from './utils/fetch.mts'
|
|
5
|
+
import { isSuccessStatusCode } from './utils/response.mts'
|
|
6
|
+
import { createCouchDbUrl } from './utils/url.mts'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Performs a health check against the target CouchDB database using `HEAD /{db}`.
|
|
@@ -16,40 +16,40 @@ import { createCouchDbUrl } from "./utils/url.mts";
|
|
|
16
16
|
* @throws {OperationError} For other non-retryable response failures.
|
|
17
17
|
*/
|
|
18
18
|
export const headDB = async (configInput: CouchConfigInput): Promise<true> => {
|
|
19
|
-
const config = CouchConfig.parse(configInput)
|
|
20
|
-
const logger = createLogger(config)
|
|
21
|
-
const url = createCouchDbUrl(config.couch)
|
|
19
|
+
const config = CouchConfig.parse(configInput)
|
|
20
|
+
const logger = createLogger(config)
|
|
21
|
+
const url = createCouchDbUrl(config.couch)
|
|
22
22
|
|
|
23
|
-
let resp
|
|
23
|
+
let resp
|
|
24
24
|
try {
|
|
25
25
|
resp = await fetchCouchJson({
|
|
26
26
|
auth: config.auth,
|
|
27
|
-
method:
|
|
28
|
-
operation:
|
|
27
|
+
method: 'HEAD',
|
|
28
|
+
operation: 'headDB',
|
|
29
29
|
request: config.request,
|
|
30
|
-
url
|
|
31
|
-
})
|
|
30
|
+
url
|
|
31
|
+
})
|
|
32
32
|
|
|
33
|
-
if (!isSuccessStatusCode(
|
|
34
|
-
logger.error(`Non-success status code received: ${resp.statusCode}`)
|
|
33
|
+
if (!isSuccessStatusCode('database', resp.statusCode)) {
|
|
34
|
+
logger.error(`Non-success status code received: ${resp.statusCode}`)
|
|
35
35
|
throw createResponseError({
|
|
36
36
|
body: resp.body,
|
|
37
|
-
defaultMessage:
|
|
38
|
-
operation:
|
|
39
|
-
statusCode: resp.statusCode
|
|
40
|
-
})
|
|
37
|
+
defaultMessage: 'Database health check failed',
|
|
38
|
+
operation: 'headDB',
|
|
39
|
+
statusCode: resp.statusCode
|
|
40
|
+
})
|
|
41
41
|
}
|
|
42
42
|
} catch (err) {
|
|
43
|
-
logger.error(
|
|
44
|
-
RetryableError.handleNetworkError(err,
|
|
43
|
+
logger.error('Error during head operation:', err)
|
|
44
|
+
RetryableError.handleNetworkError(err, 'headDB')
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
if (!resp) {
|
|
48
|
-
logger.error(
|
|
49
|
-
throw new RetryableError(
|
|
50
|
-
operation:
|
|
51
|
-
})
|
|
48
|
+
logger.error('No response received from head request')
|
|
49
|
+
throw new RetryableError('Database health check failed', 503, {
|
|
50
|
+
operation: 'headDB'
|
|
51
|
+
})
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
return true
|
|
55
|
-
}
|
|
54
|
+
return true
|
|
55
|
+
}
|