@unkey/api 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -297,6 +297,12 @@ interface paths {
297
297
  /** @description Determines the speed at which tokens are refilled, in milliseconds. */
298
298
  refillInterval: number;
299
299
  };
300
+ /**
301
+ * @description Sets if key is enabled or disabled. Disabled keys are not valid.
302
+ * @default true
303
+ * @example false
304
+ */
305
+ enabled?: boolean;
300
306
  };
301
307
  };
302
308
  };
@@ -462,11 +468,14 @@ interface paths {
462
468
  * - NOT_FOUND: the key does not exist or has expired
463
469
  * - FORBIDDEN: the key is not allowed to access the api
464
470
  * - USAGE_EXCEEDED: the key has exceeded its request limit
465
- * - RATE_LIMITED: the key has been ratelimited,
466
- *
471
+ * - RATE_LIMITED: the key has been ratelimited
472
+ * - UNAUTHORIZED: the key is not authorized
473
+ * - DISABLED: the key is disabled
467
474
  * @enum {string}
468
475
  */
469
- code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED";
476
+ code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | "UNAUTHORIZED" | "DISABLED";
477
+ /** @description Sets the key to be enabled or disabled. Disabled keys will not verify. */
478
+ enabled?: boolean;
470
479
  };
471
480
  };
472
481
  };
@@ -596,6 +605,11 @@ interface paths {
596
605
  /** @description The amount of verifications to refill for each occurrence is determined individually for each key. */
597
606
  amount: number;
598
607
  }) | null;
608
+ /**
609
+ * @description Set if key is enabled or disabled. If disabled, the key cannot be used to verify.
610
+ * @example true
611
+ */
612
+ enabled?: boolean;
599
613
  };
600
614
  };
601
615
  };
@@ -732,6 +746,92 @@ interface paths {
732
746
  };
733
747
  };
734
748
  };
749
+ "/v1/keys.getVerifications": {
750
+ get: {
751
+ parameters: {
752
+ query?: {
753
+ keyId?: string;
754
+ ownerId?: string;
755
+ start?: number | null;
756
+ end?: number | null;
757
+ granularity?: "day";
758
+ };
759
+ };
760
+ responses: {
761
+ /** @description The configuration for a single key */
762
+ 200: {
763
+ content: {
764
+ "application/json": {
765
+ verifications: {
766
+ /**
767
+ * @description The timestamp of the usage data
768
+ * @example 1620000000000
769
+ */
770
+ time: number;
771
+ /**
772
+ * @description The number of successful requests
773
+ * @example 100
774
+ */
775
+ success: number;
776
+ /**
777
+ * @description The number of requests that were rate limited
778
+ * @example 10
779
+ */
780
+ rateLimited: number;
781
+ /**
782
+ * @description The number of requests that exceeded the usage limit
783
+ * @example 0
784
+ */
785
+ usageExceeded: number;
786
+ }[];
787
+ };
788
+ };
789
+ };
790
+ /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */
791
+ 400: {
792
+ content: {
793
+ "application/json": components["schemas"]["ErrBadRequest"];
794
+ };
795
+ };
796
+ /** @description Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. */
797
+ 401: {
798
+ content: {
799
+ "application/json": components["schemas"]["ErrUnauthorized"];
800
+ };
801
+ };
802
+ /** @description The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. */
803
+ 403: {
804
+ content: {
805
+ "application/json": components["schemas"]["ErrForbidden"];
806
+ };
807
+ };
808
+ /** @description The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. */
809
+ 404: {
810
+ content: {
811
+ "application/json": components["schemas"]["ErrNotFound"];
812
+ };
813
+ };
814
+ /** @description This response is sent when a request conflicts with the current state of the server. */
815
+ 409: {
816
+ content: {
817
+ "application/json": components["schemas"]["ErrConflict"];
818
+ };
819
+ };
820
+ /** @description The user has sent too many requests in a given amount of time ("rate limiting") */
821
+ 429: {
822
+ content: {
823
+ "application/json": components["schemas"]["ErrTooManyRequests"];
824
+ };
825
+ };
826
+ /** @description The server has encountered a situation it does not know how to handle. */
827
+ 500: {
828
+ content: {
829
+ "application/json": components["schemas"]["ErrInternalServerError"];
830
+ };
831
+ };
832
+ };
833
+ };
834
+ };
735
835
  "/vx/keys.getVerifications": {
736
836
  get: {
737
837
  parameters: {
@@ -740,7 +840,7 @@ interface paths {
740
840
  ownerId?: string;
741
841
  start?: number | null;
742
842
  end?: number | null;
743
- granularity?: "hour" | "day" | "month";
843
+ granularity?: "day";
744
844
  };
745
845
  };
746
846
  responses: {
@@ -1601,7 +1701,7 @@ interface paths {
1601
1701
  * @example NOT_FOUND
1602
1702
  * @enum {string}
1603
1703
  */
1604
- code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED";
1704
+ code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | "UNAUTHORIZED" | "DISABLED";
1605
1705
  };
1606
1706
  };
1607
1707
  };
@@ -2194,6 +2294,11 @@ interface components {
2194
2294
  /** @description Determines the speed at which tokens are refilled, in milliseconds. */
2195
2295
  refillInterval: number;
2196
2296
  };
2297
+ /**
2298
+ * @description Sets if key is enabled or disabled. Disabled keys are not valid.
2299
+ * @example true
2300
+ */
2301
+ enabled?: boolean;
2197
2302
  };
2198
2303
  };
2199
2304
  responses: never;
@@ -2285,6 +2390,7 @@ declare class Unkey {
2285
2390
  delete: (req: paths["/v1/keys.deleteKey"]["post"]["requestBody"]["content"]["application/json"]) => Promise<Result<paths["/v1/keys.deleteKey"]["post"]["responses"]["200"]["content"]["application/json"]>>;
2286
2391
  updateRemaining: (req: paths["/v1/keys.updateRemaining"]["post"]["requestBody"]["content"]["application/json"]) => Promise<Result<paths["/v1/keys.updateRemaining"]["post"]["responses"]["200"]["content"]["application/json"]>>;
2287
2392
  get: (req: paths["/v1/keys.getKey"]["get"]["parameters"]["query"]) => Promise<Result<paths["/v1/keys.getKey"]["get"]["responses"]["200"]["content"]["application/json"]>>;
2393
+ getVerifications: (req: paths["/v1/keys.getVerifications"]["get"]["parameters"]["query"]) => Promise<Result<paths["/v1/keys.getVerifications"]["get"]["responses"]["200"]["content"]["application/json"]>>;
2288
2394
  };
2289
2395
  get apis(): {
2290
2396
  create: (req: paths["/v1/apis.createApi"]["post"]["requestBody"]["content"]["application/json"]) => Promise<Result<paths["/v1/apis.createApi"]["post"]["responses"]["200"]["content"]["application/json"]>>;
@@ -2342,9 +2448,10 @@ declare function verifyKey(req: string | {
2342
2448
  reset: number;
2343
2449
  } | undefined;
2344
2450
  remaining?: number | undefined;
2345
- code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | undefined;
2451
+ code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | "UNAUTHORIZED" | "DISABLED" | undefined;
2452
+ enabled?: boolean | undefined;
2346
2453
  };
2347
2454
  error?: undefined;
2348
2455
  }>;
2349
2456
 
2350
- export { ErrorResponse, Unkey, UnkeyOptions, verifyKey };
2457
+ export { type ErrorResponse, Unkey, type UnkeyOptions, verifyKey };
package/dist/index.d.ts CHANGED
@@ -297,6 +297,12 @@ interface paths {
297
297
  /** @description Determines the speed at which tokens are refilled, in milliseconds. */
298
298
  refillInterval: number;
299
299
  };
300
+ /**
301
+ * @description Sets if key is enabled or disabled. Disabled keys are not valid.
302
+ * @default true
303
+ * @example false
304
+ */
305
+ enabled?: boolean;
300
306
  };
301
307
  };
302
308
  };
@@ -462,11 +468,14 @@ interface paths {
462
468
  * - NOT_FOUND: the key does not exist or has expired
463
469
  * - FORBIDDEN: the key is not allowed to access the api
464
470
  * - USAGE_EXCEEDED: the key has exceeded its request limit
465
- * - RATE_LIMITED: the key has been ratelimited,
466
- *
471
+ * - RATE_LIMITED: the key has been ratelimited
472
+ * - UNAUTHORIZED: the key is not authorized
473
+ * - DISABLED: the key is disabled
467
474
  * @enum {string}
468
475
  */
469
- code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED";
476
+ code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | "UNAUTHORIZED" | "DISABLED";
477
+ /** @description Sets the key to be enabled or disabled. Disabled keys will not verify. */
478
+ enabled?: boolean;
470
479
  };
471
480
  };
472
481
  };
@@ -596,6 +605,11 @@ interface paths {
596
605
  /** @description The amount of verifications to refill for each occurrence is determined individually for each key. */
597
606
  amount: number;
598
607
  }) | null;
608
+ /**
609
+ * @description Set if key is enabled or disabled. If disabled, the key cannot be used to verify.
610
+ * @example true
611
+ */
612
+ enabled?: boolean;
599
613
  };
600
614
  };
601
615
  };
@@ -732,6 +746,92 @@ interface paths {
732
746
  };
733
747
  };
734
748
  };
749
+ "/v1/keys.getVerifications": {
750
+ get: {
751
+ parameters: {
752
+ query?: {
753
+ keyId?: string;
754
+ ownerId?: string;
755
+ start?: number | null;
756
+ end?: number | null;
757
+ granularity?: "day";
758
+ };
759
+ };
760
+ responses: {
761
+ /** @description The configuration for a single key */
762
+ 200: {
763
+ content: {
764
+ "application/json": {
765
+ verifications: {
766
+ /**
767
+ * @description The timestamp of the usage data
768
+ * @example 1620000000000
769
+ */
770
+ time: number;
771
+ /**
772
+ * @description The number of successful requests
773
+ * @example 100
774
+ */
775
+ success: number;
776
+ /**
777
+ * @description The number of requests that were rate limited
778
+ * @example 10
779
+ */
780
+ rateLimited: number;
781
+ /**
782
+ * @description The number of requests that exceeded the usage limit
783
+ * @example 0
784
+ */
785
+ usageExceeded: number;
786
+ }[];
787
+ };
788
+ };
789
+ };
790
+ /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */
791
+ 400: {
792
+ content: {
793
+ "application/json": components["schemas"]["ErrBadRequest"];
794
+ };
795
+ };
796
+ /** @description Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. */
797
+ 401: {
798
+ content: {
799
+ "application/json": components["schemas"]["ErrUnauthorized"];
800
+ };
801
+ };
802
+ /** @description The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. */
803
+ 403: {
804
+ content: {
805
+ "application/json": components["schemas"]["ErrForbidden"];
806
+ };
807
+ };
808
+ /** @description The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. */
809
+ 404: {
810
+ content: {
811
+ "application/json": components["schemas"]["ErrNotFound"];
812
+ };
813
+ };
814
+ /** @description This response is sent when a request conflicts with the current state of the server. */
815
+ 409: {
816
+ content: {
817
+ "application/json": components["schemas"]["ErrConflict"];
818
+ };
819
+ };
820
+ /** @description The user has sent too many requests in a given amount of time ("rate limiting") */
821
+ 429: {
822
+ content: {
823
+ "application/json": components["schemas"]["ErrTooManyRequests"];
824
+ };
825
+ };
826
+ /** @description The server has encountered a situation it does not know how to handle. */
827
+ 500: {
828
+ content: {
829
+ "application/json": components["schemas"]["ErrInternalServerError"];
830
+ };
831
+ };
832
+ };
833
+ };
834
+ };
735
835
  "/vx/keys.getVerifications": {
736
836
  get: {
737
837
  parameters: {
@@ -740,7 +840,7 @@ interface paths {
740
840
  ownerId?: string;
741
841
  start?: number | null;
742
842
  end?: number | null;
743
- granularity?: "hour" | "day" | "month";
843
+ granularity?: "day";
744
844
  };
745
845
  };
746
846
  responses: {
@@ -1601,7 +1701,7 @@ interface paths {
1601
1701
  * @example NOT_FOUND
1602
1702
  * @enum {string}
1603
1703
  */
1604
- code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED";
1704
+ code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | "UNAUTHORIZED" | "DISABLED";
1605
1705
  };
1606
1706
  };
1607
1707
  };
@@ -2194,6 +2294,11 @@ interface components {
2194
2294
  /** @description Determines the speed at which tokens are refilled, in milliseconds. */
2195
2295
  refillInterval: number;
2196
2296
  };
2297
+ /**
2298
+ * @description Sets if key is enabled or disabled. Disabled keys are not valid.
2299
+ * @example true
2300
+ */
2301
+ enabled?: boolean;
2197
2302
  };
2198
2303
  };
2199
2304
  responses: never;
@@ -2285,6 +2390,7 @@ declare class Unkey {
2285
2390
  delete: (req: paths["/v1/keys.deleteKey"]["post"]["requestBody"]["content"]["application/json"]) => Promise<Result<paths["/v1/keys.deleteKey"]["post"]["responses"]["200"]["content"]["application/json"]>>;
2286
2391
  updateRemaining: (req: paths["/v1/keys.updateRemaining"]["post"]["requestBody"]["content"]["application/json"]) => Promise<Result<paths["/v1/keys.updateRemaining"]["post"]["responses"]["200"]["content"]["application/json"]>>;
2287
2392
  get: (req: paths["/v1/keys.getKey"]["get"]["parameters"]["query"]) => Promise<Result<paths["/v1/keys.getKey"]["get"]["responses"]["200"]["content"]["application/json"]>>;
2393
+ getVerifications: (req: paths["/v1/keys.getVerifications"]["get"]["parameters"]["query"]) => Promise<Result<paths["/v1/keys.getVerifications"]["get"]["responses"]["200"]["content"]["application/json"]>>;
2288
2394
  };
2289
2395
  get apis(): {
2290
2396
  create: (req: paths["/v1/apis.createApi"]["post"]["requestBody"]["content"]["application/json"]) => Promise<Result<paths["/v1/apis.createApi"]["post"]["responses"]["200"]["content"]["application/json"]>>;
@@ -2342,9 +2448,10 @@ declare function verifyKey(req: string | {
2342
2448
  reset: number;
2343
2449
  } | undefined;
2344
2450
  remaining?: number | undefined;
2345
- code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | undefined;
2451
+ code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | "UNAUTHORIZED" | "DISABLED" | undefined;
2452
+ enabled?: boolean | undefined;
2346
2453
  };
2347
2454
  error?: undefined;
2348
2455
  }>;
2349
2456
 
2350
- export { ErrorResponse, Unkey, UnkeyOptions, verifyKey };
2457
+ export { type ErrorResponse, Unkey, type UnkeyOptions, verifyKey };
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ __export(src_exports, {
26
26
  module.exports = __toCommonJS(src_exports);
27
27
 
28
28
  // package.json
29
- var version = "0.14.0";
29
+ var version = "0.16.0";
30
30
 
31
31
  // src/client.ts
32
32
  var Unkey = class {
@@ -60,6 +60,9 @@ var Unkey = class {
60
60
  const url = new URL(`${this.baseUrl}/${req.path.join("/")}`);
61
61
  if (req.query) {
62
62
  for (const [k, v] of Object.entries(req.query)) {
63
+ if (v === null) {
64
+ continue;
65
+ }
63
66
  url.searchParams.set(k, v.toString());
64
67
  }
65
68
  }
@@ -148,6 +151,13 @@ var Unkey = class {
148
151
  method: "GET",
149
152
  query: req
150
153
  });
154
+ },
155
+ getVerifications: async (req) => {
156
+ return await this.fetch({
157
+ path: ["v1", "keys.getVerifications"],
158
+ method: "GET",
159
+ query: req
160
+ });
151
161
  }
152
162
  };
153
163
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../package.json","../src/client.ts","../src/verify.ts"],"sourcesContent":["export * from \"./client\";\nexport * from \"./verify\";\nexport * from \"./errors\";\n","{\n \"name\": \"@unkey/api\",\n \"version\": \"0.14.0\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"license\": \"MIT\",\n \"private\": false,\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"unkey\",\n \"client\",\n \"api\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/unkeyed/unkey/issues\"\n },\n \"homepage\": \"https://github.com/unkeyed/unkey#readme\",\n \"files\": [\n \"./dist/**\"\n ],\n \"author\": \"Andreas Thomas <andreas@chronark.com>\",\n \"scripts\": {\n \"test\": \"bun test\",\n \"test:coverage\": \"bun test --coverage\",\n \"generate\": \"openapi-typescript https://api.unkey.dev/openapi.json -o ./src/openapi.d.ts\",\n \"build\": \"pnpm generate && tsup\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.8.7\",\n \"@unkey/tsconfig\": \"workspace:^\",\n \"openapi-typescript\": \"^6.7.2\",\n \"tsup\": \"^7.2.0\",\n \"tsx\": \"^3.14.0\",\n \"typescript\": \"^5.2.2\"\n }\n}\n","import { version } from \"../package.json\";\nimport { ErrorResponse } from \"./errors\";\nimport type { paths } from \"./openapi\";\nexport type UnkeyOptions = (\n | {\n token?: never;\n\n /**\n * The root key from unkey.dev.\n *\n * You can create/manage your root keys here:\n * https://unkey.dev/app/settings/root-keys\n */\n rootKey: string;\n }\n | {\n /**\n * The workspace key from unkey.dev\n *\n * @deprecated Use `rootKey`\n */\n token: string;\n rootKey?: never;\n }\n) & {\n /**\n * @default https://api.unkey.dev\n */\n baseUrl?: string;\n\n /**\n * Retry on network errors\n */\n retry?: {\n /**\n * How many attempts should be made\n * The maximum number of requests will be `attempts + 1`\n * `0` means no retries\n *\n * @default 5\n */\n attempts?: number;\n /**\n * Return how many milliseconds to wait until the next attempt is made\n *\n * @default `(retryCount) => Math.round(Math.exp(retryCount) * 10)),`\n */\n backoff?: (retryCount: number) => number;\n };\n /**\n * Customize the `fetch` cache behaviour\n */\n cache?: RequestCache;\n\n /**\n * The version of the SDK instantiating this client.\n *\n * This is used for internal metrics and is not covered by semver, and may change at any time.\n *\n * You can leave this blank unless you are building a wrapper around this SDK.\n */\n wrapperSdkVersion?: `v${string}`;\n};\n\ntype ApiRequest = {\n path: string[];\n} & (\n | {\n method: \"GET\";\n body?: never;\n query?: Record<string, string | number | boolean>;\n }\n | {\n method: \"POST\";\n body?: unknown;\n query?: never;\n }\n);\n\ntype Result<R> =\n | {\n result: R;\n error?: never;\n }\n | {\n result?: never;\n error: ErrorResponse[\"error\"];\n };\n\nexport class Unkey {\n public readonly baseUrl: string;\n private readonly rootKey: string;\n private readonly cache?: RequestCache;\n private readonly sdkVersions: `v${string}`[] = [];\n\n public readonly retry: {\n attempts: number;\n backoff: (retryCount: number) => number;\n };\n\n constructor(opts: UnkeyOptions) {\n this.baseUrl = opts.baseUrl ?? \"https://api.unkey.dev\";\n this.rootKey = opts.rootKey ?? opts.token;\n this.sdkVersions.push(`v${version}`);\n if (opts.wrapperSdkVersion) {\n this.sdkVersions.push(opts.wrapperSdkVersion);\n }\n\n this.cache = opts.cache;\n /**\n * Even though typescript should prevent this, some people still pass undefined or empty strings\n */\n if (!this.rootKey) {\n throw new Error(\n \"Unkey root key must be set, maybe you passed in `undefined` or an empty string?\",\n );\n }\n\n this.retry = {\n attempts: opts.retry?.attempts ?? 5,\n backoff: opts.retry?.backoff ?? ((n) => Math.round(Math.exp(n) * 10)),\n };\n }\n\n private async fetch<TResult>(req: ApiRequest): Promise<Result<TResult>> {\n let res: Response | null = null;\n let err: Error | null = null;\n for (let i = 0; i <= this.retry.attempts; i++) {\n const url = new URL(`${this.baseUrl}/${req.path.join(\"/\")}`);\n if (req.query) {\n for (const [k, v] of Object.entries(req.query)) {\n url.searchParams.set(k, v.toString());\n }\n }\n res = await fetch(url, {\n method: req.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.rootKey}`,\n \"Unkey-SDK\": this.sdkVersions.join(\",\"),\n },\n cache: this.cache,\n body: JSON.stringify(req.body),\n }).catch((e: Error) => {\n err = e;\n return null; // set `res` to `null`\n });\n if (res?.ok) {\n return { result: (await res.json()) as TResult };\n }\n const backoff = this.retry.backoff(i);\n console.debug(\n \"attempt %d of %d to reach %s failed, retrying in %d ms: %s\",\n i + 1,\n this.retry.attempts + 1,\n url,\n backoff,\n // @ts-ignore I don't understand why `err` is `never`\n err?.message,\n );\n await new Promise((r) => setTimeout(r, backoff));\n }\n\n if (res) {\n return { error: (await res.json()) as ErrorResponse[\"error\"] };\n }\n\n return {\n error: {\n // @ts-ignore\n code: \"FETCH_ERROR\",\n // @ts-ignore I don't understand why `err` is `never`\n message: err?.message ?? \"No response\",\n docs: \"https://developer.mozilla.org/en-US/docs/Web/API/fetch\",\n requestId: \"N/A\",\n },\n };\n }\n\n public get keys() {\n return {\n create: async (\n req: paths[\"/v1/keys.createKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.createKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.createKey\"],\n method: \"POST\",\n body: req,\n });\n },\n update: async (\n req: paths[\"/v1/keys.updateKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.updateKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.updateKey\"],\n method: \"POST\",\n body: req,\n });\n },\n verify: async (\n req: paths[\"/v1/keys.verifyKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.verifyKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.verifyKey\"],\n method: \"POST\",\n body: req,\n });\n },\n delete: async (\n req: paths[\"/v1/keys.deleteKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.deleteKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.deleteKey\"],\n method: \"POST\",\n body: req,\n });\n },\n updateRemaining: async (\n req: paths[\"/v1/keys.updateRemaining\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.updateRemaining\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.updateRemaining\"],\n method: \"POST\",\n body: req,\n });\n },\n get: async (\n req: paths[\"/v1/keys.getKey\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/keys.getKey\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.getKey\"],\n method: \"GET\",\n query: req,\n });\n },\n };\n }\n\n public get apis() {\n return {\n create: async (\n req: paths[\"/v1/apis.createApi\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/apis.createApi\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.createApi\"],\n method: \"POST\",\n body: req,\n });\n },\n delete: async (\n req: paths[\"/v1/apis.deleteApi\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/apis.deleteApi\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.deleteApi\"],\n method: \"POST\",\n body: req,\n });\n },\n get: async (\n req: paths[\"/v1/apis.getApi\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/apis.getApi\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.getApi\"],\n method: \"GET\",\n query: req,\n });\n },\n listKeys: async (\n req: paths[\"/v1/apis.listKeys\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/apis.listKeys\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.listKeys\"],\n method: \"GET\",\n query: req,\n });\n },\n };\n }\n}\n","import { Unkey } from \"./client\";\n\n/**\n * Verify a key\n *\n * @example\n * ```ts\n * const { result, error } = await verifyKey(\"key_123\")\n * if (error){\n * // handle potential network or bad request error\n * // a link to our docs will be in the `error.docs` field\n * console.error(error.message)\n * return\n * }\n * if (!result.valid) {\n * // do not grant access\n * return\n * }\n *\n * // process request\n * console.log(result)\n * ```\n */\nexport function verifyKey(req: string | { key: string; apiId: string }) {\n // yes this is empty to make typescript happy but we don't need a token for verifying keys\n // it's not the cleanest but it works for now :)\n const unkey = new Unkey({ rootKey: \"public\" });\n return unkey.keys.verify(typeof req === \"string\" ? { key: req } : req);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEE,cAAW;;;ACuFN,IAAM,QAAN,MAAY;AAAA,EACD;AAAA,EACC;AAAA,EACA;AAAA,EACA,cAA8B,CAAC;AAAA,EAEhC;AAAA,EAKhB,YAAY,MAAoB;AAC9B,SAAK,UAAU,KAAK,WAAW;AAC/B,SAAK,UAAU,KAAK,WAAW,KAAK;AACpC,SAAK,YAAY,KAAK,IAAI,OAAO,EAAE;AACnC,QAAI,KAAK,mBAAmB;AAC1B,WAAK,YAAY,KAAK,KAAK,iBAAiB;AAAA,IAC9C;AAEA,SAAK,QAAQ,KAAK;AAIlB,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,SAAK,QAAQ;AAAA,MACX,UAAU,KAAK,OAAO,YAAY;AAAA,MAClC,SAAS,KAAK,OAAO,YAAY,CAAC,MAAM,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,EAAE;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,MAAc,MAAe,KAA2C;AACtE,QAAI,MAAuB;AAC3B,QAAI,MAAoB;AACxB,aAAS,IAAI,GAAG,KAAK,KAAK,MAAM,UAAU,KAAK;AAC7C,YAAM,MAAM,IAAI,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE;AAC3D,UAAI,IAAI,OAAO;AACb,mBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,KAAK,GAAG;AAC9C,cAAI,aAAa,IAAI,GAAG,EAAE,SAAS,CAAC;AAAA,QACtC;AAAA,MACF;AACA,YAAM,MAAM,MAAM,KAAK;AAAA,QACrB,QAAQ,IAAI;AAAA,QACZ,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,UAAU,KAAK,OAAO;AAAA,UACrC,aAAa,KAAK,YAAY,KAAK,GAAG;AAAA,QACxC;AAAA,QACA,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK,UAAU,IAAI,IAAI;AAAA,MAC/B,CAAC,EAAE,MAAM,CAAC,MAAa;AACrB,cAAM;AACN,eAAO;AAAA,MACT,CAAC;AACD,UAAI,KAAK,IAAI;AACX,eAAO,EAAE,QAAS,MAAM,IAAI,KAAK,EAAc;AAAA,MACjD;AACA,YAAM,UAAU,KAAK,MAAM,QAAQ,CAAC;AACpC,cAAQ;AAAA,QACN;AAAA,QACA,IAAI;AAAA,QACJ,KAAK,MAAM,WAAW;AAAA,QACtB;AAAA,QACA;AAAA;AAAA,QAEA,KAAK;AAAA,MACP;AACA,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAAA,IACjD;AAEA,QAAI,KAAK;AACP,aAAO,EAAE,OAAQ,MAAM,IAAI,KAAK,EAA6B;AAAA,IAC/D;AAEA,WAAO;AAAA,MACL,OAAO;AAAA;AAAA,QAEL,MAAM;AAAA;AAAA,QAEN,SAAS,KAAK,WAAW;AAAA,QACzB,MAAM;AAAA,QACN,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAW,OAAO;AAChB,WAAO;AAAA,MACL,QAAQ,OACN,QAKG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,gBAAgB;AAAA,UAC7B,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACA,QAAQ,OACN,QAKG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,gBAAgB;AAAA,UAC7B,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACA,QAAQ,OACN,QAKG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,gBAAgB;AAAA,UAC7B,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACA,QAAQ,OACN,QAKG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,gBAAgB;AAAA,UAC7B,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACA,iBAAiB,OACf,QAKG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,sBAAsB;AAAA,UACnC,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACA,KAAK,OACH,QAGG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,aAAa;AAAA,UAC1B,QAAQ;AAAA,UACR,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAW,OAAO;AAChB,WAAO;AAAA,MACL,QAAQ,OACN,QAKG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,gBAAgB;AAAA,UAC7B,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACA,QAAQ,OACN,QAKG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,gBAAgB;AAAA,UAC7B,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,MACA,KAAK,OACH,QAGG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,aAAa;AAAA,UAC1B,QAAQ;AAAA,UACR,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,MACA,UAAU,OACR,QAGG;AACH,eAAO,MAAM,KAAK,MAAM;AAAA,UACtB,MAAM,CAAC,MAAM,eAAe;AAAA,UAC5B,QAAQ;AAAA,UACR,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;ACjSO,SAAS,UAAU,KAA8C;AAGtE,QAAM,QAAQ,IAAI,MAAM,EAAE,SAAS,SAAS,CAAC;AAC7C,SAAO,MAAM,KAAK,OAAO,OAAO,QAAQ,WAAW,EAAE,KAAK,IAAI,IAAI,GAAG;AACvE;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../package.json","../src/client.ts","../src/verify.ts"],"sourcesContent":["export * from \"./client\";\nexport * from \"./verify\";\nexport * from \"./errors\";\n","{\n \"name\": \"@unkey/api\",\n \"version\": \"0.16.0\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"license\": \"MIT\",\n \"private\": false,\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"unkey\",\n \"client\",\n \"api\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/unkeyed/unkey/issues\"\n },\n \"homepage\": \"https://github.com/unkeyed/unkey#readme\",\n \"files\": [\n \"./dist/**\"\n ],\n \"author\": \"Andreas Thomas <andreas@chronark.com>\",\n \"scripts\": {\n \"test\": \"bun test\",\n \"test:coverage\": \"bun test --coverage\",\n \"generate\": \"openapi-typescript https://api.unkey.dev/openapi.json -o ./src/openapi.d.ts\",\n \"build\": \"pnpm generate && tsup\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.8.7\",\n \"@unkey/tsconfig\": \"workspace:^\",\n \"openapi-typescript\": \"^6.7.2\",\n \"tsup\": \"^7.2.0\",\n \"tsx\": \"^3.14.0\",\n \"typescript\": \"^5.2.2\"\n }\n}\n","import { version } from \"../package.json\";\nimport { ErrorResponse } from \"./errors\";\nimport type { paths } from \"./openapi\";\nexport type UnkeyOptions = (\n | {\n token?: never;\n\n /**\n * The root key from unkey.dev.\n *\n * You can create/manage your root keys here:\n * https://unkey.dev/app/settings/root-keys\n */\n rootKey: string;\n }\n | {\n /**\n * The workspace key from unkey.dev\n *\n * @deprecated Use `rootKey`\n */\n token: string;\n rootKey?: never;\n }\n) & {\n /**\n * @default https://api.unkey.dev\n */\n baseUrl?: string;\n\n /**\n * Retry on network errors\n */\n retry?: {\n /**\n * How many attempts should be made\n * The maximum number of requests will be `attempts + 1`\n * `0` means no retries\n *\n * @default 5\n */\n attempts?: number;\n /**\n * Return how many milliseconds to wait until the next attempt is made\n *\n * @default `(retryCount) => Math.round(Math.exp(retryCount) * 10)),`\n */\n backoff?: (retryCount: number) => number;\n };\n /**\n * Customize the `fetch` cache behaviour\n */\n cache?: RequestCache;\n\n /**\n * The version of the SDK instantiating this client.\n *\n * This is used for internal metrics and is not covered by semver, and may change at any time.\n *\n * You can leave this blank unless you are building a wrapper around this SDK.\n */\n wrapperSdkVersion?: `v${string}`;\n};\n\ntype ApiRequest = {\n path: string[];\n} & (\n | {\n method: \"GET\";\n body?: never;\n query?: Record<string, string | number | boolean | null>;\n }\n | {\n method: \"POST\";\n body?: unknown;\n query?: never;\n }\n);\n\ntype Result<R> =\n | {\n result: R;\n error?: never;\n }\n | {\n result?: never;\n error: ErrorResponse[\"error\"];\n };\n\nexport class Unkey {\n public readonly baseUrl: string;\n private readonly rootKey: string;\n private readonly cache?: RequestCache;\n private readonly sdkVersions: `v${string}`[] = [];\n\n public readonly retry: {\n attempts: number;\n backoff: (retryCount: number) => number;\n };\n\n constructor(opts: UnkeyOptions) {\n this.baseUrl = opts.baseUrl ?? \"https://api.unkey.dev\";\n this.rootKey = opts.rootKey ?? opts.token;\n this.sdkVersions.push(`v${version}`);\n if (opts.wrapperSdkVersion) {\n this.sdkVersions.push(opts.wrapperSdkVersion);\n }\n\n this.cache = opts.cache;\n /**\n * Even though typescript should prevent this, some people still pass undefined or empty strings\n */\n if (!this.rootKey) {\n throw new Error(\n \"Unkey root key must be set, maybe you passed in `undefined` or an empty string?\",\n );\n }\n\n this.retry = {\n attempts: opts.retry?.attempts ?? 5,\n backoff: opts.retry?.backoff ?? ((n) => Math.round(Math.exp(n) * 10)),\n };\n }\n\n private async fetch<TResult>(req: ApiRequest): Promise<Result<TResult>> {\n let res: Response | null = null;\n let err: Error | null = null;\n for (let i = 0; i <= this.retry.attempts; i++) {\n const url = new URL(`${this.baseUrl}/${req.path.join(\"/\")}`);\n if (req.query) {\n for (const [k, v] of Object.entries(req.query)) {\n if (v === null) {\n continue;\n }\n url.searchParams.set(k, v.toString());\n }\n }\n res = await fetch(url, {\n method: req.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.rootKey}`,\n \"Unkey-SDK\": this.sdkVersions.join(\",\"),\n },\n cache: this.cache,\n body: JSON.stringify(req.body),\n }).catch((e: Error) => {\n err = e;\n return null; // set `res` to `null`\n });\n if (res?.ok) {\n return { result: (await res.json()) as TResult };\n }\n const backoff = this.retry.backoff(i);\n console.debug(\n \"attempt %d of %d to reach %s failed, retrying in %d ms: %s\",\n i + 1,\n this.retry.attempts + 1,\n url,\n backoff,\n // @ts-ignore I don't understand why `err` is `never`\n err?.message,\n );\n await new Promise((r) => setTimeout(r, backoff));\n }\n\n if (res) {\n return { error: (await res.json()) as ErrorResponse[\"error\"] };\n }\n\n return {\n error: {\n // @ts-ignore\n code: \"FETCH_ERROR\",\n // @ts-ignore I don't understand why `err` is `never`\n message: err?.message ?? \"No response\",\n docs: \"https://developer.mozilla.org/en-US/docs/Web/API/fetch\",\n requestId: \"N/A\",\n },\n };\n }\n\n public get keys() {\n return {\n create: async (\n req: paths[\"/v1/keys.createKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.createKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.createKey\"],\n method: \"POST\",\n body: req,\n });\n },\n update: async (\n req: paths[\"/v1/keys.updateKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.updateKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.updateKey\"],\n method: \"POST\",\n body: req,\n });\n },\n verify: async (\n req: paths[\"/v1/keys.verifyKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.verifyKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.verifyKey\"],\n method: \"POST\",\n body: req,\n });\n },\n delete: async (\n req: paths[\"/v1/keys.deleteKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.deleteKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.deleteKey\"],\n method: \"POST\",\n body: req,\n });\n },\n updateRemaining: async (\n req: paths[\"/v1/keys.updateRemaining\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.updateRemaining\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.updateRemaining\"],\n method: \"POST\",\n body: req,\n });\n },\n get: async (\n req: paths[\"/v1/keys.getKey\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/keys.getKey\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.getKey\"],\n method: \"GET\",\n query: req,\n });\n },\n getVerifications: async (\n req: paths[\"/v1/keys.getVerifications\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.getVerifications\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.getVerifications\"],\n method: \"GET\",\n query: req,\n });\n },\n };\n }\n\n public get apis() {\n return {\n create: async (\n req: paths[\"/v1/apis.createApi\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/apis.createApi\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.createApi\"],\n method: \"POST\",\n body: req,\n });\n },\n delete: async (\n req: paths[\"/v1/apis.deleteApi\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/apis.deleteApi\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.deleteApi\"],\n method: \"POST\",\n body: req,\n });\n },\n get: async (\n req: paths[\"/v1/apis.getApi\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/apis.getApi\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.getApi\"],\n method: \"GET\",\n query: req,\n });\n },\n listKeys: async (\n req: paths[\"/v1/apis.listKeys\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/apis.listKeys\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.listKeys\"],\n method: \"GET\",\n query: req,\n });\n },\n };\n }\n}\n","import { Unkey } from \"./client\";\n\n/**\n * Verify a key\n *\n * @example\n * ```ts\n * const { result, error } = await verifyKey(\"key_123\")\n * if (error){\n * // handle potential network or bad request error\n * // a link to our docs will be in the `error.docs` field\n * console.error(error.message)\n * return\n * }\n * if (!result.valid) {\n * // do not grant access\n * return\n * }\n *\n * // process request\n * console.log(result)\n * ```\n */\nexport function verifyKey(req: string | { key: string; apiId: string }) {\n // yes this is empty to make typescript happy but we don't need a token for verifying keys\n // it's not the cleanest but it works for now :)\n const unkey = new Unkey({ rootKey: \"public\" });\n return unkey.keys.verify(typeof req === \"string\" ? { key: req } : req);\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.14.0";
2
+ var version = "0.16.0";
3
3
 
4
4
  // src/client.ts
5
5
  var Unkey = class {
@@ -33,6 +33,9 @@ var Unkey = class {
33
33
  const url = new URL(`${this.baseUrl}/${req.path.join("/")}`);
34
34
  if (req.query) {
35
35
  for (const [k, v] of Object.entries(req.query)) {
36
+ if (v === null) {
37
+ continue;
38
+ }
36
39
  url.searchParams.set(k, v.toString());
37
40
  }
38
41
  }
@@ -121,6 +124,13 @@ var Unkey = class {
121
124
  method: "GET",
122
125
  query: req
123
126
  });
127
+ },
128
+ getVerifications: async (req) => {
129
+ return await this.fetch({
130
+ path: ["v1", "keys.getVerifications"],
131
+ method: "GET",
132
+ query: req
133
+ });
124
134
  }
125
135
  };
126
136
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../package.json","../src/client.ts","../src/verify.ts"],"sourcesContent":["{\n \"name\": \"@unkey/api\",\n \"version\": \"0.14.0\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"license\": \"MIT\",\n \"private\": false,\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"unkey\",\n \"client\",\n \"api\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/unkeyed/unkey/issues\"\n },\n \"homepage\": \"https://github.com/unkeyed/unkey#readme\",\n \"files\": [\n \"./dist/**\"\n ],\n \"author\": \"Andreas Thomas <andreas@chronark.com>\",\n \"scripts\": {\n \"test\": \"bun test\",\n \"test:coverage\": \"bun test --coverage\",\n \"generate\": \"openapi-typescript https://api.unkey.dev/openapi.json -o ./src/openapi.d.ts\",\n \"build\": \"pnpm generate && tsup\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.8.7\",\n \"@unkey/tsconfig\": \"workspace:^\",\n \"openapi-typescript\": \"^6.7.2\",\n \"tsup\": \"^7.2.0\",\n \"tsx\": \"^3.14.0\",\n \"typescript\": \"^5.2.2\"\n }\n}\n","import { version } from \"../package.json\";\nimport { ErrorResponse } from \"./errors\";\nimport type { paths } from \"./openapi\";\nexport type UnkeyOptions = (\n | {\n token?: never;\n\n /**\n * The root key from unkey.dev.\n *\n * You can create/manage your root keys here:\n * https://unkey.dev/app/settings/root-keys\n */\n rootKey: string;\n }\n | {\n /**\n * The workspace key from unkey.dev\n *\n * @deprecated Use `rootKey`\n */\n token: string;\n rootKey?: never;\n }\n) & {\n /**\n * @default https://api.unkey.dev\n */\n baseUrl?: string;\n\n /**\n * Retry on network errors\n */\n retry?: {\n /**\n * How many attempts should be made\n * The maximum number of requests will be `attempts + 1`\n * `0` means no retries\n *\n * @default 5\n */\n attempts?: number;\n /**\n * Return how many milliseconds to wait until the next attempt is made\n *\n * @default `(retryCount) => Math.round(Math.exp(retryCount) * 10)),`\n */\n backoff?: (retryCount: number) => number;\n };\n /**\n * Customize the `fetch` cache behaviour\n */\n cache?: RequestCache;\n\n /**\n * The version of the SDK instantiating this client.\n *\n * This is used for internal metrics and is not covered by semver, and may change at any time.\n *\n * You can leave this blank unless you are building a wrapper around this SDK.\n */\n wrapperSdkVersion?: `v${string}`;\n};\n\ntype ApiRequest = {\n path: string[];\n} & (\n | {\n method: \"GET\";\n body?: never;\n query?: Record<string, string | number | boolean>;\n }\n | {\n method: \"POST\";\n body?: unknown;\n query?: never;\n }\n);\n\ntype Result<R> =\n | {\n result: R;\n error?: never;\n }\n | {\n result?: never;\n error: ErrorResponse[\"error\"];\n };\n\nexport class Unkey {\n public readonly baseUrl: string;\n private readonly rootKey: string;\n private readonly cache?: RequestCache;\n private readonly sdkVersions: `v${string}`[] = [];\n\n public readonly retry: {\n attempts: number;\n backoff: (retryCount: number) => number;\n };\n\n constructor(opts: UnkeyOptions) {\n this.baseUrl = opts.baseUrl ?? \"https://api.unkey.dev\";\n this.rootKey = opts.rootKey ?? opts.token;\n this.sdkVersions.push(`v${version}`);\n if (opts.wrapperSdkVersion) {\n this.sdkVersions.push(opts.wrapperSdkVersion);\n }\n\n this.cache = opts.cache;\n /**\n * Even though typescript should prevent this, some people still pass undefined or empty strings\n */\n if (!this.rootKey) {\n throw new Error(\n \"Unkey root key must be set, maybe you passed in `undefined` or an empty string?\",\n );\n }\n\n this.retry = {\n attempts: opts.retry?.attempts ?? 5,\n backoff: opts.retry?.backoff ?? ((n) => Math.round(Math.exp(n) * 10)),\n };\n }\n\n private async fetch<TResult>(req: ApiRequest): Promise<Result<TResult>> {\n let res: Response | null = null;\n let err: Error | null = null;\n for (let i = 0; i <= this.retry.attempts; i++) {\n const url = new URL(`${this.baseUrl}/${req.path.join(\"/\")}`);\n if (req.query) {\n for (const [k, v] of Object.entries(req.query)) {\n url.searchParams.set(k, v.toString());\n }\n }\n res = await fetch(url, {\n method: req.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.rootKey}`,\n \"Unkey-SDK\": this.sdkVersions.join(\",\"),\n },\n cache: this.cache,\n body: JSON.stringify(req.body),\n }).catch((e: Error) => {\n err = e;\n return null; // set `res` to `null`\n });\n if (res?.ok) {\n return { result: (await res.json()) as TResult };\n }\n const backoff = this.retry.backoff(i);\n console.debug(\n \"attempt %d of %d to reach %s failed, retrying in %d ms: %s\",\n i + 1,\n this.retry.attempts + 1,\n url,\n backoff,\n // @ts-ignore I don't understand why `err` is `never`\n err?.message,\n );\n await new Promise((r) => setTimeout(r, backoff));\n }\n\n if (res) {\n return { error: (await res.json()) as ErrorResponse[\"error\"] };\n }\n\n return {\n error: {\n // @ts-ignore\n code: \"FETCH_ERROR\",\n // @ts-ignore I don't understand why `err` is `never`\n message: err?.message ?? \"No response\",\n docs: \"https://developer.mozilla.org/en-US/docs/Web/API/fetch\",\n requestId: \"N/A\",\n },\n };\n }\n\n public get keys() {\n return {\n create: async (\n req: paths[\"/v1/keys.createKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.createKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.createKey\"],\n method: \"POST\",\n body: req,\n });\n },\n update: async (\n req: paths[\"/v1/keys.updateKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.updateKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.updateKey\"],\n method: \"POST\",\n body: req,\n });\n },\n verify: async (\n req: paths[\"/v1/keys.verifyKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.verifyKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.verifyKey\"],\n method: \"POST\",\n body: req,\n });\n },\n delete: async (\n req: paths[\"/v1/keys.deleteKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.deleteKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.deleteKey\"],\n method: \"POST\",\n body: req,\n });\n },\n updateRemaining: async (\n req: paths[\"/v1/keys.updateRemaining\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.updateRemaining\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.updateRemaining\"],\n method: \"POST\",\n body: req,\n });\n },\n get: async (\n req: paths[\"/v1/keys.getKey\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/keys.getKey\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.getKey\"],\n method: \"GET\",\n query: req,\n });\n },\n };\n }\n\n public get apis() {\n return {\n create: async (\n req: paths[\"/v1/apis.createApi\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/apis.createApi\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.createApi\"],\n method: \"POST\",\n body: req,\n });\n },\n delete: async (\n req: paths[\"/v1/apis.deleteApi\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/apis.deleteApi\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.deleteApi\"],\n method: \"POST\",\n body: req,\n });\n },\n get: async (\n req: paths[\"/v1/apis.getApi\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/apis.getApi\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.getApi\"],\n method: \"GET\",\n query: req,\n });\n },\n listKeys: async (\n req: paths[\"/v1/apis.listKeys\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/apis.listKeys\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.listKeys\"],\n method: \"GET\",\n query: req,\n });\n },\n };\n }\n}\n","import { Unkey } from \"./client\";\n\n/**\n * Verify a key\n *\n * @example\n * ```ts\n * const { result, error } = await verifyKey(\"key_123\")\n * if (error){\n * // handle potential network or bad request error\n * // a link to our docs will be in the `error.docs` field\n * console.error(error.message)\n * return\n * }\n * if (!result.valid) {\n * // do not grant access\n * return\n * }\n *\n * // process request\n * console.log(result)\n * ```\n */\nexport function verifyKey(req: string | { key: string; apiId: string }) {\n // yes this is empty to make typescript happy but we don't need a token for verifying keys\n // it's not the cleanest but it works for now :)\n const unkey = new Unkey({ rootKey: \"public\" });\n return unkey.keys.verify(typeof req === \"string\" ? { key: req } : req);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../package.json","../src/client.ts","../src/verify.ts"],"sourcesContent":["{\n \"name\": \"@unkey/api\",\n \"version\": \"0.16.0\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"license\": \"MIT\",\n \"private\": false,\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"unkey\",\n \"client\",\n \"api\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/unkeyed/unkey/issues\"\n },\n \"homepage\": \"https://github.com/unkeyed/unkey#readme\",\n \"files\": [\n \"./dist/**\"\n ],\n \"author\": \"Andreas Thomas <andreas@chronark.com>\",\n \"scripts\": {\n \"test\": \"bun test\",\n \"test:coverage\": \"bun test --coverage\",\n \"generate\": \"openapi-typescript https://api.unkey.dev/openapi.json -o ./src/openapi.d.ts\",\n \"build\": \"pnpm generate && tsup\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.8.7\",\n \"@unkey/tsconfig\": \"workspace:^\",\n \"openapi-typescript\": \"^6.7.2\",\n \"tsup\": \"^7.2.0\",\n \"tsx\": \"^3.14.0\",\n \"typescript\": \"^5.2.2\"\n }\n}\n","import { version } from \"../package.json\";\nimport { ErrorResponse } from \"./errors\";\nimport type { paths } from \"./openapi\";\nexport type UnkeyOptions = (\n | {\n token?: never;\n\n /**\n * The root key from unkey.dev.\n *\n * You can create/manage your root keys here:\n * https://unkey.dev/app/settings/root-keys\n */\n rootKey: string;\n }\n | {\n /**\n * The workspace key from unkey.dev\n *\n * @deprecated Use `rootKey`\n */\n token: string;\n rootKey?: never;\n }\n) & {\n /**\n * @default https://api.unkey.dev\n */\n baseUrl?: string;\n\n /**\n * Retry on network errors\n */\n retry?: {\n /**\n * How many attempts should be made\n * The maximum number of requests will be `attempts + 1`\n * `0` means no retries\n *\n * @default 5\n */\n attempts?: number;\n /**\n * Return how many milliseconds to wait until the next attempt is made\n *\n * @default `(retryCount) => Math.round(Math.exp(retryCount) * 10)),`\n */\n backoff?: (retryCount: number) => number;\n };\n /**\n * Customize the `fetch` cache behaviour\n */\n cache?: RequestCache;\n\n /**\n * The version of the SDK instantiating this client.\n *\n * This is used for internal metrics and is not covered by semver, and may change at any time.\n *\n * You can leave this blank unless you are building a wrapper around this SDK.\n */\n wrapperSdkVersion?: `v${string}`;\n};\n\ntype ApiRequest = {\n path: string[];\n} & (\n | {\n method: \"GET\";\n body?: never;\n query?: Record<string, string | number | boolean | null>;\n }\n | {\n method: \"POST\";\n body?: unknown;\n query?: never;\n }\n);\n\ntype Result<R> =\n | {\n result: R;\n error?: never;\n }\n | {\n result?: never;\n error: ErrorResponse[\"error\"];\n };\n\nexport class Unkey {\n public readonly baseUrl: string;\n private readonly rootKey: string;\n private readonly cache?: RequestCache;\n private readonly sdkVersions: `v${string}`[] = [];\n\n public readonly retry: {\n attempts: number;\n backoff: (retryCount: number) => number;\n };\n\n constructor(opts: UnkeyOptions) {\n this.baseUrl = opts.baseUrl ?? \"https://api.unkey.dev\";\n this.rootKey = opts.rootKey ?? opts.token;\n this.sdkVersions.push(`v${version}`);\n if (opts.wrapperSdkVersion) {\n this.sdkVersions.push(opts.wrapperSdkVersion);\n }\n\n this.cache = opts.cache;\n /**\n * Even though typescript should prevent this, some people still pass undefined or empty strings\n */\n if (!this.rootKey) {\n throw new Error(\n \"Unkey root key must be set, maybe you passed in `undefined` or an empty string?\",\n );\n }\n\n this.retry = {\n attempts: opts.retry?.attempts ?? 5,\n backoff: opts.retry?.backoff ?? ((n) => Math.round(Math.exp(n) * 10)),\n };\n }\n\n private async fetch<TResult>(req: ApiRequest): Promise<Result<TResult>> {\n let res: Response | null = null;\n let err: Error | null = null;\n for (let i = 0; i <= this.retry.attempts; i++) {\n const url = new URL(`${this.baseUrl}/${req.path.join(\"/\")}`);\n if (req.query) {\n for (const [k, v] of Object.entries(req.query)) {\n if (v === null) {\n continue;\n }\n url.searchParams.set(k, v.toString());\n }\n }\n res = await fetch(url, {\n method: req.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.rootKey}`,\n \"Unkey-SDK\": this.sdkVersions.join(\",\"),\n },\n cache: this.cache,\n body: JSON.stringify(req.body),\n }).catch((e: Error) => {\n err = e;\n return null; // set `res` to `null`\n });\n if (res?.ok) {\n return { result: (await res.json()) as TResult };\n }\n const backoff = this.retry.backoff(i);\n console.debug(\n \"attempt %d of %d to reach %s failed, retrying in %d ms: %s\",\n i + 1,\n this.retry.attempts + 1,\n url,\n backoff,\n // @ts-ignore I don't understand why `err` is `never`\n err?.message,\n );\n await new Promise((r) => setTimeout(r, backoff));\n }\n\n if (res) {\n return { error: (await res.json()) as ErrorResponse[\"error\"] };\n }\n\n return {\n error: {\n // @ts-ignore\n code: \"FETCH_ERROR\",\n // @ts-ignore I don't understand why `err` is `never`\n message: err?.message ?? \"No response\",\n docs: \"https://developer.mozilla.org/en-US/docs/Web/API/fetch\",\n requestId: \"N/A\",\n },\n };\n }\n\n public get keys() {\n return {\n create: async (\n req: paths[\"/v1/keys.createKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.createKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.createKey\"],\n method: \"POST\",\n body: req,\n });\n },\n update: async (\n req: paths[\"/v1/keys.updateKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.updateKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.updateKey\"],\n method: \"POST\",\n body: req,\n });\n },\n verify: async (\n req: paths[\"/v1/keys.verifyKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.verifyKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.verifyKey\"],\n method: \"POST\",\n body: req,\n });\n },\n delete: async (\n req: paths[\"/v1/keys.deleteKey\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.deleteKey\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.deleteKey\"],\n method: \"POST\",\n body: req,\n });\n },\n updateRemaining: async (\n req: paths[\"/v1/keys.updateRemaining\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.updateRemaining\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.updateRemaining\"],\n method: \"POST\",\n body: req,\n });\n },\n get: async (\n req: paths[\"/v1/keys.getKey\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/keys.getKey\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.getKey\"],\n method: \"GET\",\n query: req,\n });\n },\n getVerifications: async (\n req: paths[\"/v1/keys.getVerifications\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<\n paths[\"/v1/keys.getVerifications\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"keys.getVerifications\"],\n method: \"GET\",\n query: req,\n });\n },\n };\n }\n\n public get apis() {\n return {\n create: async (\n req: paths[\"/v1/apis.createApi\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/apis.createApi\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.createApi\"],\n method: \"POST\",\n body: req,\n });\n },\n delete: async (\n req: paths[\"/v1/apis.deleteApi\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"],\n ): Promise<\n Result<\n paths[\"/v1/apis.deleteApi\"][\"post\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]\n >\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.deleteApi\"],\n method: \"POST\",\n body: req,\n });\n },\n get: async (\n req: paths[\"/v1/apis.getApi\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/apis.getApi\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.getApi\"],\n method: \"GET\",\n query: req,\n });\n },\n listKeys: async (\n req: paths[\"/v1/apis.listKeys\"][\"get\"][\"parameters\"][\"query\"],\n ): Promise<\n Result<paths[\"/v1/apis.listKeys\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"]>\n > => {\n return await this.fetch({\n path: [\"v1\", \"apis.listKeys\"],\n method: \"GET\",\n query: req,\n });\n },\n };\n }\n}\n","import { Unkey } from \"./client\";\n\n/**\n * Verify a key\n *\n * @example\n * ```ts\n * const { result, error } = await verifyKey(\"key_123\")\n * if (error){\n * // handle potential network or bad request error\n * // a link to our docs will be in the `error.docs` field\n * console.error(error.message)\n * return\n * }\n * if (!result.valid) {\n * // do not grant access\n * return\n * }\n *\n * // process request\n * console.log(result)\n * ```\n */\nexport function verifyKey(req: string | { key: string; apiId: string }) {\n // yes this is empty to make typescript happy but we don't need a token for verifying keys\n // it's not the cleanest but it works for now :)\n const unkey = new Unkey({ rootKey: \"public\" });\n return unkey.keys.verify(typeof req === \"string\" ? { key: req } : req);\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unkey/api",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "license": "MIT",