@apifuse/provider-sdk 2.1.0-beta.6 → 2.1.0-beta.9
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/CHANGELOG.md +15 -0
- package/bin/apifuse-perf.ts +18 -9
- package/dist/ceremonies/index.d.ts +41 -0
- package/dist/ceremonies/index.js +490 -0
- package/dist/choice-token.d.ts +24 -0
- package/dist/choice-token.js +74 -0
- package/dist/cli/commands.d.ts +10 -0
- package/dist/cli/commands.js +80 -0
- package/dist/cli/create.d.ts +47 -0
- package/dist/cli/create.js +762 -0
- package/dist/config/loader.d.ts +107 -0
- package/dist/config/loader.js +935 -0
- package/dist/contract-json.d.ts +9 -0
- package/dist/contract-json.js +51 -0
- package/dist/contract-serialization.d.ts +4 -0
- package/dist/contract-serialization.js +78 -0
- package/dist/contract-types.d.ts +49 -0
- package/dist/contract-types.js +1 -0
- package/dist/contract.d.ts +6 -0
- package/dist/contract.js +155 -0
- package/dist/define.d.ts +97 -0
- package/dist/define.js +1320 -0
- package/dist/dev.d.ts +9 -0
- package/dist/dev.js +15 -0
- package/dist/errors.d.ts +59 -0
- package/dist/errors.js +97 -0
- package/dist/i18n/catalog.d.ts +29 -0
- package/dist/i18n/catalog.js +159 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.js +2 -0
- package/dist/i18n/keys.d.ts +10 -0
- package/dist/i18n/keys.js +34 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +37 -0
- package/dist/lint.d.ts +73 -0
- package/dist/lint.js +702 -0
- package/dist/observability.d.ts +5 -0
- package/dist/observability.js +39 -0
- package/dist/provider.d.ts +9 -0
- package/dist/provider.js +8 -0
- package/dist/public-schema-field-lint.d.ts +2 -0
- package/dist/public-schema-field-lint.js +158 -0
- package/dist/recipes/gov-api.d.ts +19 -0
- package/dist/recipes/gov-api.js +72 -0
- package/dist/recipes/rest-api.d.ts +21 -0
- package/dist/recipes/rest-api.js +115 -0
- package/dist/runtime/auth-flow.d.ts +14 -0
- package/dist/runtime/auth-flow.js +44 -0
- package/dist/runtime/browser.d.ts +25 -0
- package/dist/runtime/browser.js +1034 -0
- package/dist/runtime/cache.d.ts +10 -0
- package/dist/runtime/cache.js +372 -0
- package/dist/runtime/choice.d.ts +15 -0
- package/dist/runtime/choice.js +435 -0
- package/dist/runtime/credential.d.ts +8 -0
- package/dist/runtime/credential.js +61 -0
- package/dist/runtime/env.d.ts +2 -0
- package/dist/runtime/env.js +10 -0
- package/dist/runtime/executor.d.ts +16 -0
- package/dist/runtime/executor.js +51 -0
- package/dist/runtime/http.d.ts +8 -0
- package/dist/runtime/http.js +706 -0
- package/dist/runtime/insights.d.ts +9 -0
- package/dist/runtime/insights.js +324 -0
- package/dist/runtime/instrumentation.d.ts +8 -0
- package/dist/runtime/instrumentation.js +269 -0
- package/dist/runtime/key-derivation.d.ts +24 -0
- package/dist/runtime/key-derivation.js +73 -0
- package/dist/runtime/keyring.d.ts +25 -0
- package/dist/runtime/keyring.js +93 -0
- package/dist/runtime/namespace.d.ts +9 -0
- package/dist/runtime/namespace.js +19 -0
- package/dist/runtime/otlp.d.ts +39 -0
- package/dist/runtime/otlp.js +103 -0
- package/dist/runtime/perf.d.ts +12 -0
- package/dist/runtime/perf.js +52 -0
- package/dist/runtime/prevalidate.d.ts +12 -0
- package/dist/runtime/prevalidate.js +173 -0
- package/dist/runtime/provider.d.ts +2 -0
- package/dist/runtime/provider.js +11 -0
- package/dist/runtime/proxy-errors.d.ts +21 -0
- package/dist/runtime/proxy-errors.js +83 -0
- package/dist/runtime/proxy-telemetry.d.ts +8 -0
- package/dist/runtime/proxy-telemetry.js +174 -0
- package/dist/runtime/redis.d.ts +17 -0
- package/dist/runtime/redis.js +82 -0
- package/dist/runtime/request-options.d.ts +3 -0
- package/dist/runtime/request-options.js +42 -0
- package/dist/runtime/state.d.ts +17 -0
- package/dist/runtime/state.js +344 -0
- package/dist/runtime/stealth.d.ts +18 -0
- package/dist/runtime/stealth.js +834 -0
- package/dist/runtime/stt.d.ts +22 -0
- package/dist/runtime/stt.js +480 -0
- package/dist/runtime/trace.d.ts +26 -0
- package/dist/runtime/trace.js +142 -0
- package/dist/runtime/waterfall.d.ts +12 -0
- package/dist/runtime/waterfall.js +147 -0
- package/dist/schema.d.ts +74 -0
- package/dist/schema.js +243 -0
- package/dist/serve.d.ts +1 -0
- package/dist/serve.js +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +2 -0
- package/dist/server/serve.d.ts +64 -0
- package/dist/server/serve.js +1110 -0
- package/dist/server/types.d.ts +136 -0
- package/dist/server/types.js +86 -0
- package/dist/stealth/profiles.d.ts +4 -0
- package/dist/stealth/profiles.js +259 -0
- package/dist/stream.d.ts +44 -0
- package/dist/stream.js +151 -0
- package/dist/testing/helpers.d.ts +23 -0
- package/dist/testing/helpers.js +95 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +2 -0
- package/dist/testing/run.d.ts +34 -0
- package/dist/testing/run.js +303 -0
- package/dist/types.d.ts +1326 -0
- package/dist/types.js +61 -0
- package/dist/utils/date.d.ts +6 -0
- package/dist/utils/date.js +101 -0
- package/dist/utils/parse.d.ts +16 -0
- package/dist/utils/parse.js +51 -0
- package/dist/utils/text.d.ts +4 -0
- package/dist/utils/text.js +14 -0
- package/dist/utils/transform.d.ts +8 -0
- package/dist/utils/transform.js +48 -0
- package/package.json +109 -107
- package/src/runtime/stealth.ts +8 -1
- package/src/types.ts +2 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { providerStateRedisUrlFromEnv } from "../config/loader";
|
|
2
|
+
import { ProviderError } from "../errors";
|
|
3
|
+
import { createProviderRedisClient, ensureRedisReady, withRedisTimeout, } from "./redis";
|
|
4
|
+
const DEFAULT_REDIS_TIMEOUT_MS = 250;
|
|
5
|
+
const REDIS_STATE_PREFIX = "apifuse:provider-state:v1";
|
|
6
|
+
const redisBackends = new Map();
|
|
7
|
+
function getRedisBackend(redisUrl) {
|
|
8
|
+
const existing = redisBackends.get(redisUrl);
|
|
9
|
+
if (existing)
|
|
10
|
+
return existing;
|
|
11
|
+
const redis = createProviderRedisClient({
|
|
12
|
+
redisUrl,
|
|
13
|
+
timeoutMs: DEFAULT_REDIS_TIMEOUT_MS,
|
|
14
|
+
onError: () => {
|
|
15
|
+
// Runtime state operations fail closed at their call sites. Avoid noisy
|
|
16
|
+
// unhandled Redis errors from background reconnect attempts.
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
const backend = { redis };
|
|
20
|
+
redisBackends.set(redisUrl, backend);
|
|
21
|
+
return backend;
|
|
22
|
+
}
|
|
23
|
+
async function withRequiredRedis(operation) {
|
|
24
|
+
return await withRedisTimeout(operation, {
|
|
25
|
+
timeoutMs: DEFAULT_REDIS_TIMEOUT_MS,
|
|
26
|
+
onTimeout: () => {
|
|
27
|
+
throw new UnsupportedProviderStateError("Provider runtime state Redis timed out");
|
|
28
|
+
},
|
|
29
|
+
onError: () => {
|
|
30
|
+
throw new UnsupportedProviderStateError("Provider runtime state Redis is unavailable");
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async function requireRedisReady(redis) {
|
|
35
|
+
if (await ensureRedisReady(redis, DEFAULT_REDIS_TIMEOUT_MS))
|
|
36
|
+
return;
|
|
37
|
+
throw new UnsupportedProviderStateError("Provider runtime state Redis is unavailable");
|
|
38
|
+
}
|
|
39
|
+
function providerStatePrefix(providerId, namespace) {
|
|
40
|
+
return `${REDIS_STATE_PREFIX}:${providerId ?? "default"}:${namespace}`;
|
|
41
|
+
}
|
|
42
|
+
function providerStateKey(providerId, namespace, key) {
|
|
43
|
+
return `${providerStatePrefix(providerId, namespace)}:${key}`;
|
|
44
|
+
}
|
|
45
|
+
function publicStateKey(providerId, namespace, redisKey) {
|
|
46
|
+
const prefix = `${providerStatePrefix(providerId, namespace)}:`;
|
|
47
|
+
return redisKey.startsWith(prefix) ? redisKey.slice(prefix.length) : redisKey;
|
|
48
|
+
}
|
|
49
|
+
function parseStateDurationMs(ttl) {
|
|
50
|
+
const match = /^(\d+)(ms|s|m|h|d)$/.exec(ttl ?? "1h");
|
|
51
|
+
if (!match)
|
|
52
|
+
return 3_600_000;
|
|
53
|
+
const amount = Number(match[1]);
|
|
54
|
+
const unit = match[2];
|
|
55
|
+
const multiplier = unit === "ms"
|
|
56
|
+
? 1
|
|
57
|
+
: unit === "s"
|
|
58
|
+
? 1_000
|
|
59
|
+
: unit === "m"
|
|
60
|
+
? 60_000
|
|
61
|
+
: unit === "h"
|
|
62
|
+
? 3_600_000
|
|
63
|
+
: 86_400_000;
|
|
64
|
+
return Math.max(1, amount * multiplier);
|
|
65
|
+
}
|
|
66
|
+
function resolveExpiresAt(ttl) {
|
|
67
|
+
return new Date(Date.now() + parseStateDurationMs(ttl)).toISOString();
|
|
68
|
+
}
|
|
69
|
+
function envelopeFromJson(key, raw) {
|
|
70
|
+
if (!raw)
|
|
71
|
+
return null;
|
|
72
|
+
const parsed = JSON.parse(raw);
|
|
73
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const record = Object.fromEntries(Object.entries(parsed));
|
|
77
|
+
if (typeof record.version !== "number" ||
|
|
78
|
+
typeof record.expiresAt !== "string" ||
|
|
79
|
+
typeof record.createdAt !== "string" ||
|
|
80
|
+
typeof record.updatedAt !== "string" ||
|
|
81
|
+
!("value" in record)) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
key,
|
|
86
|
+
value: record.value,
|
|
87
|
+
version: record.version,
|
|
88
|
+
expiresAt: record.expiresAt,
|
|
89
|
+
createdAt: record.createdAt,
|
|
90
|
+
updatedAt: record.updatedAt,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function redisEnvelope(value, version, createdAt, expiresAt) {
|
|
94
|
+
const updatedAt = new Date().toISOString();
|
|
95
|
+
return { value, version, expiresAt, createdAt, updatedAt };
|
|
96
|
+
}
|
|
97
|
+
class RedisProviderStateNamespace {
|
|
98
|
+
backend;
|
|
99
|
+
providerId;
|
|
100
|
+
namespaceName;
|
|
101
|
+
options;
|
|
102
|
+
constructor(backend, providerId, namespaceName, options) {
|
|
103
|
+
this.backend = backend;
|
|
104
|
+
this.providerId = providerId;
|
|
105
|
+
this.namespaceName = namespaceName;
|
|
106
|
+
this.options = options;
|
|
107
|
+
}
|
|
108
|
+
redisKey(key) {
|
|
109
|
+
return providerStateKey(this.providerId, this.namespaceName, key);
|
|
110
|
+
}
|
|
111
|
+
prefix() {
|
|
112
|
+
return `${providerStatePrefix(this.providerId, this.namespaceName)}:`;
|
|
113
|
+
}
|
|
114
|
+
async activeKeys() {
|
|
115
|
+
await requireRedisReady(this.backend.redis);
|
|
116
|
+
return await withRequiredRedis(() => this.backend.redis.keys(`${this.prefix()}*`));
|
|
117
|
+
}
|
|
118
|
+
enforceValueSize(value) {
|
|
119
|
+
const bytes = Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
120
|
+
if (bytes > this.options.maxValueBytes) {
|
|
121
|
+
throw new UnsupportedProviderStateError(`Provider runtime state value exceeds maxValueBytes (${bytes} > ${this.options.maxValueBytes})`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async enforceMaxEntries(key) {
|
|
125
|
+
const keys = await this.activeKeys();
|
|
126
|
+
const redisKey = this.redisKey(key);
|
|
127
|
+
const otherKeys = keys.filter((candidate) => candidate !== redisKey);
|
|
128
|
+
if (otherKeys.length >= this.options.maxEntries) {
|
|
129
|
+
throw new UnsupportedProviderStateError(`Provider runtime state namespace quota exceeded (${otherKeys.length + 1} > ${this.options.maxEntries})`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async list(options) {
|
|
133
|
+
const keys = (await this.activeKeys()).filter((key) => {
|
|
134
|
+
const publicKey = publicStateKey(this.providerId, this.namespaceName, key);
|
|
135
|
+
return options?.prefix ? publicKey.startsWith(options.prefix) : true;
|
|
136
|
+
});
|
|
137
|
+
const limited = keys.slice(0, Math.max(0, options?.limit ?? keys.length));
|
|
138
|
+
if (limited.length === 0)
|
|
139
|
+
return [];
|
|
140
|
+
const values = await withRequiredRedis(() => this.backend.redis.mget(limited));
|
|
141
|
+
return values.flatMap((raw, index) => {
|
|
142
|
+
const key = limited[index];
|
|
143
|
+
if (!key)
|
|
144
|
+
return [];
|
|
145
|
+
const value = envelopeFromJson(publicStateKey(this.providerId, this.namespaceName, key), raw);
|
|
146
|
+
return value ? [value] : [];
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
async get(key) {
|
|
150
|
+
await requireRedisReady(this.backend.redis);
|
|
151
|
+
const raw = await withRequiredRedis(() => this.backend.redis.get(this.redisKey(key)));
|
|
152
|
+
return envelopeFromJson(key, raw);
|
|
153
|
+
}
|
|
154
|
+
async set(key, value, options) {
|
|
155
|
+
this.enforceValueSize(value);
|
|
156
|
+
await this.enforceMaxEntries(key);
|
|
157
|
+
const current = await this.get(key);
|
|
158
|
+
const createdAt = current?.createdAt ?? new Date().toISOString();
|
|
159
|
+
const version = (current?.version ?? 0) + 1;
|
|
160
|
+
const ttl = options?.ttl ?? this.options.defaultTtl;
|
|
161
|
+
const ttlMs = parseStateDurationMs(ttl);
|
|
162
|
+
const expiresAt = resolveExpiresAt(ttl);
|
|
163
|
+
const envelope = redisEnvelope(value, version, createdAt, expiresAt);
|
|
164
|
+
await withRequiredRedis(() => this.backend.redis.set(this.redisKey(key), JSON.stringify(envelope), "PX", ttlMs));
|
|
165
|
+
return {
|
|
166
|
+
key,
|
|
167
|
+
value,
|
|
168
|
+
version,
|
|
169
|
+
expiresAt,
|
|
170
|
+
createdAt,
|
|
171
|
+
updatedAt: envelope.updatedAt,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async patch(key, partial, options) {
|
|
175
|
+
const current = (await this.get(key))?.value ?? {};
|
|
176
|
+
// biome-ignore lint/suspicious/noExplicitAny: patch preserves the caller-provided generic state shape.
|
|
177
|
+
const merged = { ...current, ...partial };
|
|
178
|
+
return await this.set(key, merged, options);
|
|
179
|
+
}
|
|
180
|
+
async compareAndSet(key, expectedVersion, value, options) {
|
|
181
|
+
this.enforceValueSize(value);
|
|
182
|
+
const current = await this.get(key);
|
|
183
|
+
if ((current?.version ?? 0) !== expectedVersion) {
|
|
184
|
+
return { ok: false, current };
|
|
185
|
+
}
|
|
186
|
+
return { ok: true, value: await this.set(key, value, options) };
|
|
187
|
+
}
|
|
188
|
+
async delete(key) {
|
|
189
|
+
await requireRedisReady(this.backend.redis);
|
|
190
|
+
await withRequiredRedis(() => this.backend.redis.del(this.redisKey(key)));
|
|
191
|
+
}
|
|
192
|
+
async increment(key, field, delta = 1, options) {
|
|
193
|
+
const current = (await this.get(key))?.value ?? {};
|
|
194
|
+
const previous = typeof current[field] === "number" ? current[field] : 0;
|
|
195
|
+
return await this.set(key, { ...current, [field]: previous + delta }, options);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
class RedisProviderRuntimeState {
|
|
199
|
+
backend;
|
|
200
|
+
providerId;
|
|
201
|
+
constructor(options) {
|
|
202
|
+
this.backend = getRedisBackend(options.redisUrl);
|
|
203
|
+
this.providerId = options.providerId;
|
|
204
|
+
}
|
|
205
|
+
namespace(name, options) {
|
|
206
|
+
return new RedisProviderStateNamespace(this.backend, this.providerId, name, options);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
export class UnsupportedProviderStateError extends ProviderError {
|
|
210
|
+
constructor(message = "Provider runtime state is not available in this runtime") {
|
|
211
|
+
super(message, { code: "PROVIDER_STATE_UNSUPPORTED" });
|
|
212
|
+
this.name = "UnsupportedProviderStateError";
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
class UnsupportedProviderStateNamespace {
|
|
216
|
+
async list(_options) {
|
|
217
|
+
throw new UnsupportedProviderStateError();
|
|
218
|
+
}
|
|
219
|
+
async get(_key) {
|
|
220
|
+
throw new UnsupportedProviderStateError();
|
|
221
|
+
}
|
|
222
|
+
async set(_key, _value, _options) {
|
|
223
|
+
throw new UnsupportedProviderStateError();
|
|
224
|
+
}
|
|
225
|
+
async patch(_key, _partial, _options) {
|
|
226
|
+
throw new UnsupportedProviderStateError();
|
|
227
|
+
}
|
|
228
|
+
async compareAndSet(_key, _expectedVersion, _value, _options) {
|
|
229
|
+
throw new UnsupportedProviderStateError();
|
|
230
|
+
}
|
|
231
|
+
async delete(_key) {
|
|
232
|
+
throw new UnsupportedProviderStateError();
|
|
233
|
+
}
|
|
234
|
+
async increment(_key, _field, _delta, _options) {
|
|
235
|
+
throw new UnsupportedProviderStateError();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
class UnsupportedProviderRuntimeState {
|
|
239
|
+
namespace(_name, _options) {
|
|
240
|
+
return new UnsupportedProviderStateNamespace();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
class MemoryProviderStateNamespace {
|
|
244
|
+
options;
|
|
245
|
+
// biome-ignore lint/suspicious/noExplicitAny: in-memory state stores heterogeneous generic values by key.
|
|
246
|
+
values = new Map();
|
|
247
|
+
constructor(options) {
|
|
248
|
+
this.options = options;
|
|
249
|
+
}
|
|
250
|
+
pruneExpired(nowMs = Date.now()) {
|
|
251
|
+
for (const [key, row] of this.values.entries()) {
|
|
252
|
+
if (row.expiresAt && Date.parse(row.expiresAt) <= nowMs) {
|
|
253
|
+
this.values.delete(key);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async list(_options) {
|
|
258
|
+
this.pruneExpired();
|
|
259
|
+
const rows = Array.from(this.values.values()).filter((value) => _options?.prefix ? value.key.startsWith(_options.prefix) : true);
|
|
260
|
+
return rows.slice(0, _options?.limit);
|
|
261
|
+
}
|
|
262
|
+
async get(key) {
|
|
263
|
+
this.pruneExpired();
|
|
264
|
+
return this.values.get(key) ?? null;
|
|
265
|
+
}
|
|
266
|
+
async set(key, value, options) {
|
|
267
|
+
this.pruneExpired();
|
|
268
|
+
const now = new Date().toISOString();
|
|
269
|
+
const current = this.values.get(key);
|
|
270
|
+
const expiresAt = resolveMemoryStateExpiresAt(options?.ttl ?? this.options.defaultTtl);
|
|
271
|
+
const row = {
|
|
272
|
+
key,
|
|
273
|
+
value,
|
|
274
|
+
version: (current?.version ?? 0) + 1,
|
|
275
|
+
expiresAt,
|
|
276
|
+
createdAt: current?.createdAt ?? now,
|
|
277
|
+
updatedAt: now,
|
|
278
|
+
};
|
|
279
|
+
this.values.set(key, row);
|
|
280
|
+
return row;
|
|
281
|
+
}
|
|
282
|
+
async patch(_key, _partial, _options) {
|
|
283
|
+
throw new UnsupportedProviderStateError("In-memory provider runtime state does not support patch");
|
|
284
|
+
}
|
|
285
|
+
async compareAndSet(_key, _expectedVersion, _value, _options) {
|
|
286
|
+
throw new UnsupportedProviderStateError("In-memory provider runtime state does not support compareAndSet");
|
|
287
|
+
}
|
|
288
|
+
async delete(key) {
|
|
289
|
+
this.values.delete(key);
|
|
290
|
+
}
|
|
291
|
+
async increment(_key, _field, _delta = 1, _options) {
|
|
292
|
+
throw new UnsupportedProviderStateError("In-memory provider runtime state does not support increment");
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
class MemoryProviderRuntimeState {
|
|
296
|
+
namespaces = new Map();
|
|
297
|
+
namespace(name, _options) {
|
|
298
|
+
const existing = this.namespaces.get(name);
|
|
299
|
+
if (existing)
|
|
300
|
+
return existing;
|
|
301
|
+
const created = new MemoryProviderStateNamespace(_options);
|
|
302
|
+
this.namespaces.set(name, created);
|
|
303
|
+
return created;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function resolveMemoryStateExpiresAt(ttl) {
|
|
307
|
+
const match = /^(\d+)(ms|s|m|h|d)$/.exec(ttl ?? "1h");
|
|
308
|
+
if (!match)
|
|
309
|
+
return new Date(Date.now() + 3_600_000).toISOString();
|
|
310
|
+
const amount = Number(match[1]);
|
|
311
|
+
const unit = match[2];
|
|
312
|
+
const multiplier = unit === "ms"
|
|
313
|
+
? 1
|
|
314
|
+
: unit === "s"
|
|
315
|
+
? 1_000
|
|
316
|
+
: unit === "m"
|
|
317
|
+
? 60_000
|
|
318
|
+
: unit === "h"
|
|
319
|
+
? 3_600_000
|
|
320
|
+
: 86_400_000;
|
|
321
|
+
return new Date(Date.now() + amount * multiplier).toISOString();
|
|
322
|
+
}
|
|
323
|
+
export function createRedisProviderRuntimeState(options) {
|
|
324
|
+
return new RedisProviderRuntimeState(options);
|
|
325
|
+
}
|
|
326
|
+
export function createProviderRuntimeStateFromEnv(options = {}) {
|
|
327
|
+
const redisUrl = providerStateRedisUrlFromEnv();
|
|
328
|
+
if (redisUrl) {
|
|
329
|
+
return createRedisProviderRuntimeState({
|
|
330
|
+
redisUrl,
|
|
331
|
+
providerId: options.providerId,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
if (options.allowMemoryFallback === true) {
|
|
335
|
+
return new MemoryProviderRuntimeState();
|
|
336
|
+
}
|
|
337
|
+
return createUnsupportedProviderRuntimeState();
|
|
338
|
+
}
|
|
339
|
+
export function createMemoryProviderRuntimeState() {
|
|
340
|
+
return new MemoryProviderRuntimeState();
|
|
341
|
+
}
|
|
342
|
+
export function createUnsupportedProviderRuntimeState() {
|
|
343
|
+
return new UnsupportedProviderRuntimeState();
|
|
344
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ImpitResponse } from "impit";
|
|
2
|
+
import type { ProxyResolutionOptions } from "../config/loader";
|
|
3
|
+
import type { StealthClient, StealthResponse } from "../types";
|
|
4
|
+
export type StealthClientOptions = ProxyResolutionOptions & {
|
|
5
|
+
warn?: (message: string) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Proxy-only stealth transport overrides. Use only for upstream proxy products
|
|
8
|
+
* that terminate CONNECT with a private CA instead of tunneling the origin
|
|
9
|
+
* certificate chain.
|
|
10
|
+
*/
|
|
11
|
+
proxyStealth?: {
|
|
12
|
+
insecureSkipVerify?: boolean;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
type StealthTransportResponse = Pick<ImpitResponse, "arrayBuffer" | "headers" | "json" | "ok" | "status" | "text" | "url">;
|
|
16
|
+
export declare function normalizeResponse(response: StealthTransportResponse): Promise<StealthResponse>;
|
|
17
|
+
export declare function createStealthClient(baseUrl: string, defaultProfileOrOptions?: string | StealthClientOptions, clientOptions?: StealthClientOptions): StealthClient;
|
|
18
|
+
export {};
|