@chainfuse/helpers 3.5.6 → 3.6.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 +10 -0
- package/dist/buffers.d.mts +25 -1
- package/dist/buffers.mjs +91 -8
- package/dist/crypto.mjs +3 -1
- package/dist/db.d.mts +8 -8
- package/dist/db.mjs +9 -20
- package/dist/discord.d.mts +3 -3
- package/dist/net.d.mts +51 -151
- package/dist/net.mjs +168 -136
- package/dist/uuid8.d.mts +37 -0
- package/dist/uuid8.mjs +83 -0
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -15,3 +15,13 @@ import helpers from '@chainfuse/helpers';
|
|
|
15
15
|
|
|
16
16
|
// TODO: DEMONSTRATE API
|
|
17
17
|
```
|
|
18
|
+
|
|
19
|
+
## UUIDv8
|
|
20
|
+
|
|
21
|
+
Based on UUIDv7 but with added values to prevent unnecessary lookups
|
|
22
|
+
|
|
23
|
+
`01f3ffff-fc18-8bb7-9120-cabc55668d92`
|
|
24
|
+
|
|
25
|
+
| 01f3ffff-fc18 | 8 | bb7 | 9 | 12 | 0 | cabc55668d92 |
|
|
26
|
+
| ----------------------------------------- | ------------ | --------------------------------- | -------------------------------- | ---------------------------------------- | ----------- | -------------- |
|
|
27
|
+
| 48bit Timestamp (Unix epoch milliseconds) | UUID Version | Suffix random (`000` if director) | variant (2 bits) + 2 random bits | `DOCombinedLocations` (`00` if anywhere) | `ShardType` | 48 random bits |
|
package/dist/buffers.d.mts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { UndefinedProperties } from '@chainfuse/types';
|
|
2
|
-
import type
|
|
2
|
+
import { type PrefixedUuid, type UuidExport, type UUIDExtract } from '@chainfuse/types/d1';
|
|
3
|
+
import * as z from 'zod/mini';
|
|
4
|
+
import type { Version8Options } from './uuid8.mjs';
|
|
3
5
|
export type UuidExportBlobInput = Buffer | UuidExport['blob'];
|
|
4
6
|
export declare class BufferHelpers {
|
|
5
7
|
static bigintToBuffer(number: bigint): Promise<ArrayBuffer>;
|
|
@@ -9,7 +11,22 @@ export declare class BufferHelpers {
|
|
|
9
11
|
static bufferToHex(buffer: UuidExportBlobInput): Promise<string>;
|
|
10
12
|
static base64ToBuffer(rawBase64: string): Promise<ArrayBuffer>;
|
|
11
13
|
static bufferToBase64(buffer: UuidExportBlobInput, urlSafe: boolean): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated Use `BufferHelpers.generateUuid7` instead
|
|
16
|
+
*/
|
|
12
17
|
static get generateUuid(): Promise<UuidExport>;
|
|
18
|
+
static v7OptionsBase: z.ZodMiniObject<{
|
|
19
|
+
/**
|
|
20
|
+
* RFC "timestamp" field
|
|
21
|
+
*/
|
|
22
|
+
msecs: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniNumberFormat, z.ZodMiniPipe<z.ZodMiniDate<Date>, z.ZodMiniTransform<number, Date>>]>>;
|
|
23
|
+
/**
|
|
24
|
+
* 32-bit sequence Number between 0 - 0xffffffff. This may be provided to help ensure uniqueness for UUIDs generated within the same millisecond time interval. Default = random value.
|
|
25
|
+
*/
|
|
26
|
+
seq: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
static generateUuid7(_options?: z.input<Awaited<typeof this.v7OptionsBase>>): Promise<UuidExport>;
|
|
29
|
+
static generateUuid8(options?: Omit<Version8Options, 'random' | 'rng'>): Promise<UuidExport>;
|
|
13
30
|
static uuidConvert(input: undefined): Promise<UndefinedProperties<UuidExport>>;
|
|
14
31
|
static uuidConvert(prefixedUtf: PrefixedUuid): Promise<UuidExport>;
|
|
15
32
|
static uuidConvert(input: UuidExport['utf8']): Promise<UuidExport>;
|
|
@@ -17,4 +34,11 @@ export declare class BufferHelpers {
|
|
|
17
34
|
static uuidConvert(input: UuidExportBlobInput): Promise<UuidExport>;
|
|
18
35
|
static uuidConvert(input: UuidExport['base64']): Promise<UuidExport>;
|
|
19
36
|
static uuidConvert(input: UuidExport['base64url']): Promise<UuidExport>;
|
|
37
|
+
static uuidExtractor(input: undefined): Promise<UUIDExtract>;
|
|
38
|
+
static uuidExtractor(prefixedUtf: PrefixedUuid): Promise<UUIDExtract>;
|
|
39
|
+
static uuidExtractor(input: UuidExport['utf8']): Promise<UUIDExtract>;
|
|
40
|
+
static uuidExtractor(input: UuidExport['hex']): Promise<UUIDExtract>;
|
|
41
|
+
static uuidExtractor(input: UuidExportBlobInput): Promise<UUIDExtract>;
|
|
42
|
+
static uuidExtractor(input: UuidExport['base64']): Promise<UUIDExtract>;
|
|
43
|
+
static uuidExtractor(input: UuidExport['base64url']): Promise<UUIDExtract>;
|
|
20
44
|
}
|
package/dist/buffers.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { UUIDExtract7, UUIDExtract8 } from '@chainfuse/types/d1';
|
|
2
|
+
import * as z from 'zod/mini';
|
|
1
3
|
import { BufferHelpersInternals } from "./bufferInternals.mjs";
|
|
2
4
|
import { CryptoHelpers } from './crypto.mjs';
|
|
3
5
|
export class BufferHelpers {
|
|
@@ -18,27 +20,67 @@ export class BufferHelpers {
|
|
|
18
20
|
return BufferHelpersInternals.node_bufferToHex(buffer).catch(() => BufferHelpersInternals.browser_bufferToHex(buffer));
|
|
19
21
|
}
|
|
20
22
|
static base64ToBuffer(rawBase64) {
|
|
21
|
-
return
|
|
23
|
+
return Promise.any([
|
|
22
24
|
z
|
|
23
25
|
.base64()
|
|
24
|
-
.trim()
|
|
25
|
-
.nonempty()
|
|
26
|
+
.check(z.trim(), z.minLength(1))
|
|
26
27
|
.parseAsync(rawBase64)
|
|
27
28
|
.then((base64) => BufferHelpersInternals.node_base64ToBuffer(base64, false).catch(() => BufferHelpersInternals.browser_base64ToBuffer(base64))),
|
|
28
29
|
z
|
|
29
30
|
.base64url()
|
|
30
|
-
.trim()
|
|
31
|
-
.nonempty()
|
|
31
|
+
.check(z.trim(), z.minLength(1))
|
|
32
32
|
.parseAsync(rawBase64)
|
|
33
33
|
.then((base64url) => BufferHelpersInternals.node_base64ToBuffer(base64url, true).catch(() => BufferHelpersInternals.browser_base64UrlToBuffer(base64url))),
|
|
34
|
-
])
|
|
34
|
+
]);
|
|
35
35
|
}
|
|
36
36
|
static bufferToBase64(buffer, urlSafe) {
|
|
37
37
|
return BufferHelpersInternals.node_bufferToBase64(buffer, urlSafe).catch(() => BufferHelpersInternals.browser_bufferToBase64(buffer, urlSafe));
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* @deprecated Use `BufferHelpers.generateUuid7` instead
|
|
41
|
+
*/
|
|
39
42
|
static get generateUuid() {
|
|
40
|
-
return
|
|
41
|
-
|
|
43
|
+
return this.generateUuid7();
|
|
44
|
+
}
|
|
45
|
+
static v7OptionsBase = z.object({
|
|
46
|
+
/**
|
|
47
|
+
* RFC "timestamp" field
|
|
48
|
+
*/
|
|
49
|
+
msecs: z.optional(z.union([
|
|
50
|
+
z.int().check(z.nonnegative()),
|
|
51
|
+
// Allow converting from Date object
|
|
52
|
+
z.pipe(z.date(), z.transform((date) => date.getTime())),
|
|
53
|
+
])),
|
|
54
|
+
/**
|
|
55
|
+
* 32-bit sequence Number between 0 - 0xffffffff. This may be provided to help ensure uniqueness for UUIDs generated within the same millisecond time interval. Default = random value.
|
|
56
|
+
*/
|
|
57
|
+
seq: z.optional(z.int().check(z.minimum(0), z.maximum(0xffffffff))),
|
|
58
|
+
});
|
|
59
|
+
static generateUuid7(_options) {
|
|
60
|
+
return Promise.all([
|
|
61
|
+
//
|
|
62
|
+
import('uuid'),
|
|
63
|
+
this.v7OptionsBase.parseAsync(_options ?? {}),
|
|
64
|
+
CryptoHelpers.secretBytes(16),
|
|
65
|
+
]).then(([{ v7: uuidv7 }, options, random]) => {
|
|
66
|
+
const uuid = uuidv7({ msecs: options.msecs, random, seq: options.seq });
|
|
67
|
+
const uuidHex = uuid.replaceAll('-', '');
|
|
68
|
+
return this.hexToBuffer(uuidHex).then((blob) => Promise.all([this.bufferToBase64(blob, false), this.bufferToBase64(blob, true)]).then(([base64, base64url]) => ({
|
|
69
|
+
utf8: uuid,
|
|
70
|
+
hex: uuidHex,
|
|
71
|
+
blob,
|
|
72
|
+
base64,
|
|
73
|
+
base64url,
|
|
74
|
+
})));
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
static generateUuid8(options) {
|
|
78
|
+
return Promise.all([import('./uuid8.mjs'), CryptoHelpers.secretBytes(16)]).then(([{ v8: uuidv8 }, random]) => {
|
|
79
|
+
const uuid = uuidv8({
|
|
80
|
+
// @ts-expect-error they're the exact same
|
|
81
|
+
random,
|
|
82
|
+
...options,
|
|
83
|
+
});
|
|
42
84
|
const uuidHex = uuid.replaceAll('-', '');
|
|
43
85
|
return this.hexToBuffer(uuidHex).then((blob) => Promise.all([this.bufferToBase64(blob, false), this.bufferToBase64(blob, true)]).then(([base64, base64url]) => ({
|
|
44
86
|
utf8: uuid,
|
|
@@ -134,4 +176,45 @@ export class BufferHelpers {
|
|
|
134
176
|
base64url: undefined,
|
|
135
177
|
}))();
|
|
136
178
|
}
|
|
179
|
+
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
180
|
+
static uuidExtractor(input) {
|
|
181
|
+
return this.uuidConvert(
|
|
182
|
+
// @ts-expect-error it's the same type
|
|
183
|
+
input).then(async ({ utf8, hex: _hex }) => {
|
|
184
|
+
const { success: hexSuccess, data: hex } = z.hex().check(z.length(32)).safeParse(_hex);
|
|
185
|
+
if (hexSuccess) {
|
|
186
|
+
const { success: utf8v7Success } = z.uuid({ version: 'v7' }).safeParse(utf8);
|
|
187
|
+
const { success: utf8v8Success } = z.uuid({ version: 'v8' }).safeParse(utf8);
|
|
188
|
+
if (utf8v7Success || utf8v8Success) {
|
|
189
|
+
if (utf8v8Success) {
|
|
190
|
+
const suffix_hex = hex.substring(13, 16);
|
|
191
|
+
const suffix_buffer = await BufferHelpers.hexToBuffer(suffix_hex);
|
|
192
|
+
return UUIDExtract8.parseAsync({
|
|
193
|
+
date: Number(BigInt(`0x${hex.substring(0, 12)}`)),
|
|
194
|
+
location: parseInt(hex.slice(17, 19), 16),
|
|
195
|
+
shardType: parseInt(hex.slice(19, 20), 16),
|
|
196
|
+
suffix: suffix_hex === '000'
|
|
197
|
+
? undefined
|
|
198
|
+
: {
|
|
199
|
+
hex: suffix_hex,
|
|
200
|
+
base64: await BufferHelpers.bufferToBase64(suffix_buffer, false),
|
|
201
|
+
base64url: await BufferHelpers.bufferToBase64(suffix_buffer, true),
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
return UUIDExtract7.parseAsync({
|
|
207
|
+
date: Number(BigInt(`0x${hex.substring(0, 12)}`)),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
throw new Error('Unsupported UUID version provided');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
throw new Error('Invalid UUID provided');
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
137
220
|
}
|
package/dist/crypto.mjs
CHANGED
|
@@ -5,7 +5,9 @@ export class CryptoHelpers {
|
|
|
5
5
|
return CryptoHelpersInternals.node_secretBytes(byteSize).catch(() => CryptoHelpersInternals.browser_secretBytes(byteSize));
|
|
6
6
|
}
|
|
7
7
|
static base16secret(secretLength) {
|
|
8
|
-
return this.secretBytes(secretLength / 2)
|
|
8
|
+
return this.secretBytes(Math.ceil(secretLength / 2))
|
|
9
|
+
.then((bytes) => BufferHelpers.bufferToHex(bytes.buffer))
|
|
10
|
+
.then((hex) => hex.substring(0, secretLength));
|
|
9
11
|
}
|
|
10
12
|
static base62secret(secretLength) {
|
|
11
13
|
const LOWER_CHAR_SET = 'abcdefghijklmnopqrstuvwxyz';
|
package/dist/db.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Cache as DrizzleCache, type MutationOption } from 'drizzle-orm/cache/core';
|
|
2
2
|
import type { CacheConfig } from 'drizzle-orm/cache/core/types';
|
|
3
|
-
import
|
|
3
|
+
import * as z from 'zod/mini';
|
|
4
4
|
/**
|
|
5
5
|
* Interface for CacheStorage-like objects that can be used as drop-in replacements.
|
|
6
6
|
* This interface ensures compatibility with the Web API CacheStorage while allowing for custom implementations that provide the same core functionality.
|
|
@@ -28,12 +28,12 @@ export declare class SQLCache<C extends CacheStorageLike> extends DrizzleCache {
|
|
|
28
28
|
private ttlCutoff;
|
|
29
29
|
private _strategy;
|
|
30
30
|
private usedTablesPerKey;
|
|
31
|
-
static constructorArgs
|
|
32
|
-
dbName: z.
|
|
33
|
-
dbType: z.
|
|
34
|
-
cacheTTL: z.
|
|
35
|
-
cachePurge: z.
|
|
36
|
-
strategy: z.
|
|
31
|
+
static constructorArgs: z.ZodMiniObject<{
|
|
32
|
+
dbName: z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string, string>>;
|
|
33
|
+
dbType: z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string, string>>;
|
|
34
|
+
cacheTTL: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
35
|
+
cachePurge: z.ZodMiniDefault<z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniDate<Date>]>>;
|
|
36
|
+
strategy: z.ZodMiniDefault<z.ZodMiniEnum<{
|
|
37
37
|
explicit: "explicit";
|
|
38
38
|
all: "all";
|
|
39
39
|
}>>;
|
|
@@ -49,7 +49,7 @@ export declare class SQLCache<C extends CacheStorageLike> extends DrizzleCache {
|
|
|
49
49
|
* - `all`: All queries are cached globally.
|
|
50
50
|
* @param cacheStore - The cache store to use. Can be a CacheStorage or CacheStorage-like object that atleast contains the `open()` function
|
|
51
51
|
*/
|
|
52
|
-
constructor(args: z.input<
|
|
52
|
+
constructor(args: z.input<(typeof SQLCache)['constructorArgs']>, cacheStore?: C);
|
|
53
53
|
/**
|
|
54
54
|
* For the strategy, we have two options:
|
|
55
55
|
* - `explicit`: The cache is used only when .$withCache() is added to a query.
|
package/dist/db.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Cache as DrizzleCache } from 'drizzle-orm/cache/core';
|
|
2
2
|
import { is } from 'drizzle-orm/entity';
|
|
3
3
|
import { getTableName, Table } from 'drizzle-orm/table';
|
|
4
|
-
import
|
|
4
|
+
import * as z from 'zod/mini';
|
|
5
5
|
import { CryptoHelpers } from "./crypto.mjs";
|
|
6
6
|
/**
|
|
7
7
|
* SQLCache is a cache implementation for SQL query results, using Web CacheStorage (supports drop in replacements).
|
|
@@ -23,24 +23,13 @@ export class SQLCache extends DrizzleCache {
|
|
|
23
23
|
_strategy;
|
|
24
24
|
// This object will be used to store which query keys were used for a specific table, so we can later use it for invalidation.
|
|
25
25
|
usedTablesPerKey = {};
|
|
26
|
-
static constructorArgs(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
.string()
|
|
34
|
-
.nonempty()
|
|
35
|
-
.transform((val) => encodeURIComponent(val)),
|
|
36
|
-
cacheTTL: z
|
|
37
|
-
.int()
|
|
38
|
-
.nonnegative()
|
|
39
|
-
.default(5 * 60),
|
|
40
|
-
cachePurge: z.union([z.boolean(), z.date()]).default(false),
|
|
41
|
-
strategy: z.enum(['explicit', 'all']).default('explicit'),
|
|
42
|
-
});
|
|
43
|
-
}
|
|
26
|
+
static constructorArgs = z.object({
|
|
27
|
+
dbName: z.pipe(z.string().check(z.minLength(1)), z.transform((val) => encodeURIComponent(val))),
|
|
28
|
+
dbType: z.pipe(z.string().check(z.minLength(1)), z.transform((val) => encodeURIComponent(val))),
|
|
29
|
+
cacheTTL: z._default(z.int().check(z.nonnegative()), 5 * 60),
|
|
30
|
+
cachePurge: z._default(z.union([z.boolean(), z.date()]), false),
|
|
31
|
+
strategy: z._default(z.enum(['explicit', 'all']), 'explicit'),
|
|
32
|
+
});
|
|
44
33
|
/**
|
|
45
34
|
* Creates an instance of the class with the specified database name, type, and cache TTL.
|
|
46
35
|
*
|
|
@@ -54,7 +43,7 @@ export class SQLCache extends DrizzleCache {
|
|
|
54
43
|
*/
|
|
55
44
|
constructor(args, cacheStore) {
|
|
56
45
|
super();
|
|
57
|
-
const { dbName, dbType, cacheTTL, cachePurge, strategy } = SQLCache.constructorArgs
|
|
46
|
+
const { dbName, dbType, cacheTTL, cachePurge, strategy } = SQLCache.constructorArgs.parse(args);
|
|
58
47
|
this.dbName = dbName;
|
|
59
48
|
this.dbType = dbType;
|
|
60
49
|
cacheStore ??= globalThis.caches;
|
package/dist/discord.d.mts
CHANGED
|
@@ -23,15 +23,15 @@ export declare class DiscordHelpers {
|
|
|
23
23
|
color: z.ZodDefault<z.ZodBoolean>;
|
|
24
24
|
custom: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnion<[z.ZodVoid, z.ZodPromise<z.ZodVoid>]>>>;
|
|
25
25
|
}, "strip", z.ZodTypeAny, {
|
|
26
|
-
level: number;
|
|
27
26
|
error: number;
|
|
27
|
+
level: number;
|
|
28
28
|
color: boolean;
|
|
29
29
|
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
30
30
|
}, {
|
|
31
|
-
|
|
31
|
+
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
32
32
|
error?: number | undefined;
|
|
33
|
+
level?: number | undefined;
|
|
33
34
|
color?: boolean | undefined;
|
|
34
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
35
35
|
}>>>;
|
|
36
36
|
static discordRest(apiKey: string, logging: z.input<Awaited<ReturnType<typeof DiscordHelpers.disordRestLogging>>>, cacheTtl?: number, forceCache?: boolean, executionContext?: ExecutionContext, restOptions?: Partial<Omit<RESTOptions, 'agent' | 'authPrefix' | 'makeRequest'>>): Promise<import("@discordjs/rest").REST>;
|
|
37
37
|
static userIcon(userId: bigint | string, userIconHash?: Parameters<CDN['avatar']>[1] | null, guildId?: bigint | string, memberIconHash?: Parameters<CDN['avatar']>[1] | null, options?: Parameters<CDN['avatar']>[2]): string;
|
package/dist/net.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export type LoggingFetchInitType<RI extends RequestInit = RequestInit> = RI & z3.input<Awaited<ReturnType<typeof NetHelpers.loggingFetchInit>>>;
|
|
1
|
+
import * as z from 'zod/mini';
|
|
2
|
+
export type LoggingFetchInitType<RI extends RequestInit = RequestInit> = RI & z.input<typeof NetHelpers.loggingFetchInit>;
|
|
4
3
|
/**
|
|
5
4
|
* Enum representing HTTP request methods.
|
|
6
5
|
*
|
|
@@ -18,138 +17,73 @@ export declare enum Methods {
|
|
|
18
17
|
'PATCH' = "PATCH"
|
|
19
18
|
}
|
|
20
19
|
export declare class NetHelpers {
|
|
21
|
-
static
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
color: boolean;
|
|
31
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
32
|
-
}, {
|
|
33
|
-
level?: number | undefined;
|
|
34
|
-
error?: number | undefined;
|
|
35
|
-
color?: boolean | undefined;
|
|
36
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
37
|
-
}>>;
|
|
38
|
-
cf: z3.ZodDefault<z3.ZodObject<{
|
|
20
|
+
static customLogging: z.ZodMiniFunction<z.ZodMiniTuple<readonly [z.ZodMiniAny], z.ZodMiniAny>, z.ZodMiniUnion<readonly [z.ZodMiniPromise<z.ZodMiniVoid>, z.ZodMiniVoid]>>;
|
|
21
|
+
static cfApiConfig: z.ZodMiniDefault<z.ZodMiniObject<{
|
|
22
|
+
logging: z.ZodMiniDefault<z.ZodMiniObject<{
|
|
23
|
+
level: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
24
|
+
error: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
25
|
+
color: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
|
|
26
|
+
custom: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniFunction<z.ZodMiniTuple<readonly [z.ZodMiniAny], z.ZodMiniAny>, z.ZodMiniUnion<readonly [z.ZodMiniPromise<z.ZodMiniVoid>, z.ZodMiniVoid]>>, z.ZodMiniTransform<(args_0: any, ...args: any[]) => void | Promise<void>, z.core.$InferOuterFunctionType<z.ZodMiniTuple<readonly [z.ZodMiniAny], z.ZodMiniAny>, z.ZodMiniUnion<readonly [z.ZodMiniPromise<z.ZodMiniVoid>, z.ZodMiniVoid]>>>>>;
|
|
27
|
+
}, z.core.$strip>>;
|
|
28
|
+
cf: z.ZodMiniDefault<z.ZodMiniObject<{
|
|
39
29
|
/**
|
|
40
30
|
* Whether Cloudflare Apps should be enabled for this request
|
|
41
31
|
* @link https://www.cloudflare.com/apps/
|
|
42
32
|
* @default true
|
|
43
33
|
*/
|
|
44
|
-
apps:
|
|
34
|
+
apps: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
|
|
45
35
|
/**
|
|
46
36
|
* Treats all content as static and caches all file types beyond the Cloudflare default cached content. Respects cache headers from the origin web server. This is equivalent to setting the Page Rule Cache Level (to Cache Everything).
|
|
47
37
|
* @default false
|
|
48
38
|
* @note This option applies to GET and HEAD request methods only
|
|
49
39
|
*/
|
|
50
|
-
cacheEverything:
|
|
40
|
+
cacheEverything: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
|
|
51
41
|
/**
|
|
52
|
-
* A request
|
|
42
|
+
* A request's cache key is what determines if two requests are the same for caching purposes. If a request has the same cache key as some previous request, then Cloudflare can serve the same cached response for both.
|
|
53
43
|
*/
|
|
54
|
-
cacheKey:
|
|
44
|
+
cacheKey: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
55
45
|
/**
|
|
56
46
|
* This option appends additional Cache-Tag headers to the response from the origin server. This allows for purges of cached content based on tags provided by the Worker, without modifications to the origin server. This is performed using the Purge by Tag feature.
|
|
57
47
|
*/
|
|
58
|
-
cacheTags:
|
|
48
|
+
cacheTags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
59
49
|
/**
|
|
60
50
|
* This option forces Cloudflare to cache the response for this request, regardless of what headers are seen on the response. This is equivalent to setting two Page Rules: Edge Cache TTL and Cache Level (to Cache Everything). The value must be zero or a positive number. A value of 0 indicates that the cache asset expires immediately.
|
|
61
51
|
* @note This option applies to GET and HEAD request methods only.
|
|
62
52
|
*/
|
|
63
|
-
cacheTtl:
|
|
53
|
+
cacheTtl: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
|
|
64
54
|
/**
|
|
65
|
-
* This option is a version of the cacheTtl feature which chooses a TTL based on the response
|
|
55
|
+
* This option is a version of the cacheTtl feature which chooses a TTL based on the response's status code. If the response to this request has a status code that matches, Cloudflare will cache for the instructed time and override cache instructives sent by the origin. For example: { "200-299": 86400, "404": 1, "500-599": 0 }. The value can be any integer, including zero and negative integers. A value of 0 indicates that the cache asset expires immediately. Any negative value instructs Cloudflare not to cache at all.
|
|
66
56
|
* @note This option applies to GET and HEAD request methods only.
|
|
67
57
|
*/
|
|
68
|
-
cacheTtlByStatus:
|
|
58
|
+
cacheTtlByStatus: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniNumberFormat>>;
|
|
69
59
|
/**
|
|
70
60
|
* Whether Mirage should be enabled for this request, if otherwise configured for this zone.
|
|
71
61
|
* @link https://www.cloudflare.com/website-optimization/mirage/
|
|
72
62
|
* @default true
|
|
73
63
|
*/
|
|
74
|
-
mirage:
|
|
64
|
+
mirage: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
|
|
75
65
|
/**
|
|
76
66
|
* Sets Polish mode. The possible values are lossy, lossless or off.
|
|
77
67
|
* @link https://blog.cloudflare.com/introducing-polish-automatic-image-optimizati/
|
|
78
68
|
*/
|
|
79
|
-
polish:
|
|
69
|
+
polish: z.ZodMiniOptional<z.ZodMiniEnum<{
|
|
70
|
+
lossy: "lossy";
|
|
71
|
+
lossless: "lossless";
|
|
72
|
+
off: "off";
|
|
73
|
+
}>>;
|
|
80
74
|
/**
|
|
81
75
|
* Whether ScrapeShield should be enabled for this request, if otherwise configured for this zone.
|
|
82
76
|
* @link https://blog.cloudflare.com/introducing-scrapeshield-discover-defend-dete/
|
|
83
77
|
* @default true
|
|
84
78
|
*/
|
|
85
|
-
scrapeShield:
|
|
79
|
+
scrapeShield: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
|
|
86
80
|
/**
|
|
87
81
|
* Enables or disables WebP image format in Polish.
|
|
88
82
|
* @link https://blog.cloudflare.com/a-very-webp-new-year-from-cloudflare/
|
|
89
83
|
*/
|
|
90
|
-
webp:
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
cacheEverything: boolean;
|
|
94
|
-
mirage: boolean;
|
|
95
|
-
scrapeShield: boolean;
|
|
96
|
-
cacheKey?: string | undefined;
|
|
97
|
-
cacheTags?: [string, ...string[]] | undefined;
|
|
98
|
-
cacheTtl?: number | undefined;
|
|
99
|
-
cacheTtlByStatus?: Record<string, number> | undefined;
|
|
100
|
-
polish?: "lossy" | "lossless" | "off" | undefined;
|
|
101
|
-
webp?: boolean | undefined;
|
|
102
|
-
}, {
|
|
103
|
-
apps?: boolean | undefined;
|
|
104
|
-
cacheEverything?: boolean | undefined;
|
|
105
|
-
cacheKey?: string | undefined;
|
|
106
|
-
cacheTags?: [string, ...string[]] | undefined;
|
|
107
|
-
cacheTtl?: number | undefined;
|
|
108
|
-
cacheTtlByStatus?: Record<string, number> | undefined;
|
|
109
|
-
mirage?: boolean | undefined;
|
|
110
|
-
polish?: "lossy" | "lossless" | "off" | undefined;
|
|
111
|
-
scrapeShield?: boolean | undefined;
|
|
112
|
-
webp?: boolean | undefined;
|
|
113
|
-
}>>;
|
|
114
|
-
}, "strip", z3.ZodTypeAny, {
|
|
115
|
-
logging: {
|
|
116
|
-
level: number;
|
|
117
|
-
error: number;
|
|
118
|
-
color: boolean;
|
|
119
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
120
|
-
};
|
|
121
|
-
cf: {
|
|
122
|
-
apps: boolean;
|
|
123
|
-
cacheEverything: boolean;
|
|
124
|
-
mirage: boolean;
|
|
125
|
-
scrapeShield: boolean;
|
|
126
|
-
cacheKey?: string | undefined;
|
|
127
|
-
cacheTags?: [string, ...string[]] | undefined;
|
|
128
|
-
cacheTtl?: number | undefined;
|
|
129
|
-
cacheTtlByStatus?: Record<string, number> | undefined;
|
|
130
|
-
polish?: "lossy" | "lossless" | "off" | undefined;
|
|
131
|
-
webp?: boolean | undefined;
|
|
132
|
-
};
|
|
133
|
-
}, {
|
|
134
|
-
logging?: {
|
|
135
|
-
level?: number | undefined;
|
|
136
|
-
error?: number | undefined;
|
|
137
|
-
color?: boolean | undefined;
|
|
138
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
139
|
-
} | undefined;
|
|
140
|
-
cf?: {
|
|
141
|
-
apps?: boolean | undefined;
|
|
142
|
-
cacheEverything?: boolean | undefined;
|
|
143
|
-
cacheKey?: string | undefined;
|
|
144
|
-
cacheTags?: [string, ...string[]] | undefined;
|
|
145
|
-
cacheTtl?: number | undefined;
|
|
146
|
-
cacheTtlByStatus?: Record<string, number> | undefined;
|
|
147
|
-
mirage?: boolean | undefined;
|
|
148
|
-
polish?: "lossy" | "lossless" | "off" | undefined;
|
|
149
|
-
scrapeShield?: boolean | undefined;
|
|
150
|
-
webp?: boolean | undefined;
|
|
151
|
-
} | undefined;
|
|
152
|
-
}>>>;
|
|
84
|
+
webp: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
|
|
85
|
+
}, z.core.$strip>>;
|
|
86
|
+
}, z.core.$strip>>;
|
|
153
87
|
/**
|
|
154
88
|
* Creates an instance of the Cloudflare API client with enhanced logging capabilities.
|
|
155
89
|
*
|
|
@@ -168,55 +102,21 @@ export declare class NetHelpers {
|
|
|
168
102
|
* - Formatting and coloring log output for better readability.
|
|
169
103
|
* - Stripping redundant parts of URLs and wrapping unique IDs in brackets with color coding.
|
|
170
104
|
*/
|
|
171
|
-
static cfApi(apiKey: string, config?:
|
|
172
|
-
static
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
color?: boolean | undefined;
|
|
187
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
188
|
-
}>>;
|
|
189
|
-
}, "strip", z3.ZodTypeAny, {
|
|
190
|
-
logging: {
|
|
191
|
-
level: number;
|
|
192
|
-
error: number;
|
|
193
|
-
color: boolean;
|
|
194
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
195
|
-
};
|
|
196
|
-
}, {
|
|
197
|
-
logging?: {
|
|
198
|
-
level?: number | undefined;
|
|
199
|
-
error?: number | undefined;
|
|
200
|
-
color?: boolean | undefined;
|
|
201
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
202
|
-
} | undefined;
|
|
203
|
-
}>>;
|
|
204
|
-
static loggingFetchInitLogging(): Promise<z3.ZodDefault<z3.ZodObject<{
|
|
205
|
-
level: z3.ZodDefault<z3.ZodNumber>;
|
|
206
|
-
error: z3.ZodDefault<z3.ZodNumber>;
|
|
207
|
-
color: z3.ZodDefault<z3.ZodBoolean>;
|
|
208
|
-
custom: z3.ZodOptional<z3.ZodFunction<z3.ZodTuple<[], z3.ZodUnknown>, z3.ZodUnion<[z3.ZodVoid, z3.ZodPromise<z3.ZodVoid>]>>>;
|
|
209
|
-
}, "strip", z3.ZodTypeAny, {
|
|
210
|
-
level: number;
|
|
211
|
-
error: number;
|
|
212
|
-
color: boolean;
|
|
213
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
214
|
-
}, {
|
|
215
|
-
level?: number | undefined;
|
|
216
|
-
error?: number | undefined;
|
|
217
|
-
color?: boolean | undefined;
|
|
218
|
-
custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
|
|
219
|
-
}>>>;
|
|
105
|
+
static cfApi(apiKey: string, config?: z.input<typeof NetHelpers.cfApiConfig>): Promise<import("cloudflare").Cloudflare>;
|
|
106
|
+
static loggingFetchInitLogging: z.ZodMiniDefault<z.ZodMiniObject<{
|
|
107
|
+
level: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
108
|
+
error: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
109
|
+
color: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
|
|
110
|
+
custom: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniFunction<z.ZodMiniTuple<readonly [z.ZodMiniAny], z.ZodMiniAny>, z.ZodMiniUnion<readonly [z.ZodMiniPromise<z.ZodMiniVoid>, z.ZodMiniVoid]>>, z.ZodMiniTransform<(args_0: any, ...args: any[]) => void | Promise<void>, z.core.$InferOuterFunctionType<z.ZodMiniTuple<readonly [z.ZodMiniAny], z.ZodMiniAny>, z.ZodMiniUnion<readonly [z.ZodMiniPromise<z.ZodMiniVoid>, z.ZodMiniVoid]>>>>>;
|
|
111
|
+
}, z.core.$strip>>;
|
|
112
|
+
static loggingFetchInit: z.ZodMiniObject<{
|
|
113
|
+
logging: z.ZodMiniDefault<z.ZodMiniObject<{
|
|
114
|
+
level: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
115
|
+
error: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
116
|
+
color: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
|
|
117
|
+
custom: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniFunction<z.ZodMiniTuple<readonly [z.ZodMiniAny], z.ZodMiniAny>, z.ZodMiniUnion<readonly [z.ZodMiniPromise<z.ZodMiniVoid>, z.ZodMiniVoid]>>, z.ZodMiniTransform<(args_0: any, ...args: any[]) => void | Promise<void>, z.core.$InferOuterFunctionType<z.ZodMiniTuple<readonly [z.ZodMiniAny], z.ZodMiniAny>, z.ZodMiniUnion<readonly [z.ZodMiniPromise<z.ZodMiniVoid>, z.ZodMiniVoid]>>>>>;
|
|
118
|
+
}, z.core.$strip>>;
|
|
119
|
+
}, z.core.$strip>;
|
|
220
120
|
/**
|
|
221
121
|
* A utility function that wraps the native `fetch` API with enhanced capabilities.
|
|
222
122
|
* This function allows for customizable logging of request and response details, including headers, body, and status, with support for colorized output and custom logging handlers.
|
|
@@ -288,12 +188,12 @@ export declare class NetHelpers {
|
|
|
288
188
|
* @returns {Record<string, number | null>} An object where keys are metric names (with optional descriptions) and values are the durations in milliseconds or null.
|
|
289
189
|
*/
|
|
290
190
|
static serverTiming(serverTimingHeader?: string): Record<string, number | null>;
|
|
291
|
-
static withRetryInit
|
|
292
|
-
maxRetries:
|
|
293
|
-
initialDelay:
|
|
294
|
-
maxDelay:
|
|
295
|
-
backoffFactor:
|
|
296
|
-
},
|
|
191
|
+
static withRetryInit: z.ZodMiniDefault<z.ZodMiniObject<{
|
|
192
|
+
maxRetries: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
193
|
+
initialDelay: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
194
|
+
maxDelay: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
195
|
+
backoffFactor: z.ZodMiniDefault<z.ZodMiniNumberFormat>;
|
|
196
|
+
}, z.core.$strip>>;
|
|
297
197
|
/**
|
|
298
198
|
* Executes an asynchronous operation with configurable retry logic.
|
|
299
199
|
*
|
|
@@ -319,5 +219,5 @@ export declare class NetHelpers {
|
|
|
319
219
|
* // With custom retry configuration
|
|
320
220
|
* await NetHelpers.withRetry(() => apiCall(), { maxRetries: 5, initialDelay: 200 })
|
|
321
221
|
*/
|
|
322
|
-
static withRetry<T>(operation: () => Promise<T>, config?:
|
|
222
|
+
static withRetry<T>(operation: () => Promise<T>, config?: z.input<typeof NetHelpers.withRetryInit>): Promise<T>;
|
|
323
223
|
}
|
package/dist/net.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as z from 'zod/mini';
|
|
1
2
|
/**
|
|
2
3
|
* Enum representing HTTP request methods.
|
|
3
4
|
*
|
|
@@ -16,87 +17,97 @@ export var Methods;
|
|
|
16
17
|
Methods["PATCH"] = "PATCH";
|
|
17
18
|
})(Methods || (Methods = {}));
|
|
18
19
|
export class NetHelpers {
|
|
19
|
-
static
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
20
|
+
static customLogging = z.function({
|
|
21
|
+
input: z.tuple([z.any()], z.any()),
|
|
22
|
+
output: z.union([z.promise(z.void()), z.void()]),
|
|
23
|
+
});
|
|
24
|
+
static cfApiConfig = z._default(z.object({
|
|
25
|
+
logging: z._default(z.object({
|
|
26
|
+
level: z._default(z.int().check(z.minimum(0), z.maximum(3)), 0),
|
|
27
|
+
error: z._default(z.int().check(z.minimum(0), z.maximum(3)), 1),
|
|
28
|
+
color: z._default(z.boolean(), true),
|
|
29
|
+
custom: z.optional(z.pipe(this.customLogging,
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
z.transform((fn) => fn))),
|
|
32
|
+
}), {
|
|
33
|
+
level: 0,
|
|
34
|
+
error: 1,
|
|
35
|
+
color: true,
|
|
36
|
+
}),
|
|
37
|
+
cf: z._default(z.object({
|
|
38
|
+
/**
|
|
39
|
+
* Whether Cloudflare Apps should be enabled for this request
|
|
40
|
+
* @link https://www.cloudflare.com/apps/
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
apps: z._default(z.boolean(), true),
|
|
44
|
+
/**
|
|
45
|
+
* Treats all content as static and caches all file types beyond the Cloudflare default cached content. Respects cache headers from the origin web server. This is equivalent to setting the Page Rule Cache Level (to Cache Everything).
|
|
46
|
+
* @default false
|
|
47
|
+
* @note This option applies to GET and HEAD request methods only
|
|
48
|
+
*/
|
|
49
|
+
cacheEverything: z._default(z.boolean(), false),
|
|
50
|
+
/**
|
|
51
|
+
* A request's cache key is what determines if two requests are the same for caching purposes. If a request has the same cache key as some previous request, then Cloudflare can serve the same cached response for both.
|
|
52
|
+
*/
|
|
53
|
+
cacheKey: z.optional(z.string().check(z.minLength(1))),
|
|
54
|
+
/**
|
|
55
|
+
* This option appends additional Cache-Tag headers to the response from the origin server. This allows for purges of cached content based on tags provided by the Worker, without modifications to the origin server. This is performed using the Purge by Tag feature.
|
|
56
|
+
*/
|
|
57
|
+
cacheTags: z.optional(z.array(z.string().check(z.minLength(1))).check(z.minLength(1))),
|
|
58
|
+
/**
|
|
59
|
+
* This option forces Cloudflare to cache the response for this request, regardless of what headers are seen on the response. This is equivalent to setting two Page Rules: Edge Cache TTL and Cache Level (to Cache Everything). The value must be zero or a positive number. A value of 0 indicates that the cache asset expires immediately.
|
|
60
|
+
* @note This option applies to GET and HEAD request methods only.
|
|
61
|
+
*/
|
|
62
|
+
cacheTtl: z.optional(z.int().check(z.nonnegative())),
|
|
63
|
+
/**
|
|
64
|
+
* This option is a version of the cacheTtl feature which chooses a TTL based on the response's status code. If the response to this request has a status code that matches, Cloudflare will cache for the instructed time and override cache instructives sent by the origin. For example: { "200-299": 86400, "404": 1, "500-599": 0 }. The value can be any integer, including zero and negative integers. A value of 0 indicates that the cache asset expires immediately. Any negative value instructs Cloudflare not to cache at all.
|
|
65
|
+
* @note This option applies to GET and HEAD request methods only.
|
|
66
|
+
*/
|
|
67
|
+
cacheTtlByStatus: z.optional(z.record(z.string().check(z.minLength(1), z.regex(/^(1|2|3|4|5)\d{2}(-(1|2|3|4|5)\d{2})?$/)), z.int())),
|
|
68
|
+
// image:
|
|
69
|
+
/**
|
|
70
|
+
* Whether Mirage should be enabled for this request, if otherwise configured for this zone.
|
|
71
|
+
* @link https://www.cloudflare.com/website-optimization/mirage/
|
|
72
|
+
* @default true
|
|
73
|
+
*/
|
|
74
|
+
mirage: z._default(z.boolean(), true),
|
|
75
|
+
/**
|
|
76
|
+
* Sets Polish mode. The possible values are lossy, lossless or off.
|
|
77
|
+
* @link https://blog.cloudflare.com/introducing-polish-automatic-image-optimizati/
|
|
78
|
+
*/
|
|
79
|
+
polish: z.optional(z.enum(['lossy', 'lossless', 'off'])),
|
|
80
|
+
// resolveOverride:
|
|
81
|
+
/**
|
|
82
|
+
* Whether ScrapeShield should be enabled for this request, if otherwise configured for this zone.
|
|
83
|
+
* @link https://blog.cloudflare.com/introducing-scrapeshield-discover-defend-dete/
|
|
84
|
+
* @default true
|
|
85
|
+
*/
|
|
86
|
+
scrapeShield: z._default(z.boolean(), true),
|
|
87
|
+
/**
|
|
88
|
+
* Enables or disables WebP image format in Polish.
|
|
89
|
+
* @link https://blog.cloudflare.com/a-very-webp-new-year-from-cloudflare/
|
|
90
|
+
*/
|
|
91
|
+
webp: z.optional(z.boolean()),
|
|
92
|
+
}), {
|
|
93
|
+
apps: true,
|
|
94
|
+
cacheEverything: false,
|
|
95
|
+
mirage: true,
|
|
96
|
+
scrapeShield: true,
|
|
97
|
+
}),
|
|
98
|
+
}), {
|
|
99
|
+
logging: {
|
|
100
|
+
level: 0,
|
|
101
|
+
error: 1,
|
|
102
|
+
color: true,
|
|
103
|
+
},
|
|
104
|
+
cf: {
|
|
105
|
+
apps: true,
|
|
106
|
+
cacheEverything: false,
|
|
107
|
+
mirage: true,
|
|
108
|
+
scrapeShield: true,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
100
111
|
/**
|
|
101
112
|
* Creates an instance of the Cloudflare API client with enhanced logging capabilities.
|
|
102
113
|
*
|
|
@@ -119,7 +130,7 @@ export class NetHelpers {
|
|
|
119
130
|
return Promise.all([
|
|
120
131
|
//
|
|
121
132
|
import('cloudflare'),
|
|
122
|
-
NetHelpers.cfApiConfig
|
|
133
|
+
NetHelpers.cfApiConfig.parseAsync(config),
|
|
123
134
|
]).then(([{ Cloudflare }, config]) => new Cloudflare({
|
|
124
135
|
apiToken: apiKey,
|
|
125
136
|
fetch: (info, init) => this.loggingFetch(info, {
|
|
@@ -134,7 +145,9 @@ export class NetHelpers {
|
|
|
134
145
|
error: config.logging.error === 1 ? 2 : config.logging.error,
|
|
135
146
|
...('color' in config.logging && { color: config.logging.color }),
|
|
136
147
|
...((config.logging.level > 0 || config.logging.error > 0) && {
|
|
137
|
-
custom: async (...
|
|
148
|
+
custom: this.customLogging.implementAsync(async (args_0, ...args_x) => {
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
150
|
+
const args = [args_0, ...args_x];
|
|
138
151
|
const [, id, , url, headers] = args;
|
|
139
152
|
const customUrl = new URL(url);
|
|
140
153
|
const customHeaders = new Headers(headers);
|
|
@@ -152,16 +165,28 @@ export class NetHelpers {
|
|
|
152
165
|
if ('custom' in config && config.logging.custom) {
|
|
153
166
|
// We faked level 1 as 2 to get headers for ray-id
|
|
154
167
|
if (config.logging.level === 1 || config.logging.error === 1) {
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
169
|
+
const [argsFirst, ...argsRest] = args.slice(0, -1);
|
|
155
170
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
156
|
-
return config.logging.custom(
|
|
171
|
+
return config.logging.custom(argsFirst, ...argsRest);
|
|
157
172
|
}
|
|
158
173
|
else {
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
175
|
+
const [argsFirst, ...argsRest] = args;
|
|
159
176
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
160
|
-
return config.logging.custom(...
|
|
177
|
+
return config.logging.custom(argsFirst, ...argsRest);
|
|
161
178
|
}
|
|
162
179
|
}
|
|
163
180
|
else {
|
|
164
|
-
await Promise.all([
|
|
181
|
+
await Promise.all([
|
|
182
|
+
// Try the new native one
|
|
183
|
+
import('node:util')
|
|
184
|
+
.then(({ stripVTControlCharacters }) => stripVTControlCharacters)
|
|
185
|
+
// For web or unavailable node in general
|
|
186
|
+
.catch(() => import('strip-ansi').then(({ default: stripAnsi }) => stripAnsi)),
|
|
187
|
+
import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })),
|
|
188
|
+
import("./index.mjs"),
|
|
189
|
+
]).then(([ansiStripper, chalk, { Helpers }]) => {
|
|
165
190
|
// We faked level 1 as 2 to get headers for ray-id
|
|
166
191
|
if (config.logging.level === 1) {
|
|
167
192
|
console.info('CF Rest',
|
|
@@ -174,9 +199,9 @@ export class NetHelpers {
|
|
|
174
199
|
// Wrap id in brackets
|
|
175
200
|
.map((value) => {
|
|
176
201
|
if (value === id) {
|
|
177
|
-
const wrappedString = `[${
|
|
202
|
+
const wrappedString = `[${ansiStripper(id)}]`;
|
|
178
203
|
if (config.logging.color) {
|
|
179
|
-
return chalk.rgb(...Helpers.uniqueIdColor(
|
|
204
|
+
return chalk.rgb(...Helpers.uniqueIdColor(ansiStripper(id)))(wrappedString);
|
|
180
205
|
}
|
|
181
206
|
else {
|
|
182
207
|
return wrappedString;
|
|
@@ -202,9 +227,9 @@ export class NetHelpers {
|
|
|
202
227
|
// Wrap id in brackets
|
|
203
228
|
.map((value) => {
|
|
204
229
|
if (value === id) {
|
|
205
|
-
const wrappedString = `[${
|
|
230
|
+
const wrappedString = `[${ansiStripper(id)}]`;
|
|
206
231
|
if (config.logging.color) {
|
|
207
|
-
return chalk.rgb(...Helpers.uniqueIdColor(
|
|
232
|
+
return chalk.rgb(...Helpers.uniqueIdColor(ansiStripper(id)))(wrappedString);
|
|
208
233
|
}
|
|
209
234
|
else {
|
|
210
235
|
return wrappedString;
|
|
@@ -229,9 +254,9 @@ export class NetHelpers {
|
|
|
229
254
|
// Wrap id in brackets
|
|
230
255
|
.map((value) => {
|
|
231
256
|
if (value === id) {
|
|
232
|
-
const wrappedString = `[${
|
|
257
|
+
const wrappedString = `[${ansiStripper(id)}]`;
|
|
233
258
|
if (config.logging.color) {
|
|
234
|
-
return chalk.rgb(...Helpers.uniqueIdColor(
|
|
259
|
+
return chalk.rgb(...Helpers.uniqueIdColor(ansiStripper(id)))(wrappedString);
|
|
235
260
|
}
|
|
236
261
|
else {
|
|
237
262
|
return wrappedString;
|
|
@@ -256,9 +281,9 @@ export class NetHelpers {
|
|
|
256
281
|
// Wrap id in brackets
|
|
257
282
|
.map((value) => {
|
|
258
283
|
if (value === id) {
|
|
259
|
-
const wrappedString = `[${
|
|
284
|
+
const wrappedString = `[${ansiStripper(id)}]`;
|
|
260
285
|
if (config.logging.color) {
|
|
261
|
-
return chalk.rgb(...Helpers.uniqueIdColor(
|
|
286
|
+
return chalk.rgb(...Helpers.uniqueIdColor(ansiStripper(id)))(wrappedString);
|
|
262
287
|
}
|
|
263
288
|
else {
|
|
264
289
|
return wrappedString;
|
|
@@ -275,30 +300,27 @@ export class NetHelpers {
|
|
|
275
300
|
}
|
|
276
301
|
});
|
|
277
302
|
}
|
|
278
|
-
},
|
|
303
|
+
}),
|
|
279
304
|
}),
|
|
280
305
|
},
|
|
281
306
|
}),
|
|
282
307
|
}));
|
|
283
308
|
}
|
|
284
|
-
static
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
})
|
|
300
|
-
.default({}));
|
|
301
|
-
}
|
|
309
|
+
static loggingFetchInitLogging = z._default(z.object({
|
|
310
|
+
level: z._default(z.int().check(z.minimum(0), z.maximum(3)), 0),
|
|
311
|
+
error: z._default(z.int().check(z.minimum(0), z.maximum(3)), 1),
|
|
312
|
+
color: z._default(z.boolean(), true),
|
|
313
|
+
custom: z.optional(z.pipe(this.customLogging,
|
|
314
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
315
|
+
z.transform((fn) => fn))),
|
|
316
|
+
}), {
|
|
317
|
+
level: 0,
|
|
318
|
+
error: 1,
|
|
319
|
+
color: true,
|
|
320
|
+
});
|
|
321
|
+
static loggingFetchInit = z.object({
|
|
322
|
+
logging: this.loggingFetchInitLogging,
|
|
323
|
+
});
|
|
302
324
|
/**
|
|
303
325
|
* A utility function that wraps the native `fetch` API with enhanced capabilities.
|
|
304
326
|
* This function allows for customizable logging of request and response details, including headers, body, and status, with support for colorized output and custom logging handlers.
|
|
@@ -335,9 +357,15 @@ export class NetHelpers {
|
|
|
335
357
|
*/
|
|
336
358
|
static loggingFetch(info, init) {
|
|
337
359
|
return Promise.all([
|
|
338
|
-
|
|
339
|
-
.
|
|
340
|
-
|
|
360
|
+
z
|
|
361
|
+
.pipe(z._default(z.looseObject(this.loggingFetchInit.def.shape), {
|
|
362
|
+
logging: {
|
|
363
|
+
level: 0,
|
|
364
|
+
error: 1,
|
|
365
|
+
color: true,
|
|
366
|
+
},
|
|
367
|
+
}), z.transform((parsed) => parsed))
|
|
368
|
+
.parseAsync(init),
|
|
341
369
|
import("./crypto.mjs").then(({ CryptoHelpers }) => CryptoHelpers.base62secret(8)),
|
|
342
370
|
]).then(async ([init, id]) => {
|
|
343
371
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -393,8 +421,10 @@ export class NetHelpers {
|
|
|
393
421
|
]).catch(() => { });
|
|
394
422
|
}
|
|
395
423
|
if (init.logging.level > 0 && 'custom' in init.logging && init.logging.custom) {
|
|
424
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
425
|
+
const [requestLoggingItemsFirst, ...requestLoggingItemsRest] = requestLoggingItems;
|
|
396
426
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
397
|
-
await init.logging.custom(...
|
|
427
|
+
await init.logging.custom(requestLoggingItemsFirst, ...requestLoggingItemsRest);
|
|
398
428
|
}
|
|
399
429
|
else if (init.logging.level > 0) {
|
|
400
430
|
console.info(
|
|
@@ -459,15 +489,21 @@ export class NetHelpers {
|
|
|
459
489
|
.catch(() => { });
|
|
460
490
|
}
|
|
461
491
|
if (init.logging.level > 0 && 'custom' in init.logging && init.logging.custom) {
|
|
492
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
493
|
+
const [responseLoggingItemsFirst, ...responseLoggingItemsRest] = responseLoggingItems;
|
|
462
494
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
463
|
-
await init.logging.custom(...
|
|
495
|
+
await init.logging.custom(responseLoggingItemsFirst, ...responseLoggingItemsRest);
|
|
464
496
|
}
|
|
465
497
|
else if (init.logging.error > 0 && !response.ok && 'custom' in init.logging && init.logging.custom) {
|
|
466
498
|
// Send request errors too (since we barely now know if error or not)
|
|
499
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
500
|
+
const [requestErrorItemsFirst, ...requestErrorItemsRest] = requestErrorItems;
|
|
467
501
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
468
|
-
await init.logging.custom(...
|
|
502
|
+
await init.logging.custom(requestErrorItemsFirst, ...requestErrorItemsRest);
|
|
503
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
504
|
+
const [responseErrorItemsFirst, ...responseErrorItemsRest] = responseErrorItems;
|
|
469
505
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
470
|
-
await init.logging.custom(...
|
|
506
|
+
await init.logging.custom(responseErrorItemsFirst, ...responseErrorItemsRest);
|
|
471
507
|
}
|
|
472
508
|
else if (init.logging.level > 0) {
|
|
473
509
|
console.info(
|
|
@@ -621,21 +657,17 @@ export class NetHelpers {
|
|
|
621
657
|
}
|
|
622
658
|
return result;
|
|
623
659
|
}
|
|
624
|
-
static withRetryInit(
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
maxDelay: 1000,
|
|
636
|
-
backoffFactor: 2,
|
|
637
|
-
}));
|
|
638
|
-
}
|
|
660
|
+
static withRetryInit = z._default(z.object({
|
|
661
|
+
maxRetries: z._default(z.int().check(z.nonnegative()), 3),
|
|
662
|
+
initialDelay: z._default(z.int().check(z.nonnegative()), 100),
|
|
663
|
+
maxDelay: z._default(z.int().check(z.nonnegative()), 1000),
|
|
664
|
+
backoffFactor: z._default(z.int().check(z.nonnegative()), 2),
|
|
665
|
+
}), {
|
|
666
|
+
maxRetries: 3,
|
|
667
|
+
initialDelay: 100,
|
|
668
|
+
maxDelay: 1000,
|
|
669
|
+
backoffFactor: 2,
|
|
670
|
+
});
|
|
639
671
|
/**
|
|
640
672
|
* Executes an asynchronous operation with configurable retry logic.
|
|
641
673
|
*
|
|
@@ -662,7 +694,7 @@ export class NetHelpers {
|
|
|
662
694
|
* await NetHelpers.withRetry(() => apiCall(), { maxRetries: 5, initialDelay: 200 })
|
|
663
695
|
*/
|
|
664
696
|
static withRetry(operation, config) {
|
|
665
|
-
return Promise.all([NetHelpers.withRetryInit
|
|
697
|
+
return Promise.all([NetHelpers.withRetryInit.parseAsync(config), import('./common.mjs')]).then(async ([config, { Helpers }]) => {
|
|
666
698
|
let lastError;
|
|
667
699
|
let delay = config.initialDelay;
|
|
668
700
|
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
package/dist/uuid8.d.mts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DOCombinedLocations } from '@chainfuse/types';
|
|
2
|
+
import { ShardType } from '@chainfuse/types/d0';
|
|
3
|
+
import * as z from 'zod/mini';
|
|
4
|
+
export declare const v8Options: z.ZodMiniUnion<readonly [z.ZodMiniObject<{
|
|
5
|
+
msecs: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniNumberFormat, z.ZodMiniPipe<z.ZodMiniDate<Date>, z.ZodMiniTransform<number, Date>>]>>;
|
|
6
|
+
seq: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
|
|
7
|
+
location: z.ZodMiniUnion<readonly [z.ZodMiniDefault<z.ZodMiniCustomStringFormat<"hex">>, z.ZodMiniPipe<z.ZodMiniDefault<z.ZodMiniEnum<typeof DOCombinedLocations>>, z.ZodMiniTransform<string, DOCombinedLocations>>]>;
|
|
8
|
+
shardType: z.ZodMiniUnion<readonly [z.ZodMiniDefault<z.ZodMiniCustomStringFormat<"hex">>, z.ZodMiniPipe<z.ZodMiniDefault<z.ZodMiniEnum<typeof ShardType>>, z.ZodMiniTransform<string, ShardType>>]>;
|
|
9
|
+
suffix: z.ZodMiniUnion<readonly [z.ZodMiniDefault<z.ZodMiniCustomStringFormat<"hex">>, z.ZodMiniPipe<z.ZodMiniDefault<z.ZodMiniCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>>, z.ZodMiniTransform<string, Uint8Array<ArrayBuffer>>>]>;
|
|
10
|
+
random: z.ZodMiniOptional<z.ZodMiniCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>>;
|
|
11
|
+
}, z.core.$strip>, z.ZodMiniObject<{
|
|
12
|
+
msecs: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniNumberFormat, z.ZodMiniPipe<z.ZodMiniDate<Date>, z.ZodMiniTransform<number, Date>>]>>;
|
|
13
|
+
seq: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
|
|
14
|
+
location: z.ZodMiniUnion<readonly [z.ZodMiniDefault<z.ZodMiniCustomStringFormat<"hex">>, z.ZodMiniPipe<z.ZodMiniDefault<z.ZodMiniEnum<typeof DOCombinedLocations>>, z.ZodMiniTransform<string, DOCombinedLocations>>]>;
|
|
15
|
+
shardType: z.ZodMiniUnion<readonly [z.ZodMiniDefault<z.ZodMiniCustomStringFormat<"hex">>, z.ZodMiniPipe<z.ZodMiniDefault<z.ZodMiniEnum<typeof ShardType>>, z.ZodMiniTransform<string, ShardType>>]>;
|
|
16
|
+
suffix: z.ZodMiniUnion<readonly [z.ZodMiniDefault<z.ZodMiniCustomStringFormat<"hex">>, z.ZodMiniPipe<z.ZodMiniDefault<z.ZodMiniCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>>, z.ZodMiniTransform<string, Uint8Array<ArrayBuffer>>>]>;
|
|
17
|
+
rng: z.ZodMiniOptional<z.ZodMiniFunction<z.ZodMiniTuple<[], null>, z.ZodMiniCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>>>;
|
|
18
|
+
}, z.core.$strip>]>;
|
|
19
|
+
export type Version8Options = z.input<typeof v8Options>;
|
|
20
|
+
/**
|
|
21
|
+
* Generates a UUID version 8 with custom fields for location, shard type, and suffix.
|
|
22
|
+
*
|
|
23
|
+
* This function creates a UUID v8 by starting with a UUID v7 and then injecting custom fields into specific positions to encode regional information, shard types, and additional suffixes for distributed system identification.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Configuration options for UUID generation
|
|
26
|
+
* @param options.msecs - RFC "timestamp" field - milliseconds since epoch or Date object
|
|
27
|
+
* @param options.seq - 32-bit sequence number (0 - 0xffffffff) for uniqueness within same millisecond
|
|
28
|
+
* @param options.location - Location identifier as hex string or DOCombinedLocations enum
|
|
29
|
+
* @param options.shardType - Shard type as hex string or ShardType enum
|
|
30
|
+
* @param options.suffix - Custom suffix as hex string or Uint8Array of 2 bytes
|
|
31
|
+
* @param options.random - Array of 16 random bytes for UUID generation
|
|
32
|
+
* @param options.rng - Alternative random number generator function
|
|
33
|
+
*
|
|
34
|
+
* @returns A UUID v8 string with embedded location, shard type, and suffix information
|
|
35
|
+
*/
|
|
36
|
+
export declare function v8(_options?: Version8Options): string;
|
|
37
|
+
export default v8;
|
package/dist/uuid8.mjs
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { DOCombinedLocations } from '@chainfuse/types';
|
|
2
|
+
import { ShardType } from '@chainfuse/types/d0';
|
|
3
|
+
import { v7 } from 'uuid';
|
|
4
|
+
import * as z from 'zod/mini';
|
|
5
|
+
import { BufferHelpersInternals } from "./bufferInternals.mjs";
|
|
6
|
+
const v8OptionsBase = z.object({
|
|
7
|
+
/**
|
|
8
|
+
* RFC "timestamp" field
|
|
9
|
+
*/
|
|
10
|
+
msecs: z.optional(z.union([
|
|
11
|
+
z.int().check(z.nonnegative()),
|
|
12
|
+
// Allow converting from Date object
|
|
13
|
+
z.pipe(z.date(), z.transform((date) => date.getTime())),
|
|
14
|
+
])),
|
|
15
|
+
/**
|
|
16
|
+
* 32-bit sequence Number between 0 - 0xffffffff. This may be provided to help ensure uniqueness for UUIDs generated within the same millisecond time interval. Default = random value.
|
|
17
|
+
*/
|
|
18
|
+
seq: z.optional(z.int().check(z.minimum(0), z.maximum(0xffffffff))),
|
|
19
|
+
location: z.union([
|
|
20
|
+
//
|
|
21
|
+
z._default(z.hex().check(z.length(2)), '00'),
|
|
22
|
+
z.pipe(z._default(z.enum(DOCombinedLocations), DOCombinedLocations.none), z.transform((l) => l.toString(16).padStart(2, '0').slice(-2))),
|
|
23
|
+
]),
|
|
24
|
+
shardType: z.union([
|
|
25
|
+
//
|
|
26
|
+
z._default(z.hex().check(z.length(1)), '0'),
|
|
27
|
+
z.pipe(z._default(z.enum(ShardType), ShardType.Director), z.transform((st) => st.toString(16).padStart(1, '0'))),
|
|
28
|
+
]),
|
|
29
|
+
suffix: z.union([
|
|
30
|
+
z._default(z.hex().check(z.length(3)), '000'),
|
|
31
|
+
// It's technically 1.5 bytes, but we round up to nearest integer
|
|
32
|
+
z.pipe(z._default(z.instanceof(Uint8Array).check(z.refine((arr) => arr.byteLength === 2, { message: 'suffix must be a Uint8Array of 2 bytes' })), new Uint8Array(2)), z.transform((arr) => BufferHelpersInternals.browser_bufferToHex(arr.buffer).padStart(3, '0').slice(-3))),
|
|
33
|
+
]),
|
|
34
|
+
});
|
|
35
|
+
export const v8Options = z.union([
|
|
36
|
+
z.extend(v8OptionsBase, {
|
|
37
|
+
/**
|
|
38
|
+
* Array of 16 random bytes (0-255) used to generate other fields
|
|
39
|
+
*/
|
|
40
|
+
random: z.optional(z.instanceof(Uint8Array).check(z.refine((arr) => arr.byteLength === 16, { message: '`random` must be a Uint8Array of 16 random bytes' }))),
|
|
41
|
+
}),
|
|
42
|
+
z.extend(v8OptionsBase, {
|
|
43
|
+
/**
|
|
44
|
+
* Alternative to options.random, a Function that returns an Array of 16 random bytes (0-255)
|
|
45
|
+
*/
|
|
46
|
+
rng: z.optional(z.function({
|
|
47
|
+
input: [],
|
|
48
|
+
output: z.instanceof(Uint8Array).check(z.refine((arr) => arr.byteLength === 16, { message: '`random` must be a Uint8Array of 16 random bytes' })),
|
|
49
|
+
})),
|
|
50
|
+
}),
|
|
51
|
+
]);
|
|
52
|
+
function replaceByIndex(input, start, end, replacement) {
|
|
53
|
+
return input.slice(0, start) + replacement + input.slice(end);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Generates a UUID version 8 with custom fields for location, shard type, and suffix.
|
|
57
|
+
*
|
|
58
|
+
* This function creates a UUID v8 by starting with a UUID v7 and then injecting custom fields into specific positions to encode regional information, shard types, and additional suffixes for distributed system identification.
|
|
59
|
+
*
|
|
60
|
+
* @param options - Configuration options for UUID generation
|
|
61
|
+
* @param options.msecs - RFC "timestamp" field - milliseconds since epoch or Date object
|
|
62
|
+
* @param options.seq - 32-bit sequence number (0 - 0xffffffff) for uniqueness within same millisecond
|
|
63
|
+
* @param options.location - Location identifier as hex string or DOCombinedLocations enum
|
|
64
|
+
* @param options.shardType - Shard type as hex string or ShardType enum
|
|
65
|
+
* @param options.suffix - Custom suffix as hex string or Uint8Array of 2 bytes
|
|
66
|
+
* @param options.random - Array of 16 random bytes for UUID generation
|
|
67
|
+
* @param options.rng - Alternative random number generator function
|
|
68
|
+
*
|
|
69
|
+
* @returns A UUID v8 string with embedded location, shard type, and suffix information
|
|
70
|
+
*/
|
|
71
|
+
export function v8(_options) {
|
|
72
|
+
const options = v8Options.parse(_options ?? {});
|
|
73
|
+
// 36 character string including hyphens
|
|
74
|
+
const uuid7 = v7(options);
|
|
75
|
+
// Swap version
|
|
76
|
+
const uuid8 = replaceByIndex(uuid7, 14, 15, '8');
|
|
77
|
+
// Inject
|
|
78
|
+
const uuid8Suffix = replaceByIndex(uuid8, 15, 18, options.suffix);
|
|
79
|
+
const uuid8SuffixLocation = replaceByIndex(uuid8Suffix, 20, 22, options.location);
|
|
80
|
+
const uuid8SuffixLocationShard = replaceByIndex(uuid8SuffixLocation, 22, 23, options.shardType);
|
|
81
|
+
return uuid8SuffixLocationShard;
|
|
82
|
+
}
|
|
83
|
+
export default v8;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainfuse/helpers",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "ChainFuse",
|
|
6
6
|
"homepage": "https://github.com/ChainFuse/packages/tree/main/packages/helpers#readme",
|
|
@@ -72,11 +72,15 @@
|
|
|
72
72
|
"./net": {
|
|
73
73
|
"import": "./dist/net.mjs",
|
|
74
74
|
"types": "./dist/net.d.mts"
|
|
75
|
+
},
|
|
76
|
+
"./uuid8": {
|
|
77
|
+
"import": "./dist/uuid8.mjs",
|
|
78
|
+
"types": "./dist/uuid8.d.mts"
|
|
75
79
|
}
|
|
76
80
|
},
|
|
77
81
|
"prettier": "@demosjarco/prettier-config",
|
|
78
82
|
"dependencies": {
|
|
79
|
-
"@chainfuse/types": "^2.
|
|
83
|
+
"@chainfuse/types": "^2.12.1",
|
|
80
84
|
"@discordjs/rest": "^2.6.0",
|
|
81
85
|
"chalk": "^5.6.2",
|
|
82
86
|
"cloudflare": "^5.0.0",
|
|
@@ -86,8 +90,8 @@
|
|
|
86
90
|
"zod": "^4.1.5"
|
|
87
91
|
},
|
|
88
92
|
"devDependencies": {
|
|
89
|
-
"@cloudflare/workers-types": "^4.
|
|
93
|
+
"@cloudflare/workers-types": "^4.20250909.0",
|
|
90
94
|
"@types/node": "^22.18.1"
|
|
91
95
|
},
|
|
92
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "4259cf9c169a4aced88159526927fe52bde6d658"
|
|
93
97
|
}
|