@quiltt/react 3.5.3 → 3.5.5
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 +26 -0
- package/dist/QuilttAuthProvider-client-CV5hYba6.js +7621 -0
- package/dist/QuilttSettingsProvider-client-BOiVpLF3.js +18 -0
- package/dist/index.d.ts +153 -8
- package/dist/index.js +66 -2
- package/dist/useEventListener-client-CTa_g_PX.js +34 -0
- package/dist/useIsomorphicLayoutEffect-client-DeTHOKz1.js +9 -0
- package/dist/useQuilttClient-client-pzCXNLH2.js +6 -0
- package/dist/useQuilttConnector-client-hd0LT34T.js +121 -0
- package/dist/useQuilttSession-client-CcRhqoXG.js +37 -0
- package/dist/useQuilttSettings-client-DU_Qfc8X.js +12 -0
- package/dist/useScript-client-Cx5nb9RW.js +88 -0
- package/dist/useSession-client-Cew1m26_.js +60 -0
- package/dist/useStorage-client-C91C8oXS.js +61 -0
- package/package.json +12 -12
- package/src/components/QuilttButton.tsx +3 -2
- package/src/components/QuilttContainer.tsx +3 -2
- package/src/hooks/session/useAuthenticateSession.ts +1 -1
- package/src/hooks/session/useImportSession.ts +1 -1
- package/src/hooks/useQuilttClient.ts +2 -0
- package/src/hooks/useQuilttSession.ts +3 -1
- package/src/hooks/useScript.ts +1 -0
- package/src/version.ts +1 -1
- package/dist/QuilttContainer-ac11f5d0.d.ts +0 -30
- package/dist/QuilttSettingsProvider-d1d44353.d.ts +0 -26
- package/dist/components/index.cjs +0 -2
- package/dist/components/index.cjs.map +0 -1
- package/dist/components/index.d.ts +0 -4
- package/dist/components/index.js +0 -2
- package/dist/components/index.js.map +0 -1
- package/dist/hooks/helpers/index.cjs +0 -2
- package/dist/hooks/helpers/index.cjs.map +0 -1
- package/dist/hooks/helpers/index.d.ts +0 -2
- package/dist/hooks/helpers/index.js +0 -2
- package/dist/hooks/helpers/index.js.map +0 -1
- package/dist/hooks/index.cjs +0 -2
- package/dist/hooks/index.cjs.map +0 -1
- package/dist/hooks/index.d.ts +0 -6
- package/dist/hooks/index.js +0 -2
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/session/index.cjs +0 -2
- package/dist/hooks/session/index.cjs.map +0 -1
- package/dist/hooks/session/index.d.ts +0 -3
- package/dist/hooks/session/index.js +0 -2
- package/dist/hooks/session/index.js.map +0 -1
- package/dist/index.cjs +0 -2
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/providers/index.cjs +0 -2
- package/dist/providers/index.cjs.map +0 -1
- package/dist/providers/index.d.ts +0 -2
- package/dist/providers/index.js +0 -2
- package/dist/providers/index.js.map +0 -1
- package/dist/useIsomorphicLayoutEffect-206cec40.d.ts +0 -14
- package/dist/useRevokeSession-1bedf71e.d.ts +0 -50
- package/dist/useStorage-a299f552.d.ts +0 -51
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import '@quiltt/core';
|
|
5
|
+
import './useSession-client-Cew1m26_.js';
|
|
6
|
+
import { Q as QuilttSettings } from './useQuilttSettings-client-DU_Qfc8X.js';
|
|
7
|
+
|
|
8
|
+
const QuilttSettingsProvider = ({ clientId, children })=>{
|
|
9
|
+
const [_clientId] = useState(clientId);
|
|
10
|
+
return /*#__PURE__*/ jsx(QuilttSettings.Provider, {
|
|
11
|
+
value: {
|
|
12
|
+
clientId: _clientId
|
|
13
|
+
},
|
|
14
|
+
children: children
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { QuilttSettingsProvider as Q };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,154 @@
|
|
|
1
|
+
import { Maybe, QuilttJWT, UsernamePayload, UnprocessableData, AuthAPI, PasscodePayload, ConnectorSDKConnectorOptions, ConnectorSDKCallbacks } from '@quiltt/core';
|
|
1
2
|
export * from '@quiltt/core';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { RefObject, useLayoutEffect, Dispatch, SetStateAction, FC, PropsWithChildren, Component, ComponentType } from 'react';
|
|
5
|
+
import { useApolloClient } from '@apollo/client/index.js';
|
|
6
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
declare function useEventListener<K extends keyof MediaQueryListEventMap>(eventName: K, handler: (event: MediaQueryListEventMap[K]) => void, element: RefObject<MediaQueryList>, options?: boolean | AddEventListenerOptions): void;
|
|
9
|
+
declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void, element?: undefined, options?: boolean | AddEventListenerOptions): void;
|
|
10
|
+
declare function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = HTMLDivElement>(eventName: K, handler: (event: HTMLElementEventMap[K]) => void, element: RefObject<T>, options?: boolean | AddEventListenerOptions): void;
|
|
11
|
+
declare function useEventListener<K extends keyof DocumentEventMap>(eventName: K, handler: (event: DocumentEventMap[K]) => void, element: RefObject<Document>, options?: boolean | AddEventListenerOptions): void;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* This hook is a browser hook. But React code could be generated from the server without the Window API.
|
|
15
|
+
* This hook switches between useEffect and useLayoutEffect following the execution environment.
|
|
16
|
+
*/
|
|
17
|
+
declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
|
|
18
|
+
|
|
19
|
+
type SetSession = Dispatch<SetStateAction<Maybe<string> | undefined>>;
|
|
20
|
+
/**
|
|
21
|
+
* useSession uses useStorage to support a global singleton style of access. When
|
|
22
|
+
* updated, all components, and windows should also invalidate.
|
|
23
|
+
*
|
|
24
|
+
* TODO: Support Rotation before Expiry
|
|
25
|
+
*
|
|
26
|
+
* Dataflow can come from two directions:
|
|
27
|
+
* 1. Login - Bottom Up
|
|
28
|
+
* This happens on login, when a token is passed up through the setSession
|
|
29
|
+
* callback. From here it needs to be stored, and shared for usage.
|
|
30
|
+
* 2. Refresh - Top Down
|
|
31
|
+
* This happens when a page is reloaded or a person returns, and everything is
|
|
32
|
+
* reinitialized.
|
|
33
|
+
*/
|
|
34
|
+
declare const useSession: (storageKey?: string) => [Maybe<QuilttJWT> | undefined, SetSession];
|
|
35
|
+
|
|
36
|
+
type IdentifySessionCallbacks = {
|
|
37
|
+
onSuccess?: () => unknown;
|
|
38
|
+
onChallenged?: () => unknown;
|
|
39
|
+
onError?: (errors: UnprocessableData) => unknown;
|
|
40
|
+
};
|
|
41
|
+
type IdentifySession = (payload: UsernamePayload, callbacks: IdentifySessionCallbacks) => Promise<unknown>;
|
|
42
|
+
type UseIdentifySession = (auth: AuthAPI, setSession: SetSession) => IdentifySession;
|
|
43
|
+
declare const useIdentifySession: UseIdentifySession;
|
|
44
|
+
|
|
45
|
+
type AuthenticateSessionCallbacks = {
|
|
46
|
+
onSuccess?: () => unknown;
|
|
47
|
+
onFailure?: () => unknown;
|
|
48
|
+
onError?: (errors: UnprocessableData) => unknown;
|
|
49
|
+
};
|
|
50
|
+
type AuthenticateSession = (payload: PasscodePayload, callbacks: AuthenticateSessionCallbacks) => Promise<unknown>;
|
|
51
|
+
type UseAuthenticateSession = (auth: AuthAPI, setSession: SetSession) => AuthenticateSession;
|
|
52
|
+
declare const useAuthenticateSession: UseAuthenticateSession;
|
|
53
|
+
|
|
54
|
+
type ImportSession = (token: string) => Promise<boolean>;
|
|
55
|
+
type UseImportSession = (auth: AuthAPI, session: Maybe<QuilttJWT> | undefined, setSession: SetSession, environmentId?: string) => ImportSession;
|
|
56
|
+
/**
|
|
57
|
+
* Optionally Accepts environmentId to validate session is from with your desired environment
|
|
58
|
+
*/
|
|
59
|
+
declare const useImportSession: UseImportSession;
|
|
60
|
+
|
|
61
|
+
type RevokeSession = () => Promise<void>;
|
|
62
|
+
type UseRevokeSession = (auth: AuthAPI, session: Maybe<QuilttJWT> | undefined, setSession: SetSession) => RevokeSession;
|
|
63
|
+
declare const useRevokeSession: UseRevokeSession;
|
|
64
|
+
|
|
65
|
+
declare const useQuilttClient: typeof useApolloClient;
|
|
66
|
+
|
|
67
|
+
declare const useQuilttConnector: (connectorId?: string, options?: ConnectorSDKConnectorOptions) => {
|
|
68
|
+
open: () => void;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
type UseQuilttSession = (environmentId?: string) => {
|
|
72
|
+
session: Maybe<QuilttJWT> | undefined;
|
|
73
|
+
importSession: ImportSession;
|
|
74
|
+
identifySession: IdentifySession;
|
|
75
|
+
authenticateSession: AuthenticateSession;
|
|
76
|
+
revokeSession: RevokeSession;
|
|
77
|
+
forgetSession: (token?: string) => Promise<void>;
|
|
78
|
+
};
|
|
79
|
+
declare const useQuilttSession: UseQuilttSession;
|
|
80
|
+
|
|
81
|
+
type QuilttSettingsContext = {
|
|
82
|
+
clientId?: string | undefined;
|
|
83
|
+
};
|
|
84
|
+
declare const QuilttSettings: react.Context<QuilttSettingsContext>;
|
|
85
|
+
declare const useQuilttSettings: () => {
|
|
86
|
+
clientId?: string | undefined;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Attempt to persist state with local storage, so it remains after refresh and
|
|
91
|
+
* across open documents. Falls back to in memory storage when localStorage is
|
|
92
|
+
* unavailable.
|
|
93
|
+
*
|
|
94
|
+
* This hook is used in the same way as useState except that you must pass the
|
|
95
|
+
* storage key in the 1st parameter. If the window object is not present (as in SSR),
|
|
96
|
+
* useStorage() will return the default nextState.
|
|
97
|
+
*
|
|
98
|
+
* Expect values to remain in sync
|
|
99
|
+
* Across Hooks
|
|
100
|
+
* Across Reloads
|
|
101
|
+
* Across Windows (Documents)
|
|
102
|
+
*
|
|
103
|
+
* @param key
|
|
104
|
+
* @param initialState
|
|
105
|
+
* @returns {Array} [storage, setStorage]
|
|
106
|
+
*/
|
|
107
|
+
declare const useStorage: <T>(key: string, initialState?: Maybe<T>) => [Maybe<T> | undefined, Dispatch<SetStateAction<Maybe<T> | undefined>>];
|
|
108
|
+
|
|
109
|
+
type QuilttAuthProviderProps = PropsWithChildren & {
|
|
110
|
+
token?: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* If a token is provided, will validate the token against the api and then import
|
|
114
|
+
* it into trusted storage. While this process is happening, the component is put
|
|
115
|
+
* into a loading state and the children are not rendered to prevent race conditions
|
|
116
|
+
* from triggering within the transitionary state.
|
|
117
|
+
*
|
|
118
|
+
*/
|
|
119
|
+
declare const QuilttAuthProvider: FC<QuilttAuthProviderProps>;
|
|
120
|
+
|
|
121
|
+
type QuilttProviderProps = PropsWithChildren & {
|
|
122
|
+
clientId?: string;
|
|
123
|
+
token?: string;
|
|
124
|
+
};
|
|
125
|
+
declare const QuilttProvider: FC<QuilttProviderProps>;
|
|
126
|
+
|
|
127
|
+
type QuilttSettingsProviderProps = PropsWithChildren & {
|
|
128
|
+
clientId?: string;
|
|
129
|
+
};
|
|
130
|
+
declare const QuilttSettingsProvider: FC<QuilttSettingsProviderProps>;
|
|
131
|
+
|
|
132
|
+
type AnyTag = string | FC<any> | (new (props: any) => Component);
|
|
133
|
+
type PropsOf<Tag> = Tag extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[Tag] : Tag extends ComponentType<infer Props> ? Props & JSX.IntrinsicAttributes : never;
|
|
134
|
+
|
|
135
|
+
type QuilttButtonProps<T extends AnyTag> = PropsWithChildren<{
|
|
136
|
+
as?: T;
|
|
137
|
+
connectorId: string;
|
|
138
|
+
connectionId?: string;
|
|
139
|
+
institution?: string;
|
|
140
|
+
} & ConnectorSDKCallbacks>;
|
|
141
|
+
declare const QuilttButton: <T extends AnyTag = "button">({ as, connectorId, connectionId, institution, onEvent, onLoad, onExit, onExitSuccess, onExitAbort, onExitError, children, ...props }: QuilttButtonProps<T> & PropsOf<T>) => react_jsx_runtime.JSX.Element;
|
|
142
|
+
|
|
143
|
+
type QuilttContainerProps<T extends AnyTag> = PropsWithChildren<{
|
|
144
|
+
as?: T;
|
|
145
|
+
connectorId: string;
|
|
146
|
+
connectionId?: string;
|
|
147
|
+
} & ConnectorSDKCallbacks>;
|
|
148
|
+
/**
|
|
149
|
+
* QuilttContainer uses globally shared callbacks. It's recommended you only use
|
|
150
|
+
* one Container at a time.
|
|
151
|
+
*/
|
|
152
|
+
declare const QuilttContainer: <T extends AnyTag = "div">({ as, connectorId, connectionId, onEvent, onLoad, onExit, onExitSuccess, onExitAbort, onExitError, children, ...props }: QuilttContainerProps<T> & PropsOf<T>) => react_jsx_runtime.JSX.Element;
|
|
153
|
+
|
|
154
|
+
export { type AuthenticateSession, type IdentifySession, type ImportSession, QuilttAuthProvider, QuilttButton, QuilttContainer, QuilttProvider, QuilttSettings, QuilttSettingsProvider, type RevokeSession, type SetSession, type UseQuilttSession, useAuthenticateSession, useEventListener, useIdentifySession, useImportSession, useIsomorphicLayoutEffect, useQuilttClient, useQuilttConnector, useQuilttSession, useQuilttSettings, useRevokeSession, useSession, useStorage };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,66 @@
|
|
|
1
|
-
var Te=Object.defineProperty,_e=Object.defineProperties;var Ae=Object.getOwnPropertyDescriptors;var g=Object.getOwnPropertySymbols;var G=Object.prototype.hasOwnProperty,q=Object.prototype.propertyIsEnumerable;var W=(t,e,r)=>e in t?Te(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,h=(t,e)=>{for(var r in e||(e={}))G.call(e,r)&&W(t,r,e[r]);if(g)for(var r of g(e))q.call(e,r)&&W(t,r,e[r]);return t},E=(t,e)=>_e(t,Ae(e));var T=(t,e)=>{var r={};for(var o in t)G.call(t,o)&&e.indexOf(o)<0&&(r[o]=t[o]);if(t!=null&&g)for(var o of g(t))e.indexOf(o)<0&&q.call(t,o)&&(r[o]=t[o]);return r};var d=(t,e,r)=>new Promise((o,n)=>{var s=u=>{try{a(r.next(u))}catch(l){n(l)}},i=u=>{try{a(r.throw(u))}catch(l){n(l)}},a=u=>u.done?o(u.value):Promise.resolve(u.value).then(s,i);a((r=r.apply(t,e)).next())});export*from"@quiltt/core";import{useEffect as Oe,useRef as Le}from"react";import{useEffect as we,useLayoutEffect as Ce}from"react";var Pe=typeof window!="undefined"?Ce:we,H=Pe;function Tt(t,e,r,o){let n=Le(e);H(()=>{n.current=e},[e]),Oe(()=>{var a;let s=(a=r==null?void 0:r.current)!=null?a:window;if(!(s&&s.addEventListener))return;let i=u=>n.current(u);return s.addEventListener(t,i,o),()=>{s.removeEventListener(t,i,o)}},[t,r,o])}import{useCallback as Re}from"react";var B=(t,e)=>Re((o,n)=>d(void 0,null,function*(){let s=yield t.identify(o);switch(s.status){case 201:if(e(s.data.token),n.onSuccess)return n.onSuccess();break;case 202:if(n.onChallenged)return n.onChallenged();break;case 422:if(n.onError)return n.onError(s.data);break;default:throw new Error(`AuthAPI.identify: Unexpected response status ${s.status}`)}}),[t,e]);import{useCallback as Ie}from"react";var J=(t,e)=>Ie((o,n)=>d(void 0,null,function*(){let s=yield t.authenticate(o);switch(s.status){case 201:if(e(s.data.token),n.onSuccess)return n.onSuccess();break;case 401:if(n.onFailure)return n.onFailure();break;case 422:if(n.onError)return n.onError(s.data);break;default:throw new Error(`AuthAPI.authenticate: Unexpected response status ${s.status}`)}}),[t,e]);import{useCallback as De}from"react";import{JsonWebTokenParse as Ne}from"@quiltt/core";var $=(t,e,r,o)=>De(s=>d(void 0,null,function*(){if(!s)return!!e;if(e&&e.token==s)return!0;let i=Ne(s);if(!i||o&&i.claims.eid!==o)return!1;let a=yield t.ping(s);switch(a.status){case 200:return r(s),!0;break;case 401:return!1;default:throw new Error(`AuthAPI.ping: Unexpected response status ${a.status}`)}}),[t,e,r,o]);import{useCallback as Qe}from"react";var X=(t,e,r)=>Qe(()=>d(void 0,null,function*(){e&&(yield t.revoke(e.token),r(null))}),[t,e,r]);var Q=function(t,e){return Q=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,o){r.__proto__=o}||function(r,o){for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(r[n]=o[n])},Q(t,e)};function Y(t,e){if(typeof e!="function"&&e!==null)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");Q(t,e);function r(){this.constructor=t}t.prototype=e===null?Object.create(e):(r.prototype=e.prototype,new r)}var M="Invariant Violation",z=Object.setPrototypeOf,Me=z===void 0?function(t,e){return t.__proto__=e,t}:z,Z=function(t){Y(e,t);function e(r){r===void 0&&(r=M);var o=t.call(this,typeof r=="number"?M+": "+r+" (see https://github.com/apollographql/invariant-packages)":r)||this;return o.framesToPop=1,o.name=M,Me(o,e.prototype),o}return e}(Error);function p(t,e){if(!t)throw new Z(e)}var ee=["debug","log","warn","error","silent"],Ue=ee.indexOf("log");function _(t){return function(){if(ee.indexOf(t)>=Ue){var e=console[t]||console.log;return e.apply(console,arguments)}}}(function(t){t.debug=_("debug"),t.log=_("log"),t.warn=_("warn"),t.error=_("error")})(p||(p={}));function c(t){try{return t()}catch(e){}}var A=c(function(){return globalThis})||c(function(){return window})||c(function(){return self})||c(function(){return global})||c(function(){return c.constructor("return this")()});var te="__",re=[te,te].join("DEV");function je(){try{return!!__DEV__}catch(t){return Object.defineProperty(A,re,{value:c(function(){return process.env.NODE_ENV})!=="production",enumerable:!1,configurable:!0,writable:!0}),A[re]}}var w=je();function y(t){try{return t()}catch(e){}}var U=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),j=!1;function ke(){U&&!y(function(){return process.env.NODE_ENV})&&!y(function(){return process})&&(Object.defineProperty(U,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),j=!0)}ke();function k(){j&&(delete U.process,j=!1)}function C(t,e){if(!!!t)throw new Error(e)}function ne(t){return P(t,[])}function P(t,e){switch(typeof t){case"string":return JSON.stringify(t);case"function":return t.name?`[function ${t.name}]`:"[function]";case"object":return Ve(t,e);default:return String(t)}}function Ve(t,e){if(t===null)return"null";if(e.includes(t))return"[Circular]";let r=[...e,t];if(Ke(t)){let o=t.toJSON();if(o!==t)return typeof o=="string"?o:P(o,r)}else if(Array.isArray(t))return We(t,r);return Fe(t,r)}function Ke(t){return typeof t.toJSON=="function"}function Fe(t,e){let r=Object.entries(t);return r.length===0?"{}":e.length>2?"["+Ge(t)+"]":"{ "+r.map(([n,s])=>n+": "+P(s,e)).join(", ")+" }"}function We(t,e){if(t.length===0)return"[]";if(e.length>2)return"[Array]";let r=Math.min(10,t.length),o=t.length-r,n=[];for(let s=0;s<r;++s)n.push(P(t[s],e));return o===1?n.push("... 1 more item"):o>1&&n.push(`... ${o} more items`),"["+n.join(", ")+"]"}function Ge(t){let e=Object.prototype.toString.call(t).replace(/^\[object /,"").replace(/]$/,"");if(e==="Object"&&typeof t.constructor=="function"){let r=t.constructor.name;if(typeof r=="string"&&r!=="")return r}return e}var b=class{constructor(e,r="GraphQL request",o={line:1,column:1}){typeof e=="string"||C(!1,`Body must be a string. Received: ${ne(e)}.`),this.body=e,this.name=r,this.locationOffset=o,this.locationOffset.line>0||C(!1,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||C(!1,"column in locationOffset is 1-indexed and must be positive.")}get[Symbol.toStringTag](){return"Source"}};function oe(){return typeof b=="function"?k():k()}function qe(){__DEV__?p(typeof w=="boolean",w):p(typeof w=="boolean",39)}oe();qe();var Gr=typeof WeakMap=="function"&&c(function(){return navigator.product})!=="ReactNative";var ie=typeof Symbol=="function"&&typeof Symbol.for=="function";var qr=typeof c(function(){return window.document.createElement})=="function",Hr=c(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1;import*as O from"react";var se=ie?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function S(){var t=O.createContext[se];return t||(Object.defineProperty(O.createContext,se,{value:t=O.createContext({}),enumerable:!1,writable:!1,configurable:!0}),t.displayName="ApolloContext"),t}import*as V from"react";var L=function(t){var e=t.client,r=t.children,o=S();return V.createElement(o.Consumer,null,function(n){return n===void 0&&(n={}),e&&n.client!==e&&(n=Object.assign({},n,{client:e})),__DEV__?p(n.client,'ApolloProvider was not passed a client instance. Make sure you pass in your client via the "client" prop.'):p(n.client,29),V.createElement(o.Provider,{value:n},r)})};import{useContext as He}from"react";function ae(t){var e=He(S()),r=t||e.client;return __DEV__?p(!!r,'Could not find "client" in the context or passed in as an option. Wrap the root component in an <ApolloProvider>, or pass an ApolloClient instance in via options.'):p(!!r,32),r}var yn=ae;import{useCallback as at,useEffect as m,useState as Se}from"react";import{useCallback as rt}from"react";import{useMemo as $e}from"react";import{useEffect as Xe,useCallback as Ye}from"react";import{JsonWebTokenParse as ze,Timeoutable as Ze}from"@quiltt/core";import{useCallback as ue,useEffect as Be,useState as Je}from"react";import{GlobalStorage as R}from"@quiltt/core";var ce=(t,e)=>{let r=ue(()=>{let i;return(i=R.get(t))!==void 0?i:e},[t,e]),[o,n]=Je(r()),s=ue(i=>{let a=i instanceof Function?i(o):i;o!==a&&R.set(t,a)},[t,o]);return Be(()=>(R.subscribe(t,n),n(r()),()=>R.unsubscribe(t,n)),[]),[o,s]};var le=ze,fe=new Ze,pe=(t="session")=>{let[e,r]=ce(t),o=$e(()=>le(e),[e]);Xe(()=>{if(!o)return;let s=o.claims.exp*1e3,i=()=>r(null);if(Date.now()>=s)i();else return fe.set(i,s-Date.now()),()=>fe.clear(i)},[o,r]);let n=Ye(s=>{let i=s instanceof Function?s(e):s;e!==i&&(!i||le(i))&&r(i)},[e,r]);return[o,n]};import{AuthAPI as nt}from"@quiltt/core";import{createContext as et,useContext as tt}from"react";var K=et({}),de=()=>{let t=tt(K);return h({},t)};var I=t=>{let{clientId:e}=de(),[r,o]=pe(),n=new nt(e),s=$(n,r,o,t),i=B(n,o),a=J(n,o),u=X(n,r,o),l=rt(f=>d(void 0,null,function*(){(!f||r&&f&&f==r.token)&&o(null)}),[r,o]);return{session:r,importSession:s,identifySession:i,authenticateSession:a,revokeSession:u,forgetSession:l}};import{useEffect as ot,useState as it}from"react";var F={};function st(t){let e=document.querySelector(`script[src="${t}"]`),r=e==null?void 0:e.getAttribute("data-status");return{node:e,status:r}}function me(t,e){let[r,o]=it(()=>{var n;return!t||e!=null&&e.shouldPreventLoad?"idle":typeof window=="undefined"?"loading":(n=F[t])!=null?n:"loading"});return ot(()=>{var u,l;if(!t||e!=null&&e.shouldPreventLoad)return;let n=F[t];if(n==="ready"||n==="error"){o(n);return}let s=st(t),i=s.node;if(i)o((l=(u=s.status)!=null?u:n)!=null?l:"loading");else{i=document.createElement("script"),i.src=t,i.async=!0,i.setAttribute("data-status","loading"),document.body.appendChild(i);let f=v=>{let x=v.type==="load"?"ready":"error";i==null||i.setAttribute("data-status",x)};i.addEventListener("load",f),i.addEventListener("error",f)}let a=f=>{let v=f.type==="load"?"ready":"error";o(v),F[t]=v};return i.addEventListener("load",a),i.addEventListener("error",a),()=>{i&&(i.removeEventListener("load",a),i.removeEventListener("error",a)),i&&(e!=null&&e.removeOnUnmount)&&i.remove()}},[t,e==null?void 0:e.shouldPreventLoad,e==null?void 0:e.removeOnUnmount]),r}import{cdnBase as ut}from"@quiltt/core";var ye="3.5.3";var D=(t,e)=>{let r=me(`${ut}/v1/connector.js?agent=react-${ye}`),{session:o}=I(),[n,s]=Se(),[i,a]=Se(!1);return m(()=>{typeof Quiltt!="undefined"&&Quiltt.authenticate(o==null?void 0:o.token)},[r,o]),m(()=>{typeof Quiltt=="undefined"||!t||(e!=null&&e.connectionId?s(Quiltt.reconnect(t,{connectionId:e.connectionId})):s(Quiltt.connect(t,{institution:e==null?void 0:e.institution})))},[r,t,e==null?void 0:e.connectionId,e==null?void 0:e.institution]),m(()=>{if(!(!n||!(e!=null&&e.onEvent)))return n.onEvent(e.onEvent),()=>n.offEvent(e.onEvent)},[n,e==null?void 0:e.onEvent]),m(()=>{if(!(!n||!(e!=null&&e.onLoad)))return n.onLoad(e.onLoad),()=>n.offLoad(e.onLoad)},[n,e==null?void 0:e.onLoad]),m(()=>{if(!(!n||!(e!=null&&e.onExit)))return n.onExit(e.onExit),()=>n.offExit(e.onExit)},[n,e==null?void 0:e.onExit]),m(()=>{if(!(!n||!(e!=null&&e.onExitSuccess)))return n.onExitSuccess(e.onExitSuccess),()=>n.offExitSuccess(e.onExitSuccess)},[n,e==null?void 0:e.onExitSuccess]),m(()=>{if(!(!n||!(e!=null&&e.onExitAbort)))return n.onExitAbort(e.onExitAbort),()=>n.offExitAbort(e.onExitAbort)},[n,e==null?void 0:e.onExitAbort]),m(()=>{if(!(!n||!(e!=null&&e.onExitError)))return n.onExitError(e.onExitError),()=>n.offExitError(e.onExitError)},[n,e==null?void 0:e.onExitError]),m(()=>{n&&i&&(a(!1),n.open())},[n,i]),{open:at(()=>{if(t)a(!0);else throw new Error("Must provide `connectorId` to `open` Quiltt Connector with Method Call")},[t,a])}};import{useEffect as ve}from"react";import{InMemoryCache as ct,QuilttClient as lt}from"@quiltt/core";import{jsx as ft}from"react/jsx-runtime";var he=new lt({cache:new ct}),be=({token:t,children:e})=>{let{session:r,importSession:o}=I();return ve(()=>{t&&o(t)},[t]),ve(()=>{he.resetStore()},[r]),ft(L,{client:he,children:e})};import{useState as pt}from"react";import{jsx as dt}from"react/jsx-runtime";var xe=({clientId:t,children:e})=>{let[r]=pt(t);return dt(K.Provider,{value:{clientId:r},children:e})};import{jsx as ge}from"react/jsx-runtime";var mo=({clientId:t,token:e,children:r})=>ge(xe,{clientId:t,children:ge(be,{token:e,children:r})});import{jsx as mt}from"react/jsx-runtime";var ho=x=>{var N=x,{as:t,connectorId:e,connectionId:r,institution:o,onEvent:n,onLoad:s,onExit:i,onExitSuccess:a,onExitAbort:u,onExitError:l,children:f}=N,v=T(N,["as","connectorId","connectionId","institution","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","children"]);let{open:Ee}=D(e,{connectionId:r,institution:o,onEvent:n,onLoad:s,onExit:i,onExitSuccess:a,onExitAbort:u,onExitError:l});return mt(t||"button",E(h({onClick:Ee,"quiltt-connection":r},v),{children:f}))};import{jsx as yt}from"react/jsx-runtime";var To=v=>{var x=v,{as:t,connectorId:e,connectionId:r,onEvent:o,onLoad:n,onExit:s,onExitSuccess:i,onExitAbort:a,onExitError:u,children:l}=x,f=T(x,["as","connectorId","connectionId","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","children"]);return D(e,{onEvent:o,onLoad:n,onExit:s,onExitSuccess:i,onExitAbort:a,onExitError:u}),yt(t||"div",E(h({"quiltt-container":e,"quiltt-connection":r},f),{children:l}))};export{be as QuilttAuthProvider,ho as QuilttButton,To as QuilttContainer,mo as QuilttProvider,K as QuilttSettings,xe as QuilttSettingsProvider,J as useAuthenticateSession,Tt as useEventListener,B as useIdentifySession,$ as useImportSession,Pe as useIsomorphicLayoutEffect,yn as useQuilttClient,D as useQuilttConnector,I as useQuilttSession,de as useQuilttSettings,X as useRevokeSession,pe as useSession,ce as useStorage};
|
|
2
|
-
|
|
1
|
+
export * from '@quiltt/core';
|
|
2
|
+
export { u as useEventListener } from './useEventListener-client-CTa_g_PX.js';
|
|
3
|
+
export { u as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect-client-DeTHOKz1.js';
|
|
4
|
+
import { Q as QuilttAuthProvider } from './QuilttAuthProvider-client-CV5hYba6.js';
|
|
5
|
+
export { c as useAuthenticateSession, b as useIdentifySession, a as useImportSession, d as useRevokeSession } from './QuilttAuthProvider-client-CV5hYba6.js';
|
|
6
|
+
export { u as useQuilttClient } from './useQuilttClient-client-pzCXNLH2.js';
|
|
7
|
+
import { u as useQuilttConnector } from './useQuilttConnector-client-hd0LT34T.js';
|
|
8
|
+
export { u as useQuilttSession } from './useQuilttSession-client-CcRhqoXG.js';
|
|
9
|
+
export { Q as QuilttSettings, u as useQuilttSettings } from './useQuilttSettings-client-DU_Qfc8X.js';
|
|
10
|
+
export { u as useSession } from './useSession-client-Cew1m26_.js';
|
|
11
|
+
export { u as useStorage } from './useStorage-client-C91C8oXS.js';
|
|
12
|
+
import { jsx } from 'react/jsx-runtime';
|
|
13
|
+
import { Q as QuilttSettingsProvider } from './QuilttSettingsProvider-client-BOiVpLF3.js';
|
|
14
|
+
|
|
15
|
+
const QuilttProvider = ({ clientId, token, children })=>{
|
|
16
|
+
return /*#__PURE__*/ jsx(QuilttSettingsProvider, {
|
|
17
|
+
clientId: clientId,
|
|
18
|
+
children: /*#__PURE__*/ jsx(QuilttAuthProvider, {
|
|
19
|
+
token: token,
|
|
20
|
+
children: children
|
|
21
|
+
})
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const QuilttButton = ({ as, connectorId, connectionId, institution, onEvent, onLoad, onExit, onExitSuccess, onExitAbort, onExitError, children, ...props })=>{
|
|
26
|
+
const { open } = useQuilttConnector(connectorId, {
|
|
27
|
+
connectionId,
|
|
28
|
+
institution,
|
|
29
|
+
onEvent,
|
|
30
|
+
onLoad,
|
|
31
|
+
onExit,
|
|
32
|
+
onExitSuccess,
|
|
33
|
+
onExitAbort,
|
|
34
|
+
onExitError
|
|
35
|
+
});
|
|
36
|
+
const Button = as || 'button';
|
|
37
|
+
return /*#__PURE__*/ jsx(Button, {
|
|
38
|
+
onClick: open,
|
|
39
|
+
"quiltt-connection": connectionId,
|
|
40
|
+
...props,
|
|
41
|
+
children: children
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* QuilttContainer uses globally shared callbacks. It's recommended you only use
|
|
47
|
+
* one Container at a time.
|
|
48
|
+
*/ const QuilttContainer = ({ as, connectorId, connectionId, onEvent, onLoad, onExit, onExitSuccess, onExitAbort, onExitError, children, ...props })=>{
|
|
49
|
+
useQuilttConnector(connectorId, {
|
|
50
|
+
onEvent,
|
|
51
|
+
onLoad,
|
|
52
|
+
onExit,
|
|
53
|
+
onExitSuccess,
|
|
54
|
+
onExitAbort,
|
|
55
|
+
onExitError
|
|
56
|
+
});
|
|
57
|
+
const Container = as || 'div';
|
|
58
|
+
return /*#__PURE__*/ jsx(Container, {
|
|
59
|
+
"quiltt-container": connectorId,
|
|
60
|
+
"quiltt-connection": connectionId,
|
|
61
|
+
...props,
|
|
62
|
+
children: children
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { QuilttAuthProvider, QuilttButton, QuilttContainer, QuilttProvider, QuilttSettingsProvider, useQuilttConnector };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useRef, useEffect } from 'react';
|
|
3
|
+
import { u as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect-client-DeTHOKz1.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Supports Window, Element and Document and custom events with almost
|
|
7
|
+
* the same parameters as the native addEventListener options.
|
|
8
|
+
*/ function useEventListener(eventName, handler, element, options) {
|
|
9
|
+
// Create a ref that stores handler
|
|
10
|
+
const savedHandler = useRef(handler);
|
|
11
|
+
useIsomorphicLayoutEffect(()=>{
|
|
12
|
+
savedHandler.current = handler;
|
|
13
|
+
}, [
|
|
14
|
+
handler
|
|
15
|
+
]);
|
|
16
|
+
useEffect(()=>{
|
|
17
|
+
// Define the listening target
|
|
18
|
+
const targetElement = element?.current ?? window;
|
|
19
|
+
if (!(targetElement && targetElement.addEventListener)) return;
|
|
20
|
+
// Create event listener that calls handler function stored in ref
|
|
21
|
+
const listener = (event)=>savedHandler.current(event);
|
|
22
|
+
targetElement.addEventListener(eventName, listener, options);
|
|
23
|
+
// Remove event listener on cleanup
|
|
24
|
+
return ()=>{
|
|
25
|
+
targetElement.removeEventListener(eventName, listener, options);
|
|
26
|
+
};
|
|
27
|
+
}, [
|
|
28
|
+
eventName,
|
|
29
|
+
element,
|
|
30
|
+
options
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { useEventListener as u };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useLayoutEffect, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This hook is a browser hook. But React code could be generated from the server without the Window API.
|
|
6
|
+
* This hook switches between useEffect and useLayoutEffect following the execution environment.
|
|
7
|
+
*/ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
|
|
8
|
+
|
|
9
|
+
export { useIsomorphicLayoutEffect as u };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
3
|
+
import { u as useQuilttSession } from './useQuilttSession-client-CcRhqoXG.js';
|
|
4
|
+
import { u as useScript } from './useScript-client-Cx5nb9RW.js';
|
|
5
|
+
import { cdnBase } from '@quiltt/core';
|
|
6
|
+
|
|
7
|
+
// Generated by genversion.
|
|
8
|
+
const version = '3.5.5';
|
|
9
|
+
|
|
10
|
+
const useQuilttConnector = (connectorId, options)=>{
|
|
11
|
+
const status = useScript(`${cdnBase}/v1/connector.js?agent=react-${version}`);
|
|
12
|
+
const { session } = useQuilttSession();
|
|
13
|
+
const [connector, setConnector] = useState();
|
|
14
|
+
const [isOpening, setIsOpening] = useState(false);
|
|
15
|
+
// Set Session
|
|
16
|
+
useEffect(()=>{
|
|
17
|
+
if (typeof Quiltt === 'undefined') return;
|
|
18
|
+
Quiltt.authenticate(session?.token);
|
|
19
|
+
}, [
|
|
20
|
+
status,
|
|
21
|
+
session
|
|
22
|
+
]);
|
|
23
|
+
// Set Connector
|
|
24
|
+
useEffect(()=>{
|
|
25
|
+
if (typeof Quiltt === 'undefined' || !connectorId) return;
|
|
26
|
+
if (options?.connectionId) {
|
|
27
|
+
setConnector(Quiltt.reconnect(connectorId, {
|
|
28
|
+
connectionId: options.connectionId
|
|
29
|
+
}));
|
|
30
|
+
} else {
|
|
31
|
+
setConnector(Quiltt.connect(connectorId, {
|
|
32
|
+
institution: options?.institution
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
}, [
|
|
36
|
+
status,
|
|
37
|
+
connectorId,
|
|
38
|
+
options?.connectionId,
|
|
39
|
+
options?.institution
|
|
40
|
+
]);
|
|
41
|
+
// onEvent
|
|
42
|
+
useEffect(()=>{
|
|
43
|
+
if (!connector || !options?.onEvent) return;
|
|
44
|
+
connector.onEvent(options.onEvent);
|
|
45
|
+
return ()=>connector.offEvent(options.onEvent);
|
|
46
|
+
}, [
|
|
47
|
+
connector,
|
|
48
|
+
options?.onEvent
|
|
49
|
+
]);
|
|
50
|
+
// onLoad
|
|
51
|
+
useEffect(()=>{
|
|
52
|
+
if (!connector || !options?.onLoad) return;
|
|
53
|
+
connector.onLoad(options.onLoad);
|
|
54
|
+
return ()=>connector.offLoad(options.onLoad);
|
|
55
|
+
}, [
|
|
56
|
+
connector,
|
|
57
|
+
options?.onLoad
|
|
58
|
+
]);
|
|
59
|
+
// onExit
|
|
60
|
+
useEffect(()=>{
|
|
61
|
+
if (!connector || !options?.onExit) return;
|
|
62
|
+
connector.onExit(options.onExit);
|
|
63
|
+
return ()=>connector.offExit(options.onExit);
|
|
64
|
+
}, [
|
|
65
|
+
connector,
|
|
66
|
+
options?.onExit
|
|
67
|
+
]);
|
|
68
|
+
// onExitSuccess
|
|
69
|
+
useEffect(()=>{
|
|
70
|
+
if (!connector || !options?.onExitSuccess) return;
|
|
71
|
+
connector.onExitSuccess(options.onExitSuccess);
|
|
72
|
+
return ()=>connector.offExitSuccess(options.onExitSuccess);
|
|
73
|
+
}, [
|
|
74
|
+
connector,
|
|
75
|
+
options?.onExitSuccess
|
|
76
|
+
]);
|
|
77
|
+
// onExitAbort
|
|
78
|
+
useEffect(()=>{
|
|
79
|
+
if (!connector || !options?.onExitAbort) return;
|
|
80
|
+
connector.onExitAbort(options.onExitAbort);
|
|
81
|
+
return ()=>connector.offExitAbort(options.onExitAbort);
|
|
82
|
+
}, [
|
|
83
|
+
connector,
|
|
84
|
+
options?.onExitAbort
|
|
85
|
+
]);
|
|
86
|
+
// onExitError
|
|
87
|
+
useEffect(()=>{
|
|
88
|
+
if (!connector || !options?.onExitError) return;
|
|
89
|
+
connector.onExitError(options.onExitError);
|
|
90
|
+
return ()=>connector.offExitError(options.onExitError);
|
|
91
|
+
}, [
|
|
92
|
+
connector,
|
|
93
|
+
options?.onExitError
|
|
94
|
+
]);
|
|
95
|
+
// This is used to hide any potential race conditions from usage; allowing
|
|
96
|
+
// interaction before the script may have loaded.
|
|
97
|
+
useEffect(()=>{
|
|
98
|
+
if (connector && isOpening) {
|
|
99
|
+
setIsOpening(false);
|
|
100
|
+
connector.open();
|
|
101
|
+
}
|
|
102
|
+
}, [
|
|
103
|
+
connector,
|
|
104
|
+
isOpening
|
|
105
|
+
]);
|
|
106
|
+
const open = useCallback(()=>{
|
|
107
|
+
if (connectorId) {
|
|
108
|
+
setIsOpening(true);
|
|
109
|
+
} else {
|
|
110
|
+
throw new Error('Must provide `connectorId` to `open` Quiltt Connector with Method Call');
|
|
111
|
+
}
|
|
112
|
+
}, [
|
|
113
|
+
connectorId,
|
|
114
|
+
setIsOpening
|
|
115
|
+
]);
|
|
116
|
+
return {
|
|
117
|
+
open
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export { useQuilttConnector as u };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { u as useSession } from './useSession-client-Cew1m26_.js';
|
|
4
|
+
import { AuthAPI } from '@quiltt/core';
|
|
5
|
+
import { a as useImportSession, b as useIdentifySession, c as useAuthenticateSession, d as useRevokeSession } from './QuilttAuthProvider-client-CV5hYba6.js';
|
|
6
|
+
import { u as useQuilttSettings } from './useQuilttSettings-client-DU_Qfc8X.js';
|
|
7
|
+
|
|
8
|
+
const useQuilttSession = (environmentId)=>{
|
|
9
|
+
const { clientId } = useQuilttSettings();
|
|
10
|
+
const [session, setSession] = useSession();
|
|
11
|
+
const auth = new AuthAPI(clientId);
|
|
12
|
+
const importSession = useImportSession(auth, session, setSession, environmentId);
|
|
13
|
+
const identifySession = useIdentifySession(auth, setSession);
|
|
14
|
+
const authenticateSession = useAuthenticateSession(auth, setSession);
|
|
15
|
+
const revokeSession = useRevokeSession(auth, session, setSession);
|
|
16
|
+
/**
|
|
17
|
+
* Forget current session.
|
|
18
|
+
* @param token specific token to forget, to help guard against async processes clearing the wrong session
|
|
19
|
+
*/ const forgetSession = useCallback(async (token)=>{
|
|
20
|
+
if (!token || session && token && token === session.token) {
|
|
21
|
+
setSession(null);
|
|
22
|
+
}
|
|
23
|
+
}, [
|
|
24
|
+
session,
|
|
25
|
+
setSession
|
|
26
|
+
]);
|
|
27
|
+
return {
|
|
28
|
+
session,
|
|
29
|
+
importSession,
|
|
30
|
+
identifySession,
|
|
31
|
+
authenticateSession,
|
|
32
|
+
revokeSession,
|
|
33
|
+
forgetSession
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { useQuilttSession as u };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
|
|
4
|
+
const QuilttSettings = createContext({});
|
|
5
|
+
const useQuilttSettings = ()=>{
|
|
6
|
+
const settings = useContext(QuilttSettings);
|
|
7
|
+
return {
|
|
8
|
+
...settings
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export { QuilttSettings as Q, useQuilttSettings as u };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
// Cached script statuses
|
|
5
|
+
const cachedScriptStatuses = {};
|
|
6
|
+
function getScriptNode(src) {
|
|
7
|
+
const node = document.querySelector(`script[src="${src}"]`);
|
|
8
|
+
const status = node?.getAttribute('data-status');
|
|
9
|
+
return {
|
|
10
|
+
node,
|
|
11
|
+
status
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
// @see https://usehooks-ts.com/react-hook/use-script
|
|
15
|
+
function useScript(src, options) {
|
|
16
|
+
const [status, setStatus] = useState(()=>{
|
|
17
|
+
if (!src || options?.shouldPreventLoad) {
|
|
18
|
+
return 'idle';
|
|
19
|
+
}
|
|
20
|
+
if (typeof window === 'undefined') {
|
|
21
|
+
// SSR Handling - always return 'loading'
|
|
22
|
+
return 'loading';
|
|
23
|
+
}
|
|
24
|
+
return cachedScriptStatuses[src] ?? 'loading';
|
|
25
|
+
});
|
|
26
|
+
useEffect(()=>{
|
|
27
|
+
if (!src || options?.shouldPreventLoad) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const cachedScriptStatus = cachedScriptStatuses[src];
|
|
31
|
+
if (cachedScriptStatus === 'ready' || cachedScriptStatus === 'error') {
|
|
32
|
+
// If the script is already cached, set its status immediately
|
|
33
|
+
setStatus(cachedScriptStatus);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// Fetch existing script element by src
|
|
37
|
+
// It may have been added by another instance of this hook
|
|
38
|
+
const script = getScriptNode(src);
|
|
39
|
+
let scriptNode = script.node;
|
|
40
|
+
if (!scriptNode) {
|
|
41
|
+
// Create script element and add it to document body
|
|
42
|
+
scriptNode = document.createElement('script');
|
|
43
|
+
scriptNode.src = src;
|
|
44
|
+
scriptNode.async = true;
|
|
45
|
+
scriptNode.setAttribute('data-status', 'loading');
|
|
46
|
+
document.body.appendChild(scriptNode);
|
|
47
|
+
// Store status in attribute on script
|
|
48
|
+
// This can be read by other instances of this hook
|
|
49
|
+
const setAttributeFromEvent = (event)=>{
|
|
50
|
+
const scriptStatus = event.type === 'load' ? 'ready' : 'error';
|
|
51
|
+
scriptNode?.setAttribute('data-status', scriptStatus);
|
|
52
|
+
};
|
|
53
|
+
scriptNode.addEventListener('load', setAttributeFromEvent);
|
|
54
|
+
scriptNode.addEventListener('error', setAttributeFromEvent);
|
|
55
|
+
} else {
|
|
56
|
+
// Grab existing script status from attribute and set to state.
|
|
57
|
+
setStatus(script.status ?? cachedScriptStatus ?? 'loading');
|
|
58
|
+
}
|
|
59
|
+
// Script event handler to update status in state
|
|
60
|
+
// Note: Even if the script already exists we still need to add
|
|
61
|
+
// event handlers to update the state for *this* hook instance.
|
|
62
|
+
const setStateFromEvent = (event)=>{
|
|
63
|
+
const newStatus = event.type === 'load' ? 'ready' : 'error';
|
|
64
|
+
setStatus(newStatus);
|
|
65
|
+
cachedScriptStatuses[src] = newStatus;
|
|
66
|
+
};
|
|
67
|
+
// Add event listeners
|
|
68
|
+
scriptNode.addEventListener('load', setStateFromEvent);
|
|
69
|
+
scriptNode.addEventListener('error', setStateFromEvent);
|
|
70
|
+
// Remove event listeners on cleanup
|
|
71
|
+
return ()=>{
|
|
72
|
+
if (scriptNode) {
|
|
73
|
+
scriptNode.removeEventListener('load', setStateFromEvent);
|
|
74
|
+
scriptNode.removeEventListener('error', setStateFromEvent);
|
|
75
|
+
}
|
|
76
|
+
if (scriptNode && options?.removeOnUnmount) {
|
|
77
|
+
scriptNode.remove();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}, [
|
|
81
|
+
src,
|
|
82
|
+
options?.shouldPreventLoad,
|
|
83
|
+
options?.removeOnUnmount
|
|
84
|
+
]);
|
|
85
|
+
return status;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { useScript as u };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useMemo, useEffect, useCallback } from 'react';
|
|
3
|
+
import { Timeoutable, JsonWebTokenParse } from '@quiltt/core';
|
|
4
|
+
import { u as useStorage } from './useStorage-client-C91C8oXS.js';
|
|
5
|
+
|
|
6
|
+
const parse = JsonWebTokenParse;
|
|
7
|
+
/**
|
|
8
|
+
* Singleton timeout, allows hooks to come and go, while ensuring that there is
|
|
9
|
+
* one notification being sent, preventing race conditions.
|
|
10
|
+
*/ const sessionTimer = new Timeoutable();
|
|
11
|
+
/**
|
|
12
|
+
* useSession uses useStorage to support a global singleton style of access. When
|
|
13
|
+
* updated, all components, and windows should also invalidate.
|
|
14
|
+
*
|
|
15
|
+
* TODO: Support Rotation before Expiry
|
|
16
|
+
*
|
|
17
|
+
* Dataflow can come from two directions:
|
|
18
|
+
* 1. Login - Bottom Up
|
|
19
|
+
* This happens on login, when a token is passed up through the setSession
|
|
20
|
+
* callback. From here it needs to be stored, and shared for usage.
|
|
21
|
+
* 2. Refresh - Top Down
|
|
22
|
+
* This happens when a page is reloaded or a person returns, and everything is
|
|
23
|
+
* reinitialized.
|
|
24
|
+
*/ const useSession = (storageKey = 'session')=>{
|
|
25
|
+
const [token, setToken] = useStorage(storageKey);
|
|
26
|
+
const session = useMemo(()=>parse(token), [
|
|
27
|
+
token
|
|
28
|
+
]);
|
|
29
|
+
// Clear session if/when it expires
|
|
30
|
+
useEffect(()=>{
|
|
31
|
+
if (!session) return;
|
|
32
|
+
const expirationMS = session.claims.exp * 1000;
|
|
33
|
+
const expire = ()=>setToken(null);
|
|
34
|
+
if (Date.now() >= expirationMS) {
|
|
35
|
+
expire();
|
|
36
|
+
} else {
|
|
37
|
+
sessionTimer.set(expire, expirationMS - Date.now());
|
|
38
|
+
return ()=>sessionTimer.clear(expire);
|
|
39
|
+
}
|
|
40
|
+
}, [
|
|
41
|
+
session,
|
|
42
|
+
setToken
|
|
43
|
+
]);
|
|
44
|
+
// Bubbles up from Login
|
|
45
|
+
const setSession = useCallback((nextState)=>{
|
|
46
|
+
const newState = nextState instanceof Function ? nextState(token) : nextState;
|
|
47
|
+
if (token !== newState && (!newState || parse(newState))) {
|
|
48
|
+
setToken(newState);
|
|
49
|
+
}
|
|
50
|
+
}, [
|
|
51
|
+
token,
|
|
52
|
+
setToken
|
|
53
|
+
]);
|
|
54
|
+
return [
|
|
55
|
+
session,
|
|
56
|
+
setSession
|
|
57
|
+
];
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export { useSession as u };
|