@usequeek/app-sdk 0.5.0 → 0.6.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 +172 -16
- package/dist/app-auth.d.ts +23 -2
- package/dist/app-auth.d.ts.map +1 -1
- package/dist/app-auth.js +40 -6
- package/dist/app-auth.js.map +1 -1
- package/dist/auth-fetch.d.ts +90 -0
- package/dist/auth-fetch.d.ts.map +1 -0
- package/dist/auth-fetch.js +261 -0
- package/dist/auth-fetch.js.map +1 -0
- package/dist/client.d.ts +32 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6 -2
- package/dist/client.js.map +1 -1
- package/dist/frame.d.ts +233 -4
- package/dist/frame.d.ts.map +1 -1
- package/dist/frame.js +694 -19
- package/dist/frame.js.map +1 -1
- package/dist/handoff.d.ts +32 -2
- package/dist/handoff.d.ts.map +1 -1
- package/dist/handoff.js +2 -1
- package/dist/handoff.js.map +1 -1
- package/dist/hono.d.ts +13 -0
- package/dist/hono.d.ts.map +1 -1
- package/dist/hono.js +15 -0
- package/dist/hono.js.map +1 -1
- package/dist/index.d.ts +11 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -6
- package/dist/index.js.map +1 -1
- package/dist/install-handlers.d.ts +33 -8
- package/dist/install-handlers.d.ts.map +1 -1
- package/dist/install-handlers.js +133 -15
- package/dist/install-handlers.js.map +1 -1
- package/dist/merchant-schema.d.ts +1550 -68
- package/dist/merchant-schema.d.ts.map +1 -1
- package/dist/merchant-schema.js +1 -1
- package/dist/proxy.d.ts +122 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +204 -0
- package/dist/proxy.js.map +1 -0
- package/dist/react.d.ts +78 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +262 -0
- package/dist/react.js.map +1 -0
- package/dist/scopes.d.ts +174 -0
- package/dist/scopes.d.ts.map +1 -0
- package/dist/scopes.js +297 -0
- package/dist/scopes.js.map +1 -0
- package/dist/server.d.ts +2 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/session.d.ts +52 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +99 -12
- package/dist/session.js.map +1 -1
- package/dist/store.d.ts +33 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +114 -4
- package/dist/store.js.map +1 -1
- package/dist/theme.d.ts +96 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +158 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.d.ts +30 -15
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +57 -19
- package/dist/tokens.js.map +1 -1
- package/dist/webhooks.d.ts.map +1 -1
- package/dist/webhooks.js +1 -1
- package/dist/webhooks.js.map +1 -1
- package/package.json +17 -5
- package/CHANGELOG.md +0 -150
- package/openapi/merchant.json +0 -21452
package/dist/react.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/**
|
|
3
|
+
* Optional React bindings for `@usequeek/app-sdk` (U2).
|
|
4
|
+
*
|
|
5
|
+
* Import from `@usequeek/app-sdk/react` (requires the optional `react`
|
|
6
|
+
* peer) — a thin layer built ONLY on the framework-free core (`frame.js` /
|
|
7
|
+
* `theme.js`): `<QueekProvider>` owns one bridge subscription, and
|
|
8
|
+
* `useQueek()` exposes `{ toast, saveBar, title, navigate, pickResource,
|
|
9
|
+
* theme }` over it.
|
|
10
|
+
*
|
|
11
|
+
* No JSX in this file (the build stays plain `tsc`, no `jsx` flag).
|
|
12
|
+
*/
|
|
13
|
+
import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
14
|
+
import { listenToDashboard, sendNavigated, sendOpen, sendPickResource, sendReady, sendSaveBar, sendTitle, sendToast, } from "./frame.js";
|
|
15
|
+
import { applyTheme, getThemeModeFromUrl, rememberThemeMode, syncThemeUrl } from "./theme.js";
|
|
16
|
+
/** A pick with no dashboard answer settles after this long (never deadlocks). */
|
|
17
|
+
export const PICK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
18
|
+
/**
|
|
19
|
+
* How long after `ready` the provider waits for the dashboard's capability
|
|
20
|
+
* handshake (on its `theme` message) before treating the dashboard as legacy.
|
|
21
|
+
*/
|
|
22
|
+
export const HANDSHAKE_TIMEOUT_MS = 1500;
|
|
23
|
+
const QueekBridgeContext = createContext(null);
|
|
24
|
+
function globalWindow() {
|
|
25
|
+
const win = globalThis.window;
|
|
26
|
+
return win?.location !== undefined ? (win ?? null) : null;
|
|
27
|
+
}
|
|
28
|
+
function resolveConfig(props, win) {
|
|
29
|
+
return {
|
|
30
|
+
postTarget: props.postTarget ?? win?.parent,
|
|
31
|
+
listenTarget: props.listenTarget ?? win ?? undefined,
|
|
32
|
+
getHref: props.getHref ?? (() => win?.location.href ?? ""),
|
|
33
|
+
expectSource: props.expectSource !== undefined ? props.expectSource : (win?.parent ?? undefined),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function QueekProvider(props) {
|
|
37
|
+
const { dashboardOrigin, children, sdkVersion } = props;
|
|
38
|
+
const win = useMemo(() => globalWindow(), []);
|
|
39
|
+
// Capabilities keyed by content: a new inline array with the same entries
|
|
40
|
+
// keeps the subscription (and the single ready) stable.
|
|
41
|
+
const capKey = JSON.stringify(props.capabilities ?? []);
|
|
42
|
+
const capabilities = useMemo(() => JSON.parse(capKey), [capKey]);
|
|
43
|
+
// Latest wiring lives in a ref: parent re-renders (inline arrays, fresh
|
|
44
|
+
// closures) must NOT resubscribe the bridge or re-announce ready.
|
|
45
|
+
const configRef = useRef(resolveConfig(props, win));
|
|
46
|
+
configRef.current = resolveConfig(props, win);
|
|
47
|
+
// "light" until the mount effect reads the URL — the first render must
|
|
48
|
+
// match SSR to avoid a hydration mismatch.
|
|
49
|
+
const modeRef = useRef("light");
|
|
50
|
+
const themeHandlers = useRef(new Set());
|
|
51
|
+
const titleHandlers = useRef(new Set());
|
|
52
|
+
const saveBarHandlers = useRef(new Set());
|
|
53
|
+
const navigateHandlers = useRef(new Set());
|
|
54
|
+
const pendingPick = useRef(null);
|
|
55
|
+
const pickCounter = useRef(0);
|
|
56
|
+
// The dashboard's own capabilities, learned from its `theme` handshake.
|
|
57
|
+
// undefined = unknown; `legacy` flips when the handshake never arrives.
|
|
58
|
+
const dashboardCaps = useRef(undefined);
|
|
59
|
+
const handshakeLegacy = useRef(false);
|
|
60
|
+
const handshakeWaiters = useRef(new Set());
|
|
61
|
+
const flushHandshake = useCallback(() => {
|
|
62
|
+
const waiters = [...handshakeWaiters.current];
|
|
63
|
+
handshakeWaiters.current.clear();
|
|
64
|
+
for (const waiter of waiters) {
|
|
65
|
+
waiter(dashboardCaps.current);
|
|
66
|
+
}
|
|
67
|
+
}, []);
|
|
68
|
+
const settlePick = useCallback((value, requestId) => {
|
|
69
|
+
const pending = pendingPick.current;
|
|
70
|
+
// Stale answers (an earlier, timed-out pick) never settle the current one.
|
|
71
|
+
if (pending === null || requestId !== pending.requestId) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
pendingPick.current = null;
|
|
75
|
+
clearTimeout(pending.timer);
|
|
76
|
+
pending.resolve(value);
|
|
77
|
+
}, []);
|
|
78
|
+
const failPick = useCallback((error) => {
|
|
79
|
+
const pending = pendingPick.current;
|
|
80
|
+
pendingPick.current = null;
|
|
81
|
+
if (pending !== null) {
|
|
82
|
+
clearTimeout(pending.timer);
|
|
83
|
+
pending.reject(error);
|
|
84
|
+
}
|
|
85
|
+
}, []);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
const config = configRef.current;
|
|
88
|
+
dashboardCaps.current = undefined;
|
|
89
|
+
handshakeLegacy.current = false;
|
|
90
|
+
sendReady(dashboardOrigin, config.postTarget, { capabilities, sdkVersion });
|
|
91
|
+
const handshakeTimer = setTimeout(() => {
|
|
92
|
+
if (dashboardCaps.current === undefined) {
|
|
93
|
+
handshakeLegacy.current = true;
|
|
94
|
+
flushHandshake();
|
|
95
|
+
}
|
|
96
|
+
}, HANDSHAKE_TIMEOUT_MS);
|
|
97
|
+
handshakeTimer.unref?.();
|
|
98
|
+
// Sync the URL theme after mount (render stayed SSR-safe "light").
|
|
99
|
+
const initial = getThemeModeFromUrl(config.getHref());
|
|
100
|
+
rememberThemeMode(initial);
|
|
101
|
+
if (initial !== modeRef.current) {
|
|
102
|
+
modeRef.current = initial;
|
|
103
|
+
applyTheme(initial);
|
|
104
|
+
for (const handler of themeHandlers.current) {
|
|
105
|
+
handler(initial);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const stop = listenToDashboard({
|
|
109
|
+
dashboardOrigin,
|
|
110
|
+
target: config.listenTarget,
|
|
111
|
+
expectSource: config.expectSource ?? undefined,
|
|
112
|
+
onTheme: (theme) => {
|
|
113
|
+
modeRef.current = theme.mode;
|
|
114
|
+
applyTheme(theme.mode);
|
|
115
|
+
rememberThemeMode(theme.mode);
|
|
116
|
+
syncThemeUrl(theme.mode, { getHref: config.getHref });
|
|
117
|
+
for (const handler of themeHandlers.current) {
|
|
118
|
+
handler(theme.mode);
|
|
119
|
+
}
|
|
120
|
+
if (theme.capabilities !== undefined) {
|
|
121
|
+
clearTimeout(handshakeTimer);
|
|
122
|
+
dashboardCaps.current = theme.capabilities;
|
|
123
|
+
flushHandshake();
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
onTitleAction: (id) => {
|
|
127
|
+
for (const handler of titleHandlers.current) {
|
|
128
|
+
handler(id);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
onSaveBarAction: (action) => {
|
|
132
|
+
for (const handler of saveBarHandlers.current) {
|
|
133
|
+
handler(action);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
onNavigate: (path) => {
|
|
137
|
+
for (const handler of navigateHandlers.current) {
|
|
138
|
+
handler(path);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
onResourcePicked: (items, requestId) => settlePick(items, requestId),
|
|
142
|
+
onResourcePickCancelled: (requestId) => settlePick(null, requestId),
|
|
143
|
+
});
|
|
144
|
+
return () => {
|
|
145
|
+
clearTimeout(handshakeTimer);
|
|
146
|
+
handshakeWaiters.current.clear();
|
|
147
|
+
failPick(new Error("QueekProvider unmounted"));
|
|
148
|
+
stop();
|
|
149
|
+
};
|
|
150
|
+
}, [dashboardOrigin, capabilities, sdkVersion, flushHandshake, settlePick, failPick]);
|
|
151
|
+
const state = useMemo(() => ({
|
|
152
|
+
dashboardOrigin,
|
|
153
|
+
post: (send) => send(dashboardOrigin, configRef.current.postTarget),
|
|
154
|
+
subscribeTheme: (handler) => {
|
|
155
|
+
themeHandlers.current.add(handler);
|
|
156
|
+
return () => {
|
|
157
|
+
themeHandlers.current.delete(handler);
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
subscribeTitleAction: (handler) => {
|
|
161
|
+
titleHandlers.current.add(handler);
|
|
162
|
+
return () => {
|
|
163
|
+
titleHandlers.current.delete(handler);
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
subscribeSaveBarAction: (handler) => {
|
|
167
|
+
saveBarHandlers.current.add(handler);
|
|
168
|
+
return () => {
|
|
169
|
+
saveBarHandlers.current.delete(handler);
|
|
170
|
+
};
|
|
171
|
+
},
|
|
172
|
+
subscribeNavigate: (handler) => {
|
|
173
|
+
navigateHandlers.current.add(handler);
|
|
174
|
+
return () => {
|
|
175
|
+
navigateHandlers.current.delete(handler);
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
requestPick: (request) => {
|
|
179
|
+
// Validate BEFORE registering: an invalid request rejects at once
|
|
180
|
+
// and can never deadlock a later pick.
|
|
181
|
+
if (typeof request !== "object" ||
|
|
182
|
+
request === null ||
|
|
183
|
+
request.resourceType !== "product") {
|
|
184
|
+
return Promise.reject(new Error("pickResource supports product resources only"));
|
|
185
|
+
}
|
|
186
|
+
if (pendingPick.current !== null) {
|
|
187
|
+
return Promise.reject(new Error("pickResource already in progress"));
|
|
188
|
+
}
|
|
189
|
+
pickCounter.current += 1;
|
|
190
|
+
const requestId = `pick-${pickCounter.current}`;
|
|
191
|
+
return new Promise((resolve, reject) => {
|
|
192
|
+
const timer = setTimeout(() => {
|
|
193
|
+
failPick(new Error("pickResource timed out"));
|
|
194
|
+
}, PICK_TIMEOUT_MS);
|
|
195
|
+
timer.unref?.();
|
|
196
|
+
// Registered before the capability check so a second pick during the
|
|
197
|
+
// handshake wait is rejected as "in progress".
|
|
198
|
+
pendingPick.current = { requestId, resolve, reject, timer };
|
|
199
|
+
const dispatch = (caps) => {
|
|
200
|
+
if (pendingPick.current?.requestId !== requestId) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (caps === undefined || !caps.includes("pick-resource")) {
|
|
204
|
+
failPick(new Error("dashboard does not support pick-resource"));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
sendPickResource(dashboardOrigin, configRef.current.postTarget, { ...request, requestId });
|
|
208
|
+
};
|
|
209
|
+
if (dashboardCaps.current !== undefined) {
|
|
210
|
+
dispatch(dashboardCaps.current);
|
|
211
|
+
}
|
|
212
|
+
else if (handshakeLegacy.current) {
|
|
213
|
+
dispatch(undefined);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
handshakeWaiters.current.add(dispatch);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
currentMode: () => modeRef.current,
|
|
221
|
+
}), [dashboardOrigin, failPick]);
|
|
222
|
+
return createElement(QueekBridgeContext.Provider, { value: state }, children);
|
|
223
|
+
}
|
|
224
|
+
function useBridge() {
|
|
225
|
+
const bridge = useContext(QueekBridgeContext);
|
|
226
|
+
if (bridge === null) {
|
|
227
|
+
throw new Error("useQueek must be used inside <QueekProvider>");
|
|
228
|
+
}
|
|
229
|
+
return bridge;
|
|
230
|
+
}
|
|
231
|
+
/** Bridge actions + live theme over the framework-free core. */
|
|
232
|
+
export function useQueek() {
|
|
233
|
+
const bridge = useBridge();
|
|
234
|
+
const { post } = bridge;
|
|
235
|
+
// "light" first (matches SSR); the effect below syncs the live mode, so a
|
|
236
|
+
// dark URL theme never causes a hydration mismatch.
|
|
237
|
+
const [mode, setMode] = useState("light");
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
setMode(bridge.currentMode());
|
|
240
|
+
return bridge.subscribeTheme(setMode);
|
|
241
|
+
}, [bridge]);
|
|
242
|
+
const toast = useCallback((message, options) => {
|
|
243
|
+
post((origin, target) => sendToast(origin, target, message, options));
|
|
244
|
+
}, [post]);
|
|
245
|
+
const saveBar = useMemo(() => ({
|
|
246
|
+
dirty: () => post((origin, target) => sendSaveBar(origin, target, "dirty")),
|
|
247
|
+
clean: () => post((origin, target) => sendSaveBar(origin, target, "clean")),
|
|
248
|
+
onAction: (handler) => bridge.subscribeSaveBarAction(handler),
|
|
249
|
+
}), [bridge, post]);
|
|
250
|
+
const title = useMemo(() => ({
|
|
251
|
+
set: (heading, actions) => post((origin, target) => sendTitle(origin, target, heading, actions)),
|
|
252
|
+
onAction: (handler) => bridge.subscribeTitleAction(handler),
|
|
253
|
+
}), [bridge, post]);
|
|
254
|
+
const navigate = useMemo(() => ({
|
|
255
|
+
report: (path) => post((origin, target) => sendNavigated(origin, target, path)),
|
|
256
|
+
onNavigate: (handler) => bridge.subscribeNavigate(handler),
|
|
257
|
+
open: (openTarget) => post((origin, target) => sendOpen(origin, target, openTarget)),
|
|
258
|
+
}), [bridge, post]);
|
|
259
|
+
const pickResource = useCallback((request) => bridge.requestPick(request), [bridge]);
|
|
260
|
+
return useMemo(() => ({ toast, saveBar, title, navigate, pickResource, theme: { mode } }), [toast, saveBar, title, navigate, pickResource, mode]);
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"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"}
|
package/dist/scopes.d.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { QueekApiError } from "./client.js";
|
|
2
|
+
import type { InstallationStore } from "./store.js";
|
|
3
|
+
/**
|
|
4
|
+
* Optional scopes (plan item 6, Shopify `scopes.query / request / revoke`
|
|
5
|
+
* parity — symbol names cited only).
|
|
6
|
+
*
|
|
7
|
+
* - `queryScopes`: the cached effective grant split against the app's own
|
|
8
|
+
* declared-optional list. Store-read only, never a fetch: the app-credential
|
|
9
|
+
* surface exposes the effective grant but no declared-optional list, so
|
|
10
|
+
* the split needs the app's manifest knowledge (passed at client
|
|
11
|
+
* construction). No network, no guessing.
|
|
12
|
+
* - `requestScopes`: builds the dashboard deep link that opens the
|
|
13
|
+
* merchant's consent screen in the dashboard. The SDK never renders
|
|
14
|
+
* consent — it hands the app a link shaped like the bridge
|
|
15
|
+
* `open`/`navigate` targets (dashboard-relative path, or an absolute URL
|
|
16
|
+
* under a given dashboard origin) for the app to open via `sendOpen` or
|
|
17
|
+
* redirect to. The consent screen itself ships with the dashboard (plan
|
|
18
|
+
* item 8), which honours this link shape.
|
|
19
|
+
* - `revokeScopes`: `POST
|
|
20
|
+
* /api/v1/apps/installations/{installation}/scopes/revoke` with the app
|
|
21
|
+
* JWT (same credential as mint/resync — never auth:sanctum, never the
|
|
22
|
+
* installation token). Body `{scopes[]}` (1–50, backend
|
|
23
|
+
* `RevokeAppScopesRequest`); an `Idempotency-Key` rides the write for
|
|
24
|
+
* discipline (generated when the caller does not supply one — the client
|
|
25
|
+
* write discipline), though the route is naturally idempotent: revoking
|
|
26
|
+
* a never-granted optional scope is 200 with no change. Required scopes
|
|
27
|
+
* refuse 422 `app_scope_required` (surfaced as `AppScopeRequiredError`).
|
|
28
|
+
* On 200 the cached grant is refreshed from the response and the cached
|
|
29
|
+
* token dropped only when the grant moved (same compare-and-clear as the
|
|
30
|
+
* scopes_update handler — the backend rewrites live token rows in place,
|
|
31
|
+
* so the drop is backstop, not mechanism).
|
|
32
|
+
*
|
|
33
|
+
* Types here are hand-written: the revoke endpoint and the scopes_update
|
|
34
|
+
* handoff live on the app-credential surface, which the frozen
|
|
35
|
+
* `openapi/merchant.json` does not cover (types are generated app-side by
|
|
36
|
+
* `queek app codegen`; the merchant spec file is never hand-edited).
|
|
37
|
+
*/
|
|
38
|
+
/** 422 on the revoke endpoint: required scopes are never revocable (uninstall is the remedy). */
|
|
39
|
+
export declare const APP_SCOPE_REQUIRED_CODE = "app_scope_required";
|
|
40
|
+
/** 422 on the approve path: the scope is not declared by the live manifest version. */
|
|
41
|
+
export declare const APP_SCOPE_UNDECLARED_CODE = "app_scope_undeclared";
|
|
42
|
+
/** True for a required-scope refusal on the revoke endpoint (422 `app_scope_required`). */
|
|
43
|
+
export declare function isAppScopeRequired(status: number, code: string | undefined): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* A required-scope refusal, typed so callers switch on the class (or
|
|
46
|
+
* `code`), never on `message`. Carries the offending scopes when the
|
|
47
|
+
* backend named them.
|
|
48
|
+
*/
|
|
49
|
+
export declare class AppScopeRequiredError extends QueekApiError {
|
|
50
|
+
readonly scopes: string[];
|
|
51
|
+
constructor(status: number, message: string, scopes: string[]);
|
|
52
|
+
}
|
|
53
|
+
/** Build an `AppScopeRequiredError` from a parsed 422, tolerantly reading the named scopes. */
|
|
54
|
+
export declare function appScopeRequiredFromError(error: QueekApiError): AppScopeRequiredError;
|
|
55
|
+
/** Thrown when a scope list fails client-side validation — before any fetch. */
|
|
56
|
+
export declare class InvalidScopesError extends Error {
|
|
57
|
+
readonly code = "invalid_scopes";
|
|
58
|
+
constructor(message: string);
|
|
59
|
+
}
|
|
60
|
+
/** Backend `RevokeAppScopesRequest` bounds, mirrored client-side. */
|
|
61
|
+
export declare const MAX_SCOPE_LIST = 50;
|
|
62
|
+
export declare const MAX_SCOPE_LENGTH = 120;
|
|
63
|
+
/**
|
|
64
|
+
* Validate + normalise a scope list (trim, drop empties, dedupe keeping
|
|
65
|
+
* first order). Mirrors the backend contract (`required array min:1
|
|
66
|
+
* max:50`, string items) so a malformed call fails before any fetch.
|
|
67
|
+
*/
|
|
68
|
+
export declare function normaliseScopeList(scopes: unknown): string[];
|
|
69
|
+
/** The cached-grant split `queryScopes` returns. */
|
|
70
|
+
export interface InstallationScopes {
|
|
71
|
+
/** The cached effective grant (grant ∩ tracked manifest), as stored. */
|
|
72
|
+
granted: string[];
|
|
73
|
+
/** The granted scopes that are app-declared optional (granted ∩ declared list, granted order). */
|
|
74
|
+
optional: string[];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Split a cached grant against the app's declared-optional list (the app's
|
|
78
|
+
* own manifest knowledge). Pure — no store, no network.
|
|
79
|
+
*/
|
|
80
|
+
export declare function splitInstallationScopes(granted: string[], declaredOptional?: string[]): InstallationScopes;
|
|
81
|
+
/** App-API path of the revoke endpoint below the app base (sibling of the mint path). */
|
|
82
|
+
export declare function revokeScopesPath(installationId: string): string;
|
|
83
|
+
export interface ScopeRequestLinkOptions {
|
|
84
|
+
/** The app's dashboard slug (addresses the consent screen). */
|
|
85
|
+
appSlug: string;
|
|
86
|
+
/** Optional scopes to request (validated + normalised). */
|
|
87
|
+
scopes: string[];
|
|
88
|
+
/**
|
|
89
|
+
* Exact dashboard origin (e.g. from the embed query). When given, the
|
|
90
|
+
* link is absolute under it; otherwise dashboard-relative (the bridge
|
|
91
|
+
* `open` convention — resolves under the dashboard origin).
|
|
92
|
+
*/
|
|
93
|
+
dashboardOrigin?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Build the dashboard deep link that opens the merchant's consent screen
|
|
97
|
+
* in the dashboard. Pure — no store, no network. Shaped like the bridge
|
|
98
|
+
* `open` targets: a dashboard-relative path, or an absolute https URL
|
|
99
|
+
* under `dashboardOrigin` (refused exactly like `sendOpen` refuses a bad
|
|
100
|
+
* target).
|
|
101
|
+
*
|
|
102
|
+
* Link shape (the SDK↔dashboard contract the consent screen honours —
|
|
103
|
+
* the only query route the dashboard `AppsPage` serves):
|
|
104
|
+
* `/apps?app={slug}&view=scopes&scopes={a},{b}` (each scope
|
|
105
|
+
* URL-encoded, comma-separated). The link carries the slug + the scope
|
|
106
|
+
* list only: the dashboard resolves the installation from the signed-in
|
|
107
|
+
* store.
|
|
108
|
+
*/
|
|
109
|
+
export declare function buildScopeRequestLink(options: ScopeRequestLinkOptions): string;
|
|
110
|
+
/** Options for the cached-grant read. */
|
|
111
|
+
export interface QueryScopesOptions {
|
|
112
|
+
/** Per-call declared-optional list (wins over the client option). */
|
|
113
|
+
optionalScopes?: string[];
|
|
114
|
+
}
|
|
115
|
+
/** Options for the scope-request link. */
|
|
116
|
+
export interface RequestScopesLinkOptions {
|
|
117
|
+
/** Per-call app slug (wins over the client option). */
|
|
118
|
+
appSlug?: string;
|
|
119
|
+
/** Per-call dashboard origin (wins over the client option). */
|
|
120
|
+
dashboardOrigin?: string;
|
|
121
|
+
}
|
|
122
|
+
/** Options for the app-initiated revoke. */
|
|
123
|
+
export interface RevokeScopesOptions {
|
|
124
|
+
/** Write idempotency (generated when omitted — the client write discipline). */
|
|
125
|
+
idempotencyKey?: string;
|
|
126
|
+
signal?: AbortSignal;
|
|
127
|
+
}
|
|
128
|
+
export interface InstallationScopesClientOptions {
|
|
129
|
+
/** The installation UUID (addresses the revoke endpoint). */
|
|
130
|
+
installationId: string;
|
|
131
|
+
/** The installation row cache: query reads it, revoke refreshes it. */
|
|
132
|
+
store: InstallationStore;
|
|
133
|
+
/**
|
|
134
|
+
* A fresh app JWT per call — e.g. `() => provider.signJwt()`. The revoke
|
|
135
|
+
* endpoint takes the same app credential as mint/resync (never
|
|
136
|
+
* auth:sanctum, never the installation token).
|
|
137
|
+
*/
|
|
138
|
+
signJwt: () => string;
|
|
139
|
+
fetchImpl?: typeof fetch;
|
|
140
|
+
/** Sent as User-Agent. Defaults to `queek-app/1.0`. */
|
|
141
|
+
userAgent?: string;
|
|
142
|
+
/** Extra allowed `apiBase` hosts (test/local backends). */
|
|
143
|
+
allowedApiHosts?: string[];
|
|
144
|
+
/** The app's dashboard slug (addresses the scope-request consent screen); per-call override wins. */
|
|
145
|
+
appSlug?: string;
|
|
146
|
+
/**
|
|
147
|
+
* The app's manifest-declared optional scopes — the app's own knowledge
|
|
148
|
+
* (the app-credential surface exposes the effective grant but no
|
|
149
|
+
* declared list). Feeds the `queryScopes` split; per-call override wins.
|
|
150
|
+
*/
|
|
151
|
+
optionalScopes?: string[];
|
|
152
|
+
/** Exact dashboard origin for absolute scope-request links; per-call override wins. */
|
|
153
|
+
dashboardOrigin?: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The per-installation scopes session (Shopify `scopes.query / request /
|
|
157
|
+
* revoke` parity — symbol names cited only). A sibling of the installation
|
|
158
|
+
* client, not a method on it: the installation client's exact type is a
|
|
159
|
+
* committed contract (the generics compat guard), so the scopes surface
|
|
160
|
+
* lives here, wired to the same store + token provider.
|
|
161
|
+
*
|
|
162
|
+
* - `queryScopes` reads the cached grant (no network).
|
|
163
|
+
* - `requestScopes` builds the dashboard deep link the merchant approves
|
|
164
|
+
* at (pure — the SDK never renders consent).
|
|
165
|
+
* - `revokeScopes` calls the app-authenticated revoke endpoint and
|
|
166
|
+
* refreshes the cache.
|
|
167
|
+
*/
|
|
168
|
+
export interface InstallationScopesClient {
|
|
169
|
+
queryScopes(options?: QueryScopesOptions): Promise<InstallationScopes>;
|
|
170
|
+
requestScopes(scopes: string[], options?: RequestScopesLinkOptions): string;
|
|
171
|
+
revokeScopes(scopes: string[], options?: RevokeScopesOptions): Promise<string[]>;
|
|
172
|
+
}
|
|
173
|
+
export declare function createInstallationScopesClient(options: InstallationScopesClientOptions): InstallationScopesClient;
|
|
174
|
+
//# sourceMappingURL=scopes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../src/scopes.ts"],"names":[],"mappings":"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"}
|