@geekmidas/client 10.0.0-alpha.9 → 10.0.0-alpha.91
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 +40 -57
- package/dist/auth-fetcher.cjs +78 -3
- package/dist/auth-fetcher.cjs.map +1 -0
- package/dist/auth-fetcher.d.cts +156 -3
- package/dist/auth-fetcher.d.cts.map +1 -0
- package/dist/auth-fetcher.d.mts +156 -3
- package/dist/auth-fetcher.d.mts.map +1 -0
- package/dist/auth-fetcher.mjs +77 -3
- package/dist/auth-fetcher.mjs.map +1 -0
- package/dist/endpoint-hooks.cjs +11 -15
- package/dist/endpoint-hooks.cjs.map +1 -1
- package/dist/endpoint-hooks.d.cts +4 -7
- package/dist/endpoint-hooks.d.cts.map +1 -1
- package/dist/endpoint-hooks.d.mts +4 -7
- package/dist/endpoint-hooks.d.mts.map +1 -1
- package/dist/endpoint-hooks.mjs +5 -9
- package/dist/endpoint-hooks.mjs.map +1 -1
- package/dist/fetcher.cjs +115 -3
- package/dist/fetcher.cjs.map +1 -0
- package/dist/fetcher.d.cts +24 -3
- package/dist/fetcher.d.cts.map +1 -0
- package/dist/fetcher.d.mts +24 -3
- package/dist/fetcher.d.mts.map +1 -0
- package/dist/fetcher.mjs +90 -2
- package/dist/fetcher.mjs.map +1 -0
- package/dist/index.cjs +13 -6
- package/dist/index.d.cts +7 -5
- package/dist/index.d.mts +7 -5
- package/dist/index.mjs +7 -6
- package/dist/infer.cjs +0 -1
- package/dist/infer.d.cts +130 -2
- package/dist/infer.d.cts.map +1 -0
- package/dist/infer.d.mts +130 -2
- package/dist/infer.d.mts.map +1 -0
- package/dist/infer.mjs +1 -1
- package/dist/methods.cjs +21 -0
- package/dist/methods.cjs.map +1 -0
- package/dist/methods.d.cts +23 -0
- package/dist/methods.d.cts.map +1 -0
- package/dist/methods.d.mts +23 -0
- package/dist/methods.d.mts.map +1 -0
- package/dist/methods.mjs +19 -0
- package/dist/methods.mjs.map +1 -0
- package/dist/openapi-hooks.cjs +13 -16
- package/dist/openapi-hooks.cjs.map +1 -1
- package/dist/openapi-hooks.d.cts +8 -11
- package/dist/openapi-hooks.d.cts.map +1 -1
- package/dist/openapi-hooks.d.mts +8 -11
- package/dist/openapi-hooks.d.mts.map +1 -1
- package/dist/openapi-hooks.mjs +9 -12
- package/dist/openapi-hooks.mjs.map +1 -1
- package/dist/openapi-types.d.cts +5 -6
- package/dist/openapi-types.d.cts.map +1 -1
- package/dist/openapi-types.d.mts +5 -6
- package/dist/openapi-types.d.mts.map +1 -1
- package/dist/react-query.cjs +17 -16
- package/dist/react-query.cjs.map +1 -1
- package/dist/react-query.d.cts +12 -17
- package/dist/react-query.d.cts.map +1 -1
- package/dist/react-query.d.mts +12 -17
- package/dist/react-query.d.mts.map +1 -1
- package/dist/react-query.mjs +10 -9
- package/dist/react-query.mjs.map +1 -1
- package/dist/telemetry-g3BE86Wd.d.cts +68 -0
- package/dist/telemetry-g3BE86Wd.d.cts.map +1 -0
- package/dist/telemetry-g3BE86Wd.d.mts +68 -0
- package/dist/telemetry-g3BE86Wd.d.mts.map +1 -0
- package/dist/telemetry.cjs +128 -0
- package/dist/telemetry.cjs.map +1 -0
- package/dist/telemetry.d.cts +2 -0
- package/dist/telemetry.d.mts +2 -0
- package/dist/telemetry.mjs +125 -0
- package/dist/telemetry.mjs.map +1 -0
- package/dist/types.cjs +0 -1
- package/dist/types.d.cts +122 -2
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +122 -2
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +1 -1
- package/package.json +22 -9
- package/dist/auth-fetcher-CBYuL6rx.d.cts +0 -158
- package/dist/auth-fetcher-CBYuL6rx.d.cts.map +0 -1
- package/dist/auth-fetcher-DOj0iz21.mjs +0 -77
- package/dist/auth-fetcher-DOj0iz21.mjs.map +0 -1
- package/dist/auth-fetcher-DxS8zOLc.d.mts +0 -158
- package/dist/auth-fetcher-DxS8zOLc.d.mts.map +0 -1
- package/dist/auth-fetcher-HILABmws.cjs +0 -82
- package/dist/auth-fetcher-HILABmws.cjs.map +0 -1
- package/dist/chunk-CUT6urMc.cjs +0 -30
- package/dist/fetcher-C1xtCKpT.d.mts +0 -25
- package/dist/fetcher-C1xtCKpT.d.mts.map +0 -1
- package/dist/fetcher-CakjC9C7.mjs +0 -88
- package/dist/fetcher-CakjC9C7.mjs.map +0 -1
- package/dist/fetcher-CwnSqc4D.cjs +0 -100
- package/dist/fetcher-CwnSqc4D.cjs.map +0 -1
- package/dist/fetcher-cDrfwN-Y.d.cts +0 -25
- package/dist/fetcher-cDrfwN-Y.d.cts.map +0 -1
- package/dist/infer-6KKCgmg1.cjs +0 -0
- package/dist/infer-CPRqfabW.d.cts +0 -133
- package/dist/infer-CPRqfabW.d.cts.map +0 -1
- package/dist/infer-D9CgpOuc.d.mts +0 -133
- package/dist/infer-D9CgpOuc.d.mts.map +0 -1
- package/dist/infer-uCUq1whM.mjs +0 -0
- package/dist/openapi.cjs +0 -526
- package/dist/openapi.cjs.map +0 -1
- package/dist/openapi.mjs +0 -501
- package/dist/openapi.mjs.map +0 -1
- package/dist/types-BH8WgGrm.mjs +0 -0
- package/dist/types-BMGM6sZc.d.mts +0 -110
- package/dist/types-BMGM6sZc.d.mts.map +0 -1
- package/dist/types-DMQMHePI.d.cts +0 -110
- package/dist/types-DMQMHePI.d.cts.map +0 -1
- package/dist/types-a8gm_IaQ.cjs +0 -0
package/README.md
CHANGED
|
@@ -40,8 +40,8 @@ import { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';
|
|
|
40
40
|
// React Query client (class-based)
|
|
41
41
|
import { createTypedQueryClient } from '@geekmidas/client/react-query';
|
|
42
42
|
|
|
43
|
-
// OpenAPI hooks
|
|
44
|
-
import {
|
|
43
|
+
// OpenAPI hooks from a paths type
|
|
44
|
+
import { createOpenAPIHooks } from '@geekmidas/client/openapi';
|
|
45
45
|
|
|
46
46
|
// Type utilities
|
|
47
47
|
import type { TypedApiFunction, FilteredRequestConfig } from '@geekmidas/client/types';
|
|
@@ -76,7 +76,7 @@ interface API {
|
|
|
76
76
|
email: string;
|
|
77
77
|
};
|
|
78
78
|
};
|
|
79
|
-
'GET /users
|
|
79
|
+
'GET /users/{id}': {
|
|
80
80
|
params: {
|
|
81
81
|
id: string;
|
|
82
82
|
};
|
|
@@ -102,7 +102,7 @@ const user = await api('POST /users', {
|
|
|
102
102
|
});
|
|
103
103
|
// user is typed as { id: string; name: string; email: string }
|
|
104
104
|
|
|
105
|
-
const singleUser = await api('GET /users
|
|
105
|
+
const singleUser = await api('GET /users/{id}', {
|
|
106
106
|
params: { id: '123' }
|
|
107
107
|
});
|
|
108
108
|
// singleUser is typed as { id: string; name: string; email: string }
|
|
@@ -280,6 +280,26 @@ function CreateUser() {
|
|
|
280
280
|
}
|
|
281
281
|
```
|
|
282
282
|
|
|
283
|
+
### Method Calls
|
|
284
|
+
|
|
285
|
+
Every client also answers by method — the same request as
|
|
286
|
+
`api('POST /users', …)`, with the method as the call:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
await api.get('/health'); // declares nothing → no second argument
|
|
290
|
+
await api.get('/users/{id}', { params: { id: '123' } }); // path params → argument required
|
|
291
|
+
await api.post('/users', { body: { name: 'Ada', email } }); // body → argument required
|
|
292
|
+
await api.get('/search', { query: { q: 'ada' } }); // required query key → required
|
|
293
|
+
await api.get('/users', { query: { page: 2 } }); // optional query → optional
|
|
294
|
+
|
|
295
|
+
await api.post('/users', { body: { name: 'Ada' } }); // ❌ `email` is missing
|
|
296
|
+
await api.get('/health', { body: {} }); // ❌ GET /health takes no body
|
|
297
|
+
await api.post('/health'); // ❌ /health has no POST
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
The route autocompletes per method — only routes with a `POST` appear in
|
|
301
|
+
`api.post` — and the second argument has only the keys the endpoint declares.
|
|
302
|
+
|
|
283
303
|
### Type-Safe Config Requirements
|
|
284
304
|
|
|
285
305
|
The generated client enforces config requirements at the type level:
|
|
@@ -379,48 +399,11 @@ const api = Object.assign(fetcher, hooks);
|
|
|
379
399
|
|
|
380
400
|
## OpenAPI Code Generation
|
|
381
401
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
# Programmatic usage
|
|
389
|
-
import { generateReactQueryHooks } from '@geekmidas/client/openapi';
|
|
390
|
-
import fs from 'fs/promises';
|
|
391
|
-
|
|
392
|
-
const spec = JSON.parse(await fs.readFile('api-docs.json', 'utf-8'));
|
|
393
|
-
const code = await generateReactQueryHooks(spec);
|
|
394
|
-
await fs.writeFile('./src/api/generated.ts', code);
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
Generated hooks example:
|
|
398
|
-
|
|
399
|
-
```typescript
|
|
400
|
-
// Generated from OpenAPI spec
|
|
401
|
-
export const api = createTypedQueryClient<{
|
|
402
|
-
'GET /users': {
|
|
403
|
-
response: User[];
|
|
404
|
-
};
|
|
405
|
-
'POST /users': {
|
|
406
|
-
body: CreateUserRequest;
|
|
407
|
-
response: User;
|
|
408
|
-
};
|
|
409
|
-
// ... all your endpoints
|
|
410
|
-
}>({
|
|
411
|
-
baseUrl: process.env.REACT_APP_API_URL
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
// Use generated hooks
|
|
415
|
-
function MyComponent() {
|
|
416
|
-
const { data: users } = api.useQuery('GET /users');
|
|
417
|
-
const createUser = api.useMutation('POST /users');
|
|
418
|
-
|
|
419
|
-
return (
|
|
420
|
-
// Your component
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
|
-
```
|
|
402
|
+
Each surface's typed client is written by `gkm build` (and kept current by
|
|
403
|
+
`gkm dev`) to the workspace root's `.gkm/client/<surface>.ts`, imported as
|
|
404
|
+
`@<name>/client/<surface>`: its `createApi()` returns a typed
|
|
405
|
+
fetcher with React Query hooks, built from the endpoints themselves rather
|
|
406
|
+
than from a spec file.
|
|
424
407
|
|
|
425
408
|
## Advanced Features
|
|
426
409
|
|
|
@@ -433,14 +416,14 @@ Type-safe cache invalidation:
|
|
|
433
416
|
await api.invalidateQueries('GET /users');
|
|
434
417
|
|
|
435
418
|
// Invalidate with params
|
|
436
|
-
await api.invalidateQueries('GET /users
|
|
419
|
+
await api.invalidateQueries('GET /users/{id}', {
|
|
437
420
|
params: { id: '123' }
|
|
438
421
|
});
|
|
439
422
|
|
|
440
423
|
// Invalidate multiple queries
|
|
441
424
|
await Promise.all([
|
|
442
425
|
api.invalidateQueries('GET /users'),
|
|
443
|
-
api.invalidateQueries('GET /users
|
|
426
|
+
api.invalidateQueries('GET /users/{id}')
|
|
444
427
|
]);
|
|
445
428
|
```
|
|
446
429
|
|
|
@@ -449,20 +432,20 @@ await Promise.all([
|
|
|
449
432
|
Implement optimistic UI updates:
|
|
450
433
|
|
|
451
434
|
```typescript
|
|
452
|
-
const updateUser = api.useMutation('PUT /users
|
|
435
|
+
const updateUser = api.useMutation('PUT /users/{id}', {
|
|
453
436
|
onMutate: async (variables) => {
|
|
454
437
|
// Cancel outgoing refetches
|
|
455
|
-
await api.cancelQueries('GET /users
|
|
438
|
+
await api.cancelQueries('GET /users/{id}', {
|
|
456
439
|
params: { id: variables.params.id }
|
|
457
440
|
});
|
|
458
441
|
|
|
459
442
|
// Snapshot previous value
|
|
460
|
-
const previousUser = api.getQueryData('GET /users
|
|
443
|
+
const previousUser = api.getQueryData('GET /users/{id}', {
|
|
461
444
|
params: { id: variables.params.id }
|
|
462
445
|
});
|
|
463
446
|
|
|
464
447
|
// Optimistically update
|
|
465
|
-
api.setQueryData('GET /users
|
|
448
|
+
api.setQueryData('GET /users/{id}', {
|
|
466
449
|
params: { id: variables.params.id }
|
|
467
450
|
}, variables.body);
|
|
468
451
|
|
|
@@ -471,14 +454,14 @@ const updateUser = api.useMutation('PUT /users/:id', {
|
|
|
471
454
|
onError: (err, variables, context) => {
|
|
472
455
|
// Rollback on error
|
|
473
456
|
if (context?.previousUser) {
|
|
474
|
-
api.setQueryData('GET /users
|
|
457
|
+
api.setQueryData('GET /users/{id}', {
|
|
475
458
|
params: { id: variables.params.id }
|
|
476
459
|
}, context.previousUser);
|
|
477
460
|
}
|
|
478
461
|
},
|
|
479
462
|
onSettled: (data, error, variables) => {
|
|
480
463
|
// Refetch after mutation
|
|
481
|
-
api.invalidateQueries('GET /users
|
|
464
|
+
api.invalidateQueries('GET /users/{id}', {
|
|
482
465
|
params: { id: variables.params.id }
|
|
483
466
|
});
|
|
484
467
|
}
|
|
@@ -499,7 +482,7 @@ const api = createTypedFetcher<API>({
|
|
|
499
482
|
});
|
|
500
483
|
|
|
501
484
|
// Per-request headers
|
|
502
|
-
const user = await api('GET /users
|
|
485
|
+
const user = await api('GET /users/{id}', {
|
|
503
486
|
params: { id: '123' },
|
|
504
487
|
headers: {
|
|
505
488
|
'X-Request-ID': requestId
|
|
@@ -515,7 +498,7 @@ Handle errors with full type safety:
|
|
|
515
498
|
import { HttpError } from '@geekmidas/errors';
|
|
516
499
|
|
|
517
500
|
try {
|
|
518
|
-
const user = await api('GET /users
|
|
501
|
+
const user = await api('GET /users/{id}', {
|
|
519
502
|
params: { id: '123' }
|
|
520
503
|
});
|
|
521
504
|
} catch (error) {
|
|
@@ -575,7 +558,7 @@ function UsersList() {
|
|
|
575
558
|
|
|
576
559
|
const handleUserHover = (userId: string) => {
|
|
577
560
|
// Prefetch user details on hover
|
|
578
|
-
api.prefetchQuery('GET /users
|
|
561
|
+
api.prefetchQuery('GET /users/{id}', {
|
|
579
562
|
params: { id: userId }
|
|
580
563
|
});
|
|
581
564
|
};
|
package/dist/auth-fetcher.cjs
CHANGED
|
@@ -1,4 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_methods = require("./methods.cjs");
|
|
3
|
+
const require_fetcher = require("./fetcher.cjs");
|
|
4
|
+
//#region src/auth-fetcher.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates an auth-aware fetcher that automatically applies the correct
|
|
7
|
+
* authentication based on the endpoint being called.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { endpointAuth, securitySchemes, paths } from './openapi';
|
|
12
|
+
* import { TokenClient } from '@geekmidas/auth/client';
|
|
13
|
+
*
|
|
14
|
+
* const tokenClient = new TokenClient({ ... });
|
|
15
|
+
*
|
|
16
|
+
* const api = createAuthAwareFetcher<paths>({
|
|
17
|
+
* baseURL: 'https://api.example.com',
|
|
18
|
+
* endpointAuth,
|
|
19
|
+
* securitySchemes,
|
|
20
|
+
* authStrategies: {
|
|
21
|
+
* bearer: { type: 'bearer', tokenProvider: tokenClient },
|
|
22
|
+
* iam: { type: 'iam', signer: awsSigner },
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Bearer auth automatically applied
|
|
27
|
+
* const user = await api('GET /users/{id}', { params: { id: '123' } });
|
|
28
|
+
*
|
|
29
|
+
* // IAM SigV4 auth automatically applied
|
|
30
|
+
* const tenant = await api('POST /tenants', { body: { name: 'Acme' } });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
function createAuthAwareFetcher(options) {
|
|
34
|
+
const { endpointAuth, securitySchemes, authStrategies, onRequest: userOnRequest, ...fetcherOptions } = options;
|
|
35
|
+
const baseFetcher = new require_fetcher.TypedFetcher({
|
|
36
|
+
...fetcherOptions,
|
|
37
|
+
onRequest: userOnRequest
|
|
38
|
+
});
|
|
39
|
+
const fetcher = async (endpoint, config) => {
|
|
40
|
+
const schemeName = endpointAuth[endpoint];
|
|
41
|
+
let authHeaders = {};
|
|
42
|
+
if (schemeName) {
|
|
43
|
+
const scheme = securitySchemes[schemeName];
|
|
44
|
+
const strategy = authStrategies[schemeName];
|
|
45
|
+
if (strategy && scheme) authHeaders = await resolveAuthHeaders(strategy, scheme);
|
|
46
|
+
}
|
|
47
|
+
const existingHeaders = config && "headers" in config && config.headers ? config.headers : {};
|
|
48
|
+
const mergedConfig = {
|
|
49
|
+
...config,
|
|
50
|
+
headers: {
|
|
51
|
+
...authHeaders,
|
|
52
|
+
...existingHeaders
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
return baseFetcher.request(endpoint, mergedConfig);
|
|
56
|
+
};
|
|
57
|
+
const api = fetcher;
|
|
58
|
+
return Object.assign(api, require_methods.methodCalls(api));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolves auth headers based on the strategy and scheme.
|
|
62
|
+
*/
|
|
63
|
+
async function resolveAuthHeaders(strategy, scheme) {
|
|
64
|
+
switch (strategy.type) {
|
|
65
|
+
case "bearer": return strategy.tokenProvider.createValidAuthHeaders();
|
|
66
|
+
case "apiKey": {
|
|
67
|
+
const apiKey = await strategy.apiKeyProvider.getApiKey();
|
|
68
|
+
const headerName = strategy.headerName || scheme.name || "X-API-Key";
|
|
69
|
+
if (scheme.in === "header" || !scheme.in) return { [headerName]: apiKey };
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
72
|
+
case "iam": return {};
|
|
73
|
+
default: return {};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
exports.createAuthAwareFetcher = createAuthAwareFetcher;
|
|
3
78
|
|
|
4
|
-
|
|
79
|
+
//# sourceMappingURL=auth-fetcher.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-fetcher.cjs","names":["TypedFetcher","methodCalls"],"sources":["../src/auth-fetcher.ts"],"sourcesContent":["import { TypedFetcher } from './fetcher';\nimport { type MethodCalls, methodCalls } from './methods';\nimport type {\n\tExtractEndpointResponse,\n\tFetcherOptions,\n\tFilteredRequestConfig,\n\tTypedApiFunction,\n\tTypedEndpoint,\n} from './types';\n\nexport type { FetcherOptions } from './types';\n\n/**\n * Security scheme object matching OpenAPI 3.1 specification.\n */\nexport interface SecuritySchemeObject {\n\ttype: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n\tdescription?: string;\n\tname?: string;\n\tin?: 'query' | 'header' | 'cookie';\n\tscheme?: string;\n\tbearerFormat?: string;\n\tflows?: Record<string, unknown>;\n\topenIdConnectUrl?: string;\n\t[key: string]: unknown;\n}\n\n/**\n * Extract all non-null security scheme IDs that are actually used in the API.\n * This gives us the union of scheme names that endpoints require.\n */\nexport type UsedSecuritySchemes<\n\tEndpointAuth extends Record<string, string | null>,\n> = NonNullable<EndpointAuth[keyof EndpointAuth]>;\n\n/**\n * Interface for token storage and retrieval.\n * Compatible with @geekmidas/auth TokenClient.\n */\nexport interface TokenProvider {\n\t/**\n\t * Get a valid access token, refreshing if necessary.\n\t */\n\tgetValidAccessToken(): Promise<string | null>;\n\n\t/**\n\t * Create Authorization headers from the current token.\n\t */\n\tcreateValidAuthHeaders(): Promise<Record<string, string>>;\n}\n\n/**\n * Interface for API key providers.\n */\nexport interface ApiKeyProvider {\n\t/**\n\t * Get the API key value.\n\t */\n\tgetApiKey(): Promise<string> | string;\n}\n\n/**\n * Interface for AWS SigV4 request signing.\n */\nexport interface AwsSigner {\n\t/**\n\t * Sign a request with AWS SigV4.\n\t * @param url - The request URL\n\t * @param init - The request init object\n\t * @returns Headers to add to the request\n\t */\n\tsign(url: string, init: RequestInit): Promise<Record<string, string>>;\n}\n\n/**\n * Auth strategy configuration for a specific security scheme type.\n */\nexport type AuthStrategy =\n\t| { type: 'bearer'; tokenProvider: TokenProvider }\n\t| { type: 'apiKey'; apiKeyProvider: ApiKeyProvider; headerName?: string }\n\t| { type: 'iam'; signer: AwsSigner }\n\t| { type: 'none' };\n\n/**\n * Options for creating an auth-aware fetcher.\n *\n * @template EndpointAuth - Map of endpoint strings to their auth scheme (or null for public)\n * @template SecuritySchemes - Available security scheme definitions\n */\nexport interface AuthFetcherOptions<\n\tEndpointAuth extends Record<string, string | null>,\n\tSecuritySchemes extends Record<string, SecuritySchemeObject>,\n> extends Omit<FetcherOptions, 'onRequest'> {\n\t/**\n\t * Runtime map of endpoints to their required auth scheme.\n\t * Generated by `gkm openapi --ts`.\n\t */\n\tendpointAuth: EndpointAuth;\n\n\t/**\n\t * Security scheme definitions.\n\t * Generated by `gkm openapi --ts`.\n\t */\n\tsecuritySchemes: SecuritySchemes;\n\n\t/**\n\t * Auth strategies for security schemes that are actually used.\n\t * Only schemes referenced in endpointAuth are required.\n\t *\n\t * @example\n\t * ```typescript\n\t * // If endpointAuth has: { 'GET /users': 'jwt', 'POST /data': 'iam', 'GET /public': null }\n\t * // Then authStrategies must include strategies for 'jwt' and 'iam'\n\t * authStrategies: {\n\t * jwt: { type: 'bearer', tokenProvider },\n\t * iam: { type: 'iam', signer: awsSigner },\n\t * }\n\t * ```\n\t */\n\tauthStrategies: Record<UsedSecuritySchemes<EndpointAuth>, AuthStrategy>;\n\n\t/**\n\t * Optional request interceptor (runs after auth headers are added).\n\t */\n\tonRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;\n}\n\n/**\n * Creates an auth-aware fetcher that automatically applies the correct\n * authentication based on the endpoint being called.\n *\n * @example\n * ```typescript\n * import { endpointAuth, securitySchemes, paths } from './openapi';\n * import { TokenClient } from '@geekmidas/auth/client';\n *\n * const tokenClient = new TokenClient({ ... });\n *\n * const api = createAuthAwareFetcher<paths>({\n * baseURL: 'https://api.example.com',\n * endpointAuth,\n * securitySchemes,\n * authStrategies: {\n * bearer: { type: 'bearer', tokenProvider: tokenClient },\n * iam: { type: 'iam', signer: awsSigner },\n * },\n * });\n *\n * // Bearer auth automatically applied\n * const user = await api('GET /users/{id}', { params: { id: '123' } });\n *\n * // IAM SigV4 auth automatically applied\n * const tenant = await api('POST /tenants', { body: { name: 'Acme' } });\n * ```\n */\nexport function createAuthAwareFetcher<\n\tPaths,\n\tEndpointAuth extends Record<string, string | null> = Record<\n\t\tstring,\n\t\tstring | null\n\t>,\n\tSecuritySchemes extends Record<string, SecuritySchemeObject> = Record<\n\t\tstring,\n\t\tSecuritySchemeObject\n\t>,\n>(\n\toptions: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n\t\tbaseURL: string;\n\t},\n): TypedApiFunction<Paths> & MethodCalls<Paths> {\n\tconst {\n\t\tendpointAuth,\n\t\tsecuritySchemes,\n\t\tauthStrategies,\n\t\tonRequest: userOnRequest,\n\t\t...fetcherOptions\n\t} = options;\n\n\t// Create base fetcher with user's onRequest if provided\n\tconst baseFetcher = new TypedFetcher<Paths>({\n\t\t...fetcherOptions,\n\t\tonRequest: userOnRequest,\n\t});\n\n\tconst fetcher = async <T extends TypedEndpoint<Paths>>(\n\t\tendpoint: T,\n\t\tconfig?: FilteredRequestConfig<Paths, T>,\n\t): Promise<ExtractEndpointResponse<Paths, T>> => {\n\t\t// Look up auth requirement for this endpoint\n\t\tconst schemeName = endpointAuth[endpoint as keyof EndpointAuth] as\n\t\t\t| string\n\t\t\t| null;\n\n\t\tlet authHeaders: Record<string, string> = {};\n\n\t\tif (schemeName) {\n\t\t\tconst scheme = securitySchemes[schemeName as keyof SecuritySchemes];\n\t\t\t// Since authStrategies is now required to have all used schemes,\n\t\t\t// we can safely access it - TypeScript ensures the strategy exists\n\t\t\tconst strategy =\n\t\t\t\tauthStrategies[schemeName as UsedSecuritySchemes<EndpointAuth>];\n\n\t\t\tif (strategy && scheme) {\n\t\t\t\tauthHeaders = await resolveAuthHeaders(strategy, scheme);\n\t\t\t}\n\t\t}\n\n\t\t// Merge auth headers with config headers\n\t\tconst existingHeaders =\n\t\t\tconfig && 'headers' in config && config.headers\n\t\t\t\t? (config.headers as Record<string, string>)\n\t\t\t\t: {};\n\n\t\tconst mergedConfig = {\n\t\t\t...config,\n\t\t\theaders: {\n\t\t\t\t...authHeaders,\n\t\t\t\t...existingHeaders,\n\t\t\t},\n\t\t} as unknown as FilteredRequestConfig<Paths, T>;\n\n\t\treturn baseFetcher.request(endpoint, mergedConfig);\n\t};\n\n\tconst api = fetcher as TypedApiFunction<Paths>;\n\treturn Object.assign(api, methodCalls<Paths>(api));\n}\n\n/**\n * Resolves auth headers based on the strategy and scheme.\n */\nasync function resolveAuthHeaders(\n\tstrategy: AuthStrategy,\n\tscheme: SecuritySchemeObject,\n): Promise<Record<string, string>> {\n\tswitch (strategy.type) {\n\t\tcase 'bearer': {\n\t\t\treturn strategy.tokenProvider.createValidAuthHeaders();\n\t\t}\n\n\t\tcase 'apiKey': {\n\t\t\tconst apiKey = await strategy.apiKeyProvider.getApiKey();\n\t\t\tconst headerName = strategy.headerName || scheme.name || 'X-API-Key';\n\n\t\t\tif (scheme.in === 'header' || !scheme.in) {\n\t\t\t\treturn { [headerName]: apiKey };\n\t\t\t}\n\t\t\t// Note: query and cookie API keys are handled differently\n\t\t\t// For now, we only support header-based API keys\n\t\t\treturn {};\n\t\t}\n\n\t\tcase 'iam': {\n\t\t\t// IAM signing requires the full URL and request config\n\t\t\t// This is a simplified version - full implementation would need\n\t\t\t// access to the complete request\n\t\t\t// For now, return empty - the actual signing should be done\n\t\t\t// in a custom onRequest interceptor if needed\n\t\t\treturn {};\n\t\t}\n\t\tdefault:\n\t\t\treturn {};\n\t}\n}\n\n/**\n * Type helper to extract the security scheme ID from an endpoint.\n */\nexport type GetEndpointAuth<\n\tEndpointAuth extends Record<string, string | null>,\n\tEndpoint extends keyof EndpointAuth,\n> = EndpointAuth[Endpoint];\n\n/**\n * Type helper to get all authenticated endpoints.\n */\nexport type AuthenticatedEndpoints<\n\tEndpointAuth extends Record<string, string | null>,\n> = {\n\t[K in keyof EndpointAuth]: EndpointAuth[K] extends null ? never : K;\n}[keyof EndpointAuth];\n\n/**\n * Type helper to get all public endpoints.\n */\nexport type PublicEndpoints<\n\tEndpointAuth extends Record<string, string | null>,\n> = {\n\t[K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never;\n}[keyof EndpointAuth];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2JA,SAAgB,uBAWf,SAG+C;CAC/C,MAAM,EACL,cACA,iBACA,gBACA,WAAW,eACX,GAAG,mBACA;CAGJ,MAAM,cAAc,IAAIA,gBAAAA,aAAoB;EAC3C,GAAG;EACH,WAAW;CACZ,CAAC;CAED,MAAM,UAAU,OACf,UACA,WACgD;EAEhD,MAAM,aAAa,aAAa;EAIhC,IAAI,cAAsC,CAAC;EAE3C,IAAI,YAAY;GACf,MAAM,SAAS,gBAAgB;GAG/B,MAAM,WACL,eAAe;GAEhB,IAAI,YAAY,QACf,cAAc,MAAM,mBAAmB,UAAU,MAAM;EAEzD;EAGA,MAAM,kBACL,UAAU,aAAa,UAAU,OAAO,UACpC,OAAO,UACR,CAAC;EAEL,MAAM,eAAe;GACpB,GAAG;GACH,SAAS;IACR,GAAG;IACH,GAAG;GACJ;EACD;EAEA,OAAO,YAAY,QAAQ,UAAU,YAAY;CAClD;CAEA,MAAM,MAAM;CACZ,OAAO,OAAO,OAAO,KAAKC,gBAAAA,YAAmB,GAAG,CAAC;AAClD;;;;AAKA,eAAe,mBACd,UACA,QACkC;CAClC,QAAQ,SAAS,MAAjB;EACC,KAAK,UACJ,OAAO,SAAS,cAAc,uBAAuB;EAGtD,KAAK,UAAU;GACd,MAAM,SAAS,MAAM,SAAS,eAAe,UAAU;GACvD,MAAM,aAAa,SAAS,cAAc,OAAO,QAAQ;GAEzD,IAAI,OAAO,OAAO,YAAY,CAAC,OAAO,IACrC,OAAO,GAAG,aAAa,OAAO;GAI/B,OAAO,CAAC;EACT;EAEA,KAAK,OAMJ,OAAO,CAAC;EAET,SACC,OAAO,CAAC;CACV;AACD"}
|
package/dist/auth-fetcher.d.cts
CHANGED
|
@@ -1,3 +1,156 @@
|
|
|
1
|
-
import { FetcherOptions } from "./types
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { FetcherOptions, TypedApiFunction } from "./types.cjs";
|
|
2
|
+
import { MethodCalls } from "./methods.cjs";
|
|
3
|
+
//#region src/auth-fetcher.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Security scheme object matching OpenAPI 3.1 specification.
|
|
6
|
+
*/
|
|
7
|
+
export interface SecuritySchemeObject {
|
|
8
|
+
type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';
|
|
9
|
+
description?: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
in?: 'query' | 'header' | 'cookie';
|
|
12
|
+
scheme?: string;
|
|
13
|
+
bearerFormat?: string;
|
|
14
|
+
flows?: Record<string, unknown>;
|
|
15
|
+
openIdConnectUrl?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Extract all non-null security scheme IDs that are actually used in the API.
|
|
20
|
+
* This gives us the union of scheme names that endpoints require.
|
|
21
|
+
*/
|
|
22
|
+
export type UsedSecuritySchemes<EndpointAuth extends Record<string, string | null>> = NonNullable<EndpointAuth[keyof EndpointAuth]>;
|
|
23
|
+
/**
|
|
24
|
+
* Interface for token storage and retrieval.
|
|
25
|
+
* Compatible with @geekmidas/auth TokenClient.
|
|
26
|
+
*/
|
|
27
|
+
export interface TokenProvider {
|
|
28
|
+
/**
|
|
29
|
+
* Get a valid access token, refreshing if necessary.
|
|
30
|
+
*/
|
|
31
|
+
getValidAccessToken(): Promise<string | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Create Authorization headers from the current token.
|
|
34
|
+
*/
|
|
35
|
+
createValidAuthHeaders(): Promise<Record<string, string>>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Interface for API key providers.
|
|
39
|
+
*/
|
|
40
|
+
export interface ApiKeyProvider {
|
|
41
|
+
/**
|
|
42
|
+
* Get the API key value.
|
|
43
|
+
*/
|
|
44
|
+
getApiKey(): Promise<string> | string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Interface for AWS SigV4 request signing.
|
|
48
|
+
*/
|
|
49
|
+
export interface AwsSigner {
|
|
50
|
+
/**
|
|
51
|
+
* Sign a request with AWS SigV4.
|
|
52
|
+
* @param url - The request URL
|
|
53
|
+
* @param init - The request init object
|
|
54
|
+
* @returns Headers to add to the request
|
|
55
|
+
*/
|
|
56
|
+
sign(url: string, init: RequestInit): Promise<Record<string, string>>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Auth strategy configuration for a specific security scheme type.
|
|
60
|
+
*/
|
|
61
|
+
export type AuthStrategy = {
|
|
62
|
+
type: 'bearer';
|
|
63
|
+
tokenProvider: TokenProvider;
|
|
64
|
+
} | {
|
|
65
|
+
type: 'apiKey';
|
|
66
|
+
apiKeyProvider: ApiKeyProvider;
|
|
67
|
+
headerName?: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'iam';
|
|
70
|
+
signer: AwsSigner;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'none';
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Options for creating an auth-aware fetcher.
|
|
76
|
+
*
|
|
77
|
+
* @template EndpointAuth - Map of endpoint strings to their auth scheme (or null for public)
|
|
78
|
+
* @template SecuritySchemes - Available security scheme definitions
|
|
79
|
+
*/
|
|
80
|
+
export interface AuthFetcherOptions<EndpointAuth extends Record<string, string | null>, SecuritySchemes extends Record<string, SecuritySchemeObject>> extends Omit<FetcherOptions, 'onRequest'> {
|
|
81
|
+
/**
|
|
82
|
+
* Runtime map of endpoints to their required auth scheme.
|
|
83
|
+
* Generated by `gkm openapi --ts`.
|
|
84
|
+
*/
|
|
85
|
+
endpointAuth: EndpointAuth;
|
|
86
|
+
/**
|
|
87
|
+
* Security scheme definitions.
|
|
88
|
+
* Generated by `gkm openapi --ts`.
|
|
89
|
+
*/
|
|
90
|
+
securitySchemes: SecuritySchemes;
|
|
91
|
+
/**
|
|
92
|
+
* Auth strategies for security schemes that are actually used.
|
|
93
|
+
* Only schemes referenced in endpointAuth are required.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // If endpointAuth has: { 'GET /users': 'jwt', 'POST /data': 'iam', 'GET /public': null }
|
|
98
|
+
* // Then authStrategies must include strategies for 'jwt' and 'iam'
|
|
99
|
+
* authStrategies: {
|
|
100
|
+
* jwt: { type: 'bearer', tokenProvider },
|
|
101
|
+
* iam: { type: 'iam', signer: awsSigner },
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
authStrategies: Record<UsedSecuritySchemes<EndpointAuth>, AuthStrategy>;
|
|
106
|
+
/**
|
|
107
|
+
* Optional request interceptor (runs after auth headers are added).
|
|
108
|
+
*/
|
|
109
|
+
onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates an auth-aware fetcher that automatically applies the correct
|
|
113
|
+
* authentication based on the endpoint being called.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* import { endpointAuth, securitySchemes, paths } from './openapi';
|
|
118
|
+
* import { TokenClient } from '@geekmidas/auth/client';
|
|
119
|
+
*
|
|
120
|
+
* const tokenClient = new TokenClient({ ... });
|
|
121
|
+
*
|
|
122
|
+
* const api = createAuthAwareFetcher<paths>({
|
|
123
|
+
* baseURL: 'https://api.example.com',
|
|
124
|
+
* endpointAuth,
|
|
125
|
+
* securitySchemes,
|
|
126
|
+
* authStrategies: {
|
|
127
|
+
* bearer: { type: 'bearer', tokenProvider: tokenClient },
|
|
128
|
+
* iam: { type: 'iam', signer: awsSigner },
|
|
129
|
+
* },
|
|
130
|
+
* });
|
|
131
|
+
*
|
|
132
|
+
* // Bearer auth automatically applied
|
|
133
|
+
* const user = await api('GET /users/{id}', { params: { id: '123' } });
|
|
134
|
+
*
|
|
135
|
+
* // IAM SigV4 auth automatically applied
|
|
136
|
+
* const tenant = await api('POST /tenants', { body: { name: 'Acme' } });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare function createAuthAwareFetcher<Paths, EndpointAuth extends Record<string, string | null> = Record<string, string | null>, SecuritySchemes extends Record<string, SecuritySchemeObject> = Record<string, SecuritySchemeObject>>(options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {
|
|
140
|
+
baseURL: string;
|
|
141
|
+
}): TypedApiFunction<Paths> & MethodCalls<Paths>;
|
|
142
|
+
/**
|
|
143
|
+
* Type helper to extract the security scheme ID from an endpoint.
|
|
144
|
+
*/
|
|
145
|
+
export type GetEndpointAuth<EndpointAuth extends Record<string, string | null>, Endpoint extends keyof EndpointAuth> = EndpointAuth[Endpoint];
|
|
146
|
+
/**
|
|
147
|
+
* Type helper to get all authenticated endpoints.
|
|
148
|
+
*/
|
|
149
|
+
export type AuthenticatedEndpoints<EndpointAuth extends Record<string, string | null>> = { [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? never : K; }[keyof EndpointAuth];
|
|
150
|
+
/**
|
|
151
|
+
* Type helper to get all public endpoints.
|
|
152
|
+
*/
|
|
153
|
+
export type PublicEndpoints<EndpointAuth extends Record<string, string | null>> = { [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never; }[keyof EndpointAuth];
|
|
154
|
+
//#endregion
|
|
155
|
+
export type { FetcherOptions };
|
|
156
|
+
//# sourceMappingURL=auth-fetcher.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-fetcher.d.cts","names":[],"sources":["../src/auth-fetcher.ts"],"mappings":";;;;;;iBAeiB;EAChB;EACA;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR;GACC;;;;;;YAOU,oBACX,qBAAqB,iCAClB,YAAY,mBAAmB;;;;;iBAMlB;;;;EAIhB,uBAAuB;;;;EAKvB,0BAA0B,QAAQ;;;;;iBAMlB;;;;EAIhB,aAAa;;;;;iBAMG;;;;;;;EAOhB,KAAK,aAAa,MAAM,cAAc,QAAQ;;;;;YAMnC;EACP;EAAgB,eAAe;;EAC/B;EAAgB,gBAAgB;EAAgB;;EAChD;EAAa,QAAQ;;EACrB;;;;;;;;iBAQY,mBAChB,qBAAqB,+BACrB,wBAAwB,eAAe,+BAC9B,KAAK;;;;;EAKd,cAAc;;;;;EAMd,iBAAiB;;;;;;;;;;;;;;;EAgBjB,gBAAgB,OAAO,oBAAoB,eAAe;;;;EAK1D,aAAa,QAAQ,gBAAgB,cAAc,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA+B5C,uBACf,OACA,qBAAqB,gCAAgC,+BAIrD,wBAAwB,eAAe,wBAAwB,eAE9D,uBAGD,SAAS,mBAAmB,cAAc;EACzC;IAEC,iBAAiB,SAAS,YAAY;;;;YAmG7B,gBACX,qBAAqB,+BACrB,uBAAuB,gBACpB,aAAa;;;;YAKL,uBACX,qBAAqB,oCAEpB,WAAW,eAAe,aAAa,0BAA0B,WAC3D;;;;YAKI,gBACX,qBAAqB,oCAEpB,WAAW,eAAe,aAAa,kBAAkB,mBACnD"}
|
package/dist/auth-fetcher.d.mts
CHANGED
|
@@ -1,3 +1,156 @@
|
|
|
1
|
-
import { FetcherOptions } from "./types
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { FetcherOptions, TypedApiFunction } from "./types.mjs";
|
|
2
|
+
import { MethodCalls } from "./methods.mjs";
|
|
3
|
+
//#region src/auth-fetcher.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Security scheme object matching OpenAPI 3.1 specification.
|
|
6
|
+
*/
|
|
7
|
+
export interface SecuritySchemeObject {
|
|
8
|
+
type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';
|
|
9
|
+
description?: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
in?: 'query' | 'header' | 'cookie';
|
|
12
|
+
scheme?: string;
|
|
13
|
+
bearerFormat?: string;
|
|
14
|
+
flows?: Record<string, unknown>;
|
|
15
|
+
openIdConnectUrl?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Extract all non-null security scheme IDs that are actually used in the API.
|
|
20
|
+
* This gives us the union of scheme names that endpoints require.
|
|
21
|
+
*/
|
|
22
|
+
export type UsedSecuritySchemes<EndpointAuth extends Record<string, string | null>> = NonNullable<EndpointAuth[keyof EndpointAuth]>;
|
|
23
|
+
/**
|
|
24
|
+
* Interface for token storage and retrieval.
|
|
25
|
+
* Compatible with @geekmidas/auth TokenClient.
|
|
26
|
+
*/
|
|
27
|
+
export interface TokenProvider {
|
|
28
|
+
/**
|
|
29
|
+
* Get a valid access token, refreshing if necessary.
|
|
30
|
+
*/
|
|
31
|
+
getValidAccessToken(): Promise<string | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Create Authorization headers from the current token.
|
|
34
|
+
*/
|
|
35
|
+
createValidAuthHeaders(): Promise<Record<string, string>>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Interface for API key providers.
|
|
39
|
+
*/
|
|
40
|
+
export interface ApiKeyProvider {
|
|
41
|
+
/**
|
|
42
|
+
* Get the API key value.
|
|
43
|
+
*/
|
|
44
|
+
getApiKey(): Promise<string> | string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Interface for AWS SigV4 request signing.
|
|
48
|
+
*/
|
|
49
|
+
export interface AwsSigner {
|
|
50
|
+
/**
|
|
51
|
+
* Sign a request with AWS SigV4.
|
|
52
|
+
* @param url - The request URL
|
|
53
|
+
* @param init - The request init object
|
|
54
|
+
* @returns Headers to add to the request
|
|
55
|
+
*/
|
|
56
|
+
sign(url: string, init: RequestInit): Promise<Record<string, string>>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Auth strategy configuration for a specific security scheme type.
|
|
60
|
+
*/
|
|
61
|
+
export type AuthStrategy = {
|
|
62
|
+
type: 'bearer';
|
|
63
|
+
tokenProvider: TokenProvider;
|
|
64
|
+
} | {
|
|
65
|
+
type: 'apiKey';
|
|
66
|
+
apiKeyProvider: ApiKeyProvider;
|
|
67
|
+
headerName?: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'iam';
|
|
70
|
+
signer: AwsSigner;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'none';
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Options for creating an auth-aware fetcher.
|
|
76
|
+
*
|
|
77
|
+
* @template EndpointAuth - Map of endpoint strings to their auth scheme (or null for public)
|
|
78
|
+
* @template SecuritySchemes - Available security scheme definitions
|
|
79
|
+
*/
|
|
80
|
+
export interface AuthFetcherOptions<EndpointAuth extends Record<string, string | null>, SecuritySchemes extends Record<string, SecuritySchemeObject>> extends Omit<FetcherOptions, 'onRequest'> {
|
|
81
|
+
/**
|
|
82
|
+
* Runtime map of endpoints to their required auth scheme.
|
|
83
|
+
* Generated by `gkm openapi --ts`.
|
|
84
|
+
*/
|
|
85
|
+
endpointAuth: EndpointAuth;
|
|
86
|
+
/**
|
|
87
|
+
* Security scheme definitions.
|
|
88
|
+
* Generated by `gkm openapi --ts`.
|
|
89
|
+
*/
|
|
90
|
+
securitySchemes: SecuritySchemes;
|
|
91
|
+
/**
|
|
92
|
+
* Auth strategies for security schemes that are actually used.
|
|
93
|
+
* Only schemes referenced in endpointAuth are required.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // If endpointAuth has: { 'GET /users': 'jwt', 'POST /data': 'iam', 'GET /public': null }
|
|
98
|
+
* // Then authStrategies must include strategies for 'jwt' and 'iam'
|
|
99
|
+
* authStrategies: {
|
|
100
|
+
* jwt: { type: 'bearer', tokenProvider },
|
|
101
|
+
* iam: { type: 'iam', signer: awsSigner },
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
authStrategies: Record<UsedSecuritySchemes<EndpointAuth>, AuthStrategy>;
|
|
106
|
+
/**
|
|
107
|
+
* Optional request interceptor (runs after auth headers are added).
|
|
108
|
+
*/
|
|
109
|
+
onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates an auth-aware fetcher that automatically applies the correct
|
|
113
|
+
* authentication based on the endpoint being called.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* import { endpointAuth, securitySchemes, paths } from './openapi';
|
|
118
|
+
* import { TokenClient } from '@geekmidas/auth/client';
|
|
119
|
+
*
|
|
120
|
+
* const tokenClient = new TokenClient({ ... });
|
|
121
|
+
*
|
|
122
|
+
* const api = createAuthAwareFetcher<paths>({
|
|
123
|
+
* baseURL: 'https://api.example.com',
|
|
124
|
+
* endpointAuth,
|
|
125
|
+
* securitySchemes,
|
|
126
|
+
* authStrategies: {
|
|
127
|
+
* bearer: { type: 'bearer', tokenProvider: tokenClient },
|
|
128
|
+
* iam: { type: 'iam', signer: awsSigner },
|
|
129
|
+
* },
|
|
130
|
+
* });
|
|
131
|
+
*
|
|
132
|
+
* // Bearer auth automatically applied
|
|
133
|
+
* const user = await api('GET /users/{id}', { params: { id: '123' } });
|
|
134
|
+
*
|
|
135
|
+
* // IAM SigV4 auth automatically applied
|
|
136
|
+
* const tenant = await api('POST /tenants', { body: { name: 'Acme' } });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare function createAuthAwareFetcher<Paths, EndpointAuth extends Record<string, string | null> = Record<string, string | null>, SecuritySchemes extends Record<string, SecuritySchemeObject> = Record<string, SecuritySchemeObject>>(options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {
|
|
140
|
+
baseURL: string;
|
|
141
|
+
}): TypedApiFunction<Paths> & MethodCalls<Paths>;
|
|
142
|
+
/**
|
|
143
|
+
* Type helper to extract the security scheme ID from an endpoint.
|
|
144
|
+
*/
|
|
145
|
+
export type GetEndpointAuth<EndpointAuth extends Record<string, string | null>, Endpoint extends keyof EndpointAuth> = EndpointAuth[Endpoint];
|
|
146
|
+
/**
|
|
147
|
+
* Type helper to get all authenticated endpoints.
|
|
148
|
+
*/
|
|
149
|
+
export type AuthenticatedEndpoints<EndpointAuth extends Record<string, string | null>> = { [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? never : K; }[keyof EndpointAuth];
|
|
150
|
+
/**
|
|
151
|
+
* Type helper to get all public endpoints.
|
|
152
|
+
*/
|
|
153
|
+
export type PublicEndpoints<EndpointAuth extends Record<string, string | null>> = { [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never; }[keyof EndpointAuth];
|
|
154
|
+
//#endregion
|
|
155
|
+
export type { FetcherOptions };
|
|
156
|
+
//# sourceMappingURL=auth-fetcher.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-fetcher.d.mts","names":[],"sources":["../src/auth-fetcher.ts"],"mappings":";;;;;;iBAeiB;EAChB;EACA;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR;GACC;;;;;;YAOU,oBACX,qBAAqB,iCAClB,YAAY,mBAAmB;;;;;iBAMlB;;;;EAIhB,uBAAuB;;;;EAKvB,0BAA0B,QAAQ;;;;;iBAMlB;;;;EAIhB,aAAa;;;;;iBAMG;;;;;;;EAOhB,KAAK,aAAa,MAAM,cAAc,QAAQ;;;;;YAMnC;EACP;EAAgB,eAAe;;EAC/B;EAAgB,gBAAgB;EAAgB;;EAChD;EAAa,QAAQ;;EACrB;;;;;;;;iBAQY,mBAChB,qBAAqB,+BACrB,wBAAwB,eAAe,+BAC9B,KAAK;;;;;EAKd,cAAc;;;;;EAMd,iBAAiB;;;;;;;;;;;;;;;EAgBjB,gBAAgB,OAAO,oBAAoB,eAAe;;;;EAK1D,aAAa,QAAQ,gBAAgB,cAAc,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA+B5C,uBACf,OACA,qBAAqB,gCAAgC,+BAIrD,wBAAwB,eAAe,wBAAwB,eAE9D,uBAGD,SAAS,mBAAmB,cAAc;EACzC;IAEC,iBAAiB,SAAS,YAAY;;;;YAmG7B,gBACX,qBAAqB,+BACrB,uBAAuB,gBACpB,aAAa;;;;YAKL,uBACX,qBAAqB,oCAEpB,WAAW,eAAe,aAAa,0BAA0B,WAC3D;;;;YAKI,gBACX,qBAAqB,oCAEpB,WAAW,eAAe,aAAa,kBAAkB,mBACnD"}
|