@laconius/core 0.1.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/LICENSE +73 -0
- package/README.md +31 -0
- package/lib/module/auth.js +182 -0
- package/lib/module/auth.js.map +1 -0
- package/lib/module/client.js +99 -0
- package/lib/module/client.js.map +1 -0
- package/lib/module/config.js +72 -0
- package/lib/module/config.js.map +1 -0
- package/lib/module/converters.js +31 -0
- package/lib/module/converters.js.map +1 -0
- package/lib/module/create-config.js +36 -0
- package/lib/module/create-config.js.map +1 -0
- package/lib/module/endpoints.js +89 -0
- package/lib/module/endpoints.js.map +1 -0
- package/lib/module/errors.js +76 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/i18n.js +84 -0
- package/lib/module/i18n.js.map +1 -0
- package/lib/module/index.js +18 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/media.js +182 -0
- package/lib/module/media.js.map +1 -0
- package/lib/module/models.js +2 -0
- package/lib/module/models.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/provider.js +182 -0
- package/lib/module/provider.js.map +1 -0
- package/lib/module/runtime.js +43 -0
- package/lib/module/runtime.js.map +1 -0
- package/lib/module/single-flight.js +23 -0
- package/lib/module/single-flight.js.map +1 -0
- package/lib/module/site-context.js +74 -0
- package/lib/module/site-context.js.map +1 -0
- package/lib/module/stores.js +66 -0
- package/lib/module/stores.js.map +1 -0
- package/lib/module/translations.js +42 -0
- package/lib/module/translations.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/auth.d.ts +31 -0
- package/lib/typescript/src/auth.d.ts.map +1 -0
- package/lib/typescript/src/client.d.ts +31 -0
- package/lib/typescript/src/client.d.ts.map +1 -0
- package/lib/typescript/src/config.d.ts +150 -0
- package/lib/typescript/src/config.d.ts.map +1 -0
- package/lib/typescript/src/converters.d.ts +17 -0
- package/lib/typescript/src/converters.d.ts.map +1 -0
- package/lib/typescript/src/create-config.d.ts +11 -0
- package/lib/typescript/src/create-config.d.ts.map +1 -0
- package/lib/typescript/src/endpoints.d.ts +36 -0
- package/lib/typescript/src/endpoints.d.ts.map +1 -0
- package/lib/typescript/src/errors.d.ts +43 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/i18n.d.ts +20 -0
- package/lib/typescript/src/i18n.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +17 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/media.d.ts +81 -0
- package/lib/typescript/src/media.d.ts.map +1 -0
- package/lib/typescript/src/models.d.ts +327 -0
- package/lib/typescript/src/models.d.ts.map +1 -0
- package/lib/typescript/src/provider.d.ts +37 -0
- package/lib/typescript/src/provider.d.ts.map +1 -0
- package/lib/typescript/src/runtime.d.ts +26 -0
- package/lib/typescript/src/runtime.d.ts.map +1 -0
- package/lib/typescript/src/single-flight.d.ts +7 -0
- package/lib/typescript/src/single-flight.d.ts.map +1 -0
- package/lib/typescript/src/site-context.d.ts +28 -0
- package/lib/typescript/src/site-context.d.ts.map +1 -0
- package/lib/typescript/src/stores.d.ts +54 -0
- package/lib/typescript/src/stores.d.ts.map +1 -0
- package/lib/typescript/src/translations.d.ts +40 -0
- package/lib/typescript/src/translations.d.ts.map +1 -0
- package/package.json +77 -0
- package/src/auth.ts +223 -0
- package/src/client.ts +133 -0
- package/src/config.ts +191 -0
- package/src/converters.ts +47 -0
- package/src/create-config.ts +29 -0
- package/src/endpoints.ts +133 -0
- package/src/errors.ts +104 -0
- package/src/i18n.ts +108 -0
- package/src/index.ts +123 -0
- package/src/media.ts +209 -0
- package/src/models.ts +384 -0
- package/src/provider.tsx +229 -0
- package/src/runtime.ts +57 -0
- package/src/single-flight.ts +23 -0
- package/src/site-context.ts +77 -0
- package/src/stores.ts +94 -0
- package/src/translations.ts +40 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { QueryClient, QueryClientProvider, focusManager, onlineManager, useQueryClient } from '@tanstack/react-query';
|
|
4
|
+
import * as Network from 'expo-network';
|
|
5
|
+
import { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore } from 'react';
|
|
6
|
+
import { AppState } from 'react-native';
|
|
7
|
+
import { createAuthClient } from "./auth.js";
|
|
8
|
+
import { createHttpClient } from "./client.js";
|
|
9
|
+
import { createConverterRegistry } from "./converters.js";
|
|
10
|
+
import { LaconiusHttpError } from "./errors.js";
|
|
11
|
+
import { createTranslator } from "./i18n.js";
|
|
12
|
+
import { setActiveRuntime } from "./runtime.js";
|
|
13
|
+
import { resolveCurrency, resolveLanguage, useSessionStore, useSiteContextStore } from "./stores.js";
|
|
14
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
15
|
+
const LaconiusContext = /*#__PURE__*/createContext(undefined);
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Fails loud at mount: without a backend the app does not exist, and failing at request forty
|
|
19
|
+
* only hides the cause. Individual unconfigured endpoints degrade through `isConfigured()`.
|
|
20
|
+
*/
|
|
21
|
+
function assertValidConfig(config) {
|
|
22
|
+
const missing = [];
|
|
23
|
+
if (!config.backend?.occ?.baseUrl) missing.push('backend.occ.baseUrl');
|
|
24
|
+
if (!config.backend?.occ?.baseSite) missing.push('backend.occ.baseSite');
|
|
25
|
+
if (config.auth) {
|
|
26
|
+
for (const key of ['clientId', 'redirectUri', 'authServerUrl']) {
|
|
27
|
+
if (!config.auth[key]) missing.push(`auth.${key}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (missing.length > 0) {
|
|
31
|
+
throw new Error(`[laconius] Incomplete configuration: ${missing.join(', ')} ${missing.length === 1 ? 'is' : 'are'} required.`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Retry policy of chapter 09, overridable through `queryClient.setQueryDefaults`. */
|
|
36
|
+
export function createDefaultQueryClient() {
|
|
37
|
+
return new QueryClient({
|
|
38
|
+
defaultOptions: {
|
|
39
|
+
queries: {
|
|
40
|
+
staleTime: 5 * 60_000,
|
|
41
|
+
gcTime: 30 * 60_000,
|
|
42
|
+
retry: (failureCount, error) => {
|
|
43
|
+
if (error instanceof LaconiusHttpError) {
|
|
44
|
+
// 401 is not retried here: the client already refreshes once and retries once.
|
|
45
|
+
if (error.status >= 400 && error.status < 500) return false;
|
|
46
|
+
}
|
|
47
|
+
return failureCount < 2;
|
|
48
|
+
},
|
|
49
|
+
retryDelay: attempt => Math.min(1000 * 2 ** attempt, 30_000)
|
|
50
|
+
},
|
|
51
|
+
// A retried `POST /entries` can double an order line.
|
|
52
|
+
mutations: {
|
|
53
|
+
retry: false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export function LaconiusProvider({
|
|
59
|
+
config,
|
|
60
|
+
children,
|
|
61
|
+
fallback = null
|
|
62
|
+
}) {
|
|
63
|
+
const runtime = useMemo(() => {
|
|
64
|
+
assertValidConfig(config);
|
|
65
|
+
const auth = createAuthClient(config);
|
|
66
|
+
const runtime = {
|
|
67
|
+
config,
|
|
68
|
+
auth,
|
|
69
|
+
client: createHttpClient(config, auth),
|
|
70
|
+
converters: createConverterRegistry(config)
|
|
71
|
+
};
|
|
72
|
+
setActiveRuntime(runtime);
|
|
73
|
+
return runtime;
|
|
74
|
+
}, [config]);
|
|
75
|
+
useEffect(() => () => setActiveRuntime(undefined), []);
|
|
76
|
+
const queryClient = useMemo(() => config.query?.queryClient ?? createDefaultQueryClient(), [config.query?.queryClient]);
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (config.query?.wireOnlineManager === false) return;
|
|
79
|
+
return onlineManager.setEventListener(setOnline => {
|
|
80
|
+
const subscription = Network.addNetworkStateListener(state => {
|
|
81
|
+
setOnline(state.isInternetReachable ?? state.isConnected ?? true);
|
|
82
|
+
});
|
|
83
|
+
return () => subscription.remove();
|
|
84
|
+
});
|
|
85
|
+
}, [config.query?.wireOnlineManager]);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (config.query?.wireFocusManager === false) return;
|
|
88
|
+
const subscription = AppState.addEventListener('change', status => focusManager.setFocused(status === 'active'));
|
|
89
|
+
return () => subscription.remove();
|
|
90
|
+
}, [config.query?.wireFocusManager]);
|
|
91
|
+
|
|
92
|
+
// Cold start: exchange the stored refresh token once, before the first authenticated call.
|
|
93
|
+
const [hydrated, setHydrated] = useState(false);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
let cancelled = false;
|
|
96
|
+
runtime.auth.hydrate().catch(error => config.onError?.(error, {})).finally(() => {
|
|
97
|
+
if (!cancelled) setHydrated(true);
|
|
98
|
+
});
|
|
99
|
+
return () => {
|
|
100
|
+
cancelled = true;
|
|
101
|
+
};
|
|
102
|
+
}, [runtime, config]);
|
|
103
|
+
return /*#__PURE__*/_jsx(LaconiusContext.Provider, {
|
|
104
|
+
value: runtime,
|
|
105
|
+
children: /*#__PURE__*/_jsx(QueryClientProvider, {
|
|
106
|
+
client: queryClient,
|
|
107
|
+
children: hydrated ? children : fallback
|
|
108
|
+
})
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
export function useLaconius() {
|
|
112
|
+
const runtime = useContext(LaconiusContext);
|
|
113
|
+
if (!runtime) {
|
|
114
|
+
throw new Error('[laconius] useLaconius must be used inside <LaconiusProvider>.');
|
|
115
|
+
}
|
|
116
|
+
return runtime;
|
|
117
|
+
}
|
|
118
|
+
export const useLaconiusConfig = () => useLaconius().config;
|
|
119
|
+
|
|
120
|
+
/** Re-renders on a language change, so a switch retranslates and refetches in one move. */
|
|
121
|
+
export function useTranslation() {
|
|
122
|
+
const {
|
|
123
|
+
config
|
|
124
|
+
} = useLaconius();
|
|
125
|
+
// Subscribed for the re-render; the value itself comes from `resolveLanguage`, which is where
|
|
126
|
+
// a stored value that the config no longer offers is dropped.
|
|
127
|
+
const language = useSiteContextStore(state => state.language);
|
|
128
|
+
return useMemo(() => createTranslator({
|
|
129
|
+
translations: config.i18n?.translations,
|
|
130
|
+
language: resolveLanguage(config) ?? 'en',
|
|
131
|
+
fallbackLanguage: config.i18n?.fallbackLanguage,
|
|
132
|
+
translate: config.i18n?.translate
|
|
133
|
+
}), [config, language]);
|
|
134
|
+
}
|
|
135
|
+
export function useSiteContext() {
|
|
136
|
+
const {
|
|
137
|
+
config
|
|
138
|
+
} = useLaconius();
|
|
139
|
+
// Subscriptions, not values: reading the store directly here would show a currency the client
|
|
140
|
+
// is no longer sending, because `resolveCurrency` drops one the config no longer offers.
|
|
141
|
+
useSiteContextStore(state => state.language);
|
|
142
|
+
useSiteContextStore(state => state.currency);
|
|
143
|
+
const setLanguage = useSiteContextStore(state => state.setLanguage);
|
|
144
|
+
const setCurrency = useSiteContextStore(state => state.setCurrency);
|
|
145
|
+
return {
|
|
146
|
+
language: resolveLanguage(config),
|
|
147
|
+
currency: resolveCurrency(config),
|
|
148
|
+
languages: config.context.languages,
|
|
149
|
+
currencies: config.context.currencies,
|
|
150
|
+
baseSite: config.backend.occ.baseSite,
|
|
151
|
+
setLanguage,
|
|
152
|
+
setCurrency
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** `true` while the session store holds an access token. */
|
|
157
|
+
export function useIsLoggedIn() {
|
|
158
|
+
return useSessionStore(state => Boolean(state.accessToken));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The app owns offline UI; the provider only wires `onlineManager`. */
|
|
162
|
+
export function useIsOnline() {
|
|
163
|
+
return useSyncExternalStore(onChange => onlineManager.subscribe(onChange), () => onlineManager.isOnline(), () => true);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Revoke, clear, and drop Laconius' queries — never `queryClient.clear()`, which would wipe the
|
|
168
|
+
* app's own. Site context and recently-viewed deliberately survive.
|
|
169
|
+
*/
|
|
170
|
+
export function useLogout() {
|
|
171
|
+
const {
|
|
172
|
+
auth
|
|
173
|
+
} = useLaconius();
|
|
174
|
+
const queryClient = useQueryClient();
|
|
175
|
+
return async () => {
|
|
176
|
+
await auth.logout();
|
|
177
|
+
queryClient.removeQueries({
|
|
178
|
+
queryKey: ['laconius']
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["QueryClient","QueryClientProvider","focusManager","onlineManager","useQueryClient","Network","createContext","useContext","useEffect","useMemo","useState","useSyncExternalStore","AppState","createAuthClient","createHttpClient","createConverterRegistry","LaconiusHttpError","createTranslator","setActiveRuntime","resolveCurrency","resolveLanguage","useSessionStore","useSiteContextStore","jsx","_jsx","LaconiusContext","undefined","assertValidConfig","config","missing","backend","occ","baseUrl","push","baseSite","auth","key","length","Error","join","createDefaultQueryClient","defaultOptions","queries","staleTime","gcTime","retry","failureCount","error","status","retryDelay","attempt","Math","min","mutations","LaconiusProvider","children","fallback","runtime","client","converters","queryClient","query","wireOnlineManager","setEventListener","setOnline","subscription","addNetworkStateListener","state","isInternetReachable","isConnected","remove","wireFocusManager","addEventListener","setFocused","hydrated","setHydrated","cancelled","hydrate","catch","onError","finally","Provider","value","useLaconius","useLaconiusConfig","useTranslation","language","translations","i18n","fallbackLanguage","translate","useSiteContext","currency","setLanguage","setCurrency","languages","context","currencies","useIsLoggedIn","Boolean","accessToken","useIsOnline","onChange","subscribe","isOnline","useLogout","logout","removeQueries","queryKey"],"sourceRoot":"../../src","sources":["provider.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { resolveCurrency, resolveLanguage } from "./stores.js";
|
|
4
|
+
|
|
5
|
+
/** Everything a query factory needs without a React context to read it from. */
|
|
6
|
+
|
|
7
|
+
let active;
|
|
8
|
+
|
|
9
|
+
/** Set by `LaconiusProvider` during render, so factories work before any effect runs. */
|
|
10
|
+
export function setActiveRuntime(runtime) {
|
|
11
|
+
active = runtime;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The runtime, for `queryOptions` factories used outside React (`prefetchQuery`,
|
|
16
|
+
* `ensureQueryData`).
|
|
17
|
+
*/
|
|
18
|
+
export function getRuntime() {
|
|
19
|
+
if (!active) {
|
|
20
|
+
throw new Error('[laconius] No LaconiusProvider is mounted. Wrap your app in <LaconiusProvider config={…}>.');
|
|
21
|
+
}
|
|
22
|
+
return active;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `['laconius', <feature>, { site, lang, curr, user }, ...args]`.
|
|
27
|
+
*
|
|
28
|
+
* The context object is in every key, including product: customer-group pricing depends on the
|
|
29
|
+
* user. The `'laconius'` prefix is what makes `removeQueries(['laconius'])` safe.
|
|
30
|
+
*/
|
|
31
|
+
export function laconiusQueryKey(feature, ...args) {
|
|
32
|
+
const {
|
|
33
|
+
config,
|
|
34
|
+
auth
|
|
35
|
+
} = getRuntime();
|
|
36
|
+
return ['laconius', feature, {
|
|
37
|
+
site: config.backend.occ.baseSite,
|
|
38
|
+
lang: resolveLanguage(config),
|
|
39
|
+
curr: resolveCurrency(config),
|
|
40
|
+
user: auth.getUserId()
|
|
41
|
+
}, ...args];
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["resolveCurrency","resolveLanguage","active","setActiveRuntime","runtime","getRuntime","Error","laconiusQueryKey","feature","args","config","auth","site","backend","occ","baseSite","lang","curr","user","getUserId"],"sourceRoot":"../../src","sources":["runtime.ts"],"mappings":";;AAIA,SAASA,eAAe,EAAEC,eAAe,QAAQ,aAAU;;AAE3D;;AAQA,IAAIC,MAAmC;;AAEvC;AACA,OAAO,SAASC,gBAAgBA,CAACC,OAAoC,EAAQ;EAC3EF,MAAM,GAAGE,OAAO;AAClB;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAAA,EAAoB;EAC5C,IAAI,CAACH,MAAM,EAAE;IACX,MAAM,IAAII,KAAK,CACb,4FACF,CAAC;EACH;EACA,OAAOJ,MAAM;AACf;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,gBAAgBA,CAC9BC,OAAe,EACf,GAAGC,IAAe,EACP;EACX,MAAM;IAAEC,MAAM;IAAEC;EAAK,CAAC,GAAGN,UAAU,CAAC,CAAC;EACrC,OAAO,CACL,UAAU,EACVG,OAAO,EACP;IACEI,IAAI,EAAEF,MAAM,CAACG,OAAO,CAACC,GAAG,CAACC,QAAQ;IACjCC,IAAI,EAAEf,eAAe,CAACS,MAAM,CAAC;IAC7BO,IAAI,EAAEjB,eAAe,CAACU,MAAM,CAAC;IAC7BQ,IAAI,EAAEP,IAAI,CAACQ,SAAS,CAAC;EACvB,CAAC,EACD,GAAGV,IAAI,CACR;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Collapses concurrent calls onto one in-flight promise: N 401s cause one refresh.
|
|
5
|
+
*
|
|
6
|
+
* The next call after settlement starts a fresh one.
|
|
7
|
+
*/
|
|
8
|
+
export function singleFlight(fn) {
|
|
9
|
+
let inFlight;
|
|
10
|
+
return () => {
|
|
11
|
+
if (!inFlight) {
|
|
12
|
+
const promise = fn();
|
|
13
|
+
inFlight = promise;
|
|
14
|
+
promise.finally(() => {
|
|
15
|
+
if (inFlight === promise) inFlight = undefined;
|
|
16
|
+
}).catch(() => {
|
|
17
|
+
// The caller owns the rejection; this chain exists only to clear the slot.
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return inFlight;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=single-flight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["singleFlight","fn","inFlight","promise","finally","undefined","catch"],"sourceRoot":"../../src","sources":["single-flight.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,YAAYA,CAAIC,EAAoB,EAAoB;EACtE,IAAIC,QAAgC;EAEpC,OAAO,MAAM;IACX,IAAI,CAACA,QAAQ,EAAE;MACb,MAAMC,OAAO,GAAGF,EAAE,CAAC,CAAC;MACpBC,QAAQ,GAAGC,OAAO;MAClBA,OAAO,CACJC,OAAO,CAAC,MAAM;QACb,IAAIF,QAAQ,KAAKC,OAAO,EAAED,QAAQ,GAAGG,SAAS;MAChD,CAAC,CAAC,CACDC,KAAK,CAAC,MAAM;QACX;MAAA,CACD,CAAC;IACN;IACA,OAAOJ,QAAQ;EACjB,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { queryOptions, useQuery } from '@tanstack/react-query';
|
|
4
|
+
import { getRuntime, laconiusQueryKey } from "./runtime.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Adapters are plain objects of functions, so overriding one call is a spread and replacing the
|
|
8
|
+
* whole object is the route to a non-OCC backend.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const defaultSiteContextAdapter = {
|
|
12
|
+
async loadBaseSites({
|
|
13
|
+
client,
|
|
14
|
+
converters
|
|
15
|
+
}) {
|
|
16
|
+
const response = await client.request({
|
|
17
|
+
endpoint: 'baseSites'
|
|
18
|
+
});
|
|
19
|
+
return converters.convertAll(response?.baseSites, 'baseSite');
|
|
20
|
+
},
|
|
21
|
+
async loadLanguages({
|
|
22
|
+
client,
|
|
23
|
+
converters
|
|
24
|
+
}) {
|
|
25
|
+
const response = await client.request({
|
|
26
|
+
endpoint: 'languages'
|
|
27
|
+
});
|
|
28
|
+
return converters.convertAll(response?.languages, 'language');
|
|
29
|
+
},
|
|
30
|
+
async loadCurrencies({
|
|
31
|
+
client,
|
|
32
|
+
converters
|
|
33
|
+
}) {
|
|
34
|
+
const response = await client.request({
|
|
35
|
+
endpoint: 'currencies'
|
|
36
|
+
});
|
|
37
|
+
return converters.convertAll(response?.currencies, 'currency');
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
function adapter(runtime) {
|
|
41
|
+
return {
|
|
42
|
+
...defaultSiteContextAdapter,
|
|
43
|
+
...runtime.config.backend.adapters?.siteContext
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** `queryOptions` factories, for `prefetchQuery` / `useSuspenseQuery` without forking Laconius. */
|
|
48
|
+
export const siteContextQueries = {
|
|
49
|
+
baseSites: () => queryOptions({
|
|
50
|
+
queryKey: laconiusQueryKey('siteContext', 'baseSites'),
|
|
51
|
+
queryFn: () => {
|
|
52
|
+
const runtime = getRuntime();
|
|
53
|
+
return adapter(runtime).loadBaseSites(runtime);
|
|
54
|
+
}
|
|
55
|
+
}),
|
|
56
|
+
languages: () => queryOptions({
|
|
57
|
+
queryKey: laconiusQueryKey('siteContext', 'languages'),
|
|
58
|
+
queryFn: () => {
|
|
59
|
+
const runtime = getRuntime();
|
|
60
|
+
return adapter(runtime).loadLanguages(runtime);
|
|
61
|
+
}
|
|
62
|
+
}),
|
|
63
|
+
currencies: () => queryOptions({
|
|
64
|
+
queryKey: laconiusQueryKey('siteContext', 'currencies'),
|
|
65
|
+
queryFn: () => {
|
|
66
|
+
const runtime = getRuntime();
|
|
67
|
+
return adapter(runtime).loadCurrencies(runtime);
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
};
|
|
71
|
+
export const useBaseSites = () => useQuery(siteContextQueries.baseSites());
|
|
72
|
+
export const useLanguages = () => useQuery(siteContextQueries.languages());
|
|
73
|
+
export const useCurrencies = () => useQuery(siteContextQueries.currencies());
|
|
74
|
+
//# sourceMappingURL=site-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["queryOptions","useQuery","getRuntime","laconiusQueryKey","defaultSiteContextAdapter","loadBaseSites","client","converters","response","request","endpoint","convertAll","baseSites","loadLanguages","languages","loadCurrencies","currencies","adapter","runtime","config","backend","adapters","siteContext","siteContextQueries","queryKey","queryFn","useBaseSites","useLanguages","useCurrencies"],"sourceRoot":"../../src","sources":["site-context.ts"],"mappings":";;AAAA,SAASA,YAAY,EAAEC,QAAQ,QAAQ,uBAAuB;AAG9D,SAASC,UAAU,EAAEC,gBAAgB,QAAQ,cAAW;;AAGxD;AACA;AACA;AACA;;AASA,OAAO,MAAMC,yBAA6C,GAAG;EAC3D,MAAMC,aAAaA,CAAC;IAAEC,MAAM;IAAEC;EAAW,CAAC,EAAE;IAC1C,MAAMC,QAAQ,GAAG,MAAMF,MAAM,CAACG,OAAO,CAAwB;MAC3DC,QAAQ,EAAE;IACZ,CAAC,CAAC;IACF,OAAOH,UAAU,CAACI,UAAU,CAAoBH,QAAQ,EAAEI,SAAS,EAAE,UAAU,CAAC;EAClF,CAAC;EACD,MAAMC,aAAaA,CAAC;IAAEP,MAAM;IAAEC;EAAW,CAAC,EAAE;IAC1C,MAAMC,QAAQ,GAAG,MAAMF,MAAM,CAACG,OAAO,CAAwB;MAC3DC,QAAQ,EAAE;IACZ,CAAC,CAAC;IACF,OAAOH,UAAU,CAACI,UAAU,CAAoBH,QAAQ,EAAEM,SAAS,EAAE,UAAU,CAAC;EAClF,CAAC;EACD,MAAMC,cAAcA,CAAC;IAAET,MAAM;IAAEC;EAAW,CAAC,EAAE;IAC3C,MAAMC,QAAQ,GAAG,MAAMF,MAAM,CAACG,OAAO,CAAwB;MAC3DC,QAAQ,EAAE;IACZ,CAAC,CAAC;IACF,OAAOH,UAAU,CAACI,UAAU,CAAoBH,QAAQ,EAAEQ,UAAU,EAAE,UAAU,CAAC;EACnF;AACF,CAAC;AAED,SAASC,OAAOA,CAACC,OAAwB,EAAsB;EAC7D,OAAO;IACL,GAAGd,yBAAyB;IAC5B,GAAGc,OAAO,CAACC,MAAM,CAACC,OAAO,CAACC,QAAQ,EAAEC;EACtC,CAAC;AACH;;AAEA;AACA,OAAO,MAAMC,kBAAkB,GAAG;EAChCX,SAAS,EAAEA,CAAA,KACTZ,YAAY,CAAC;IACXwB,QAAQ,EAAErB,gBAAgB,CAAC,aAAa,EAAE,WAAW,CAAC;IACtDsB,OAAO,EAAEA,CAAA,KAAM;MACb,MAAMP,OAAO,GAAGhB,UAAU,CAAC,CAAC;MAC5B,OAAOe,OAAO,CAACC,OAAO,CAAC,CAACb,aAAa,CAACa,OAAO,CAAC;IAChD;EACF,CAAC,CAAC;EACJJ,SAAS,EAAEA,CAAA,KACTd,YAAY,CAAC;IACXwB,QAAQ,EAAErB,gBAAgB,CAAC,aAAa,EAAE,WAAW,CAAC;IACtDsB,OAAO,EAAEA,CAAA,KAAM;MACb,MAAMP,OAAO,GAAGhB,UAAU,CAAC,CAAC;MAC5B,OAAOe,OAAO,CAACC,OAAO,CAAC,CAACL,aAAa,CAACK,OAAO,CAAC;IAChD;EACF,CAAC,CAAC;EACJF,UAAU,EAAEA,CAAA,KACVhB,YAAY,CAAC;IACXwB,QAAQ,EAAErB,gBAAgB,CAAC,aAAa,EAAE,YAAY,CAAC;IACvDsB,OAAO,EAAEA,CAAA,KAAM;MACb,MAAMP,OAAO,GAAGhB,UAAU,CAAC,CAAC;MAC5B,OAAOe,OAAO,CAACC,OAAO,CAAC,CAACH,cAAc,CAACG,OAAO,CAAC;IACjD;EACF,CAAC;AACL,CAAC;AAED,OAAO,MAAMQ,YAAY,GAAGA,CAAA,KAAMzB,QAAQ,CAACsB,kBAAkB,CAACX,SAAS,CAAC,CAAC,CAAC;AAC1E,OAAO,MAAMe,YAAY,GAAGA,CAAA,KAAM1B,QAAQ,CAACsB,kBAAkB,CAACT,SAAS,CAAC,CAAC,CAAC;AAC1E,OAAO,MAAMc,aAAa,GAAGA,CAAA,KAAM3B,QAAQ,CAACsB,kBAAkB,CAACP,UAAU,CAAC,CAAC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import AsyncStorage from 'expo-sqlite/kv-store';
|
|
4
|
+
import { create } from 'zustand';
|
|
5
|
+
import { createJSONStorage, persist } from 'zustand/middleware';
|
|
6
|
+
/** Not persisted: [ADR-0003](docs/adr/0003-refresh-token-in-the-keychain.md). */
|
|
7
|
+
export const useSessionStore = create(set => ({
|
|
8
|
+
setSession: ({
|
|
9
|
+
accessToken,
|
|
10
|
+
refreshToken,
|
|
11
|
+
expiresAt
|
|
12
|
+
}) => set({
|
|
13
|
+
accessToken,
|
|
14
|
+
refreshToken,
|
|
15
|
+
expiresAt
|
|
16
|
+
}),
|
|
17
|
+
clearSession: () => set({
|
|
18
|
+
accessToken: undefined,
|
|
19
|
+
refreshToken: undefined,
|
|
20
|
+
expiresAt: undefined
|
|
21
|
+
})
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
/** Derived, never stored. Spartacus needs a `UserIdService`; Zustand does not. */
|
|
25
|
+
export function selectUserId(state) {
|
|
26
|
+
return state.accessToken ? 'current' : 'anonymous';
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Base site is immutable config; language and currency are runtime state. Both are part of every
|
|
30
|
+
* query key and drive translation lookup, so a switch retranslates and refetches in one move.
|
|
31
|
+
*/
|
|
32
|
+
export const useSiteContextStore = create()(persist(set => ({
|
|
33
|
+
setLanguage: language => set({
|
|
34
|
+
language
|
|
35
|
+
}),
|
|
36
|
+
setCurrency: currency => set({
|
|
37
|
+
currency
|
|
38
|
+
})
|
|
39
|
+
}), {
|
|
40
|
+
name: 'laconius.siteContext',
|
|
41
|
+
storage: createJSONStorage(() => AsyncStorage),
|
|
42
|
+
partialize: state => ({
|
|
43
|
+
language: state.language,
|
|
44
|
+
currency: state.currency
|
|
45
|
+
})
|
|
46
|
+
}));
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A persisted value outlives the config that produced it: drop the base store's last currency and
|
|
50
|
+
* the app restores it on every cold start, and every OCC call answers `UnsupportedCurrencyError`
|
|
51
|
+
* with no way back. So a stored value counts only while the config still offers it.
|
|
52
|
+
*/
|
|
53
|
+
function stored(value, allowed) {
|
|
54
|
+
return value !== undefined && allowed.includes(value) ? value : undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Active language, falling back to config: the store starts empty until the app picks one. */
|
|
58
|
+
export function resolveLanguage(config) {
|
|
59
|
+
return stored(useSiteContextStore.getState().language, config.context.languages) ?? config.context.defaultLanguage ?? config.context.languages[0];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Active currency, falling back to config. */
|
|
63
|
+
export function resolveCurrency(config) {
|
|
64
|
+
return stored(useSiteContextStore.getState().currency, config.context.currencies) ?? config.context.defaultCurrency ?? config.context.currencies[0];
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=stores.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["AsyncStorage","create","createJSONStorage","persist","useSessionStore","set","setSession","accessToken","refreshToken","expiresAt","clearSession","undefined","selectUserId","state","useSiteContextStore","setLanguage","language","setCurrency","currency","name","storage","partialize","stored","value","allowed","includes","resolveLanguage","config","getState","context","languages","defaultLanguage","resolveCurrency","currencies","defaultCurrency"],"sourceRoot":"../../src","sources":["stores.ts"],"mappings":";;AAAA,OAAOA,YAAY,MAAM,sBAAsB;AAC/C,SAASC,MAAM,QAAQ,SAAS;AAChC,SAASC,iBAAiB,EAAEC,OAAO,QAAQ,oBAAoB;AAe/D;AACA,OAAO,MAAMC,eAAe,GAAGH,MAAM,CAAgBI,GAAG,KAAM;EAC5DC,UAAU,EAAEA,CAAC;IAAEC,WAAW;IAAEC,YAAY;IAAEC;EAAU,CAAC,KACnDJ,GAAG,CAAC;IAAEE,WAAW;IAAEC,YAAY;IAAEC;EAAU,CAAC,CAAC;EAC/CC,YAAY,EAAEA,CAAA,KACZL,GAAG,CAAC;IACFE,WAAW,EAAEI,SAAS;IACtBH,YAAY,EAAEG,SAAS;IACvBF,SAAS,EAAEE;EACb,CAAC;AACL,CAAC,CAAC,CAAC;;AAEH;AACA,OAAO,SAASC,YAAYA,CAACC,KAE5B,EAA2B;EAC1B,OAAOA,KAAK,CAACN,WAAW,GAAG,SAAS,GAAG,WAAW;AACpD;AASA;AACA;AACA;AACA;AACA,OAAO,MAAMO,mBAAmB,GAAGb,MAAM,CAAmB,CAAC,CAC3DE,OAAO,CACJE,GAAG,KAAM;EACRU,WAAW,EAAGC,QAAQ,IAAKX,GAAG,CAAC;IAAEW;EAAS,CAAC,CAAC;EAC5CC,WAAW,EAAGC,QAAQ,IAAKb,GAAG,CAAC;IAAEa;EAAS,CAAC;AAC7C,CAAC,CAAC,EACF;EACEC,IAAI,EAAE,sBAAsB;EAC5BC,OAAO,EAAElB,iBAAiB,CAAC,MAAMF,YAAY,CAAC;EAC9CqB,UAAU,EAAGR,KAAK,KAAM;IACtBG,QAAQ,EAAEH,KAAK,CAACG,QAAQ;IACxBE,QAAQ,EAAEL,KAAK,CAACK;EAClB,CAAC;AACH,CACF,CACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,SAASI,MAAMA,CAACC,KAAyB,EAAEC,OAAiB,EAAsB;EAChF,OAAOD,KAAK,KAAKZ,SAAS,IAAIa,OAAO,CAACC,QAAQ,CAACF,KAAK,CAAC,GAAGA,KAAK,GAAGZ,SAAS;AAC3E;;AAEA;AACA,OAAO,SAASe,eAAeA,CAACC,MAE/B,EAAsB;EACrB,OACEL,MAAM,CAACR,mBAAmB,CAACc,QAAQ,CAAC,CAAC,CAACZ,QAAQ,EAAEW,MAAM,CAACE,OAAO,CAACC,SAAS,CAAC,IACzEH,MAAM,CAACE,OAAO,CAACE,eAAe,IAC9BJ,MAAM,CAACE,OAAO,CAACC,SAAS,CAAC,CAAC,CAAC;AAE/B;;AAEA;AACA,OAAO,SAASE,eAAeA,CAACL,MAE/B,EAAsB;EACrB,OACEL,MAAM,CAACR,mBAAmB,CAACc,QAAQ,CAAC,CAAC,CAACV,QAAQ,EAAES,MAAM,CAACE,OAAO,CAACI,UAAU,CAAC,IAC1EN,MAAM,CAACE,OAAO,CAACK,eAAe,IAC9BP,MAAM,CAACE,OAAO,CAACI,UAAU,CAAC,CAAC,CAAC;AAEhC","ignoreList":[]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* English error strings, ported from Spartacus'
|
|
5
|
+
* `core-libs/assets/src/translations/en/common.json` (`httpHandlers.*`), minus the checkout and
|
|
6
|
+
* payment validation keys. Other languages are the app's: Spartacus ships 17 under
|
|
7
|
+
* `core-libs/assets/src/translations/<lang>/` and is Apache-2.0.
|
|
8
|
+
*/
|
|
9
|
+
export const defaultCoreTranslations = {
|
|
10
|
+
en: {
|
|
11
|
+
common: {
|
|
12
|
+
retry: 'Retry',
|
|
13
|
+
cancel: 'Cancel',
|
|
14
|
+
close: 'Close',
|
|
15
|
+
loading: 'Loading…'
|
|
16
|
+
},
|
|
17
|
+
errors: {
|
|
18
|
+
http: {
|
|
19
|
+
badRequest: 'The request could not be processed. Please check your input.',
|
|
20
|
+
unauthorized: 'Your session has expired. Please login again.',
|
|
21
|
+
forbidden: 'You are not authorized to perform this action. Please contact your administrator if you think this is a mistake.',
|
|
22
|
+
notFound: 'Item not found.',
|
|
23
|
+
conflict: 'Already exists.',
|
|
24
|
+
serverError: 'A server error occurred. Please try again later.',
|
|
25
|
+
offline: 'No connection. Please check your network and try again.',
|
|
26
|
+
unknown: 'An unknown error occurred.'
|
|
27
|
+
},
|
|
28
|
+
occ: {
|
|
29
|
+
InsufficientStockError: 'Not enough stock for this product.',
|
|
30
|
+
CartError: 'Cart errors occurred.',
|
|
31
|
+
CartEntryError: 'This cart entry could not be updated.',
|
|
32
|
+
UnknownIdentifierError: 'Item not found.',
|
|
33
|
+
CMSItemNotFoundError: 'This page is not available.',
|
|
34
|
+
ValidationError: 'Some of the information entered is not valid.',
|
|
35
|
+
DuplicateUidError: 'An account with this email address already exists.',
|
|
36
|
+
PasswordMismatchError: 'Old password incorrect.',
|
|
37
|
+
InvalidTokenError: 'Invalid code provided.'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=translations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["defaultCoreTranslations","en","common","retry","cancel","close","loading","errors","http","badRequest","unauthorized","forbidden","notFound","conflict","serverError","offline","unknown","occ","InsufficientStockError","CartError","CartEntryError","UnknownIdentifierError","CMSItemNotFoundError","ValidationError","DuplicateUidError","PasswordMismatchError","InvalidTokenError"],"sourceRoot":"../../src","sources":["translations.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,uBAAuB,GAAG;EACrCC,EAAE,EAAE;IACFC,MAAM,EAAE;MACNC,KAAK,EAAE,OAAO;MACdC,MAAM,EAAE,QAAQ;MAChBC,KAAK,EAAE,OAAO;MACdC,OAAO,EAAE;IACX,CAAC;IACDC,MAAM,EAAE;MACNC,IAAI,EAAE;QACJC,UAAU,EAAE,8DAA8D;QAC1EC,YAAY,EAAE,+CAA+C;QAC7DC,SAAS,EACP,kHAAkH;QACpHC,QAAQ,EAAE,iBAAiB;QAC3BC,QAAQ,EAAE,iBAAiB;QAC3BC,WAAW,EAAE,kDAAkD;QAC/DC,OAAO,EAAE,yDAAyD;QAClEC,OAAO,EAAE;MACX,CAAC;MACDC,GAAG,EAAE;QACHC,sBAAsB,EAAE,oCAAoC;QAC5DC,SAAS,EAAE,uBAAuB;QAClCC,cAAc,EAAE,uCAAuC;QACvDC,sBAAsB,EAAE,iBAAiB;QACzCC,oBAAoB,EAAE,6BAA6B;QACnDC,eAAe,EAAE,+CAA+C;QAChEC,iBAAiB,EAAE,oDAAoD;QACvEC,qBAAqB,EAAE,yBAAyB;QAChDC,iBAAiB,EAAE;MACrB;IACF;EACF;AACF,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as AuthSession from 'expo-auth-session';
|
|
2
|
+
import type { LaconiusConfig } from './config.js';
|
|
3
|
+
/** Refresh-token storage failed. Treated as "no stored session", never as a crash. */
|
|
4
|
+
export declare class SecureStorageError extends Error {
|
|
5
|
+
constructor(operation: string, cause: unknown);
|
|
6
|
+
}
|
|
7
|
+
export type TokenSet = {
|
|
8
|
+
accessToken: string;
|
|
9
|
+
refreshToken?: string;
|
|
10
|
+
/** Epoch milliseconds. */
|
|
11
|
+
expiresAt?: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Built from config, never from the server's discovery document: that document is wrong about
|
|
15
|
+
* its own server (it never advertises `none` for token endpoint auth, which demonstrably works).
|
|
16
|
+
*/
|
|
17
|
+
export declare function createDiscovery(authServerUrl: string): AuthSession.DiscoveryDocument;
|
|
18
|
+
export type AuthClient = {
|
|
19
|
+
/** Authorization Code + PKCE. Returns the token set, or `undefined` when the user cancelled. */
|
|
20
|
+
login: () => Promise<TokenSet | undefined>;
|
|
21
|
+
logout: () => Promise<void>;
|
|
22
|
+
/** Single-flight: concurrent callers share one token request. */
|
|
23
|
+
refresh: () => Promise<TokenSet | undefined>;
|
|
24
|
+
/** Cold start: read the stored refresh token and exchange it once. */
|
|
25
|
+
hydrate: () => Promise<TokenSet | undefined>;
|
|
26
|
+
/** Refreshes proactively when the access token is within 60s of expiry. */
|
|
27
|
+
getAccessToken: () => Promise<string | undefined>;
|
|
28
|
+
getUserId: () => string;
|
|
29
|
+
};
|
|
30
|
+
export declare function createAuthClient(config: LaconiusConfig): AuthClient;
|
|
31
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAGjD,OAAO,KAAK,EAAsB,cAAc,EAAE,MAAM,aAAU,CAAC;AAMnE,sFAAsF;AACtF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAK9C;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,GACpB,WAAW,CAAC,iBAAiB,CAO/B;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,gGAAgG;IAChG,KAAK,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC3C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,iEAAiE;IACjE,OAAO,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC7C,sEAAsE;IACtE,OAAO,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC7C,2EAA2E;IAC3E,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAClD,SAAS,EAAE,MAAM,MAAM,CAAC;CACzB,CAAC;AAIF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,UAAU,CAuKnE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AuthClient } from './auth.js';
|
|
2
|
+
import type { LaconiusConfig } from './config.js';
|
|
3
|
+
import { type EndpointResolver } from './endpoints.js';
|
|
4
|
+
export type LaconiusRequest = {
|
|
5
|
+
/** Endpoint key, resolved through `backend.occ.endpoints`. */
|
|
6
|
+
endpoint: string;
|
|
7
|
+
scope?: string;
|
|
8
|
+
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
9
|
+
urlParams?: Record<string, string | number>;
|
|
10
|
+
queryParams?: Record<string, string | number | boolean | undefined>;
|
|
11
|
+
/** Sent as JSON. */
|
|
12
|
+
body?: unknown;
|
|
13
|
+
/** Sent as `application/x-www-form-urlencoded` (OCC wants this for product reviews). */
|
|
14
|
+
form?: Record<string, string>;
|
|
15
|
+
headers?: Record<string, string>;
|
|
16
|
+
/** Skip the `Authorization` header even when a session exists. */
|
|
17
|
+
anonymous?: boolean;
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
};
|
|
20
|
+
export type LaconiusHttpClient = {
|
|
21
|
+
request<T>(options: LaconiusRequest): Promise<T>;
|
|
22
|
+
endpoints: EndpointResolver;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Lives outside React so refresh and session reads work from anywhere.
|
|
26
|
+
*
|
|
27
|
+
* `lang` and `curr` are appended here rather than by adapters — the same division Spartacus
|
|
28
|
+
* draws with an interceptor.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createHttpClient(config: LaconiusConfig, auth: AuthClient): LaconiusHttpClient;
|
|
31
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAQ,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAU,CAAC;AAC/C,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,gBAAa,CAAC;AAO5E,MAAM,MAAM,eAAe,GAAG;IAC5B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IACpE,oBAAoB;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kEAAkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACjD,SAAS,EAAE,gBAAgB,CAAC;CAC7B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,UAAU,GACf,kBAAkB,CAiFpB"}
|