@apollion-dsi/relay 0.26.0 → 0.27.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/{README.md → README.MD} +49 -1
- package/lib/index.esm.js +1 -1
- package/lib/index.js +1 -1
- package/lib/relayArgsInterface/relayArgsInterface.d.ts +44 -0
- package/lib/setupRelayEnvironment/fetchQuery.d.ts +4 -3
- package/lib/setupRelayEnvironment/setupRelayEnvironment.d.ts +22 -1
- package/lib/setupRelayEnvironment/setupRelayEnvironment.helpers.d.ts +23 -3
- package/package.json +1 -1
package/{README.md → README.MD}
RENAMED
|
@@ -50,12 +50,60 @@ import { App } from './app';
|
|
|
50
50
|
|
|
51
51
|
## Recursos do helper
|
|
52
52
|
|
|
53
|
-
- **
|
|
53
|
+
- **Autenticação** em dois modos: `Bearer` (token JS) ou **cookie
|
|
54
|
+
httpOnly** (ver abaixo).
|
|
54
55
|
- **Multipart uploads** (`fetch-multipart-graphql`) — envie arquivos
|
|
55
56
|
diretamente em mutations.
|
|
56
57
|
- **Subscriptions** via `graphql-ws`.
|
|
57
58
|
- **Network retry / refresh** plugável.
|
|
58
59
|
|
|
60
|
+
## Autenticação: Bearer vs. cookie httpOnly
|
|
61
|
+
|
|
62
|
+
O Environment suporta dois modelos de auth via `authMode`.
|
|
63
|
+
|
|
64
|
+
### `authMode: 'bearer'` (default — retrocompat)
|
|
65
|
+
|
|
66
|
+
Lê o `sessionToken` do storage (`localStorage`/`cookie` JS-legível) e
|
|
67
|
+
injeta `Authorization: Bearer <token>` em cada request. A verificação de
|
|
68
|
+
sessão usa o probe `${authUrl}user/me`. Comportamento idêntico ao das
|
|
69
|
+
versões anteriores — consumidores existentes não precisam mudar nada.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
new CreateRelayEnvironment({
|
|
73
|
+
url: 'https://api.example.com/graphql/',
|
|
74
|
+
authUrl: 'https://api.example.com/auth/',
|
|
75
|
+
useAuthorization: true, // injeta Bearer
|
|
76
|
+
storageType: 'cookie', // cookie JS-legível ou 'localStorage'
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### `authMode: 'cookie'` (sessão por cookie httpOnly — recomendado p/ SPA)
|
|
81
|
+
|
|
82
|
+
Modelo seguro: o token de sessão vive num cookie **httpOnly + SameSite**
|
|
83
|
+
(invisível ao JS, imune a XSS). O Environment **não** lê o token nem
|
|
84
|
+
injeta `Authorization` — `credentials: 'include'` (default neste modo)
|
|
85
|
+
faz o browser anexar o cookie automaticamente, inclusive cross-origin.
|
|
86
|
+
Em erro de auth (ex: 401), o refresh é disparado com `POST` em `authUrl`
|
|
87
|
+
e `credentials: 'include'` — **sem** probe a `user/me`.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
new CreateRelayEnvironment({
|
|
91
|
+
url: 'https://api.example.com/graphql/',
|
|
92
|
+
authUrl: 'https://api.example.com/auth/refresh/', // alvo do refresh on-401
|
|
93
|
+
authMode: 'cookie',
|
|
94
|
+
redirectOnError: true,
|
|
95
|
+
loginRoute: '/login',
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Opções relacionadas:
|
|
100
|
+
|
|
101
|
+
| Opção | Default | O que faz |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `authMode` | `'bearer'` | `'bearer'` (token + header) ou `'cookie'` (httpOnly). |
|
|
104
|
+
| `credentials` | cookie→`'include'`; bearer→omitido | `RequestCredentials` repassado aos fetches GraphQL e de refresh. Funciona nos dois modos. |
|
|
105
|
+
| `sessionCheckUrl` | modo-dependente | Sobrescreve a URL do probe; `false` desliga o probe (erro de auth → logout direto, sem request extra). |
|
|
106
|
+
|
|
59
107
|
## Scripts (workspace)
|
|
60
108
|
|
|
61
109
|
| Script | O que faz |
|
package/lib/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var X=Object.defineProperty;var o=(e,t)=>X(e,"name",{value:t,configurable:!0});import{Environment as ce,Network as ue,RecordSource as pe,Store as le}from"relay-runtime";import{Observable as oe,QueryResponseCache as ne}from"relay-runtime";var S=!!(typeof window!="undefined"&&window.document&&window.document.createElement),f={canUseDOM:S,canUseWorkers:typeof Worker!="undefined",canUseEventListeners:S&&!!(window.addEventListener||window.attachEvent),canUseViewport:S&&!!window.screen,isInWorker:!S};function V(e){return async t=>{let r=e.timeout,n=e.retries,i=0,s=0;return new Promise((c,l)=>{let p={};p.sendTimedRequest=()=>{i++,s=Date.now();let u=!0,d=new AbortController,m=setTimeout(()=>{if(u=!1,d.abort(),p.shouldRetry(i))e.useDebug&&console.log("fetchWithRetries: HTTP timeout, retrying."),p.retryRequest();else{let a=new Error(`fetchWithRetries(): Failed to get response from server, tried ${i} times.`);a.name="TimeOutError",l(a)}},r);fetch(e.url,{...t,signal:d.signal}).then(async a=>{if(clearTimeout(m),u)if(a.status>=200&&a.status<300)c(a);else if(p.shouldRetry(i)&&e.retryWhen.includes(a.status))e.useDebug&&console.log("fetchWithRetries: HTTP error, retrying..."),p.retryRequest();else{let P=new Error(`fetchWithRetries(): Still no successful response after ${i} retries, giving up.`);P.response=a,l(P)}}).catch(a=>{clearTimeout(m),a.name!=="AbortError"&&l(a)})},p.retryRequest=()=>{let u=n[i-1],d=s+u;setTimeout(p.sendTimedRequest,d-Date.now())},p.shouldRetry=u=>f.canUseDOM&&e.useRetries&&u<=n.length,p.sendTimedRequest()})}}o(V,"fetchWithRetries");import{PatchResolver as Z}from"fetch-multipart-graphql";var O=o(e=>e.operationKind==="mutation","isMutation"),k=o(e=>e.operationKind==="query","isQuery"),j=o(e=>!!(e&&e.force),"forceFetch"),ee=o(()=>f.canUseDOM?window.location.search.startsWith("?")?"&":"?":"","getParamsDelimiter"),v=o(()=>f.canUseDOM?window.location.pathname:"","getBrowserLocation"),g=o((e,t,r)=>{let n=e;(e!==t||r.loginRoute!==t)&&(n=`${t}${ee()}redirect=${e}`),window.location.href=n},"redirectUser");function te(e,t,r){let n=new FormData;n.append("operations",JSON.stringify({query:e.text,variables:t,operationName:e.name}));let i={};for(let s=0;s<r.files.length;s++)n.append(`${s}`,r.files[s]),i[`${s}`]=[r.path(s)];return n.append("map",JSON.stringify(i)),n}o(te,"getRequestBodyWithUploadables");function re(e,t){return JSON.stringify({name:e.name,query:e.text,variables:t})}o(re,"getRequestBodyWithoutUplodables");function B(e,t,r){return r?te(e,t,r):re(e,t)}o(B,"getRequestBody");var K=o((e,t)=>{let r=new Headers;if(t?r.append("Accept","*/*"):(r.append("Accept","application/json"),r.append("Content-type","application/json")),e.useAuthorization){let{sessionToken:n}=e.StorageHandler.getTokens();n&&v()!==e.loginRoute&&r.append("Authorization",`Bearer ${n}`)}return e.partner&&r.append("X-Partner",e.partner),r},"getHeaders"),_=o((e,t,r)=>{if(e.status<300&&e.headers&&e.headers.get("Content-Type")&&e.headers.get("Content-Type").indexOf("multipart/mixed")>=0){let n=e.body.getReader(),i=new TextDecoder,s=new Z({onResponse:o(c=>t.next(c),"onResponse")});n.read().then(o(function c({value:l,done:p}){if(p)t.complete();else{let u;try{u=i.decode(l),s.handleChunk(u)}catch(d){let m=d;m.response=e,m.statusCode=e.status,m.bodyText=u,t.error(m)}n.read().then(c)}},"sendNext"))}else e.headers&&e.headers.get("Content-Type")&&e.headers.get("Content-Type").indexOf("application/json")>=0?e.json().then(r):e.text().then(n=>{t.next([n]),t.complete()})},"handleData"),h=1e3,U=h*60;var J=o(e=>{let t=new ne({ttl:e.cacheTime,size:e.cacheSize}),r=V(e);async function n(){try{let{sessionToken:s}=e.StorageHandler.getTokens();return(await fetch(`${e.authUrl}user/me`,{headers:{"Content-Type":"application/json",Authorization:s}})).status===200}catch(s){return console.warn(`[Auth] ${s.message}`),!1}}o(n,"checkLoggedUser");async function i(s,c,l,p,u){try{let d=String(s.text);if(e.useCache&&k(s)&&!j(l)){let a=t.get(d,c);if(a){u.next(a),u.complete();return}}e.useCache&&O(s)&&t.clear();let m=await r({method:"POST",headers:K(e,p),body:B(s,c,p)});_(m,u,async a=>{if(e.useCache&&k(s)&&t.set(d,c,a),!u.closed){if(O(s)&&a.errors&&u.error(a.errors),a.errors){if(await n()||(e.StorageHandler.clear(),g("/",e.loginRoute,e)),e.redirectOnError){let z=[];Array.isArray(a.errors)&&(z=a.errors.map(({status_code:C})=>C));let F=v();z.some(C=>e.authenticationErrors.includes(C))&&F!==e.loginRoute&&(e.StorageHandler.clear(),g(F,e.loginRoute,e))}u.error(a.errors)}else a.data?u.next(a):u.error(a);u.complete()}})}catch(d){if(f.canUseDOM&&!["AbortError","TimeOutError"].includes(d.name)&&e.StorageHandler.clear(),e.redirectOnError){let a=v();a!==e.loginRoute&&g(a,e.loginRoute,e)}await n()||(e.StorageHandler.clear(),g("/",e.loginRoute,e)),u.error(d)}}return o(i,"fetchFn"),(s,c,l,p)=>oe.create(u=>{i(s,c,l,p,u)})},"createFetchFunction");import se from"js-cookie";var A=class A{get(t){throw new Error('Must implement a "GET" method')}set(t,r){throw new Error('Must implement a "SET" method')}delete(t){throw new Error('Must implement a "DELETE" method')}};o(A,"DefaultStrategy");var T=A,M=class M extends T{constructor(){super(),this.strategy=localStorage}get(t){return this.strategy.getItem(t)}set(t,r){this.strategy.setItem(t,r)}delete(t){this.strategy.removeItem(t)}};o(M,"LocalStorageStrategy");var D=M,q=class q extends T{constructor(){super(),this.strategy=se}get(t){return this.strategy.get(t)}set(t,r){this.strategy.set(t,r)}delete(t){this.strategy.remove(t)}};o(q,"CookieStrategy");var I=q,y=Symbol("storage-handler"),R=Symbol("prop-session"),b=Symbol("prop-refresh"),H=class H{constructor(t){this[R]=t.sessionStorageProp,this[b]=t.refreshStorageProp,t.storageType==="cookie"?this[y]=new I:this[y]=new D}getTokens(){return{refreshToken:this[y].get(this[b]),sessionToken:this[y].get(this[R])}}setTokens(t){this[y].set(this[b],t.refreshToken),this[y].set(this[R],t.sessionToken)}clear(){this[y].delete(this[b]),this[y].delete(this[R])}hasChangedSession({sessionToken:t}){let{sessionToken:r}=this.getTokens();return t!==r}};o(H,"StorageClass");var E=H;import{createClient as ie}from"graphql-ws";import{Observable as ae}from"relay-runtime";function Q(e){return()=>{let t=ie({url:e.socket});return(r,n)=>ae.create(i=>t.subscribe({operationName:r.name,query:r.text||"",variables:n},{next:o(s=>i.next(s),"next"),error:o(s=>i.error(s),"error"),complete:o(()=>i.complete(),"complete")}))}}o(Q,"setupSubscription");var Y=Symbol("mount-environment"),N=Symbol("handler-fetch"),L=Symbol("handler-subscription"),W=class W{constructor(t){if(this.url=t.url,this.authUrl=t.authUrl,this.socket=t.socket,this.storageType=t.storageType||"localStorage",this.cacheSize=t.cacheSize||250,this.cacheTime=t.cacheTime||U*8,this.timeout=t.timeout||U*15,this.sessionStorageProp=t.sessionStorageProp||"USER_SESSION_TOKEN",this.refreshStorageProp=t.refreshStorageProp||"USER_REFRESH_TOKEN",this.loginRoute=t.loginRoute||"/",this.useCache=t.useCache||!1,this.useDebug=t.useDebug||!1,this.useAuthorization=t.useAuthorization||!1,this.useRetries=t.useRetries||!1,this.useSubscription=t.useSubscription||!1,this.redirectOnError=t.redirectOnError||!1,this.retryWhen=t.retryWhen||[503,504,521,522,524],this.authenticationErrors=t.authenticationErrors||[401,403],this.retries=t.retries||[h,h*2,h*3,h*5,h*8,h*13,h*21,h*34],this.partner=t.partner||void 0,!this.url)throw new Error("[HTTPFetchEndpoint] You must at least set url parameter.");if(this.useAuthorization&&!this.authUrl)throw new Error('[useAuthorization] Authorization is set but no "authUrl" was provided.');if(this.StorageHandler=new E(this),this.useSubscription){if(!this.socket)throw new Error("[useSubscription] If you choose to use WebSocket you must set a socket endpoint.");this[L]=Q(this)}this[N]=J(this),this[Y]()}[(N,L,Y)](){let t=ue.create(this[N],this[L]||null),r=new pe,n=new le(r);this.Environment=new ce({network:t,store:n})}};o(W,"RelayEnvironment");var w=W;import $ from"react";var G=$.createContext(void 0);function Xe({children:e,environment:t}){return $.createElement(G.Provider,{value:{environment:t}},e)}o(Xe,"EnvironmentProvider");function Ze(){let e=$.useContext(G);if(e===void 0)throw new Error("useEnvironment must be used within a EnvironmentProvider");if(e.environment===null||e.environment===void 0)throw new Error("You should provide a Relay Environment to EnvironmentProvider component");return e}o(Ze,"useEnvironment");import{nanoid as de}from"nanoid";import{ConnectionHandler as x}from"relay-runtime";function me(e){return e!==null&&typeof e=="object"}o(me,"isObject");var ut=de();function pt({parentId:e,itemId:t,parentFieldName:r,store:n}){let i=n.get(e),s=i.getLinkedRecords(r);i.setLinkedRecords(s.filter(c=>c.dataID!==t),r)}o(pt,"listRecordRemoveUpdater");function lt({parentId:e,item:t,type:r,parentFieldName:n,store:i}){let s=i.create(t.id,r);Object.keys(t).forEach(p=>{s.setValue(t[p],p)});let c=i.get(e),l=c.getLinkedRecords(n);c.setLinkedRecords([...l,s],n)}o(lt,"listRecordAddUpdater");function he(e,t,r,n,i=!1){if(n){let s=e.get(t),c=x.getConnection(s,r);if(!c)return;i?x.insertEdgeBefore(c,n):x.insertEdgeAfter(c,n)}}o(he,"connectionUpdater");function dt({parentId:e,store:t,connectionName:r,item:n,customNode:i,itemType:s}){let c=i||t.create(n.id,s);!i&&Object.keys(n).forEach(p=>{c.setValue(n[p],p)});let l=t.create(`client:newEdge:${String(c.getDataID).match(/[^:]+$/)[0]}`,`${s}Edge`);l.setLinkedRecord(c,"node"),he(t,e,r,l)}o(dt,"optimisticConnectionUpdater");function mt({parentId:e,connectionName:t,nodeId:r,store:n}){let i=n.get(e),s=x.getConnection(i,t);if(!s){console.warn(`Connection ${t} not found on ${e}`);return}x.deleteNode(s,r)}o(mt,"connectionDeleteEdgeUpdater");function ht({object:e,proxy:t}){Object.keys(e).forEach(r=>{me(e[r])||Array.isArray(e[r])||t.setValue(e[r],r)})}o(ht,"copyObjScalarsToProxy");import{commitMutation as ye}from"relay-runtime";var St=o((e,t)=>new Promise((r,n)=>{ye(e,{...t,onError:n,onCompleted:r})}),"commitMutation");export{ut as ClientMutationID,w as CreateRelayEnvironment,Xe as EnvironmentProvider,St as commitMutation,mt as connectionDeleteEdgeUpdater,he as connectionUpdater,ht as copyObjScalarsToProxy,me as isObject,lt as listRecordAddUpdater,pt as listRecordRemoveUpdater,dt as optimisticConnectionUpdater,Ze as useEnvironment};
|
|
1
|
+
var Z=Object.defineProperty;var o=(e,t)=>Z(e,"name",{value:t,configurable:!0});import{Environment as ue,Network as le,RecordSource as de,Store as pe}from"relay-runtime";import{Observable as ne,QueryResponseCache as se}from"relay-runtime";var S=!!(typeof window!="undefined"&&window.document&&window.document.createElement),b={canUseDOM:S,canUseWorkers:typeof Worker!="undefined",canUseEventListeners:S&&!!(window.addEventListener||window.attachEvent),canUseViewport:S&&!!window.screen,isInWorker:!S};function j(e){return async t=>{let r=e.timeout,n=e.retries,i=0,s=0;return new Promise((a,l)=>{let u={};u.sendTimedRequest=()=>{i++,s=Date.now();let c=!0,h=new AbortController,m=setTimeout(()=>{if(c=!1,h.abort(),u.shouldRetry(i))e.useDebug&&console.log("fetchWithRetries: HTTP timeout, retrying."),u.retryRequest();else{let d=new Error(`fetchWithRetries(): Failed to get response from server, tried ${i} times.`);d.name="TimeOutError",l(d)}},r);fetch(e.url,{...t,signal:h.signal}).then(async d=>{if(clearTimeout(m),c)if(d.status>=200&&d.status<300)a(d);else if(u.shouldRetry(i)&&e.retryWhen.includes(d.status))e.useDebug&&console.log("fetchWithRetries: HTTP error, retrying..."),u.retryRequest();else{let p=new Error(`fetchWithRetries(): Still no successful response after ${i} retries, giving up.`);p.response=d,l(p)}}).catch(d=>{clearTimeout(m),d.name!=="AbortError"&&l(d)})},u.retryRequest=()=>{let c=n[i-1],h=s+c;setTimeout(u.sendTimedRequest,h-Date.now())},u.shouldRetry=c=>b.canUseDOM&&e.useRetries&&c<=n.length,u.sendTimedRequest()})}}o(j,"fetchWithRetries");import{PatchResolver as ee}from"fetch-multipart-graphql";var k=o(e=>e.operationKind==="mutation","isMutation"),U=o(e=>e.operationKind==="query","isQuery"),B=o(e=>!!(e&&e.force),"forceFetch"),te=o(()=>b.canUseDOM?window.location.search.startsWith("?")?"&":"?":"","getParamsDelimiter"),T=o(()=>b.canUseDOM?window.location.pathname:"","getBrowserLocation"),g=o((e,t,r)=>{let n=e;(e!==t||r.loginRoute!==t)&&(n=`${t}${te()}redirect=${e}`),window.location.href=n},"redirectUser");function re(e,t,r){let n=new FormData;n.append("operations",JSON.stringify({query:e.text,variables:t,operationName:e.name}));let i={};for(let s=0;s<r.files.length;s++)n.append(`${s}`,r.files[s]),i[`${s}`]=[r.path(s)];return n.append("map",JSON.stringify(i)),n}o(re,"getRequestBodyWithUploadables");function oe(e,t){return JSON.stringify({name:e.name,query:e.text,variables:t})}o(oe,"getRequestBodyWithoutUplodables");function K(e,t,r){return r?re(e,t,r):oe(e,t)}o(K,"getRequestBody");var O=o(e=>{if(e.credentials)return e.credentials;if(e.authMode==="cookie")return"include"},"resolveCredentials"),_=o((e,t)=>{let r=new Headers;if(t?r.append("Accept","*/*"):(r.append("Accept","application/json"),r.append("Content-type","application/json")),e.useAuthorization&&e.authMode!=="cookie"){let{sessionToken:n}=e.StorageHandler.getTokens();n&&T()!==e.loginRoute&&r.append("Authorization",`Bearer ${n}`)}return e.partner&&r.append("X-Partner",e.partner),r},"getHeaders"),J=o((e,t,r)=>{if(e.status<300&&e.headers&&e.headers.get("Content-Type")&&e.headers.get("Content-Type").indexOf("multipart/mixed")>=0){let n=e.body.getReader(),i=new TextDecoder,s=new ee({onResponse:o(a=>t.next(a),"onResponse")});n.read().then(o(function a({value:l,done:u}){if(u)t.complete();else{let c;try{c=i.decode(l),s.handleChunk(c)}catch(h){let m=h;m.response=e,m.statusCode=e.status,m.bodyText=c,t.error(m)}n.read().then(a)}},"sendNext"))}else e.headers&&e.headers.get("Content-Type")&&e.headers.get("Content-Type").indexOf("application/json")>=0?e.json().then(r):e.text().then(n=>{t.next([n]),t.complete()})},"handleData"),f=1e3,M=f*60;var Q=o(e=>{let t=new se({ttl:e.cacheTime,size:e.cacheSize}),r=j(e);async function n(){if(e.sessionCheckUrl===!1)return!1;let s=O(e);try{if(e.authMode==="cookie"){let c=e.sessionCheckUrl||e.authUrl;return(await fetch(c,{method:"POST",credentials:s||"include"})).status===200}let{sessionToken:a}=e.StorageHandler.getTokens(),l=e.sessionCheckUrl||`${e.authUrl}user/me`;return(await fetch(l,{headers:{"Content-Type":"application/json",Authorization:a},...s?{credentials:s}:{}})).status===200}catch(a){return console.warn(`[Auth] ${a.message}`),!1}}o(n,"checkSession");async function i(s,a,l,u,c){try{let h=String(s.text);if(e.useCache&&U(s)&&!B(l)){let p=t.get(h,a);if(p){c.next(p),c.complete();return}}e.useCache&&k(s)&&t.clear();let m=O(e),d=await r({method:"POST",headers:_(e,u),body:K(s,a,u),...m?{credentials:m}:{}});J(d,c,async p=>{if(e.useCache&&U(s)&&t.set(h,a,p),!c.closed){if(k(s)&&p.errors&&c.error(p.errors),p.errors){if(await n()||(e.StorageHandler.clear(),g("/",e.loginRoute,e)),e.redirectOnError){let F=[];Array.isArray(p.errors)&&(F=p.errors.map(({status_code:P})=>P));let V=T();F.some(P=>e.authenticationErrors.includes(P))&&V!==e.loginRoute&&(e.StorageHandler.clear(),g(V,e.loginRoute,e))}c.error(p.errors)}else p.data?c.next(p):c.error(p);c.complete()}})}catch(h){if(b.canUseDOM&&!["AbortError","TimeOutError"].includes(h.name)&&e.StorageHandler.clear(),e.redirectOnError){let d=T();d!==e.loginRoute&&g(d,e.loginRoute,e)}await n()||(e.StorageHandler.clear(),g("/",e.loginRoute,e)),c.error(h)}}return o(i,"fetchFn"),(s,a,l,u)=>ne.create(c=>{i(s,a,l,u,c)})},"createFetchFunction");import ie from"js-cookie";var A=class A{get(t){throw new Error('Must implement a "GET" method')}set(t,r){throw new Error('Must implement a "SET" method')}delete(t){throw new Error('Must implement a "DELETE" method')}};o(A,"DefaultStrategy");var w=A,q=class q extends w{constructor(){super(),this.strategy=localStorage}get(t){return this.strategy.getItem(t)}set(t,r){this.strategy.setItem(t,r)}delete(t){this.strategy.removeItem(t)}};o(q,"LocalStorageStrategy");var D=q,H=class H extends w{constructor(){super(),this.strategy=ie}get(t){return this.strategy.get(t)}set(t,r){this.strategy.set(t,r)}delete(t){this.strategy.remove(t)}};o(H,"CookieStrategy");var I=H,y=Symbol("storage-handler"),R=Symbol("prop-session"),E=Symbol("prop-refresh"),N=class N{constructor(t){this[R]=t.sessionStorageProp,this[E]=t.refreshStorageProp,t.storageType==="cookie"?this[y]=new I:this[y]=new D}getTokens(){return{refreshToken:this[y].get(this[E]),sessionToken:this[y].get(this[R])}}setTokens(t){this[y].set(this[E],t.refreshToken),this[y].set(this[R],t.sessionToken)}clear(){this[y].delete(this[E]),this[y].delete(this[R])}hasChangedSession({sessionToken:t}){let{sessionToken:r}=this.getTokens();return t!==r}};o(N,"StorageClass");var x=N;import{createClient as ae}from"graphql-ws";import{Observable as ce}from"relay-runtime";function Y(e){return()=>{let t=ae({url:e.socket});return(r,n)=>ce.create(i=>t.subscribe({operationName:r.name,query:r.text||"",variables:n},{next:o(s=>i.next(s),"next"),error:o(s=>i.error(s),"error"),complete:o(()=>i.complete(),"complete")}))}}o(Y,"setupSubscription");var G=Symbol("mount-environment"),W=Symbol("handler-fetch"),L=Symbol("handler-subscription"),$=class ${constructor(t){if(this.url=t.url,this.authUrl=t.authUrl,this.socket=t.socket,this.storageType=t.storageType||"localStorage",this.cacheSize=t.cacheSize||250,this.cacheTime=t.cacheTime||M*8,this.timeout=t.timeout||M*15,this.sessionStorageProp=t.sessionStorageProp||"USER_SESSION_TOKEN",this.refreshStorageProp=t.refreshStorageProp||"USER_REFRESH_TOKEN",this.loginRoute=t.loginRoute||"/",this.useCache=t.useCache||!1,this.useDebug=t.useDebug||!1,this.useAuthorization=t.useAuthorization||!1,this.authMode=t.authMode||"bearer",this.credentials=t.credentials,this.sessionCheckUrl=t.sessionCheckUrl,this.useRetries=t.useRetries||!1,this.useSubscription=t.useSubscription||!1,this.redirectOnError=t.redirectOnError||!1,this.retryWhen=t.retryWhen||[503,504,521,522,524],this.authenticationErrors=t.authenticationErrors||[401,403],this.retries=t.retries||[f,f*2,f*3,f*5,f*8,f*13,f*21,f*34],this.partner=t.partner||void 0,!this.url)throw new Error("[HTTPFetchEndpoint] You must at least set url parameter.");if(this.useAuthorization&&!this.authUrl)throw new Error('[useAuthorization] Authorization is set but no "authUrl" was provided.');if(this.authMode==="cookie"&&this.sessionCheckUrl!==!1&&!this.authUrl)throw new Error('[authMode:cookie] Cookie auth refreshes against "authUrl" \u2014 provide it or set "sessionCheckUrl: false" to disable the probe.');if(this.StorageHandler=new x(this),this.useSubscription){if(!this.socket)throw new Error("[useSubscription] If you choose to use WebSocket you must set a socket endpoint.");this[L]=Y(this)}this[W]=Q(this),this[G]()}[(W,L,G)](){let t=le.create(this[W],this[L]||null),r=new de,n=new pe(r);this.Environment=new ue({network:t,store:n})}};o($,"RelayEnvironment");var C=$;import z from"react";var X=z.createContext(void 0);function et({children:e,environment:t}){return z.createElement(X.Provider,{value:{environment:t}},e)}o(et,"EnvironmentProvider");function tt(){let e=z.useContext(X);if(e===void 0)throw new Error("useEnvironment must be used within a EnvironmentProvider");if(e.environment===null||e.environment===void 0)throw new Error("You should provide a Relay Environment to EnvironmentProvider component");return e}o(tt,"useEnvironment");import{nanoid as he}from"nanoid";import{ConnectionHandler as v}from"relay-runtime";function me(e){return e!==null&&typeof e=="object"}o(me,"isObject");var dt=he();function pt({parentId:e,itemId:t,parentFieldName:r,store:n}){let i=n.get(e),s=i.getLinkedRecords(r);i.setLinkedRecords(s.filter(a=>a.dataID!==t),r)}o(pt,"listRecordRemoveUpdater");function ht({parentId:e,item:t,type:r,parentFieldName:n,store:i}){let s=i.create(t.id,r);Object.keys(t).forEach(u=>{s.setValue(t[u],u)});let a=i.get(e),l=a.getLinkedRecords(n);a.setLinkedRecords([...l,s],n)}o(ht,"listRecordAddUpdater");function fe(e,t,r,n,i=!1){if(n){let s=e.get(t),a=v.getConnection(s,r);if(!a)return;i?v.insertEdgeBefore(a,n):v.insertEdgeAfter(a,n)}}o(fe,"connectionUpdater");function mt({parentId:e,store:t,connectionName:r,item:n,customNode:i,itemType:s}){let a=i||t.create(n.id,s);!i&&Object.keys(n).forEach(u=>{a.setValue(n[u],u)});let l=t.create(`client:newEdge:${String(a.getDataID).match(/[^:]+$/)[0]}`,`${s}Edge`);l.setLinkedRecord(a,"node"),fe(t,e,r,l)}o(mt,"optimisticConnectionUpdater");function ft({parentId:e,connectionName:t,nodeId:r,store:n}){let i=n.get(e),s=v.getConnection(i,t);if(!s){console.warn(`Connection ${t} not found on ${e}`);return}v.deleteNode(s,r)}o(ft,"connectionDeleteEdgeUpdater");function yt({object:e,proxy:t}){Object.keys(e).forEach(r=>{me(e[r])||Array.isArray(e[r])||t.setValue(e[r],r)})}o(yt,"copyObjScalarsToProxy");import{commitMutation as ye}from"relay-runtime";var Tt=o((e,t)=>new Promise((r,n)=>{ye(e,{...t,onError:n,onCompleted:r})}),"commitMutation");export{dt as ClientMutationID,C as CreateRelayEnvironment,et as EnvironmentProvider,Tt as commitMutation,ft as connectionDeleteEdgeUpdater,fe as connectionUpdater,yt as copyObjScalarsToProxy,me as isObject,ht as listRecordAddUpdater,pt as listRecordRemoveUpdater,mt as optimisticConnectionUpdater,tt as useEnvironment};
|
package/lib/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var le=Object.create;var b=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var me=Object.getOwnPropertyNames;var he=Object.getPrototypeOf,ye=Object.prototype.hasOwnProperty;var n=(e,t)=>b(e,"name",{value:t,configurable:!0});var fe=(e,t)=>{for(var r in t)b(e,r,{get:t[r],enumerable:!0})},K=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of me(t))!ye.call(e,i)&&i!==r&&b(e,i,{get:()=>t[i],enumerable:!(o=de(t,i))||o.enumerable});return e};var _=(e,t,r)=>(r=e!=null?le(he(e)):{},K(t||!e||!e.__esModule?b(r,"default",{value:e,enumerable:!0}):r,e)),ge=e=>K(b({},"__esModule",{value:!0}),e);var Ue={};fe(Ue,{ClientMutationID:()=>ve,CreateRelayEnvironment:()=>T,EnvironmentProvider:()=>xe,commitMutation:()=>ke,connectionDeleteEdgeUpdater:()=>Ce,connectionUpdater:()=>ue,copyObjScalarsToProxy:()=>Oe,isObject:()=>ce,listRecordAddUpdater:()=>we,listRecordRemoveUpdater:()=>Te,optimisticConnectionUpdater:()=>Pe,useEnvironment:()=>Se});module.exports=ge(Ue);var f=require("relay-runtime");var C=require("relay-runtime");var w=!!(typeof window!="undefined"&&window.document&&window.document.createElement),g={canUseDOM:w,canUseWorkers:typeof Worker!="undefined",canUseEventListeners:w&&!!(window.addEventListener||window.attachEvent),canUseViewport:w&&!!window.screen,isInWorker:!w};function J(e){return async t=>{let r=e.timeout,o=e.retries,i=0,s=0;return new Promise((c,l)=>{let p={};p.sendTimedRequest=()=>{i++,s=Date.now();let u=!0,d=new AbortController,m=setTimeout(()=>{if(u=!1,d.abort(),p.shouldRetry(i))e.useDebug&&console.log("fetchWithRetries: HTTP timeout, retrying."),p.retryRequest();else{let a=new Error(`fetchWithRetries(): Failed to get response from server, tried ${i} times.`);a.name="TimeOutError",l(a)}},r);fetch(e.url,{...t,signal:d.signal}).then(async a=>{if(clearTimeout(m),u)if(a.status>=200&&a.status<300)c(a);else if(p.shouldRetry(i)&&e.retryWhen.includes(a.status))e.useDebug&&console.log("fetchWithRetries: HTTP error, retrying..."),p.retryRequest();else{let U=new Error(`fetchWithRetries(): Still no successful response after ${i} retries, giving up.`);U.response=a,l(U)}}).catch(a=>{clearTimeout(m),a.name!=="AbortError"&&l(a)})},p.retryRequest=()=>{let u=o[i-1],d=s+u;setTimeout(p.sendTimedRequest,d-Date.now())},p.shouldRetry=u=>g.canUseDOM&&e.useRetries&&u<=o.length,p.sendTimedRequest()})}}n(J,"fetchWithRetries");var Q=require("fetch-multipart-graphql");var I=n(e=>e.operationKind==="mutation","isMutation"),A=n(e=>e.operationKind==="query","isQuery"),Y=n(e=>!!(e&&e.force),"forceFetch"),Re=n(()=>g.canUseDOM?window.location.search.startsWith("?")?"&":"?":"","getParamsDelimiter"),P=n(()=>g.canUseDOM?window.location.pathname:"","getBrowserLocation"),E=n((e,t,r)=>{let o=e;(e!==t||r.loginRoute!==t)&&(o=`${t}${Re()}redirect=${e}`),window.location.href=o},"redirectUser");function be(e,t,r){let o=new FormData;o.append("operations",JSON.stringify({query:e.text,variables:t,operationName:e.name}));let i={};for(let s=0;s<r.files.length;s++)o.append(`${s}`,r.files[s]),i[`${s}`]=[r.path(s)];return o.append("map",JSON.stringify(i)),o}n(be,"getRequestBodyWithUploadables");function Ee(e,t){return JSON.stringify({name:e.name,query:e.text,variables:t})}n(Ee,"getRequestBodyWithoutUplodables");function G(e,t,r){return r?be(e,t,r):Ee(e,t)}n(G,"getRequestBody");var X=n((e,t)=>{let r=new Headers;if(t?r.append("Accept","*/*"):(r.append("Accept","application/json"),r.append("Content-type","application/json")),e.useAuthorization){let{sessionToken:o}=e.StorageHandler.getTokens();o&&P()!==e.loginRoute&&r.append("Authorization",`Bearer ${o}`)}return e.partner&&r.append("X-Partner",e.partner),r},"getHeaders"),Z=n((e,t,r)=>{if(e.status<300&&e.headers&&e.headers.get("Content-Type")&&e.headers.get("Content-Type").indexOf("multipart/mixed")>=0){let o=e.body.getReader(),i=new TextDecoder,s=new Q.PatchResolver({onResponse:n(c=>t.next(c),"onResponse")});o.read().then(n(function c({value:l,done:p}){if(p)t.complete();else{let u;try{u=i.decode(l),s.handleChunk(u)}catch(d){let m=d;m.response=e,m.statusCode=e.status,m.bodyText=u,t.error(m)}o.read().then(c)}},"sendNext"))}else e.headers&&e.headers.get("Content-Type")&&e.headers.get("Content-Type").indexOf("application/json")>=0?e.json().then(r):e.text().then(o=>{t.next([o]),t.complete()})},"handleData"),h=1e3,M=h*60;var ee=n(e=>{let t=new C.QueryResponseCache({ttl:e.cacheTime,size:e.cacheSize}),r=J(e);async function o(){try{let{sessionToken:s}=e.StorageHandler.getTokens();return(await fetch(`${e.authUrl}user/me`,{headers:{"Content-Type":"application/json",Authorization:s}})).status===200}catch(s){return console.warn(`[Auth] ${s.message}`),!1}}n(o,"checkLoggedUser");async function i(s,c,l,p,u){try{let d=String(s.text);if(e.useCache&&A(s)&&!Y(l)){let a=t.get(d,c);if(a){u.next(a),u.complete();return}}e.useCache&&I(s)&&t.clear();let m=await r({method:"POST",headers:X(e,p),body:G(s,c,p)});Z(m,u,async a=>{if(e.useCache&&A(s)&&t.set(d,c,a),!u.closed){if(I(s)&&a.errors&&u.error(a.errors),a.errors){if(await o()||(e.StorageHandler.clear(),E("/",e.loginRoute,e)),e.redirectOnError){let j=[];Array.isArray(a.errors)&&(j=a.errors.map(({status_code:D})=>D));let B=P();j.some(D=>e.authenticationErrors.includes(D))&&B!==e.loginRoute&&(e.StorageHandler.clear(),E(B,e.loginRoute,e))}u.error(a.errors)}else a.data?u.next(a):u.error(a);u.complete()}})}catch(d){if(g.canUseDOM&&!["AbortError","TimeOutError"].includes(d.name)&&e.StorageHandler.clear(),e.redirectOnError){let a=P();a!==e.loginRoute&&E(a,e.loginRoute,e)}await o()||(e.StorageHandler.clear(),E("/",e.loginRoute,e)),u.error(d)}}return n(i,"fetchFn"),(s,c,l,p)=>C.Observable.create(u=>{i(s,c,l,p,u)})},"createFetchFunction");var te=_(require("js-cookie"));var N=class N{get(t){throw new Error('Must implement a "GET" method')}set(t,r){throw new Error('Must implement a "SET" method')}delete(t){throw new Error('Must implement a "DELETE" method')}};n(N,"DefaultStrategy");var O=N,L=class L extends O{constructor(){super(),this.strategy=localStorage}get(t){return this.strategy.getItem(t)}set(t,r){this.strategy.setItem(t,r)}delete(t){this.strategy.removeItem(t)}};n(L,"LocalStorageStrategy");var q=L,W=class W extends O{constructor(){super(),this.strategy=te.default}get(t){return this.strategy.get(t)}set(t,r){this.strategy.set(t,r)}delete(t){this.strategy.remove(t)}};n(W,"CookieStrategy");var H=W,y=Symbol("storage-handler"),x=Symbol("prop-session"),S=Symbol("prop-refresh"),$=class ${constructor(t){this[x]=t.sessionStorageProp,this[S]=t.refreshStorageProp,t.storageType==="cookie"?this[y]=new H:this[y]=new q}getTokens(){return{refreshToken:this[y].get(this[S]),sessionToken:this[y].get(this[x])}}setTokens(t){this[y].set(this[S],t.refreshToken),this[y].set(this[x],t.sessionToken)}clear(){this[y].delete(this[S]),this[y].delete(this[x])}hasChangedSession({sessionToken:t}){let{sessionToken:r}=this.getTokens();return t!==r}};n($,"StorageClass");var v=$;var re=require("graphql-ws"),oe=require("relay-runtime");function ne(e){return()=>{let t=(0,re.createClient)({url:e.socket});return(r,o)=>oe.Observable.create(i=>t.subscribe({operationName:r.name,query:r.text||"",variables:o},{next:n(s=>i.next(s),"next"),error:n(s=>i.error(s),"error"),complete:n(()=>i.complete(),"complete")}))}}n(ne,"setupSubscription");var se=Symbol("mount-environment"),z=Symbol("handler-fetch"),F=Symbol("handler-subscription"),V=class V{constructor(t){if(this.url=t.url,this.authUrl=t.authUrl,this.socket=t.socket,this.storageType=t.storageType||"localStorage",this.cacheSize=t.cacheSize||250,this.cacheTime=t.cacheTime||M*8,this.timeout=t.timeout||M*15,this.sessionStorageProp=t.sessionStorageProp||"USER_SESSION_TOKEN",this.refreshStorageProp=t.refreshStorageProp||"USER_REFRESH_TOKEN",this.loginRoute=t.loginRoute||"/",this.useCache=t.useCache||!1,this.useDebug=t.useDebug||!1,this.useAuthorization=t.useAuthorization||!1,this.useRetries=t.useRetries||!1,this.useSubscription=t.useSubscription||!1,this.redirectOnError=t.redirectOnError||!1,this.retryWhen=t.retryWhen||[503,504,521,522,524],this.authenticationErrors=t.authenticationErrors||[401,403],this.retries=t.retries||[h,h*2,h*3,h*5,h*8,h*13,h*21,h*34],this.partner=t.partner||void 0,!this.url)throw new Error("[HTTPFetchEndpoint] You must at least set url parameter.");if(this.useAuthorization&&!this.authUrl)throw new Error('[useAuthorization] Authorization is set but no "authUrl" was provided.');if(this.StorageHandler=new v(this),this.useSubscription){if(!this.socket)throw new Error("[useSubscription] If you choose to use WebSocket you must set a socket endpoint.");this[F]=ne(this)}this[z]=ee(this),this[se]()}[(z,F,se)](){let t=f.Network.create(this[z],this[F]||null),r=new f.RecordSource,o=new f.Store(r);this.Environment=new f.Environment({network:t,store:o})}};n(V,"RelayEnvironment");var T=V;var k=_(require("react"));var ie=k.default.createContext(void 0);function xe({children:e,environment:t}){return k.default.createElement(ie.Provider,{value:{environment:t}},e)}n(xe,"EnvironmentProvider");function Se(){let e=k.default.useContext(ie);if(e===void 0)throw new Error("useEnvironment must be used within a EnvironmentProvider");if(e.environment===null||e.environment===void 0)throw new Error("You should provide a Relay Environment to EnvironmentProvider component");return e}n(Se,"useEnvironment");var ae=require("nanoid"),R=require("relay-runtime");function ce(e){return e!==null&&typeof e=="object"}n(ce,"isObject");var ve=(0,ae.nanoid)();function Te({parentId:e,itemId:t,parentFieldName:r,store:o}){let i=o.get(e),s=i.getLinkedRecords(r);i.setLinkedRecords(s.filter(c=>c.dataID!==t),r)}n(Te,"listRecordRemoveUpdater");function we({parentId:e,item:t,type:r,parentFieldName:o,store:i}){let s=i.create(t.id,r);Object.keys(t).forEach(p=>{s.setValue(t[p],p)});let c=i.get(e),l=c.getLinkedRecords(o);c.setLinkedRecords([...l,s],o)}n(we,"listRecordAddUpdater");function ue(e,t,r,o,i=!1){if(o){let s=e.get(t),c=R.ConnectionHandler.getConnection(s,r);if(!c)return;i?R.ConnectionHandler.insertEdgeBefore(c,o):R.ConnectionHandler.insertEdgeAfter(c,o)}}n(ue,"connectionUpdater");function Pe({parentId:e,store:t,connectionName:r,item:o,customNode:i,itemType:s}){let c=i||t.create(o.id,s);!i&&Object.keys(o).forEach(p=>{c.setValue(o[p],p)});let l=t.create(`client:newEdge:${String(c.getDataID).match(/[^:]+$/)[0]}`,`${s}Edge`);l.setLinkedRecord(c,"node"),ue(t,e,r,l)}n(Pe,"optimisticConnectionUpdater");function Ce({parentId:e,connectionName:t,nodeId:r,store:o}){let i=o.get(e),s=R.ConnectionHandler.getConnection(i,t);if(!s){console.warn(`Connection ${t} not found on ${e}`);return}R.ConnectionHandler.deleteNode(s,r)}n(Ce,"connectionDeleteEdgeUpdater");function Oe({object:e,proxy:t}){Object.keys(e).forEach(r=>{ce(e[r])||Array.isArray(e[r])||t.setValue(e[r],r)})}n(Oe,"copyObjScalarsToProxy");var pe=require("relay-runtime");var ke=n((e,t)=>new Promise((r,o)=>{(0,pe.commitMutation)(e,{...t,onError:o,onCompleted:r})}),"commitMutation");0&&(module.exports={ClientMutationID,CreateRelayEnvironment,EnvironmentProvider,commitMutation,connectionDeleteEdgeUpdater,connectionUpdater,copyObjScalarsToProxy,isObject,listRecordAddUpdater,listRecordRemoveUpdater,optimisticConnectionUpdater,useEnvironment});
|
|
1
|
+
var pe=Object.create;var E=Object.defineProperty;var he=Object.getOwnPropertyDescriptor;var me=Object.getOwnPropertyNames;var fe=Object.getPrototypeOf,ye=Object.prototype.hasOwnProperty;var o=(e,t)=>E(e,"name",{value:t,configurable:!0});var be=(e,t)=>{for(var r in t)E(e,r,{get:t[r],enumerable:!0})},_=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of me(t))!ye.call(e,i)&&i!==r&&E(e,i,{get:()=>t[i],enumerable:!(n=he(t,i))||n.enumerable});return e};var J=(e,t,r)=>(r=e!=null?pe(fe(e)):{},_(t||!e||!e.__esModule?E(r,"default",{value:e,enumerable:!0}):r,e)),ge=e=>_(E({},"__esModule",{value:!0}),e);var Me={};be(Me,{ClientMutationID:()=>Te,CreateRelayEnvironment:()=>w,EnvironmentProvider:()=>ve,commitMutation:()=>Oe,connectionDeleteEdgeUpdater:()=>ke,connectionUpdater:()=>le,copyObjScalarsToProxy:()=>Ue,isObject:()=>ue,listRecordAddUpdater:()=>Ce,listRecordRemoveUpdater:()=>we,optimisticConnectionUpdater:()=>Pe,useEnvironment:()=>Se});module.exports=ge(Me);var b=require("relay-runtime");var k=require("relay-runtime");var C=!!(typeof window!="undefined"&&window.document&&window.document.createElement),g={canUseDOM:C,canUseWorkers:typeof Worker!="undefined",canUseEventListeners:C&&!!(window.addEventListener||window.attachEvent),canUseViewport:C&&!!window.screen,isInWorker:!C};function Q(e){return async t=>{let r=e.timeout,n=e.retries,i=0,s=0;return new Promise((a,l)=>{let u={};u.sendTimedRequest=()=>{i++,s=Date.now();let c=!0,h=new AbortController,m=setTimeout(()=>{if(c=!1,h.abort(),u.shouldRetry(i))e.useDebug&&console.log("fetchWithRetries: HTTP timeout, retrying."),u.retryRequest();else{let d=new Error(`fetchWithRetries(): Failed to get response from server, tried ${i} times.`);d.name="TimeOutError",l(d)}},r);fetch(e.url,{...t,signal:h.signal}).then(async d=>{if(clearTimeout(m),c)if(d.status>=200&&d.status<300)a(d);else if(u.shouldRetry(i)&&e.retryWhen.includes(d.status))e.useDebug&&console.log("fetchWithRetries: HTTP error, retrying..."),u.retryRequest();else{let p=new Error(`fetchWithRetries(): Still no successful response after ${i} retries, giving up.`);p.response=d,l(p)}}).catch(d=>{clearTimeout(m),d.name!=="AbortError"&&l(d)})},u.retryRequest=()=>{let c=n[i-1],h=s+c;setTimeout(u.sendTimedRequest,h-Date.now())},u.shouldRetry=c=>g.canUseDOM&&e.useRetries&&c<=n.length,u.sendTimedRequest()})}}o(Q,"fetchWithRetries");var Y=require("fetch-multipart-graphql");var D=o(e=>e.operationKind==="mutation","isMutation"),I=o(e=>e.operationKind==="query","isQuery"),G=o(e=>!!(e&&e.force),"forceFetch"),Re=o(()=>g.canUseDOM?window.location.search.startsWith("?")?"&":"?":"","getParamsDelimiter"),P=o(()=>g.canUseDOM?window.location.pathname:"","getBrowserLocation"),x=o((e,t,r)=>{let n=e;(e!==t||r.loginRoute!==t)&&(n=`${t}${Re()}redirect=${e}`),window.location.href=n},"redirectUser");function Ee(e,t,r){let n=new FormData;n.append("operations",JSON.stringify({query:e.text,variables:t,operationName:e.name}));let i={};for(let s=0;s<r.files.length;s++)n.append(`${s}`,r.files[s]),i[`${s}`]=[r.path(s)];return n.append("map",JSON.stringify(i)),n}o(Ee,"getRequestBodyWithUploadables");function xe(e,t){return JSON.stringify({name:e.name,query:e.text,variables:t})}o(xe,"getRequestBodyWithoutUplodables");function X(e,t,r){return r?Ee(e,t,r):xe(e,t)}o(X,"getRequestBody");var A=o(e=>{if(e.credentials)return e.credentials;if(e.authMode==="cookie")return"include"},"resolveCredentials"),Z=o((e,t)=>{let r=new Headers;if(t?r.append("Accept","*/*"):(r.append("Accept","application/json"),r.append("Content-type","application/json")),e.useAuthorization&&e.authMode!=="cookie"){let{sessionToken:n}=e.StorageHandler.getTokens();n&&P()!==e.loginRoute&&r.append("Authorization",`Bearer ${n}`)}return e.partner&&r.append("X-Partner",e.partner),r},"getHeaders"),ee=o((e,t,r)=>{if(e.status<300&&e.headers&&e.headers.get("Content-Type")&&e.headers.get("Content-Type").indexOf("multipart/mixed")>=0){let n=e.body.getReader(),i=new TextDecoder,s=new Y.PatchResolver({onResponse:o(a=>t.next(a),"onResponse")});n.read().then(o(function a({value:l,done:u}){if(u)t.complete();else{let c;try{c=i.decode(l),s.handleChunk(c)}catch(h){let m=h;m.response=e,m.statusCode=e.status,m.bodyText=c,t.error(m)}n.read().then(a)}},"sendNext"))}else e.headers&&e.headers.get("Content-Type")&&e.headers.get("Content-Type").indexOf("application/json")>=0?e.json().then(r):e.text().then(n=>{t.next([n]),t.complete()})},"handleData"),f=1e3,q=f*60;var te=o(e=>{let t=new k.QueryResponseCache({ttl:e.cacheTime,size:e.cacheSize}),r=Q(e);async function n(){if(e.sessionCheckUrl===!1)return!1;let s=A(e);try{if(e.authMode==="cookie"){let c=e.sessionCheckUrl||e.authUrl;return(await fetch(c,{method:"POST",credentials:s||"include"})).status===200}let{sessionToken:a}=e.StorageHandler.getTokens(),l=e.sessionCheckUrl||`${e.authUrl}user/me`;return(await fetch(l,{headers:{"Content-Type":"application/json",Authorization:a},...s?{credentials:s}:{}})).status===200}catch(a){return console.warn(`[Auth] ${a.message}`),!1}}o(n,"checkSession");async function i(s,a,l,u,c){try{let h=String(s.text);if(e.useCache&&I(s)&&!G(l)){let p=t.get(h,a);if(p){c.next(p),c.complete();return}}e.useCache&&D(s)&&t.clear();let m=A(e),d=await r({method:"POST",headers:Z(e,u),body:X(s,a,u),...m?{credentials:m}:{}});ee(d,c,async p=>{if(e.useCache&&I(s)&&t.set(h,a,p),!c.closed){if(D(s)&&p.errors&&c.error(p.errors),p.errors){if(await n()||(e.StorageHandler.clear(),x("/",e.loginRoute,e)),e.redirectOnError){let B=[];Array.isArray(p.errors)&&(B=p.errors.map(({status_code:M})=>M));let K=P();B.some(M=>e.authenticationErrors.includes(M))&&K!==e.loginRoute&&(e.StorageHandler.clear(),x(K,e.loginRoute,e))}c.error(p.errors)}else p.data?c.next(p):c.error(p);c.complete()}})}catch(h){if(g.canUseDOM&&!["AbortError","TimeOutError"].includes(h.name)&&e.StorageHandler.clear(),e.redirectOnError){let d=P();d!==e.loginRoute&&x(d,e.loginRoute,e)}await n()||(e.StorageHandler.clear(),x("/",e.loginRoute,e)),c.error(h)}}return o(i,"fetchFn"),(s,a,l,u)=>k.Observable.create(c=>{i(s,a,l,u,c)})},"createFetchFunction");var re=J(require("js-cookie"));var W=class W{get(t){throw new Error('Must implement a "GET" method')}set(t,r){throw new Error('Must implement a "SET" method')}delete(t){throw new Error('Must implement a "DELETE" method')}};o(W,"DefaultStrategy");var U=W,L=class L extends U{constructor(){super(),this.strategy=localStorage}get(t){return this.strategy.getItem(t)}set(t,r){this.strategy.setItem(t,r)}delete(t){this.strategy.removeItem(t)}};o(L,"LocalStorageStrategy");var H=L,$=class $ extends U{constructor(){super(),this.strategy=re.default}get(t){return this.strategy.get(t)}set(t,r){this.strategy.set(t,r)}delete(t){this.strategy.remove(t)}};o($,"CookieStrategy");var N=$,y=Symbol("storage-handler"),v=Symbol("prop-session"),S=Symbol("prop-refresh"),z=class z{constructor(t){this[v]=t.sessionStorageProp,this[S]=t.refreshStorageProp,t.storageType==="cookie"?this[y]=new N:this[y]=new H}getTokens(){return{refreshToken:this[y].get(this[S]),sessionToken:this[y].get(this[v])}}setTokens(t){this[y].set(this[S],t.refreshToken),this[y].set(this[v],t.sessionToken)}clear(){this[y].delete(this[S]),this[y].delete(this[v])}hasChangedSession({sessionToken:t}){let{sessionToken:r}=this.getTokens();return t!==r}};o(z,"StorageClass");var T=z;var oe=require("graphql-ws"),ne=require("relay-runtime");function se(e){return()=>{let t=(0,oe.createClient)({url:e.socket});return(r,n)=>ne.Observable.create(i=>t.subscribe({operationName:r.name,query:r.text||"",variables:n},{next:o(s=>i.next(s),"next"),error:o(s=>i.error(s),"error"),complete:o(()=>i.complete(),"complete")}))}}o(se,"setupSubscription");var ie=Symbol("mount-environment"),F=Symbol("handler-fetch"),V=Symbol("handler-subscription"),j=class j{constructor(t){if(this.url=t.url,this.authUrl=t.authUrl,this.socket=t.socket,this.storageType=t.storageType||"localStorage",this.cacheSize=t.cacheSize||250,this.cacheTime=t.cacheTime||q*8,this.timeout=t.timeout||q*15,this.sessionStorageProp=t.sessionStorageProp||"USER_SESSION_TOKEN",this.refreshStorageProp=t.refreshStorageProp||"USER_REFRESH_TOKEN",this.loginRoute=t.loginRoute||"/",this.useCache=t.useCache||!1,this.useDebug=t.useDebug||!1,this.useAuthorization=t.useAuthorization||!1,this.authMode=t.authMode||"bearer",this.credentials=t.credentials,this.sessionCheckUrl=t.sessionCheckUrl,this.useRetries=t.useRetries||!1,this.useSubscription=t.useSubscription||!1,this.redirectOnError=t.redirectOnError||!1,this.retryWhen=t.retryWhen||[503,504,521,522,524],this.authenticationErrors=t.authenticationErrors||[401,403],this.retries=t.retries||[f,f*2,f*3,f*5,f*8,f*13,f*21,f*34],this.partner=t.partner||void 0,!this.url)throw new Error("[HTTPFetchEndpoint] You must at least set url parameter.");if(this.useAuthorization&&!this.authUrl)throw new Error('[useAuthorization] Authorization is set but no "authUrl" was provided.');if(this.authMode==="cookie"&&this.sessionCheckUrl!==!1&&!this.authUrl)throw new Error('[authMode:cookie] Cookie auth refreshes against "authUrl" \u2014 provide it or set "sessionCheckUrl: false" to disable the probe.');if(this.StorageHandler=new T(this),this.useSubscription){if(!this.socket)throw new Error("[useSubscription] If you choose to use WebSocket you must set a socket endpoint.");this[V]=se(this)}this[F]=te(this),this[ie]()}[(F,V,ie)](){let t=b.Network.create(this[F],this[V]||null),r=new b.RecordSource,n=new b.Store(r);this.Environment=new b.Environment({network:t,store:n})}};o(j,"RelayEnvironment");var w=j;var O=J(require("react"));var ae=O.default.createContext(void 0);function ve({children:e,environment:t}){return O.default.createElement(ae.Provider,{value:{environment:t}},e)}o(ve,"EnvironmentProvider");function Se(){let e=O.default.useContext(ae);if(e===void 0)throw new Error("useEnvironment must be used within a EnvironmentProvider");if(e.environment===null||e.environment===void 0)throw new Error("You should provide a Relay Environment to EnvironmentProvider component");return e}o(Se,"useEnvironment");var ce=require("nanoid"),R=require("relay-runtime");function ue(e){return e!==null&&typeof e=="object"}o(ue,"isObject");var Te=(0,ce.nanoid)();function we({parentId:e,itemId:t,parentFieldName:r,store:n}){let i=n.get(e),s=i.getLinkedRecords(r);i.setLinkedRecords(s.filter(a=>a.dataID!==t),r)}o(we,"listRecordRemoveUpdater");function Ce({parentId:e,item:t,type:r,parentFieldName:n,store:i}){let s=i.create(t.id,r);Object.keys(t).forEach(u=>{s.setValue(t[u],u)});let a=i.get(e),l=a.getLinkedRecords(n);a.setLinkedRecords([...l,s],n)}o(Ce,"listRecordAddUpdater");function le(e,t,r,n,i=!1){if(n){let s=e.get(t),a=R.ConnectionHandler.getConnection(s,r);if(!a)return;i?R.ConnectionHandler.insertEdgeBefore(a,n):R.ConnectionHandler.insertEdgeAfter(a,n)}}o(le,"connectionUpdater");function Pe({parentId:e,store:t,connectionName:r,item:n,customNode:i,itemType:s}){let a=i||t.create(n.id,s);!i&&Object.keys(n).forEach(u=>{a.setValue(n[u],u)});let l=t.create(`client:newEdge:${String(a.getDataID).match(/[^:]+$/)[0]}`,`${s}Edge`);l.setLinkedRecord(a,"node"),le(t,e,r,l)}o(Pe,"optimisticConnectionUpdater");function ke({parentId:e,connectionName:t,nodeId:r,store:n}){let i=n.get(e),s=R.ConnectionHandler.getConnection(i,t);if(!s){console.warn(`Connection ${t} not found on ${e}`);return}R.ConnectionHandler.deleteNode(s,r)}o(ke,"connectionDeleteEdgeUpdater");function Ue({object:e,proxy:t}){Object.keys(e).forEach(r=>{ue(e[r])||Array.isArray(e[r])||t.setValue(e[r],r)})}o(Ue,"copyObjScalarsToProxy");var de=require("relay-runtime");var Oe=o((e,t)=>new Promise((r,n)=>{(0,de.commitMutation)(e,{...t,onError:n,onCompleted:r})}),"commitMutation");0&&(module.exports={ClientMutationID,CreateRelayEnvironment,EnvironmentProvider,commitMutation,connectionDeleteEdgeUpdater,connectionUpdater,copyObjScalarsToProxy,isObject,listRecordAddUpdater,listRecordRemoveUpdater,optimisticConnectionUpdater,useEnvironment});
|
|
@@ -71,6 +71,50 @@ export interface RelayArgsInterface {
|
|
|
71
71
|
* @defaultValue false
|
|
72
72
|
*/
|
|
73
73
|
useAuthorization?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Modelo de autenticação usado pelo Environment.
|
|
76
|
+
*
|
|
77
|
+
* - `'bearer'` (default, retrocompat): lê o `sessionToken` do storage
|
|
78
|
+
* JS-legível e injeta `Authorization: Bearer <token>` em cada request.
|
|
79
|
+
* A verificação de sessão usa o probe `${authUrl}user/me`.
|
|
80
|
+
* - `'cookie'`: modelo de **sessão por cookie httpOnly**. O Environment
|
|
81
|
+
* **não** lê o token em JS nem injeta `Authorization` — o cookie de
|
|
82
|
+
* sessão (httpOnly + SameSite) viaja sozinho desde que o fetch use
|
|
83
|
+
* `credentials` (default `'include'` neste modo). A renovação de
|
|
84
|
+
* sessão é disparada por erro de auth (ex: 401) chamando `authUrl`
|
|
85
|
+
* com `credentials:'include'`, sem probe a `user/me`.
|
|
86
|
+
*
|
|
87
|
+
* @defaultValue `'bearer'`
|
|
88
|
+
*/
|
|
89
|
+
authMode?: 'bearer' | 'cookie';
|
|
90
|
+
/**
|
|
91
|
+
* Valor de `credentials` repassado aos fetches GraphQL e de
|
|
92
|
+
* verificação/refresh de sessão. Use `'include'` para que o browser
|
|
93
|
+
* anexe automaticamente cookies httpOnly de sessão (inclusive
|
|
94
|
+
* cross-origin).
|
|
95
|
+
*
|
|
96
|
+
* Quando não definido: `'include'` no modo `authMode:'cookie'`, e
|
|
97
|
+
* omitido (default do browser) no modo `'bearer'` — preservando a
|
|
98
|
+
* retrocompat dos consumidores Bearer existentes.
|
|
99
|
+
*
|
|
100
|
+
* @defaultValue `authMode:'cookie'` → `'include'`; senão omitido.
|
|
101
|
+
*/
|
|
102
|
+
credentials?: RequestCredentials;
|
|
103
|
+
/**
|
|
104
|
+
* URL usada para verificar/renovar a sessão quando um erro de auth é
|
|
105
|
+
* detectado. Torna o probe configurável/opcional:
|
|
106
|
+
*
|
|
107
|
+
* - `string` — sobrescreve a URL padrão do probe.
|
|
108
|
+
* - `false` — **desliga** o probe; um erro de auth é tratado como
|
|
109
|
+
* logout direto (limpa storage + redireciona para `loginRoute`),
|
|
110
|
+
* sem nenhuma requisição extra.
|
|
111
|
+
* - não definido — usa o default do modo: `${authUrl}user/me` (GET,
|
|
112
|
+
* modo `bearer`) ou `authUrl` (POST + `credentials:'include'`, modo
|
|
113
|
+
* `cookie`).
|
|
114
|
+
*
|
|
115
|
+
* @defaultValue depende de `authMode` (veja acima).
|
|
116
|
+
*/
|
|
117
|
+
sessionCheckUrl?: string | false;
|
|
74
118
|
/**
|
|
75
119
|
* Habilita cache de respostas via `QueryResponseCache` do Relay.
|
|
76
120
|
* Por recomendação do time do Relay, vem desligado por padrão.
|
|
@@ -17,9 +17,10 @@ import { CacheConfig, Observable, RequestParameters, UploadableMap, Variables }
|
|
|
17
17
|
* (`QueryResponseCache`) antes de fazer a requisição.
|
|
18
18
|
* - Para mutations com `useCache` ligado, limpa o cache (invalidação
|
|
19
19
|
* total — Relay vai re-buscar queries afetadas).
|
|
20
|
-
* - Em caso de erro de autenticação detectado,
|
|
21
|
-
* `${authUrl}user/me
|
|
22
|
-
*
|
|
20
|
+
* - Em caso de erro de autenticação detectado, verifica/renova a sessão
|
|
21
|
+
* (modo bearer: probe `${authUrl}user/me`; modo cookie httpOnly:
|
|
22
|
+
* refresh em `authUrl` com `credentials:'include'`) e, se inválida,
|
|
23
|
+
* limpa storage e redireciona para `loginRoute`.
|
|
23
24
|
* - Erros são propagados via `sink.error()`.
|
|
24
25
|
*
|
|
25
26
|
* @param config - Instância de `CreateRelayEnvironment` configurada.
|
|
@@ -28,7 +28,7 @@ declare const kSubscriptionHandler: unique symbol;
|
|
|
28
28
|
* });
|
|
29
29
|
* ```
|
|
30
30
|
*
|
|
31
|
-
* @example Com auth JWT e retries
|
|
31
|
+
* @example Com auth JWT (Bearer) e retries
|
|
32
32
|
* ```ts
|
|
33
33
|
* const { Environment } = new CreateRelayEnvironment({
|
|
34
34
|
* url: 'https://api.example.com/graphql/',
|
|
@@ -39,6 +39,21 @@ declare const kSubscriptionHandler: unique symbol;
|
|
|
39
39
|
* });
|
|
40
40
|
* ```
|
|
41
41
|
*
|
|
42
|
+
* @example Com sessão por cookie httpOnly (modelo seguro p/ SPA)
|
|
43
|
+
* ```ts
|
|
44
|
+
* // O token de sessão fica num cookie httpOnly + SameSite (invisível ao
|
|
45
|
+
* // JS, imune a XSS). Nada é lido do storage e nenhum Bearer é injetado;
|
|
46
|
+
* // `credentials:'include'` faz o browser anexar o cookie sozinho. Em
|
|
47
|
+
* // erro de auth (401) o refresh é disparado contra `authUrl`.
|
|
48
|
+
* const { Environment } = new CreateRelayEnvironment({
|
|
49
|
+
* url: 'https://api.example.com/graphql/',
|
|
50
|
+
* authUrl: 'https://api.example.com/auth/refresh/',
|
|
51
|
+
* authMode: 'cookie',
|
|
52
|
+
* redirectOnError: true,
|
|
53
|
+
* loginRoute: '/login',
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
42
57
|
* @example Com subscriptions
|
|
43
58
|
* ```ts
|
|
44
59
|
* const { Environment } = new CreateRelayEnvironment({
|
|
@@ -65,6 +80,12 @@ export default class RelayEnvironment implements RelayArgsInterface {
|
|
|
65
80
|
useSubscription?: boolean;
|
|
66
81
|
/** Habilita injeção do header `Authorization: Bearer <token>` em cada request. */
|
|
67
82
|
useAuthorization?: boolean;
|
|
83
|
+
/** Modelo de auth: `'bearer'` (token JS + header) ou `'cookie'` (httpOnly). */
|
|
84
|
+
authMode: 'bearer' | 'cookie';
|
|
85
|
+
/** Valor de `credentials` repassado aos fetches GraphQL/refresh. */
|
|
86
|
+
credentials?: RequestCredentials;
|
|
87
|
+
/** URL de verificação/refresh de sessão; `false` desliga o probe. */
|
|
88
|
+
sessionCheckUrl?: string | false;
|
|
68
89
|
/** Habilita cache de respostas (via `QueryResponseCache` do Relay). */
|
|
69
90
|
useCache?: boolean;
|
|
70
91
|
/** TTL (ms) das entradas do cache. */
|
|
@@ -47,14 +47,34 @@ export declare const redirectUser: (url: string, redirectTo: string, config?: Re
|
|
|
47
47
|
* @param uploadables - Arquivos para upload (opcional).
|
|
48
48
|
*/
|
|
49
49
|
export declare function getRequestBody(request: RequestParameters, variables: Variables, uploadables?: UploadableMap): string | FormData;
|
|
50
|
+
/**
|
|
51
|
+
* Resolve o valor efetivo de `credentials` para os fetches (GraphQL e
|
|
52
|
+
* verificação/refresh de sessão).
|
|
53
|
+
*
|
|
54
|
+
* - Se `config.credentials` foi definido explicitamente, ele vence.
|
|
55
|
+
* - Caso contrário, no modo `authMode:'cookie'` o default é `'include'`
|
|
56
|
+
* (para o browser anexar cookies httpOnly de sessão).
|
|
57
|
+
* - No modo `'bearer'` (default) retorna `undefined` — o fetch usa o
|
|
58
|
+
* default do browser, preservando a retrocompat.
|
|
59
|
+
*
|
|
60
|
+
* @param config - Configuração do environment.
|
|
61
|
+
* @returns O `RequestCredentials` a usar, ou `undefined` para omitir.
|
|
62
|
+
*/
|
|
63
|
+
export declare const resolveCredentials: (config: any) => RequestCredentials | undefined;
|
|
50
64
|
/**
|
|
51
65
|
* Monta os headers HTTP da requisição. Para uploads, usa `Accept: *\/*`
|
|
52
66
|
* e deixa o browser definir o `Content-Type` com boundary. Para JSON,
|
|
53
67
|
* usa `application/json` em ambos.
|
|
54
68
|
*
|
|
55
|
-
*
|
|
56
|
-
* storage, anexa `Authorization: Bearer <token>` —
|
|
57
|
-
* usuário está na própria rota de login (para evitar
|
|
69
|
+
* Modo `bearer` (default): quando `useAuthorization` está ligado e existe
|
|
70
|
+
* um `sessionToken` em storage, anexa `Authorization: Bearer <token>` —
|
|
71
|
+
* exceto quando o usuário está na própria rota de login (para evitar
|
|
72
|
+
* loops).
|
|
73
|
+
*
|
|
74
|
+
* Modo `cookie` (httpOnly): **nunca** lê o token em JS nem injeta
|
|
75
|
+
* `Authorization` — o cookie de sessão viaja sozinho via `credentials`.
|
|
76
|
+
* Isso evita o header `Authorization: Bearer ` vazio que o modo bearer
|
|
77
|
+
* produziria quando o token é httpOnly e portanto invisível ao JS.
|
|
58
78
|
*
|
|
59
79
|
* Se um `partner` está configurado, adiciona o header `X-Partner`.
|
|
60
80
|
*/
|