hanzio 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,17 +2,19 @@
2
2
 
3
3
  A small TypeScript-first utility library for common application code: arrays,
4
4
  strings, promises, caching, state machines, dates, URLs, Zod helpers, API clients,
5
- JWTs, gzip, sitemap crawling, queues, secrets, and colorful terminal logging.
5
+ JWTs, sitemap crawling, queues, secrets, and colorful terminal logging.
6
6
 
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- bun add hanzio
10
+ bun add hanzio zod
11
11
  ```
12
12
 
13
13
  The package is ESM and Bun-friendly. Bun consumers resolve the `bun` export to
14
14
  the source TypeScript files, while Node/bundler consumers resolve built files
15
15
  from `dist`.
16
+ `zod` is a peer dependency because the Zod helpers and API wrapper share the
17
+ consumer application's Zod instance.
16
18
 
17
19
  ## Imports
18
20
 
@@ -27,10 +29,10 @@ Heavier or dependency-specific modules are also available as subpath exports:
27
29
  ```ts
28
30
  import { createZId } from 'hanzio/zod'
29
31
  import { jwtSign } from 'hanzio/jwt'
30
- import { compressString } from 'hanzio/gzip'
31
32
  import { getDomainSitemap } from 'hanzio/sitemap'
32
33
  import PQueue from 'hanzio/p-queue'
33
34
  import { createCoolLogger } from 'hanzio/cool-console-log'
35
+ import { defineSecretSet } from 'hanzio/secrets'
34
36
  ```
35
37
 
36
38
  The package currently publishes `src/**/*.ts` intentionally so Bun can consume
@@ -217,7 +219,7 @@ await promiseTimeout(250)
217
219
  Infisical before the rest of the program starts.
218
220
 
219
221
  ```ts
220
- import { defineSecretSet } from 'hanzio'
222
+ import { defineSecretSet } from 'hanzio/secrets'
221
223
 
222
224
  export const backendSecrets = await defineSecretSet(
223
225
  ['DATABASE_URL', 'APP_SECRET'] as const,
@@ -229,7 +231,8 @@ const databaseUrl = backendSecrets.secret('DATABASE_URL')
229
231
 
230
232
  For Vite config, `viteSecretSetPlugin(secretSet)` exposes the loaded values as
231
233
  `import.meta.env.*` replacements. Use `getViteDefine(secretSet)` if you need the
232
- raw `define` object.
234
+ raw `define` object. Import Vite helpers from `hanzio/secrets/vite` so browser
235
+ bundles do not pull in the Infisical SDK.
233
236
 
234
237
  ### Cache
235
238
 
@@ -470,17 +473,6 @@ const token = await jwtSign({ sub: 'user_1' }, 'secret')
470
473
  const payload = await jwtVerify<{ sub: string }>(token, 'secret')
471
474
  ```
472
475
 
473
- ### Gzip
474
-
475
- `compressString` and `decompressString` gzip roundtrip strings as base64.
476
-
477
- ```ts
478
- import { compressString, decompressString } from 'hanzio/gzip'
479
-
480
- const compressed = compressString('hello')
481
- const text = decompressString(compressed)
482
- ```
483
-
484
476
  ### Sitemap
485
477
 
486
478
  `getDomainSitemap` discovers and crawls sitemap URLs for a domain.
package/dist/index.d.ts CHANGED
@@ -12,6 +12,5 @@ export * from './api-wrapper';
12
12
  export * from './p-queue';
13
13
  export * from './cool-console-log';
14
14
  export * from './jwt';
15
- export * from './gzip';
16
15
  export * from './sitemap';
17
16
  export * from './secrets';
@@ -1,3 +1,3 @@
1
- import * as jose from 'jose';
2
- export declare function jwtSign<_Payload extends object>(payload: jose.JWTPayload, secret: string): Promise<string>;
3
- export declare function jwtVerify<Payload extends object>(token: string, secret: string): Promise<Payload | null>;
1
+ export type JWTPayload = Record<string, unknown>;
2
+ export declare function jwtSign<Payload extends JWTPayload>(payload: Payload, secret: string): Promise<string>;
3
+ export declare function jwtVerify<Payload extends JWTPayload>(token: string, secret: string): Promise<Payload | null>;
@@ -6,7 +6,6 @@ export type DefineSecretSetOptions<SecretKey extends string> = {
6
6
  readonly clientIdEnvKey?: string;
7
7
  readonly clientSecretEnvKey?: string;
8
8
  readonly loader?: SecretSetLoader<SecretKey>;
9
- readonly getLocalIp?: () => string;
10
9
  };
11
10
  export type SecretSetLoaderContext<SecretKey extends string> = {
12
11
  readonly keys: readonly SecretKey[];
@@ -22,6 +21,7 @@ export type SecretSet<SecretKey extends string> = {
22
21
  secrets: () => Record<SecretKey, string>;
23
22
  reload: () => Promise<SecretSet<SecretKey>>;
24
23
  };
24
+ export * from './infisical';
25
25
  export * from './vite';
26
26
  export declare function getSecretEnvironment(): SecretEnvironment;
27
27
  export declare function defineSecretSet<const SecretKeys extends readonly string[]>(keys: SecretKeys, options: DefineSecretSetOptions<SecretKeys[number]>): Promise<SecretSet<SecretKeys[number]>>;
@@ -0,0 +1,2 @@
1
+ import type { SecretSetLoaderContext } from '.';
2
+ export declare function loadInfisicalSecrets<SecretKey extends string>({ keys, projectId, environment, siteUrl, clientIdEnvKey, clientSecretEnvKey }: SecretSetLoaderContext<SecretKey>): Promise<Partial<Record<SecretKey, string>>>;
package/dist/src/index.js CHANGED
@@ -880,32 +880,110 @@ class PQueue {
880
880
  }
881
881
 
882
882
  // src/jwt/index.ts
883
- import * as jose from "jose";
883
+ var BYTE_CHUNK_SIZE = 32768;
884
+ var textEncoder = new TextEncoder;
885
+ var textDecoder = new TextDecoder;
884
886
  async function jwtSign(payload, secret) {
885
- const secretKey = new TextEncoder().encode(secret);
886
- return await new jose.SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().sign(secretKey);
887
+ const header = encodeJson({ alg: "HS256" });
888
+ const body = encodeJson({
889
+ ...payload,
890
+ iat: Math.floor(Date.now() / 1000)
891
+ });
892
+ const data = `${header}.${body}`;
893
+ const signature = await sign(data, secret);
894
+ return `${data}.${encodeBase64Url(signature)}`;
887
895
  }
888
- async function jwtVerify2(token, secret) {
896
+ async function jwtVerify(token, secret) {
889
897
  try {
890
- const secretKey = new TextEncoder().encode(secret);
891
- const { payload } = await jose.jwtVerify(token, secretKey);
898
+ const parts = token.split(".");
899
+ if (parts.length !== 3)
900
+ return null;
901
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
902
+ const header = decodeJson(encodedHeader);
903
+ if (!isJwtHeader(header))
904
+ return null;
905
+ const data = `${encodedHeader}.${encodedPayload}`;
906
+ const signature = decodeBase64Url(encodedSignature);
907
+ const isValid = await verify(data, signature, secret);
908
+ if (!isValid)
909
+ return null;
910
+ const payload = decodeJson(encodedPayload);
911
+ if (!isJwtPayload(payload) || !isTimeValid(payload))
912
+ return null;
892
913
  return payload;
893
914
  } catch (_error) {
894
915
  return null;
895
916
  }
896
917
  }
897
-
898
- // src/gzip/index.ts
899
- import pako from "pako";
900
- function compressString(input) {
901
- const uint8Array = new TextEncoder().encode(input);
902
- const compressed = pako.deflate(uint8Array);
903
- return btoa(String.fromCharCode.apply(null, compressed));
904
- }
905
- function decompressString(compressedString) {
906
- const compressedData = new Uint8Array(atob(compressedString).split("").map((char) => char.charCodeAt(0)));
907
- const decompressed = pako.inflate(compressedData);
908
- return new TextDecoder().decode(decompressed);
918
+ async function sign(data, secret) {
919
+ const key = await getKey(secret, ["sign"]);
920
+ return await getSubtleCrypto().sign("HMAC", key, encodeText(data));
921
+ }
922
+ async function verify(data, signature, secret) {
923
+ const key = await getKey(secret, ["verify"]);
924
+ return await getSubtleCrypto().verify("HMAC", key, signature, encodeText(data));
925
+ }
926
+ async function getKey(secret, usages) {
927
+ return await getSubtleCrypto().importKey("raw", encodeText(secret), {
928
+ name: "HMAC",
929
+ hash: "SHA-256"
930
+ }, false, usages);
931
+ }
932
+ function encodeJson(value) {
933
+ return encodeBase64Url(encodeText(JSON.stringify(value)));
934
+ }
935
+ function decodeJson(value) {
936
+ return JSON.parse(textDecoder.decode(decodeBase64Url(value)));
937
+ }
938
+ function encodeBase64Url(value) {
939
+ const bytes = value instanceof ArrayBuffer ? new Uint8Array(value) : value;
940
+ return btoa(bytesToBinaryString(bytes)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
941
+ }
942
+ function decodeBase64Url(value) {
943
+ const base64 = value.replaceAll("-", "+").replaceAll("_", "/");
944
+ const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
945
+ return binaryStringToBytes(atob(padded)).buffer;
946
+ }
947
+ function encodeText(value) {
948
+ return toArrayBuffer(textEncoder.encode(value));
949
+ }
950
+ function toArrayBuffer(bytes) {
951
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
952
+ }
953
+ function bytesToBinaryString(bytes) {
954
+ let binary = "";
955
+ for (let offset = 0;offset < bytes.length; offset += BYTE_CHUNK_SIZE) {
956
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + BYTE_CHUNK_SIZE));
957
+ }
958
+ return binary;
959
+ }
960
+ function binaryStringToBytes(binary) {
961
+ const bytes = new Uint8Array(binary.length);
962
+ for (let index = 0;index < binary.length; index += 1) {
963
+ bytes[index] = binary.charCodeAt(index);
964
+ }
965
+ return bytes;
966
+ }
967
+ function getSubtleCrypto() {
968
+ const subtle = globalThis.crypto?.subtle;
969
+ if (!subtle) {
970
+ throw new Error("Web Crypto is not available in this runtime");
971
+ }
972
+ return subtle;
973
+ }
974
+ function isJwtHeader(value) {
975
+ return typeof value === "object" && value !== null && "alg" in value && value.alg === "HS256";
976
+ }
977
+ function isJwtPayload(value) {
978
+ return typeof value === "object" && value !== null && !Array.isArray(value);
979
+ }
980
+ function isTimeValid(payload) {
981
+ const now = Math.floor(Date.now() / 1000);
982
+ if (typeof payload.exp === "number" && now >= payload.exp)
983
+ return false;
984
+ if (typeof payload.nbf === "number" && now < payload.nbf)
985
+ return false;
986
+ return true;
909
987
  }
910
988
 
911
989
  // src/sitemap/index.ts
@@ -1023,6 +1101,98 @@ var getDomainSitemap = async (domain, options = {}) => {
1023
1101
  return [...result.links];
1024
1102
  };
1025
1103
 
1104
+ // src/secrets/infisical.ts
1105
+ import { z as z4 } from "zod";
1106
+ var defaultFetch = globalThis.fetch;
1107
+ var infisicalAuthResponseSchema = z4.object({
1108
+ accessToken: z4.string()
1109
+ });
1110
+ var infisicalSecretSchema = z4.object({
1111
+ secretKey: z4.string(),
1112
+ secretValue: z4.string()
1113
+ });
1114
+ var infisicalSecretsResponseSchema = z4.object({
1115
+ secrets: z4.array(infisicalSecretSchema)
1116
+ });
1117
+ async function loadInfisicalSecrets({
1118
+ keys,
1119
+ projectId,
1120
+ environment,
1121
+ siteUrl,
1122
+ clientIdEnvKey,
1123
+ clientSecretEnvKey
1124
+ }) {
1125
+ const clientId = process.env[clientIdEnvKey];
1126
+ const clientSecret = process.env[clientSecretEnvKey];
1127
+ if (!clientId || !clientSecret) {
1128
+ throw new Error("Missing Infisical credentials");
1129
+ }
1130
+ const infisical = createInfisicalApiClient(siteUrl);
1131
+ const { data: auth } = await infisical.request("login", {
1132
+ reqBody: {
1133
+ clientId,
1134
+ clientSecret
1135
+ }
1136
+ });
1137
+ const { data } = await infisical.request("listSecrets", {
1138
+ reqHeaders: {
1139
+ Authorization: `Bearer ${auth.accessToken}`
1140
+ },
1141
+ reqQuery: {
1142
+ environment,
1143
+ projectId,
1144
+ secretPath: "/",
1145
+ viewSecretValue: true,
1146
+ expandSecretReferences: true,
1147
+ includeImports: true
1148
+ }
1149
+ });
1150
+ const wantedKeys = new Set(keys);
1151
+ return Object.fromEntries(data.secrets.filter((secret) => wantedKeys.has(secret.secretKey)).map((secret) => [secret.secretKey, secret.secretValue]));
1152
+ }
1153
+ function createInfisicalApiClient(siteUrl) {
1154
+ return createApiClient({
1155
+ name: "infisical",
1156
+ baseApiUrls: {
1157
+ infisical: siteUrl
1158
+ },
1159
+ defaultBaseApiUrl: "infisical",
1160
+ fetch: getFetch(),
1161
+ retries: 1,
1162
+ endpoints: {
1163
+ login: {
1164
+ method: "POST",
1165
+ path: "/api/v1/auth/universal-auth/login",
1166
+ reqBodySchema: z4.object({
1167
+ clientId: z4.string(),
1168
+ clientSecret: z4.string()
1169
+ }),
1170
+ resSchema: infisicalAuthResponseSchema,
1171
+ reqBodyFormat: "json"
1172
+ },
1173
+ listSecrets: {
1174
+ method: "GET",
1175
+ path: "/api/v4/secrets",
1176
+ reqHeadersSchema: z4.object({
1177
+ Authorization: z4.string()
1178
+ }),
1179
+ reqQuerySchema: z4.object({
1180
+ projectId: z4.string(),
1181
+ environment: z4.string(),
1182
+ secretPath: z4.string(),
1183
+ viewSecretValue: z4.boolean(),
1184
+ expandSecretReferences: z4.boolean(),
1185
+ includeImports: z4.boolean()
1186
+ }),
1187
+ resSchema: infisicalSecretsResponseSchema
1188
+ }
1189
+ }
1190
+ });
1191
+ }
1192
+ function getFetch() {
1193
+ return globalThis.fetch ?? defaultFetch;
1194
+ }
1195
+
1026
1196
  // src/secrets/vite.ts
1027
1197
  function getViteDefine(secretSet) {
1028
1198
  return Object.fromEntries(Object.entries(secretSet.secrets()).map(([key, value]) => [
@@ -1039,10 +1209,6 @@ function viteSecretSetPlugin(secretSet) {
1039
1209
  };
1040
1210
  }
1041
1211
 
1042
- // src/secrets/index.ts
1043
- import { InfisicalSDK } from "@infisical/sdk";
1044
- import { networkInterfaces } from "node:os";
1045
-
1046
1212
  // src/cool-console-log/index.ts
1047
1213
  var terminalColors = {
1048
1214
  reset: "\x1B[0m",
@@ -1150,8 +1316,6 @@ function logBanner(text, color = "cyan", options = {}) {
1150
1316
 
1151
1317
  // src/secrets/index.ts
1152
1318
  var DEFAULT_INFISICAL_SITE_URL = "https://eu.infisical.com";
1153
- var LOCAL_IP_VALUE = "LOCAL_IP";
1154
- var VPN_INTERFACE_RE = /^(utun|tun|tailscale|wg|ipsec|ppp)/i;
1155
1319
  var logger = createCoolLogger();
1156
1320
  function getSecretEnvironment() {
1157
1321
  const env = process.env.SECRETS_ENV || "development";
@@ -1164,13 +1328,7 @@ function getSecretEnvironment() {
1164
1328
  async function defineSecretSet(keys, options) {
1165
1329
  const keySet = [...new Set(keys)];
1166
1330
  const loader = options.loader ?? loadInfisicalSecrets;
1167
- const getLocalIp = options.getLocalIp ?? getLocalIpAddress;
1168
1331
  let cachedSecrets = null;
1169
- const resolveValue = (value) => {
1170
- if (value === LOCAL_IP_VALUE)
1171
- return getLocalIp();
1172
- return value;
1173
- };
1174
1332
  const loadSecrets = async (force = false) => {
1175
1333
  const envSecrets = readEnvSecrets(keySet, force ? cachedSecrets : null);
1176
1334
  const keysMissingFromEnv = keySet.filter((key) => !envSecrets[key]);
@@ -1190,7 +1348,7 @@ async function defineSecretSet(keys, options) {
1190
1348
  }
1191
1349
  const nextSecrets = Object.fromEntries(keySet.map((key) => [
1192
1350
  key,
1193
- resolveValue(envSecrets[key] ?? loadedSecrets[key])
1351
+ envSecrets[key] ?? loadedSecrets[key]
1194
1352
  ]));
1195
1353
  for (const [key, value] of Object.entries(nextSecrets)) {
1196
1354
  process.env[key] = value;
@@ -1204,7 +1362,7 @@ async function defineSecretSet(keys, options) {
1204
1362
  if (!value) {
1205
1363
  throw new Error(`Secret ${key} not found`);
1206
1364
  }
1207
- return resolveValue(value);
1365
+ return value;
1208
1366
  },
1209
1367
  secrets() {
1210
1368
  if (!cachedSecrets) {
@@ -1220,31 +1378,6 @@ async function defineSecretSet(keys, options) {
1220
1378
  await loadSecrets();
1221
1379
  return secretSet;
1222
1380
  }
1223
- async function loadInfisicalSecrets({
1224
- keys,
1225
- projectId,
1226
- environment,
1227
- siteUrl,
1228
- clientIdEnvKey,
1229
- clientSecretEnvKey
1230
- }) {
1231
- const clientId = process.env[clientIdEnvKey];
1232
- const clientSecret = process.env[clientSecretEnvKey];
1233
- if (!clientId || !clientSecret) {
1234
- throw new Error("Missing Infisical credentials");
1235
- }
1236
- const client = new InfisicalSDK({ siteUrl });
1237
- await client.auth().universalAuth.login({
1238
- clientId,
1239
- clientSecret
1240
- });
1241
- const { secrets } = await client.secrets().listSecrets({
1242
- environment,
1243
- projectId
1244
- });
1245
- const wantedKeys = new Set(keys);
1246
- return Object.fromEntries(secrets.filter((secret) => wantedKeys.has(secret.secretKey)).map((secret) => [secret.secretKey, secret.secretValue]));
1247
- }
1248
1381
  function resolveEnvironment(environment) {
1249
1382
  if (typeof environment === "function")
1250
1383
  return environment();
@@ -1262,22 +1395,6 @@ function readEnvSecrets(keys, previousSecrets = null) {
1262
1395
  return value && value !== previousSecrets?.[key];
1263
1396
  }).map((key) => [key, process.env[key]]));
1264
1397
  }
1265
- function getLocalIpAddress() {
1266
- const interfaces = networkInterfaces();
1267
- for (const name of Object.keys(interfaces)) {
1268
- if (VPN_INTERFACE_RE.test(name))
1269
- continue;
1270
- const nets = interfaces[name];
1271
- if (!nets)
1272
- continue;
1273
- for (const net of nets) {
1274
- if (net.family === "IPv4" && !net.internal) {
1275
- return net.address;
1276
- }
1277
- }
1278
- }
1279
- return "127.0.0.1";
1280
- }
1281
1398
 
1282
1399
  // src/typedswitch/index.ts
1283
1400
  function runSwitch(value, keyOrCases, casesOrDefault, defaultCase) {
@@ -1935,9 +2052,10 @@ export {
1935
2052
  normalizeSingleOrArray,
1936
2053
  logOperationSummary,
1937
2054
  logBanner,
2055
+ loadInfisicalSecrets,
1938
2056
  linearRegressionTrend,
1939
2057
  keyBy,
1940
- jwtVerify2 as jwtVerify,
2058
+ jwtVerify,
1941
2059
  jwtSign,
1942
2060
  jsonToZodSchemaMapper,
1943
2061
  isSuccess,
@@ -1957,13 +2075,11 @@ export {
1957
2075
  findArrayDifferenceByKey,
1958
2076
  extractNumber,
1959
2077
  defineSecretSet,
1960
- decompressString,
1961
2078
  createZId,
1962
2079
  createResolveColorsByKeys,
1963
2080
  createCoolLogger,
1964
2081
  createApiWrapper,
1965
2082
  createApiClient,
1966
- compressString,
1967
2083
  compact,
1968
2084
  colorize,
1969
2085
  chunkArray,
@@ -1,19 +1,110 @@
1
1
  // src/jwt/index.ts
2
- import * as jose from "jose";
2
+ var BYTE_CHUNK_SIZE = 32768;
3
+ var textEncoder = new TextEncoder;
4
+ var textDecoder = new TextDecoder;
3
5
  async function jwtSign(payload, secret) {
4
- const secretKey = new TextEncoder().encode(secret);
5
- return await new jose.SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().sign(secretKey);
6
+ const header = encodeJson({ alg: "HS256" });
7
+ const body = encodeJson({
8
+ ...payload,
9
+ iat: Math.floor(Date.now() / 1000)
10
+ });
11
+ const data = `${header}.${body}`;
12
+ const signature = await sign(data, secret);
13
+ return `${data}.${encodeBase64Url(signature)}`;
6
14
  }
7
- async function jwtVerify2(token, secret) {
15
+ async function jwtVerify(token, secret) {
8
16
  try {
9
- const secretKey = new TextEncoder().encode(secret);
10
- const { payload } = await jose.jwtVerify(token, secretKey);
17
+ const parts = token.split(".");
18
+ if (parts.length !== 3)
19
+ return null;
20
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
21
+ const header = decodeJson(encodedHeader);
22
+ if (!isJwtHeader(header))
23
+ return null;
24
+ const data = `${encodedHeader}.${encodedPayload}`;
25
+ const signature = decodeBase64Url(encodedSignature);
26
+ const isValid = await verify(data, signature, secret);
27
+ if (!isValid)
28
+ return null;
29
+ const payload = decodeJson(encodedPayload);
30
+ if (!isJwtPayload(payload) || !isTimeValid(payload))
31
+ return null;
11
32
  return payload;
12
33
  } catch (_error) {
13
34
  return null;
14
35
  }
15
36
  }
37
+ async function sign(data, secret) {
38
+ const key = await getKey(secret, ["sign"]);
39
+ return await getSubtleCrypto().sign("HMAC", key, encodeText(data));
40
+ }
41
+ async function verify(data, signature, secret) {
42
+ const key = await getKey(secret, ["verify"]);
43
+ return await getSubtleCrypto().verify("HMAC", key, signature, encodeText(data));
44
+ }
45
+ async function getKey(secret, usages) {
46
+ return await getSubtleCrypto().importKey("raw", encodeText(secret), {
47
+ name: "HMAC",
48
+ hash: "SHA-256"
49
+ }, false, usages);
50
+ }
51
+ function encodeJson(value) {
52
+ return encodeBase64Url(encodeText(JSON.stringify(value)));
53
+ }
54
+ function decodeJson(value) {
55
+ return JSON.parse(textDecoder.decode(decodeBase64Url(value)));
56
+ }
57
+ function encodeBase64Url(value) {
58
+ const bytes = value instanceof ArrayBuffer ? new Uint8Array(value) : value;
59
+ return btoa(bytesToBinaryString(bytes)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
60
+ }
61
+ function decodeBase64Url(value) {
62
+ const base64 = value.replaceAll("-", "+").replaceAll("_", "/");
63
+ const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
64
+ return binaryStringToBytes(atob(padded)).buffer;
65
+ }
66
+ function encodeText(value) {
67
+ return toArrayBuffer(textEncoder.encode(value));
68
+ }
69
+ function toArrayBuffer(bytes) {
70
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
71
+ }
72
+ function bytesToBinaryString(bytes) {
73
+ let binary = "";
74
+ for (let offset = 0;offset < bytes.length; offset += BYTE_CHUNK_SIZE) {
75
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + BYTE_CHUNK_SIZE));
76
+ }
77
+ return binary;
78
+ }
79
+ function binaryStringToBytes(binary) {
80
+ const bytes = new Uint8Array(binary.length);
81
+ for (let index = 0;index < binary.length; index += 1) {
82
+ bytes[index] = binary.charCodeAt(index);
83
+ }
84
+ return bytes;
85
+ }
86
+ function getSubtleCrypto() {
87
+ const subtle = globalThis.crypto?.subtle;
88
+ if (!subtle) {
89
+ throw new Error("Web Crypto is not available in this runtime");
90
+ }
91
+ return subtle;
92
+ }
93
+ function isJwtHeader(value) {
94
+ return typeof value === "object" && value !== null && "alg" in value && value.alg === "HS256";
95
+ }
96
+ function isJwtPayload(value) {
97
+ return typeof value === "object" && value !== null && !Array.isArray(value);
98
+ }
99
+ function isTimeValid(payload) {
100
+ const now = Math.floor(Date.now() / 1000);
101
+ if (typeof payload.exp === "number" && now >= payload.exp)
102
+ return false;
103
+ if (typeof payload.nbf === "number" && now < payload.nbf)
104
+ return false;
105
+ return true;
106
+ }
16
107
  export {
17
- jwtVerify2 as jwtVerify,
108
+ jwtVerify,
18
109
  jwtSign
19
110
  };