@openapi-qraft/react 1.9.0 → 1.10.1-beta.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @openapi-qraft/react
2
2
 
3
+ ## 1.10.1-beta.0
4
+
5
+ ## 1.10.0
6
+
7
+ ### Minor Changes
8
+
9
+ - 67c1432: Added the `<QraftSecureRequestFn />` component to enhance secure request handling. This component supports
10
+ multiple authentication methods including API Key, Basic, Bearer, and Cookie authentication. Integrates seamlessly with
11
+ QraftContext for secure API requests.
12
+
3
13
  ## 1.9.0
4
14
 
5
15
  ## 1.8.0
package/README.md CHANGED
@@ -5,6 +5,8 @@ applications,
5
5
  leveraging the power of **TanStack Query v5**. It utilizes a Proxy-based architecture to dynamically generate
6
6
  hooks with typed parameters, ensuring that your API requests are both type-safe and efficient.
7
7
 
8
+ Read the full documentation at [openapi-qraft.github.io/openapi-qraft](https://openapi-qraft.github.io/openapi-qraft/).
9
+
8
10
  ## Features
9
11
 
10
12
  - **Type-safe API Requests:** Utilize TypeScript for type-safe API requests, reducing runtime errors and improving
@@ -37,36 +39,19 @@ To get started with `@openapi-qraft/react`, you'll need to set up your client by
37
39
  of
38
40
  callbacks to handle various React Query functionalities.
39
41
 
40
- ### 1. Generate API Types
42
+ ### 1. Generate OpenAPI Types & Services
41
43
 
42
44
  Before utilizing `@openapi-qraft/react` to make typed requests, you need to define your API services by generating types
43
- and
44
- schemas from your OpenAPI specification. This ensures that your requests are type-safe and that your development
45
- experience benefits from TypeScript's power. Follow the steps below to generate your API services:
46
-
47
- #### Generating TypeScript Definitions
48
-
49
- First, generate TypeScript definitions from your OpenAPI schema
50
- using [`openapi-typescript`](https://www.npmjs.com/package/openapi-typescript). This will provide you with
51
- the necessary types for your API requests and responses.
52
-
53
- ```bash
54
- npx openapi-typescript https://api.dev.monite.com/openapi.json?version=2023-09-01 --output src/api/openapi.d.ts
55
- ```
45
+ and schemas from your OpenAPI Document.
56
46
 
57
- #### Generating Qraft Services
58
-
59
- Next, use `@openapi-qraft/cli` to generate the services and typed TanStack Query React Hooks. Ensure to specify the path
60
- to the TypeScript definitions generated in the previous step.
47
+ To generate both TypeScript definitions and services using `openapi-qraft`, run the following command in the root directory of your project:
61
48
 
62
49
  ```bash
63
- npx @openapi-qraft/cli https://api.dev.monite.com/openapi.json?version=2023-09-01 --output-dir src/api --openapi-types-import-path '../openapi.d.ts'
50
+ npx @openapi-qraft/cli --plugin tanstack-query-react --plugin openapi-typescript https://api.dev.monite.com/openapi.json?version=2023-09-01 --output-dir src/api
64
51
  ```
65
52
 
66
- By completing these steps, you will generate `openapi.d.ts`, which serves as a TypeScript representation of the
67
- specified OpenAPI, _along with a set of services_ in `src/api/services`. These elements are key to enhancing your
68
- development workflow with type
69
- safety and auto-completion features.
53
+ By completing this step, you will generate `src/api/schema.d.ts`, which serves as a TypeScript representation of the specified OpenAPI,
54
+ along with a set of services in `src/api/services/`.
70
55
 
71
56
  ### 2. Create API Client
72
57
 
@@ -418,34 +403,6 @@ qraft.entities.getEntities.useQueries({
418
403
  });
419
404
  ```
420
405
 
421
- ### [useIsFetching(...) 🔗](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useIsFetching)
422
-
423
- ```tsx
424
- function FetchStatus() {
425
- // Checks all queries `GET /entities`
426
- const fetchingTotal = qraft.entities.getEntities.useIsFetching();
427
-
428
- // Checks all queries `GET /entities/3e3e-3e3e-3e3e` and `x-monite-version: 2023-09-01` header
429
- const specificQueryKeyTotal = qraft.entities.getEntities.useIsFetching({
430
- parameters: {
431
- header: {
432
- 'x-monite-version': '2023-09-01',
433
- },
434
- path: {
435
- entity_id: '3e3e-3e3e-3e3e',
436
- },
437
- },
438
- });
439
-
440
- return (
441
- <>
442
- {!!fetchingTotal && <div>Number of queries: {fetchingTotal}...</div>}
443
- {!!specificQueryKeyTotal && <div>Loading specific query...</div>}
444
- </>
445
- );
446
- }
447
- ```
448
-
449
406
  ## [`QueryClient`](https://tanstack.com/query/latest/docs/reference/QueryClient) Methods
450
407
 
451
408
  #### [setQueryData(...) 🔗](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/setQueryData)
@@ -458,7 +415,7 @@ qraft.pet.getPetById.setQueryData(
458
415
  );
459
416
  ```
460
417
 
461
- #### [invalidateQueries(...) 🔗](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/invalidateQueries)
418
+ ### [invalidateQueries(...) 🔗](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/invalidateQueries)
462
419
 
463
420
  [Queries Invalidation 🔗](https://tanstack.com/query/latest/docs/framework/react/guides/query-invalidation) is possible
464
421
  using `<operation>.invalidateQueries(...)` method.
@@ -490,7 +447,7 @@ qraft.entities.getEntities.invalidateQueries(
490
447
  );
491
448
  ```
492
449
 
493
- ##### Invalidation without _parameters_:
450
+ #### Invalidation without _parameters_:
494
451
 
495
452
  To invalidate all queries for a specific endpoint, you can call `invalidateQueries` without any parameters:
496
453
 
@@ -507,7 +464,7 @@ To invalidate all queries for a specific endpoint, you can call `invalidateQueri
507
464
  qraft.entities.getEntities.invalidateQueries(queryClient);
508
465
  ```
509
466
 
510
- ##### Invalidation with _queryKey_:
467
+ #### Invalidation with _queryKey_:
511
468
 
512
469
  It could be useful to invalidate queries using `queryKey` directly:
513
470
 
@@ -534,7 +491,7 @@ qraft.entities.getEntities.invalidateQueries(
534
491
  );
535
492
  ```
536
493
 
537
- ##### [Invalidation with predicate: 🔗](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters)
494
+ #### [Invalidation with predicate: 🔗](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters)
538
495
 
539
496
  The `predicate(...)` function will be used as a final filter on all matching queries.
540
497
 
@@ -562,7 +519,7 @@ qraft.entities.getEntities.invalidateQueries(
562
519
  );
563
520
  ```
564
521
 
565
- #### [fetchQuery(...) 🔗](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/fetchQuery)
522
+ ### [fetchQuery(...) 🔗](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/fetchQuery)
566
523
 
567
524
  ```ts
568
525
  /**
@@ -590,7 +547,7 @@ const posts = qraft.posts.getPosts.fetchQuery(
590
547
  );
591
548
  ```
592
549
 
593
- #### [fetchInfiniteQuery(...) 🔗](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/fetchInfiniteQuery)
550
+ ### [fetchInfiniteQuery(...) 🔗](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/fetchInfiniteQuery)
594
551
 
595
552
  ```ts
596
553
  /**
@@ -0,0 +1,81 @@
1
+ import { ReactNode } from 'react';
2
+ import { QueryClient } from '@tanstack/react-query';
3
+ import type { OperationSchema, RequestFnInfo, RequestFnOptions } from './lib/requestFn.js';
4
+ interface QraftSecureRequestFnBaseProps {
5
+ requestFn<T>(schema: OperationSchema, requestInfo: RequestFnInfo, options?: RequestFnOptions): Promise<T>;
6
+ securitySchemes: SecuritySchemeHandlers<string>;
7
+ }
8
+ type RequestFn = QraftSecureRequestFnBaseProps['requestFn'];
9
+ export interface QraftSecureRequestFnProps extends QraftSecureRequestFnBaseProps {
10
+ children(secureRequestFn: QraftSecureRequestFnBaseProps['requestFn']): ReactNode;
11
+ queryClient?: QueryClient;
12
+ }
13
+ export declare function QraftSecureRequestFn({ children, requestFn, securitySchemes, queryClient: inQueryClient, }: QraftSecureRequestFnProps): import("react").FunctionComponentElement<{
14
+ children?: ReactNode;
15
+ }>;
16
+ export declare const useSecuritySchemeAuth: ({ securitySchemes, requestFn, queryClient, }: QraftSecureRequestFnBaseProps & {
17
+ queryClient: QueryClient;
18
+ }) => RequestFn;
19
+ /**
20
+ * Create a secure `requestFn` that manages security schemes.
21
+ * It will automatically fetch and refresh tokens when needed
22
+ * using QueryClient and the provided security schemes.
23
+ *
24
+ * @param securitySchemes OpenAPI security schemes.
25
+ * @param requestFn Qraft `requestFn`
26
+ * @param queryClient QueryClient instance.
27
+ */
28
+ export declare function createSecureRequestFn(securitySchemes: SecuritySchemeHandlers<string>, requestFn: RequestFn, queryClient: QueryClient): RequestFn;
29
+ /**
30
+ * @internal
31
+ */
32
+ export declare function shallowEqualObjects(newObj: Record<string, any> | string, prevObj: Record<string, any> | string | undefined): boolean;
33
+ type SecurityScheme = SecuritySchemeBearer | SecuritySchemeBasic | SecuritySchemeAPIKey | SecuritySchemeCookie;
34
+ export type SecuritySchemeBearer = string /** JWT Bearer token. **/ | {
35
+ /** Refresh interval in milliseconds. */
36
+ refreshInterval: number;
37
+ /** Token to be used for authentication. */
38
+ token: string;
39
+ };
40
+ export interface SecuritySchemeBasic {
41
+ /** Credentials to be used for authentication. */
42
+ credentials: string;
43
+ /** Refresh interval in milliseconds. */
44
+ refreshInterval: number;
45
+ }
46
+ export type SecuritySchemeAPIKey = {
47
+ /** Where the secret should be placed. */
48
+ in: 'header' | 'query';
49
+ /** Name of the secret key. */
50
+ name: string;
51
+ /** Secret to be used for authentication. */
52
+ value: string;
53
+ /** Refresh interval in milliseconds. */
54
+ refreshInterval?: number;
55
+ };
56
+ export type SecuritySchemeCookie = {
57
+ /** Where the secret should be placed. */
58
+ in: 'cookie';
59
+ /** Refresh interval in milliseconds. */
60
+ refreshInterval?: number;
61
+ };
62
+ /**
63
+ * Type definition for a handler function that manages security schemes.
64
+ * This function is invoked when a token needs to be fetched or refreshed.
65
+ *
66
+ * @param props - The properties for the handler function.
67
+ * @param props.isRefreshing - A boolean indicating the state of the token.
68
+ * It's `false` on the initial "fetch token" request, and `true` if the token is stale or updating using `refreshInterval`.
69
+ * @param props.signal - An AbortSignal that can be used to abort the request.
70
+ *
71
+ * @returns A SecurityScheme, which contains the necessary data for authentication.
72
+ */
73
+ type SecuritySchemeHandler = (props: {
74
+ isRefreshing: boolean;
75
+ signal: AbortSignal;
76
+ }) => SecurityScheme | Promise<SecurityScheme>;
77
+ export type SecuritySchemeHandlers<SecuritySchemeName extends string> = {
78
+ [key in SecuritySchemeName]: SecuritySchemeHandler;
79
+ };
80
+ export {};
81
+ //# sourceMappingURL=Unstable_QraftSecureRequestFn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Unstable_QraftSecureRequestFn.d.ts","sourceRoot":"","sources":["../src/Unstable_QraftSecureRequestFn.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2B,SAAS,EAAsB,MAAM,OAAO,CAAC;AAE/E,OAAO,EACL,WAAW,EAIZ,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,UAAU,6BAA6B;IACrC,SAAS,CAAC,CAAC,EACT,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,aAAa,EAC1B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,CAAC,CAAC,CAAC;IACd,eAAe,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;CACjD;AAED,KAAK,SAAS,GAAG,6BAA6B,CAAC,WAAW,CAAC,CAAC;AAE5D,MAAM,WAAW,yBACf,SAAQ,6BAA6B;IACrC,QAAQ,CACN,eAAe,EAAE,6BAA6B,CAAC,WAAW,CAAC,GAC1D,SAAS,CAAC;IACb,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,SAAS,EACT,eAAe,EACf,WAAW,EAAE,aAAa,GAC3B,EAAE,yBAAyB;;GAkC3B;AAED,eAAO,MAAM,qBAAqB;iBAKnB,WAAW;MACtB,SAwBH,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,sBAAsB,CAAC,MAAM,CAAC,EAC/C,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,WAAW,GACvB,SAAS,CA+BX;AA6HD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,EACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,SAAS,WAmBlD;AAED,KAAK,cAAc,GACf,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,GACpB,oBAAoB,CAAC;AAEzB,MAAM,MAAM,oBAAoB,GAC5B,MAAM,CAAC,yBAAyB,GAChC;IACE,wCAAwC;IACxC,eAAe,EAAE,MAAM,CAAC;IACxB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEN,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IAEpB,wCAAwC;IACxC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,yCAAyC;IACzC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC;IACvB,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,yCAAyC;IACzC,EAAE,EAAE,QAAQ,CAAC;IACb,wCAAwC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,KAAK,qBAAqB,GAAG,CAAC,KAAK,EAAE;IACnC,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;CACrB,KAAK,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAE/C,MAAM,MAAM,sBAAsB,CAAC,kBAAkB,SAAS,MAAM,IAAI;KACrE,GAAG,IAAI,kBAAkB,GAAG,qBAAqB;CACnD,CAAC"}
@@ -0,0 +1,187 @@
1
+ 'use client';
2
+ import { createElement, Fragment, useEffect, useMemo } from 'react';
3
+ import { QueryClient, useQueries, } from '@tanstack/react-query';
4
+ import { jwtDecode } from './lib/jwt-decode/index.js';
5
+ export function QraftSecureRequestFn({ children, requestFn, securitySchemes, queryClient: inQueryClient, }) {
6
+ const queryClient = useMemo(() => inQueryClient ??
7
+ new QueryClient({
8
+ defaultOptions: {
9
+ queries: {
10
+ staleTime: 300_000,
11
+ gcTime: 300_000,
12
+ refetchOnWindowFocus: false,
13
+ refetchOnMount: false,
14
+ refetchOnReconnect: false,
15
+ },
16
+ },
17
+ }), [inQueryClient]);
18
+ useEffect(() => {
19
+ queryClient.mount();
20
+ return () => {
21
+ return void queryClient.unmount();
22
+ };
23
+ }, [queryClient]);
24
+ const secureRequestFn = useSecuritySchemeAuth({
25
+ securitySchemes,
26
+ requestFn,
27
+ queryClient,
28
+ });
29
+ return createElement(Fragment, {
30
+ children: children(secureRequestFn),
31
+ });
32
+ }
33
+ export const useSecuritySchemeAuth = ({ securitySchemes, requestFn, queryClient, }) => {
34
+ useQueries({
35
+ queries: Object.entries(securitySchemes).map(([securitySchemeName]) => {
36
+ const queryKey = [securitySchemeName];
37
+ return {
38
+ enabled: Boolean(queryClient.getQueryData(queryKey)),
39
+ queryKey: queryKey,
40
+ queryFn: ({ signal, }) => {
41
+ const securitySchemeHandler = securitySchemes[securitySchemeName];
42
+ return securitySchemeHandler({ signal, isRefreshing: true });
43
+ },
44
+ };
45
+ }),
46
+ }, queryClient);
47
+ return useMemo(() => createSecureRequestFn(securitySchemes, requestFn, queryClient), [securitySchemes, requestFn, queryClient]);
48
+ };
49
+ /**
50
+ * Create a secure `requestFn` that manages security schemes.
51
+ * It will automatically fetch and refresh tokens when needed
52
+ * using QueryClient and the provided security schemes.
53
+ *
54
+ * @param securitySchemes OpenAPI security schemes.
55
+ * @param requestFn Qraft `requestFn`
56
+ * @param queryClient QueryClient instance.
57
+ */
58
+ export function createSecureRequestFn(securitySchemes, requestFn, queryClient) {
59
+ return async function secureRequestFn(schema, requestInfo, options) {
60
+ const availableSecuritySchemes = Object.keys(securitySchemes);
61
+ const securitySchemeName = schema.security?.find((security) => availableSecuritySchemes.includes(security));
62
+ if (!securitySchemeName) {
63
+ return requestFn(schema, requestInfo, options);
64
+ }
65
+ const securitySchemeHandler = securitySchemes[securitySchemeName];
66
+ return requestFn(schema, await createSecureRequestInfo(securitySchemeHandler, [securitySchemeName], requestInfo, queryClient), options);
67
+ };
68
+ }
69
+ /**
70
+ * Calculate the interval at which a token should be refreshed.
71
+ */
72
+ function getJwtTokenRefreshInterval(token) {
73
+ const parsedToken = jwtDecode(token);
74
+ if (!parsedToken.iat || !parsedToken.exp) {
75
+ throw new Error("JWT token must contain both 'iat' and 'exp' fields.");
76
+ }
77
+ return (parsedToken.exp - parsedToken.iat) * 1000;
78
+ }
79
+ /**
80
+ * Refresh the token if it is about to expire
81
+ * @returns The string to be used as the `Authorization` header or the object to be used in the request.
82
+ */
83
+ async function createSecureRequestInfo(handler, queryKey, requestInfo, queryClient) {
84
+ const prevSecurityResult = queryClient.getQueryData(queryKey);
85
+ const securityResult = await queryClient.fetchQuery({
86
+ queryKey,
87
+ queryFn: ({ signal }) => handler({
88
+ signal,
89
+ isRefreshing: Boolean(prevSecurityResult),
90
+ }),
91
+ });
92
+ if (!shallowEqualObjects(securityResult, prevSecurityResult)) {
93
+ const securityRefreshInterval = getSecurityRefreshInterval(securityResult);
94
+ if (securityRefreshInterval !== undefined && securityRefreshInterval > 0) {
95
+ // remove the already fetched query, before setting new defaults
96
+ queryClient.removeQueries({ queryKey, exact: true });
97
+ // set query new defaults (staleTime and gcTime)
98
+ setSecurityQueryDefaults(queryClient, queryKey, securityRefreshInterval);
99
+ // Set query data with the new token, since the old one was removed.
100
+ // New query data will follow the new defaults staleTime and gcTime.
101
+ queryClient.setQueryData(queryKey, securityResult);
102
+ }
103
+ }
104
+ const securityParameters = createSecureRequestParameters(securityResult);
105
+ if (!securityParameters)
106
+ return requestInfo;
107
+ return {
108
+ ...requestInfo,
109
+ parameters: {
110
+ ...requestInfo.parameters,
111
+ [securityParameters.in]: {
112
+ [securityParameters.name]: securityParameters.value,
113
+ ...requestInfo.parameters?.[securityParameters.in],
114
+ },
115
+ },
116
+ };
117
+ }
118
+ function setSecurityQueryDefaults(queryClient, queryKey, refreshInterval) {
119
+ // set staleTime and gcTime based on token lifetime
120
+ queryClient.setQueryDefaults(queryKey, {
121
+ // stale the token 90% before it expires
122
+ staleTime: isFinite(refreshInterval)
123
+ ? refreshInterval * 0.9
124
+ : refreshInterval,
125
+ // garbage collect the token after it expires
126
+ gcTime: isFinite(refreshInterval) ? refreshInterval : refreshInterval,
127
+ // refetch the token 80% before it expires
128
+ refetchInterval: isFinite(refreshInterval)
129
+ ? refreshInterval * 0.8
130
+ : refreshInterval,
131
+ // always refetch the token, even in the background
132
+ refetchIntervalInBackground: true,
133
+ });
134
+ }
135
+ function createSecureRequestParameters(securityResult) {
136
+ if (typeof securityResult === 'string' || 'token' in securityResult) {
137
+ return {
138
+ in: 'header',
139
+ name: 'Authorization',
140
+ value: `Bearer ${typeof securityResult === 'string' ? securityResult : securityResult.token}`,
141
+ };
142
+ }
143
+ if ('credentials' in securityResult) {
144
+ return {
145
+ in: 'header',
146
+ name: 'Authorization',
147
+ value: `Basic ${securityResult.credentials}`,
148
+ };
149
+ }
150
+ if ('in' in securityResult && securityResult.in !== 'cookie') {
151
+ return securityResult;
152
+ }
153
+ throw new Error('Security scheme must be a string, an object with a token property, an object with a credentials property, or an object with an in property that is not equal to "cookie".');
154
+ }
155
+ function getSecurityRefreshInterval(securityResult) {
156
+ if (typeof securityResult === 'string') {
157
+ return getJwtTokenRefreshInterval(securityResult);
158
+ }
159
+ if ('refreshInterval' in securityResult) {
160
+ return securityResult.refreshInterval;
161
+ }
162
+ }
163
+ /**
164
+ * @internal
165
+ */
166
+ export function shallowEqualObjects(newObj, prevObj) {
167
+ if (typeof newObj !== typeof prevObj)
168
+ return false;
169
+ if (typeof newObj === 'string')
170
+ return newObj === prevObj;
171
+ if (typeof newObj !== 'object' ||
172
+ newObj === null ||
173
+ typeof prevObj !== 'object' ||
174
+ prevObj === null ||
175
+ prevObj === undefined)
176
+ return false;
177
+ if (Object.keys(newObj).length !== Object.keys(prevObj).length)
178
+ return false;
179
+ for (const key in newObj) {
180
+ if (!Object.prototype.hasOwnProperty.call(newObj, key))
181
+ return false;
182
+ if (newObj[key] !== prevObj[key])
183
+ return false;
184
+ }
185
+ return true;
186
+ }
187
+ //# sourceMappingURL=Unstable_QraftSecureRequestFn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Unstable_QraftSecureRequestFn.js","sourceRoot":"","sources":["../src/Unstable_QraftSecureRequestFn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export interface JwtDecodeOptions {
2
+ header?: boolean;
3
+ }
4
+ export interface JwtHeader {
5
+ typ?: string;
6
+ alg?: string;
7
+ kid?: string;
8
+ }
9
+ export interface JwtPayload {
10
+ iss?: string;
11
+ sub?: string;
12
+ aud?: string[] | string;
13
+ exp?: number;
14
+ nbf?: number;
15
+ iat?: number;
16
+ jti?: string;
17
+ }
18
+ export declare class InvalidTokenError extends Error {
19
+ }
20
+ /**
21
+ * Decode a base64 string to a UTF-8 string.
22
+ * Could be used in Node.js or in the browser.
23
+ */
24
+ export declare function b64DecodeUnicode(data: string): string;
25
+ export declare function jwtDecode<T = JwtHeader>(token: string, options: JwtDecodeOptions & {
26
+ header: true;
27
+ }): T;
28
+ export declare function jwtDecode<T = JwtPayload>(token: string, options?: JwtDecodeOptions): T;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/jwt-decode/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAI/C;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrD;AAwBD,wBAAgB,SAAS,CAAC,CAAC,GAAG,SAAS,EACrC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,gBAAgB,GAAG;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,GAC3C,CAAC,CAAC;AACL,wBAAgB,SAAS,CAAC,CAAC,GAAG,UAAU,EACtC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,GACzB,CAAC,CAAC"}
@@ -0,0 +1,61 @@
1
+ export class InvalidTokenError extends Error {
2
+ }
3
+ InvalidTokenError.prototype.name = 'InvalidTokenError';
4
+ /**
5
+ * Decode a base64 string to a UTF-8 string.
6
+ * Could be used in Node.js or in the browser.
7
+ */
8
+ export function b64DecodeUnicode(data) {
9
+ if (typeof atob === 'function')
10
+ return decodeURIComponent(Array.from(atob(data), byteToPercent).join(''));
11
+ return Buffer.from(data, 'base64').toString('utf-8');
12
+ }
13
+ function base64UrlDecode(str) {
14
+ let output = str.replace(/-/g, '+').replace(/_/g, '/');
15
+ switch (output.length % 4) {
16
+ case 0:
17
+ break;
18
+ case 2:
19
+ output += '==';
20
+ break;
21
+ case 3:
22
+ output += '=';
23
+ break;
24
+ default:
25
+ throw new Error('base64 string is not of the correct length');
26
+ }
27
+ try {
28
+ return b64DecodeUnicode(output);
29
+ }
30
+ catch (err) {
31
+ return atob(output);
32
+ }
33
+ }
34
+ export function jwtDecode(token, options) {
35
+ if (typeof token !== 'string') {
36
+ throw new InvalidTokenError('Invalid token specified: must be a string');
37
+ }
38
+ options ||= {};
39
+ const pos = options.header === true ? 0 : 1;
40
+ const part = token.split('.')[pos];
41
+ if (typeof part !== 'string') {
42
+ throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);
43
+ }
44
+ let decoded;
45
+ try {
46
+ decoded = base64UrlDecode(part);
47
+ }
48
+ catch (e) {
49
+ throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);
50
+ }
51
+ try {
52
+ return JSON.parse(decoded);
53
+ }
54
+ catch (e) {
55
+ throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);
56
+ }
57
+ }
58
+ function byteToPercent(b) {
59
+ return `%${`00${b.charCodeAt(0).toString(16)}`.slice(-2)}`;
60
+ }
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/jwt-decode/index.ts"],"names":[],"mappings":"AAoBA,MAAM,OAAO,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,iBAAiB,CAAC,SAAS,CAAC,IAAI,GAAG,mBAAmB,CAAC;AAEvD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,OAAO,IAAI,KAAK,UAAU;QAC5B,OAAO,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5E,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACvD,QAAQ,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC;YACJ,MAAM;QACR,KAAK,CAAC;YACJ,MAAM,IAAI,IAAI,CAAC;YACf,MAAM;QACR,KAAK,CAAC;YACJ,MAAM,IAAI,GAAG,CAAC;YACd,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CAAC;QACH,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAUD,MAAM,UAAU,SAAS,CACvB,KAAa,EACb,OAA0B;IAE1B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,iBAAiB,CAAC,2CAA2C,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO,KAAK,EAAE,CAAC;IAEf,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAEnC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,iBAAiB,CACzB,0CAA0C,GAAG,GAAG,CAAC,EAAE,CACpD,CAAC;IACJ,CAAC;IAED,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,iBAAiB,CACzB,qDAAqD,GAAG,GAAG,CAAC,KAAM,CAAW,CAAC,OAAO,GAAG,CACzF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;IAClC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,iBAAiB,CACzB,mDAAmD,GAAG,GAAG,CAAC,KAAM,CAAW,CAAC,OAAO,GAAG,CACvF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,OAAO,IAAI,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/lib/jwt-decode/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,99 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { jwtDecode, InvalidTokenError, b64DecodeUnicode, } from './index.js';
3
+ const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIiLCJleHAiOjEzOTMyODY4OTMsImlhdCI6MTM5MzI2ODg5M30.4-iaDojEVl0pJQMjrbM1EzUIfAZgsbK_kgnVyVxFSVo';
4
+ describe('jwt-decode', () => {
5
+ it('should return default and custom claims', () => {
6
+ const decoded = jwtDecode(token);
7
+ expect(decoded.exp).toEqual(1393286893);
8
+ expect(decoded.iat).toEqual(1393268893);
9
+ expect(decoded.foo).toEqual('bar');
10
+ });
11
+ it('should return header information', () => {
12
+ const decoded = jwtDecode(token, { header: true });
13
+ expect(decoded.typ).toEqual('JWT');
14
+ expect(decoded.alg).toEqual('HS256');
15
+ });
16
+ it('should work with utf8 tokens', () => {
17
+ const utf8Token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9zw6kiLCJpYXQiOjE0MjU2NDQ5NjZ9.1CfFtdGUPs6q8kT3OGQSVlhEMdbuX0HfNSqum0023a0';
18
+ const decoded = jwtDecode(utf8Token);
19
+ expect(decoded.name).toEqual('José');
20
+ });
21
+ it('should work with binary tokens', () => {
22
+ const binaryToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9z6SIsImlhdCI6MTQyNTY0NDk2Nn0.cpnplCBxiw7Xqz5thkqs4Mo_dymvztnI0CI4BN0d1t8';
23
+ const decoded = jwtDecode(binaryToken);
24
+ expect(decoded.name).toEqual('José');
25
+ });
26
+ it('should work with double padding', () => {
27
+ const utf8Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpvc8OpIiwiaWF0IjoxNTE2MjM5MDIyfQ.7A3F5SUH2gbBSYVon5mas_Y-KCrWojorKQg7UKGVEIA';
28
+ const decoded = jwtDecode(utf8Token);
29
+ expect(decoded.name).toEqual('José');
30
+ });
31
+ it('should work with single padding', () => {
32
+ const utf8Token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpvc8OpZSIsImlhdCI6MTUxNjIzOTAyMn0.tbjJzDAylkKSV0_YGR5xBJBlFK01C82nZPLIcA3JX1g';
33
+ const decoded = jwtDecode(utf8Token);
34
+ expect(decoded.name).toEqual('Josée');
35
+ });
36
+ it('should throw InvalidTokenError on not a string', () => {
37
+ const badToken = null;
38
+ expect(() => {
39
+ jwtDecode(badToken);
40
+ }).toThrow(InvalidTokenError);
41
+ });
42
+ it('should throw InvalidTokenError on string that is not a token', () => {
43
+ const badToken = 'foobar';
44
+ expect(() => {
45
+ jwtDecode(badToken);
46
+ }).toThrow(InvalidTokenError);
47
+ });
48
+ it('should throw InvalidTokenErrors when token is null', () => {
49
+ const badToken = null;
50
+ expect(() => {
51
+ jwtDecode(badToken, { header: true });
52
+ }).toThrow(new InvalidTokenError('Invalid token specified: must be a string'));
53
+ });
54
+ it('should throw InvalidTokenErrors when missing part #1', () => {
55
+ const badToken = '.FAKE_TOKEN';
56
+ expect(() => {
57
+ jwtDecode(badToken, { header: true });
58
+ }).toThrow(/Invalid token specified: invalid json for part #1/);
59
+ });
60
+ it('should throw InvalidTokenErrors when part #1 is not valid base64', () => {
61
+ const badToken = 'TOKEN';
62
+ expect(() => {
63
+ jwtDecode(badToken, { header: true });
64
+ }).toThrow(/Invalid token specified: invalid base64 for part #1/);
65
+ });
66
+ it('should throw InvalidTokenErrors when part #1 is not valid JSON', () => {
67
+ const badToken = 'FAKE.TOKEN';
68
+ expect(() => {
69
+ jwtDecode(badToken, { header: true });
70
+ }).toThrow(/Invalid token specified: invalid json for part #1/);
71
+ });
72
+ it('should throw InvalidTokenErrors when missing part #2', () => {
73
+ const badToken = 'FAKE_TOKEN';
74
+ expect(() => {
75
+ jwtDecode(badToken);
76
+ }).toThrow(new InvalidTokenError('Invalid token specified: missing part #2'));
77
+ });
78
+ it('should throw InvalidTokenErrors when part #2 is not valid base64', () => {
79
+ const badToken = 'FAKE.TOKEN';
80
+ expect(() => {
81
+ jwtDecode(badToken);
82
+ }).toThrow(/Invalid token specified: invalid base64 for part #2/);
83
+ });
84
+ it('should throw InvalidTokenErrors when part #2 is not valid JSON', () => {
85
+ const badToken = 'FAKE.TOKEN2';
86
+ expect(() => {
87
+ jwtDecode(badToken);
88
+ }).toThrow(/Invalid token specified: invalid json for part #2/);
89
+ });
90
+ });
91
+ describe('decodeBase64', () => {
92
+ it('decodes base64', () => {
93
+ expect(b64DecodeUnicode('aGVsbG8=')).toEqual('hello');
94
+ });
95
+ it('decodes base64 non latin characters', () => {
96
+ expect(b64DecodeUnicode('5L2g5aW9')).toEqual('你好');
97
+ });
98
+ });
99
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/lib/jwt-decode/index.test.ts"],"names":[],"mappings":"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"}