@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.js
CHANGED
|
@@ -20,11 +20,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
DEFAULT_APP_API: () => DEFAULT_APP_API,
|
|
23
24
|
G8Error: () => G8Error,
|
|
24
25
|
KNOWN_WEBHOOK_EVENTS: () => KNOWN_WEBHOOK_EVENTS,
|
|
25
26
|
WebhookSignatureError: () => WebhookSignatureError,
|
|
26
27
|
backoffDelayMs: () => backoffDelayMs,
|
|
27
28
|
constructEvent: () => constructEvent,
|
|
29
|
+
createAppRequester: () => createAppRequester,
|
|
30
|
+
createGraph8AppClient: () => createGraph8AppClient,
|
|
31
|
+
createGraph8ServiceClient: () => createGraph8ServiceClient,
|
|
32
|
+
createTokenManager: () => createTokenManager,
|
|
33
|
+
exchangeBrowserToken: () => exchangeBrowserToken,
|
|
34
|
+
exchangeServiceToken: () => exchangeServiceToken,
|
|
28
35
|
g8: () => g8,
|
|
29
36
|
isRetryableStatus: () => isRetryableStatus,
|
|
30
37
|
paginate: () => paginate,
|
|
@@ -2302,13 +2309,182 @@ var G8 = class {
|
|
|
2302
2309
|
}
|
|
2303
2310
|
};
|
|
2304
2311
|
var g8 = new G8();
|
|
2312
|
+
|
|
2313
|
+
// src/appTokens.ts
|
|
2314
|
+
var DEFAULT_APP_API = "https://be.graph8.com";
|
|
2315
|
+
function createTokenManager(args) {
|
|
2316
|
+
const now = args.now ?? (() => Date.now());
|
|
2317
|
+
const skewMs = args.refreshSkewMs ?? 6e4;
|
|
2318
|
+
let token = null;
|
|
2319
|
+
let expiresAtMs = 0;
|
|
2320
|
+
let inflight = null;
|
|
2321
|
+
const doRefresh = async () => {
|
|
2322
|
+
const resp = await args.refresh();
|
|
2323
|
+
token = resp.access_token;
|
|
2324
|
+
expiresAtMs = now() + Math.max(0, resp.expires_in) * 1e3;
|
|
2325
|
+
return token;
|
|
2326
|
+
};
|
|
2327
|
+
return {
|
|
2328
|
+
async getToken(force = false) {
|
|
2329
|
+
const stillFresh = !force && token !== null && now() < expiresAtMs - skewMs;
|
|
2330
|
+
if (stillFresh) return token;
|
|
2331
|
+
if (!inflight) {
|
|
2332
|
+
inflight = doRefresh().finally(() => {
|
|
2333
|
+
inflight = null;
|
|
2334
|
+
});
|
|
2335
|
+
}
|
|
2336
|
+
return inflight;
|
|
2337
|
+
},
|
|
2338
|
+
expiresAt() {
|
|
2339
|
+
return expiresAtMs;
|
|
2340
|
+
}
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
function createAppRequester(args) {
|
|
2344
|
+
const { baseUrl, tokens, extraHeaders, fetchImpl, sleepImpl } = args;
|
|
2345
|
+
const appRequest = async (path, opts = {}) => {
|
|
2346
|
+
const headers = { ...extraHeaders ?? {}, ...opts.headers ?? {} };
|
|
2347
|
+
const reqOpts = { ...opts, headers, fetchImpl, sleepImpl };
|
|
2348
|
+
const token = await tokens.getToken();
|
|
2349
|
+
try {
|
|
2350
|
+
return await request(baseUrl, path, token, reqOpts);
|
|
2351
|
+
} catch (err) {
|
|
2352
|
+
if (err instanceof G8Error && err.status === 401) {
|
|
2353
|
+
const fresh = await tokens.getToken(true);
|
|
2354
|
+
return await request(baseUrl, path, fresh, reqOpts);
|
|
2355
|
+
}
|
|
2356
|
+
throw err;
|
|
2357
|
+
}
|
|
2358
|
+
};
|
|
2359
|
+
return appRequest;
|
|
2360
|
+
}
|
|
2361
|
+
async function exchangeBrowserToken(args) {
|
|
2362
|
+
const propelToken = await Promise.resolve(args.getPropelAuthToken());
|
|
2363
|
+
if (!propelToken) {
|
|
2364
|
+
throw new G8Error({
|
|
2365
|
+
message: "getPropelAuthToken() returned no token \u2014 cannot exchange a browser app session",
|
|
2366
|
+
status: 401,
|
|
2367
|
+
type: "app_token_invalid",
|
|
2368
|
+
code: "app_token_invalid"
|
|
2369
|
+
});
|
|
2370
|
+
}
|
|
2371
|
+
const resp = await request(
|
|
2372
|
+
args.baseUrl,
|
|
2373
|
+
"/api/v1/app-sessions/exchange",
|
|
2374
|
+
propelToken,
|
|
2375
|
+
{
|
|
2376
|
+
method: "POST",
|
|
2377
|
+
body: { app_id: args.appId, scopes: args.scopes ?? [] },
|
|
2378
|
+
fetchImpl: args.fetchImpl,
|
|
2379
|
+
sleepImpl: args.sleepImpl
|
|
2380
|
+
}
|
|
2381
|
+
);
|
|
2382
|
+
return resp.data ?? resp;
|
|
2383
|
+
}
|
|
2384
|
+
async function exchangeServiceToken(args) {
|
|
2385
|
+
const resp = await request(
|
|
2386
|
+
args.baseUrl,
|
|
2387
|
+
"/api/v1/service-token",
|
|
2388
|
+
"",
|
|
2389
|
+
{
|
|
2390
|
+
method: "POST",
|
|
2391
|
+
body: {
|
|
2392
|
+
client_id: args.clientId,
|
|
2393
|
+
client_secret: args.clientSecret,
|
|
2394
|
+
scopes: args.scopes ?? [],
|
|
2395
|
+
ttl_seconds: args.ttlSeconds ?? null
|
|
2396
|
+
},
|
|
2397
|
+
fetchImpl: args.fetchImpl,
|
|
2398
|
+
sleepImpl: args.sleepImpl
|
|
2399
|
+
}
|
|
2400
|
+
);
|
|
2401
|
+
return resp.data ?? resp;
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
// src/appClient.ts
|
|
2405
|
+
function createGraph8AppClient(config) {
|
|
2406
|
+
if (typeof config?.getPropelAuthToken !== "function") {
|
|
2407
|
+
throw new Error(
|
|
2408
|
+
"createGraph8AppClient requires getPropelAuthToken() \u2014 a function returning the caller's PropelAuth token"
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
const asRecord = config;
|
|
2412
|
+
if ("apiKey" in asRecord || "writeKey" in asRecord) {
|
|
2413
|
+
throw new Error(
|
|
2414
|
+
"createGraph8AppClient does not accept an org API key or write key in the browser \u2014 pass getPropelAuthToken() instead"
|
|
2415
|
+
);
|
|
2416
|
+
}
|
|
2417
|
+
const baseUrl = config.apiUrl || DEFAULT_APP_API;
|
|
2418
|
+
const tokens = createTokenManager({
|
|
2419
|
+
now: config.now,
|
|
2420
|
+
refreshSkewMs: config.refreshSkewMs,
|
|
2421
|
+
refresh: () => exchangeBrowserToken({
|
|
2422
|
+
baseUrl,
|
|
2423
|
+
appId: config.appId,
|
|
2424
|
+
scopes: config.scopes,
|
|
2425
|
+
getPropelAuthToken: config.getPropelAuthToken,
|
|
2426
|
+
fetchImpl: config.fetchImpl,
|
|
2427
|
+
sleepImpl: config.sleepImpl
|
|
2428
|
+
})
|
|
2429
|
+
});
|
|
2430
|
+
const req = createAppRequester({ baseUrl, tokens, fetchImpl: config.fetchImpl, sleepImpl: config.sleepImpl });
|
|
2431
|
+
return {
|
|
2432
|
+
appId: config.appId,
|
|
2433
|
+
tenantOrgId: config.tenantOrgId,
|
|
2434
|
+
request: req,
|
|
2435
|
+
getAppToken: (force = false) => tokens.getToken(force)
|
|
2436
|
+
};
|
|
2437
|
+
}
|
|
2438
|
+
function createGraph8ServiceClient(config) {
|
|
2439
|
+
if (!config?.clientId || !config?.clientSecret) {
|
|
2440
|
+
throw new Error("createGraph8ServiceClient requires clientId and clientSecret");
|
|
2441
|
+
}
|
|
2442
|
+
if (!config?.tenantOrgId) {
|
|
2443
|
+
throw new Error(
|
|
2444
|
+
"createGraph8ServiceClient requires tenantOrgId \u2014 the single consented client org this backend acts for"
|
|
2445
|
+
);
|
|
2446
|
+
}
|
|
2447
|
+
const baseUrl = config.apiUrl || DEFAULT_APP_API;
|
|
2448
|
+
const tokens = createTokenManager({
|
|
2449
|
+
now: config.now,
|
|
2450
|
+
refreshSkewMs: config.refreshSkewMs,
|
|
2451
|
+
refresh: () => exchangeServiceToken({
|
|
2452
|
+
baseUrl,
|
|
2453
|
+
clientId: config.clientId,
|
|
2454
|
+
clientSecret: config.clientSecret,
|
|
2455
|
+
scopes: config.scopes,
|
|
2456
|
+
ttlSeconds: config.ttlSeconds,
|
|
2457
|
+
fetchImpl: config.fetchImpl,
|
|
2458
|
+
sleepImpl: config.sleepImpl
|
|
2459
|
+
})
|
|
2460
|
+
});
|
|
2461
|
+
const req = createAppRequester({
|
|
2462
|
+
baseUrl,
|
|
2463
|
+
tokens,
|
|
2464
|
+
extraHeaders: { "X-Target-Org-Id": config.tenantOrgId },
|
|
2465
|
+
fetchImpl: config.fetchImpl,
|
|
2466
|
+
sleepImpl: config.sleepImpl
|
|
2467
|
+
});
|
|
2468
|
+
return {
|
|
2469
|
+
tenantOrgId: config.tenantOrgId,
|
|
2470
|
+
request: req,
|
|
2471
|
+
getServiceToken: (force = false) => tokens.getToken(force)
|
|
2472
|
+
};
|
|
2473
|
+
}
|
|
2305
2474
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2306
2475
|
0 && (module.exports = {
|
|
2476
|
+
DEFAULT_APP_API,
|
|
2307
2477
|
G8Error,
|
|
2308
2478
|
KNOWN_WEBHOOK_EVENTS,
|
|
2309
2479
|
WebhookSignatureError,
|
|
2310
2480
|
backoffDelayMs,
|
|
2311
2481
|
constructEvent,
|
|
2482
|
+
createAppRequester,
|
|
2483
|
+
createGraph8AppClient,
|
|
2484
|
+
createGraph8ServiceClient,
|
|
2485
|
+
createTokenManager,
|
|
2486
|
+
exchangeBrowserToken,
|
|
2487
|
+
exchangeServiceToken,
|
|
2312
2488
|
g8,
|
|
2313
2489
|
isRetryableStatus,
|
|
2314
2490
|
paginate,
|