@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/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,