@graph8/sdk 0.11.0 → 0.12.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 +51 -0
- package/dist/index.d.mts +226 -1
- package/dist/index.d.ts +226 -1
- package/dist/index.js +176 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +169 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2267,12 +2267,181 @@ var G8 = class {
|
|
|
2267
2267
|
}
|
|
2268
2268
|
};
|
|
2269
2269
|
var g8 = new G8();
|
|
2270
|
+
|
|
2271
|
+
// src/appTokens.ts
|
|
2272
|
+
var DEFAULT_APP_API = "https://be.graph8.com";
|
|
2273
|
+
function createTokenManager(args) {
|
|
2274
|
+
const now = args.now ?? (() => Date.now());
|
|
2275
|
+
const skewMs = args.refreshSkewMs ?? 6e4;
|
|
2276
|
+
let token = null;
|
|
2277
|
+
let expiresAtMs = 0;
|
|
2278
|
+
let inflight = null;
|
|
2279
|
+
const doRefresh = async () => {
|
|
2280
|
+
const resp = await args.refresh();
|
|
2281
|
+
token = resp.access_token;
|
|
2282
|
+
expiresAtMs = now() + Math.max(0, resp.expires_in) * 1e3;
|
|
2283
|
+
return token;
|
|
2284
|
+
};
|
|
2285
|
+
return {
|
|
2286
|
+
async getToken(force = false) {
|
|
2287
|
+
const stillFresh = !force && token !== null && now() < expiresAtMs - skewMs;
|
|
2288
|
+
if (stillFresh) return token;
|
|
2289
|
+
if (!inflight) {
|
|
2290
|
+
inflight = doRefresh().finally(() => {
|
|
2291
|
+
inflight = null;
|
|
2292
|
+
});
|
|
2293
|
+
}
|
|
2294
|
+
return inflight;
|
|
2295
|
+
},
|
|
2296
|
+
expiresAt() {
|
|
2297
|
+
return expiresAtMs;
|
|
2298
|
+
}
|
|
2299
|
+
};
|
|
2300
|
+
}
|
|
2301
|
+
function createAppRequester(args) {
|
|
2302
|
+
const { baseUrl, tokens, extraHeaders, fetchImpl, sleepImpl } = args;
|
|
2303
|
+
const appRequest = async (path, opts = {}) => {
|
|
2304
|
+
const headers = { ...extraHeaders ?? {}, ...opts.headers ?? {} };
|
|
2305
|
+
const reqOpts = { ...opts, headers, fetchImpl, sleepImpl };
|
|
2306
|
+
const token = await tokens.getToken();
|
|
2307
|
+
try {
|
|
2308
|
+
return await request(baseUrl, path, token, reqOpts);
|
|
2309
|
+
} catch (err) {
|
|
2310
|
+
if (err instanceof G8Error && err.status === 401) {
|
|
2311
|
+
const fresh = await tokens.getToken(true);
|
|
2312
|
+
return await request(baseUrl, path, fresh, reqOpts);
|
|
2313
|
+
}
|
|
2314
|
+
throw err;
|
|
2315
|
+
}
|
|
2316
|
+
};
|
|
2317
|
+
return appRequest;
|
|
2318
|
+
}
|
|
2319
|
+
async function exchangeBrowserToken(args) {
|
|
2320
|
+
const propelToken = await Promise.resolve(args.getPropelAuthToken());
|
|
2321
|
+
if (!propelToken) {
|
|
2322
|
+
throw new G8Error({
|
|
2323
|
+
message: "getPropelAuthToken() returned no token \u2014 cannot exchange a browser app session",
|
|
2324
|
+
status: 401,
|
|
2325
|
+
type: "app_token_invalid",
|
|
2326
|
+
code: "app_token_invalid"
|
|
2327
|
+
});
|
|
2328
|
+
}
|
|
2329
|
+
const resp = await request(
|
|
2330
|
+
args.baseUrl,
|
|
2331
|
+
"/api/v1/app-sessions/exchange",
|
|
2332
|
+
propelToken,
|
|
2333
|
+
{
|
|
2334
|
+
method: "POST",
|
|
2335
|
+
body: { app_id: args.appId, scopes: args.scopes ?? [] },
|
|
2336
|
+
fetchImpl: args.fetchImpl,
|
|
2337
|
+
sleepImpl: args.sleepImpl
|
|
2338
|
+
}
|
|
2339
|
+
);
|
|
2340
|
+
return resp.data ?? resp;
|
|
2341
|
+
}
|
|
2342
|
+
async function exchangeServiceToken(args) {
|
|
2343
|
+
const resp = await request(
|
|
2344
|
+
args.baseUrl,
|
|
2345
|
+
"/api/v1/service-token",
|
|
2346
|
+
"",
|
|
2347
|
+
{
|
|
2348
|
+
method: "POST",
|
|
2349
|
+
body: {
|
|
2350
|
+
client_id: args.clientId,
|
|
2351
|
+
client_secret: args.clientSecret,
|
|
2352
|
+
scopes: args.scopes ?? [],
|
|
2353
|
+
ttl_seconds: args.ttlSeconds ?? null
|
|
2354
|
+
},
|
|
2355
|
+
fetchImpl: args.fetchImpl,
|
|
2356
|
+
sleepImpl: args.sleepImpl
|
|
2357
|
+
}
|
|
2358
|
+
);
|
|
2359
|
+
return resp.data ?? resp;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
// src/appClient.ts
|
|
2363
|
+
function createGraph8AppClient(config) {
|
|
2364
|
+
if (typeof config?.getPropelAuthToken !== "function") {
|
|
2365
|
+
throw new Error(
|
|
2366
|
+
"createGraph8AppClient requires getPropelAuthToken() \u2014 a function returning the caller's PropelAuth token"
|
|
2367
|
+
);
|
|
2368
|
+
}
|
|
2369
|
+
const asRecord = config;
|
|
2370
|
+
if ("apiKey" in asRecord || "writeKey" in asRecord) {
|
|
2371
|
+
throw new Error(
|
|
2372
|
+
"createGraph8AppClient does not accept an org API key or write key in the browser \u2014 pass getPropelAuthToken() instead"
|
|
2373
|
+
);
|
|
2374
|
+
}
|
|
2375
|
+
const baseUrl = config.apiUrl || DEFAULT_APP_API;
|
|
2376
|
+
const tokens = createTokenManager({
|
|
2377
|
+
now: config.now,
|
|
2378
|
+
refreshSkewMs: config.refreshSkewMs,
|
|
2379
|
+
refresh: () => exchangeBrowserToken({
|
|
2380
|
+
baseUrl,
|
|
2381
|
+
appId: config.appId,
|
|
2382
|
+
scopes: config.scopes,
|
|
2383
|
+
getPropelAuthToken: config.getPropelAuthToken,
|
|
2384
|
+
fetchImpl: config.fetchImpl,
|
|
2385
|
+
sleepImpl: config.sleepImpl
|
|
2386
|
+
})
|
|
2387
|
+
});
|
|
2388
|
+
const req = createAppRequester({ baseUrl, tokens, fetchImpl: config.fetchImpl, sleepImpl: config.sleepImpl });
|
|
2389
|
+
return {
|
|
2390
|
+
appId: config.appId,
|
|
2391
|
+
tenantOrgId: config.tenantOrgId,
|
|
2392
|
+
request: req,
|
|
2393
|
+
getAppToken: (force = false) => tokens.getToken(force)
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2396
|
+
function createGraph8ServiceClient(config) {
|
|
2397
|
+
if (!config?.clientId || !config?.clientSecret) {
|
|
2398
|
+
throw new Error("createGraph8ServiceClient requires clientId and clientSecret");
|
|
2399
|
+
}
|
|
2400
|
+
if (!config?.tenantOrgId) {
|
|
2401
|
+
throw new Error(
|
|
2402
|
+
"createGraph8ServiceClient requires tenantOrgId \u2014 the single consented client org this backend acts for"
|
|
2403
|
+
);
|
|
2404
|
+
}
|
|
2405
|
+
const baseUrl = config.apiUrl || DEFAULT_APP_API;
|
|
2406
|
+
const tokens = createTokenManager({
|
|
2407
|
+
now: config.now,
|
|
2408
|
+
refreshSkewMs: config.refreshSkewMs,
|
|
2409
|
+
refresh: () => exchangeServiceToken({
|
|
2410
|
+
baseUrl,
|
|
2411
|
+
clientId: config.clientId,
|
|
2412
|
+
clientSecret: config.clientSecret,
|
|
2413
|
+
scopes: config.scopes,
|
|
2414
|
+
ttlSeconds: config.ttlSeconds,
|
|
2415
|
+
fetchImpl: config.fetchImpl,
|
|
2416
|
+
sleepImpl: config.sleepImpl
|
|
2417
|
+
})
|
|
2418
|
+
});
|
|
2419
|
+
const req = createAppRequester({
|
|
2420
|
+
baseUrl,
|
|
2421
|
+
tokens,
|
|
2422
|
+
extraHeaders: { "X-Target-Org-Id": config.tenantOrgId },
|
|
2423
|
+
fetchImpl: config.fetchImpl,
|
|
2424
|
+
sleepImpl: config.sleepImpl
|
|
2425
|
+
});
|
|
2426
|
+
return {
|
|
2427
|
+
tenantOrgId: config.tenantOrgId,
|
|
2428
|
+
request: req,
|
|
2429
|
+
getServiceToken: (force = false) => tokens.getToken(force)
|
|
2430
|
+
};
|
|
2431
|
+
}
|
|
2270
2432
|
export {
|
|
2433
|
+
DEFAULT_APP_API,
|
|
2271
2434
|
G8Error,
|
|
2272
2435
|
KNOWN_WEBHOOK_EVENTS,
|
|
2273
2436
|
WebhookSignatureError,
|
|
2274
2437
|
backoffDelayMs,
|
|
2275
2438
|
constructEvent,
|
|
2439
|
+
createAppRequester,
|
|
2440
|
+
createGraph8AppClient,
|
|
2441
|
+
createGraph8ServiceClient,
|
|
2442
|
+
createTokenManager,
|
|
2443
|
+
exchangeBrowserToken,
|
|
2444
|
+
exchangeServiceToken,
|
|
2276
2445
|
g8,
|
|
2277
2446
|
isRetryableStatus,
|
|
2278
2447
|
paginate,
|