hanzio 1.1.0 → 2.0.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 +832 -219
- package/dist/api-wrapper/builders.d.ts +15 -3
- package/dist/api-wrapper/create-client.d.ts +1 -1
- package/dist/api-wrapper/describe.d.ts +16 -0
- package/dist/api-wrapper/endpoint.d.ts +18 -0
- package/dist/api-wrapper/errors.d.ts +40 -2
- package/dist/api-wrapper/headers.d.ts +2 -1
- package/dist/api-wrapper/index.d.ts +5 -0
- package/dist/api-wrapper/otel.d.ts +44 -0
- package/dist/api-wrapper/paginate.d.ts +12 -0
- package/dist/api-wrapper/redaction.d.ts +2 -0
- package/dist/api-wrapper/shared.d.ts +16 -2
- package/dist/api-wrapper/testing.d.ts +23 -0
- package/dist/api-wrapper/transport.d.ts +12 -10
- package/dist/api-wrapper/types.d.ts +104 -18
- package/dist/array/index.d.ts +50 -4
- package/dist/cache/createCache.d.ts +31 -0
- package/dist/cache/index.d.ts +45 -2
- package/dist/color/contrast.d.ts +40 -0
- package/dist/color/index.d.ts +2 -0
- package/dist/{math → color}/metricsSeriesColors.d.ts +14 -7
- package/dist/cool-console-log/index.d.ts +34 -5
- package/dist/crypto/encoding.d.ts +18 -0
- package/dist/crypto/hash.d.ts +33 -0
- package/dist/crypto/index.d.ts +4 -0
- package/dist/crypto/sealer.d.ts +25 -0
- package/dist/crypto/webhook.d.ts +20 -0
- package/dist/date/index.d.ts +46 -2
- package/dist/emitter/index.d.ts +21 -0
- package/dist/error/index.d.ts +12 -0
- package/dist/format/index.d.ts +102 -0
- package/dist/function/index.d.ts +60 -0
- package/dist/guard/index.d.ts +20 -0
- package/dist/i18n/index.d.ts +37 -0
- package/dist/index-0zvtcbzy.js +224 -0
- package/dist/index-181e6vfw.js +29 -0
- package/dist/index-8r2vdzjg.js +87 -0
- package/dist/index-hy7kbb99.js +157 -0
- package/dist/{src/secrets/loaders.js → index-j1ybktbr.js} +608 -405
- package/dist/index-k9yx6bne.js +89 -0
- package/dist/index-kj1phgrx.js +169 -0
- package/dist/index-mnkcfyx8.js +78 -0
- package/dist/{p-queue/index.js → index-pwt0dz63.js} +7 -11
- package/dist/index-rp5pqghz.js +157 -0
- package/dist/index-srt06xd2.js +15 -0
- package/dist/index-wjyb9bsd.js +263 -0
- package/dist/index.d.ts +7 -7
- package/dist/jwt/index.d.ts +50 -2
- package/dist/math/index.d.ts +2 -2
- package/dist/math/linearRegressionTrend.d.ts +14 -1
- package/dist/math/scale.d.ts +8 -0
- package/dist/object/index.d.ts +19 -0
- package/dist/p-queue/index.d.ts +1 -1
- package/dist/promise/index.d.ts +97 -2
- package/dist/secrets/core.d.ts +47 -0
- package/dist/secrets/deadline.d.ts +6 -0
- package/dist/secrets/environment.d.ts +9 -0
- package/dist/secrets/errors.d.ts +11 -0
- package/dist/secrets/index.d.ts +13 -25
- package/dist/secrets/infisical-cli.d.ts +6 -0
- package/dist/secrets/infisical-config.d.ts +17 -0
- package/dist/secrets/infisical-session.d.ts +4 -0
- package/dist/secrets/infisical.d.ts +8 -13
- package/dist/secrets/loaders.d.ts +5 -12
- package/dist/secrets/vite.d.ts +7 -3
- package/dist/secrets/worker-loader.d.ts +9 -0
- package/dist/secrets/worker.d.ts +3 -0
- package/dist/sitemap/index.d.ts +48 -6
- package/dist/src/api-wrapper/index.js +60 -1100
- package/dist/src/api-wrapper/testing.js +20 -0
- package/dist/{cool-console-log → src/cool-console-log}/index.js +80 -33
- package/dist/src/crypto/index.js +195 -0
- package/dist/src/format/index.js +211 -0
- package/dist/src/i18n/index.js +36 -0
- package/dist/src/index.js +863 -2809
- package/dist/src/jwt/index.js +138 -92
- package/dist/src/p-queue/index.js +9 -437
- package/dist/src/secrets/index.js +261 -1377
- package/dist/src/secrets/vite.js +6 -17
- package/dist/src/secrets/worker.js +12 -0
- package/dist/src/sitemap/index.js +183 -511
- package/dist/src/storage/index.js +119 -0
- package/dist/src/zod/index.js +347 -174
- package/dist/state/index.d.ts +21 -0
- package/dist/storage/index.d.ts +58 -0
- package/dist/string/index.d.ts +75 -2
- package/dist/typedswitch/index.d.ts +37 -26
- package/dist/types/index.d.ts +11 -0
- package/dist/url/index.d.ts +50 -1
- package/dist/zod/index.d.ts +32 -3
- package/dist/zod/introspect.d.ts +19 -0
- package/dist/zod/jsonToZodSchemaMapper.d.ts +3 -1
- package/dist/zod/zodMinMaxFilter.d.ts +22 -3
- package/dist/zod/zodToTypeString.d.ts +8 -3
- package/package.json +87 -7
- package/src/api-wrapper/actions-impl.ts +11 -72
- package/src/api-wrapper/builders.ts +84 -52
- package/src/api-wrapper/create-client.ts +246 -96
- package/src/api-wrapper/describe.ts +157 -0
- package/src/api-wrapper/endpoint.ts +26 -0
- package/src/api-wrapper/error-reporting.ts +7 -1
- package/src/api-wrapper/errors.ts +117 -2
- package/src/api-wrapper/headers.ts +19 -1
- package/src/api-wrapper/index.ts +5 -0
- package/src/api-wrapper/otel.ts +139 -0
- package/src/api-wrapper/paginate.ts +28 -0
- package/src/api-wrapper/redaction.ts +43 -0
- package/src/api-wrapper/shared.ts +21 -2
- package/src/api-wrapper/testing.ts +48 -0
- package/src/api-wrapper/transport.ts +68 -74
- package/src/api-wrapper/types.ts +186 -18
- package/src/array/index.ts +195 -42
- package/src/cache/createCache.ts +157 -0
- package/src/cache/index.ts +235 -83
- package/src/color/contrast.ts +163 -0
- package/src/color/index.ts +22 -0
- package/src/{math → color}/metricsSeriesColors.ts +47 -49
- package/src/cool-console-log/index.ts +128 -41
- package/src/crypto/encoding.ts +83 -0
- package/src/crypto/hash.ts +170 -0
- package/src/crypto/index.ts +26 -0
- package/src/crypto/sealer.ts +168 -0
- package/src/crypto/webhook.ts +86 -0
- package/src/date/index.ts +109 -34
- package/src/emitter/index.ts +82 -0
- package/src/error/index.ts +63 -0
- package/src/format/index.ts +389 -0
- package/src/function/index.ts +201 -0
- package/src/guard/index.ts +80 -0
- package/src/i18n/index.ts +125 -0
- package/src/index.ts +11 -7
- package/src/jwt/index.ts +199 -125
- package/src/math/index.ts +5 -10
- package/src/math/linearRegressionTrend.ts +33 -8
- package/src/math/scale.ts +17 -0
- package/src/object/index.ts +99 -0
- package/src/p-queue/index.ts +2 -0
- package/src/promise/index.ts +304 -9
- package/src/secrets/core.ts +348 -0
- package/src/secrets/deadline.ts +69 -0
- package/src/secrets/environment.ts +69 -0
- package/src/secrets/errors.ts +29 -0
- package/src/secrets/index.ts +79 -210
- package/src/secrets/infisical-cli.ts +99 -0
- package/src/secrets/infisical-config.ts +70 -0
- package/src/secrets/infisical-session.ts +42 -0
- package/src/secrets/infisical.ts +214 -66
- package/src/secrets/loaders.ts +24 -48
- package/src/secrets/vite.ts +44 -15
- package/src/secrets/worker-loader.ts +56 -0
- package/src/secrets/worker.ts +4 -0
- package/src/sitemap/index.ts +293 -130
- package/src/state/index.ts +133 -81
- package/src/storage/index.ts +187 -0
- package/src/string/index.ts +261 -23
- package/src/typedswitch/index.ts +134 -103
- package/src/types/index.ts +14 -0
- package/src/url/index.ts +146 -1
- package/src/zod/index.ts +105 -9
- package/src/zod/introspect.ts +103 -0
- package/src/zod/jsonToZodSchemaMapper.ts +44 -21
- package/src/zod/zodMinMaxFilter.ts +37 -13
- package/src/zod/zodToTypeString.ts +184 -181
- package/dist/api-wrapper/index.js +0 -250
- package/dist/gzip/index.d.ts +0 -2
- package/dist/gzip/index.js +0 -16
- package/dist/index.js +0 -1823
- package/dist/jwt/index.js +0 -19
- package/dist/sitemap/index.js +0 -552
- package/dist/src/gzip/index.js +0 -16
- package/dist/src/secrets/infisical.js +0 -1194
- package/dist/zod/index.js +0 -210
|
@@ -1,80 +1,18 @@
|
|
|
1
|
+
import { createCache } from '../cache/createCache'
|
|
1
2
|
import type { ActionCache, DefineAction } from './types'
|
|
2
3
|
|
|
3
|
-
type CacheEntry = {
|
|
4
|
-
value?: unknown
|
|
5
|
-
hasValue: boolean
|
|
6
|
-
expiresAt?: number
|
|
7
|
-
inflight?: Promise<unknown>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
4
|
export function createActionCache(): ActionCache {
|
|
11
|
-
const store =
|
|
12
|
-
|
|
13
|
-
const isExpired = (entry: CacheEntry) =>
|
|
14
|
-
entry.expiresAt !== undefined && entry.expiresAt <= Date.now()
|
|
15
|
-
|
|
16
|
-
const cache = (async <T>(
|
|
5
|
+
const store = createCache()
|
|
6
|
+
const cache = (<T>(
|
|
17
7
|
key: string,
|
|
18
8
|
fn: () => Promise<T> | T,
|
|
19
9
|
options?: { ttlMs?: number }
|
|
20
|
-
): Promise<T> =>
|
|
21
|
-
const existing = store.get(key)
|
|
22
|
-
if (existing && !isExpired(existing)) {
|
|
23
|
-
if (existing.inflight) return existing.inflight as Promise<T>
|
|
24
|
-
if (existing.hasValue) return existing.value as T
|
|
25
|
-
}
|
|
10
|
+
): Promise<T> => store.getOrSet(key, fn, options)) as ActionCache
|
|
26
11
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
expiresAt:
|
|
32
|
-
options?.ttlMs !== undefined ? Date.now() + options.ttlMs : undefined
|
|
33
|
-
}
|
|
34
|
-
store.set(key, entry)
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
const value = await promise
|
|
38
|
-
entry.value = value
|
|
39
|
-
entry.hasValue = true
|
|
40
|
-
entry.inflight = undefined
|
|
41
|
-
return value
|
|
42
|
-
} catch (error) {
|
|
43
|
-
store.delete(key)
|
|
44
|
-
throw error
|
|
45
|
-
}
|
|
46
|
-
}) as ActionCache
|
|
47
|
-
|
|
48
|
-
cache.get = <T>(key: string): T | undefined => {
|
|
49
|
-
const entry = store.get(key)
|
|
50
|
-
if (!entry || !entry.hasValue) return undefined
|
|
51
|
-
if (isExpired(entry)) {
|
|
52
|
-
store.delete(key)
|
|
53
|
-
return undefined
|
|
54
|
-
}
|
|
55
|
-
return entry.value as T
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
cache.set = <T>(
|
|
59
|
-
key: string,
|
|
60
|
-
value: T,
|
|
61
|
-
options?: { ttlMs?: number }
|
|
62
|
-
): void => {
|
|
63
|
-
store.set(key, {
|
|
64
|
-
value,
|
|
65
|
-
hasValue: true,
|
|
66
|
-
expiresAt:
|
|
67
|
-
options?.ttlMs !== undefined ? Date.now() + options.ttlMs : undefined
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
cache.invalidate = (key: string): void => {
|
|
72
|
-
store.delete(key)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
cache.clear = (): void => {
|
|
76
|
-
store.clear()
|
|
77
|
-
}
|
|
12
|
+
cache.get = (key) => store.get(key)
|
|
13
|
+
cache.set = (key, value, options) => store.set(key, value, options)
|
|
14
|
+
cache.invalidate = (key) => store.delete(key)
|
|
15
|
+
cache.clear = () => store.clear()
|
|
78
16
|
|
|
79
17
|
return cache
|
|
80
18
|
}
|
|
@@ -87,10 +25,11 @@ export function makeDefineAction<TApi>(): DefineAction<TApi> {
|
|
|
87
25
|
noRuntimeInput: false as const
|
|
88
26
|
})
|
|
89
27
|
}
|
|
90
|
-
const def = args[0] as { handler: unknown }
|
|
28
|
+
const def = args[0] as { handler: unknown; input?: unknown }
|
|
91
29
|
return {
|
|
92
30
|
...def,
|
|
93
|
-
|
|
31
|
+
// A schema-validated action takes input; a bare handler doesn't.
|
|
32
|
+
noRuntimeInput: def.input === undefined
|
|
94
33
|
}
|
|
95
34
|
}
|
|
96
35
|
return defineAction as DefineAction<TApi>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ZodError } from 'zod'
|
|
2
|
+
import { buildQueryString } from '../url'
|
|
2
3
|
import { type ConfigError, RequestValidationError } from './errors'
|
|
3
4
|
import { normalizeHeaders } from './headers'
|
|
4
5
|
import type {
|
|
@@ -9,70 +10,88 @@ import type {
|
|
|
9
10
|
} from './shared'
|
|
10
11
|
import type { ApiEndpoint } from './types'
|
|
11
12
|
|
|
12
|
-
export
|
|
13
|
-
endpoint: ApiEndpoint
|
|
14
|
-
params: PathParams | undefined
|
|
15
|
-
|
|
16
|
-
baseApiUrls: Record<string, BaseApiUrl
|
|
17
|
-
defaultBaseApiUrl: string | undefined
|
|
18
|
-
url: string | undefined
|
|
13
|
+
export type BuildUrlOptions = {
|
|
14
|
+
endpoint: ApiEndpoint
|
|
15
|
+
params: PathParams | undefined
|
|
16
|
+
queryParams: QueryParams
|
|
17
|
+
baseApiUrls: Record<string, BaseApiUrl>
|
|
18
|
+
defaultBaseApiUrl: string | undefined
|
|
19
|
+
url: string | undefined
|
|
20
|
+
doNotEncodeQueryParams?: boolean
|
|
19
21
|
configError: (msg: string) => ConfigError
|
|
20
|
-
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function buildUrl(options: BuildUrlOptions) {
|
|
25
|
+
const {
|
|
26
|
+
endpoint,
|
|
27
|
+
params,
|
|
28
|
+
queryParams,
|
|
29
|
+
baseApiUrls,
|
|
30
|
+
defaultBaseApiUrl,
|
|
31
|
+
url,
|
|
32
|
+
doNotEncodeQueryParams,
|
|
33
|
+
configError
|
|
34
|
+
} = options
|
|
35
|
+
|
|
36
|
+
let finalUrl: string
|
|
21
37
|
if (url) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
finalUrl,
|
|
28
|
-
fullUrl: queryString ? `${finalUrl}?${queryString}` : finalUrl
|
|
38
|
+
finalUrl = replaceUrlPathParams(url, params, configError)
|
|
39
|
+
} else {
|
|
40
|
+
const defaultBaseUrl = defaultBaseApiUrl ?? Object.keys(baseApiUrls)[0]
|
|
41
|
+
if (!defaultBaseUrl) {
|
|
42
|
+
throw configError('At least one base API URL is required')
|
|
29
43
|
}
|
|
30
|
-
}
|
|
31
44
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
const baseUrlKey = endpoint.baseApiUrl ?? defaultBaseUrl
|
|
46
|
+
const configBaseUrl = baseApiUrls[baseUrlKey]
|
|
47
|
+
if (!configBaseUrl) {
|
|
48
|
+
throw configError(`Unknown base API URL: ${baseUrlKey}`)
|
|
49
|
+
}
|
|
36
50
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
const baseUrl =
|
|
52
|
+
typeof configBaseUrl === 'function' ? configBaseUrl() : configBaseUrl
|
|
53
|
+
const path =
|
|
54
|
+
typeof endpoint.path === 'function'
|
|
55
|
+
? endpoint.path(baseUrl)
|
|
56
|
+
: endpoint.path
|
|
57
|
+
// Substitute endpoint parameters without interpreting a port or IPv6 host as one.
|
|
58
|
+
finalUrl = joinUrlPath(
|
|
59
|
+
baseUrl,
|
|
60
|
+
replacePathParams(path, params, configError)
|
|
61
|
+
)
|
|
41
62
|
}
|
|
42
63
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
typeof endpoint.path === 'function' ? endpoint.path(baseUrl) : endpoint.path
|
|
47
|
-
const finalUrl = replacePathParams(`${baseUrl}${path}`, params, configError)
|
|
48
|
-
const queryString = new URLSearchParams(
|
|
49
|
-
buildQueryParamsRaw(endpoint, reqQuery)
|
|
50
|
-
).toString()
|
|
51
|
-
|
|
64
|
+
const queryString = buildQueryString(queryParams, {
|
|
65
|
+
encode: !doNotEncodeQueryParams
|
|
66
|
+
})
|
|
52
67
|
return {
|
|
53
68
|
finalUrl,
|
|
54
69
|
fullUrl: queryString ? `${finalUrl}?${queryString}` : finalUrl
|
|
55
70
|
}
|
|
56
71
|
}
|
|
57
72
|
|
|
58
|
-
export function
|
|
73
|
+
export function buildPathParams(
|
|
59
74
|
endpoint: ApiEndpoint,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
params: PathParams | undefined,
|
|
76
|
+
ctx: (over?: Partial<ApiErrorContext>) => ApiErrorContext
|
|
77
|
+
): PathParams | undefined {
|
|
78
|
+
if (!endpoint.reqParamsSchema) return params
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
return endpoint.reqParamsSchema.parse(params) as PathParams
|
|
82
|
+
} catch (error) {
|
|
83
|
+
if (error instanceof ZodError) {
|
|
84
|
+
throw new RequestValidationError(error, 'params', params, ctx())
|
|
85
|
+
}
|
|
86
|
+
throw error
|
|
87
|
+
}
|
|
69
88
|
}
|
|
70
89
|
|
|
71
90
|
export function buildQueryParams(
|
|
72
91
|
endpoint: ApiEndpoint,
|
|
73
92
|
query: QueryParams | undefined,
|
|
74
93
|
ctx: (over?: Partial<ApiErrorContext>) => ApiErrorContext
|
|
75
|
-
):
|
|
94
|
+
): QueryParams {
|
|
76
95
|
const defaultParams = endpoint.reqDefaultQueryParams ?? {}
|
|
77
96
|
let parsedQuery: QueryParams
|
|
78
97
|
if (endpoint.reqQuerySchema) {
|
|
@@ -87,13 +106,7 @@ export function buildQueryParams(
|
|
|
87
106
|
} else {
|
|
88
107
|
parsedQuery = query ?? {}
|
|
89
108
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return Object.fromEntries(
|
|
93
|
-
Object.entries(merged)
|
|
94
|
-
.filter(([, value]) => value !== undefined)
|
|
95
|
-
.map(([key, value]) => [key, String(value)])
|
|
96
|
-
)
|
|
109
|
+
return { ...defaultParams, ...parsedQuery }
|
|
97
110
|
}
|
|
98
111
|
|
|
99
112
|
export function buildRequestBody(
|
|
@@ -160,12 +173,31 @@ export function buildHeaders(
|
|
|
160
173
|
})
|
|
161
174
|
}
|
|
162
175
|
|
|
176
|
+
/** Joins with exactly one `/`; empty paths and query-only paths are appended as-is. */
|
|
177
|
+
export function joinUrlPath(base: string, path: string): string {
|
|
178
|
+
if (!path || path.startsWith('?')) return `${base}${path}`
|
|
179
|
+
return `${base.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Substitutes `:params` in the path of a full URL only, so ports are left alone. */
|
|
183
|
+
function replaceUrlPathParams(
|
|
184
|
+
url: string,
|
|
185
|
+
params: PathParams | undefined,
|
|
186
|
+
configError: (msg: string) => ConfigError
|
|
187
|
+
): string {
|
|
188
|
+
const origin = url.match(/^[a-z][a-z\d+.-]*:\/\/[^/?#]*/i)?.[0] ?? ''
|
|
189
|
+
const rest = url.slice(origin.length)
|
|
190
|
+
const suffixIndex = rest.search(/[?#]/)
|
|
191
|
+
const path = suffixIndex === -1 ? rest : rest.slice(0, suffixIndex)
|
|
192
|
+
return `${origin}${replacePathParams(path, params, configError)}${rest.slice(path.length)}`
|
|
193
|
+
}
|
|
194
|
+
|
|
163
195
|
export function replacePathParams(
|
|
164
196
|
path: string,
|
|
165
197
|
params: PathParams | undefined,
|
|
166
198
|
configError: (msg: string) => ConfigError
|
|
167
199
|
): string {
|
|
168
|
-
return path.replace(/:(\w
|
|
200
|
+
return path.replace(/:([A-Za-z_]\w*)/g, (_, key: string) => {
|
|
169
201
|
const value = params?.[key]
|
|
170
202
|
if (value === undefined) {
|
|
171
203
|
throw configError(`Missing required path parameter: ${key}`)
|