@geekmidas/client 0.1.1 → 0.3.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/auth-fetcher.cjs.map +1 -1
- package/dist/auth-fetcher.d.cts +1 -1
- package/dist/auth-fetcher.d.mts +1 -1
- package/dist/auth-fetcher.mjs.map +1 -1
- package/dist/fetcher-DLDD_7Sa.mjs.map +1 -1
- package/dist/fetcher-KdwHgdAl.cjs.map +1 -1
- package/dist/fetcher.d.cts +1 -1
- package/dist/fetcher.d.mts +1 -1
- package/dist/openapi-hooks.d.cts +3 -3
- package/dist/react-query.d.cts +7 -7
- package/package.json +11 -6
- package/src/auth-fetcher.ts +2 -0
- package/src/fetcher.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-fetcher.cjs","names":["options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n baseURL: string;\n }","TypedFetcher","endpoint: T","config?: FilteredRequestConfig<Paths, T>","authHeaders: Record<string, string>","strategy: AuthStrategy","scheme: SecuritySchemeObject"],"sources":["../src/auth-fetcher.ts"],"sourcesContent":["import { TypedFetcher } from './fetcher';\nimport type {\n ExtractEndpointResponse,\n FetcherOptions,\n FilteredRequestConfig,\n TypedApiFunction,\n TypedEndpoint,\n} from './types';\n\n/**\n * Security scheme object matching OpenAPI 3.1 specification.\n */\nexport interface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [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 EndpointAuth 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 /**\n * Get a valid access token, refreshing if necessary.\n */\n getValidAccessToken(): Promise<string | null>;\n\n /**\n * Create Authorization headers from the current token.\n */\n createValidAuthHeaders(): Promise<Record<string, string>>;\n}\n\n/**\n * Interface for API key providers.\n */\nexport interface ApiKeyProvider {\n /**\n * Get the API key value.\n */\n getApiKey(): Promise<string> | string;\n}\n\n/**\n * Interface for AWS SigV4 request signing.\n */\nexport interface AwsSigner {\n /**\n * Sign a request with AWS SigV4.\n * @param url - The request URL\n * @param init - The request init object\n * @returns Headers to add to the request\n */\n sign(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 | { type: 'bearer'; tokenProvider: TokenProvider }\n | { type: 'apiKey'; apiKeyProvider: ApiKeyProvider; headerName?: string }\n | { type: 'iam'; signer: AwsSigner }\n | { 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 EndpointAuth extends Record<string, string | null>,\n SecuritySchemes extends Record<string, SecuritySchemeObject>,\n> extends Omit<FetcherOptions, 'onRequest'> {\n /**\n * Runtime map of endpoints to their required auth scheme.\n * Generated by `gkm openapi --ts`.\n */\n endpointAuth: EndpointAuth;\n\n /**\n * Security scheme definitions.\n * Generated by `gkm openapi --ts`.\n */\n securitySchemes: SecuritySchemes;\n\n /**\n * Auth strategies for security schemes that are actually used.\n * Only schemes referenced in endpointAuth are required.\n *\n * @example\n * ```typescript\n * // If endpointAuth has: { 'GET /users': 'jwt', 'POST /data': 'iam', 'GET /public': null }\n * // Then authStrategies must include strategies for 'jwt' and 'iam'\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * iam: { type: 'iam', signer: awsSigner },\n * }\n * ```\n */\n authStrategies: Record<UsedSecuritySchemes<EndpointAuth>, AuthStrategy>;\n\n /**\n * Optional request interceptor (runs after auth headers are added).\n */\n onRequest?: (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 Paths,\n EndpointAuth extends Record<string, string | null> = Record<\n string,\n string | null\n >,\n SecuritySchemes extends Record<string, SecuritySchemeObject> = Record<\n string,\n SecuritySchemeObject\n >,\n>(\n options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n baseURL: string;\n },\n): TypedApiFunction<Paths> {\n const {\n endpointAuth,\n securitySchemes,\n authStrategies,\n onRequest: userOnRequest,\n ...fetcherOptions\n } = options;\n\n // Create base fetcher with user's onRequest if provided\n const baseFetcher = new TypedFetcher<Paths>({\n ...fetcherOptions,\n onRequest: userOnRequest,\n });\n\n const fetcher = async <T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ): Promise<ExtractEndpointResponse<Paths, T>> => {\n // Look up auth requirement for this endpoint\n const schemeName = endpointAuth[endpoint as keyof EndpointAuth] as\n | string\n | null;\n\n let authHeaders: Record<string, string> = {};\n\n if (schemeName) {\n const scheme = securitySchemes[schemeName as keyof SecuritySchemes];\n // Since authStrategies is now required to have all used schemes,\n // we can safely access it - TypeScript ensures the strategy exists\n const strategy =\n authStrategies[schemeName as UsedSecuritySchemes<EndpointAuth>];\n\n if (strategy) {\n authHeaders = await resolveAuthHeaders(strategy, scheme);\n }\n }\n\n // Merge auth headers with config headers\n const existingHeaders =\n config && 'headers' in config && config.headers\n ? (config.headers as Record<string, string>)\n : {};\n\n const mergedConfig = {\n ...config,\n headers: {\n ...authHeaders,\n ...existingHeaders,\n },\n } as unknown as FilteredRequestConfig<Paths, T>;\n\n return baseFetcher.request(endpoint, mergedConfig);\n };\n\n return fetcher as TypedApiFunction<Paths>;\n}\n\n/**\n * Resolves auth headers based on the strategy and scheme.\n */\nasync function resolveAuthHeaders(\n strategy: AuthStrategy,\n scheme: SecuritySchemeObject,\n): Promise<Record<string, string>> {\n switch (strategy.type) {\n case 'bearer': {\n return strategy.tokenProvider.createValidAuthHeaders();\n }\n\n case 'apiKey': {\n const apiKey = await strategy.apiKeyProvider.getApiKey();\n const headerName = strategy.headerName || scheme.name || 'X-API-Key';\n\n if (scheme.in === 'header' || !scheme.in) {\n return { [headerName]: apiKey };\n }\n // Note: query and cookie API keys are handled differently\n // For now, we only support header-based API keys\n return {};\n }\n\n case 'iam': {\n // IAM signing requires the full URL and request config\n // This is a simplified version - full implementation would need\n // access to the complete request\n // For now, return empty - the actual signing should be done\n // in a custom onRequest interceptor if needed\n return {};\n }\n\n case 'none':\n default:\n return {};\n }\n}\n\n/**\n * Type helper to extract the security scheme ID from an endpoint.\n */\nexport type GetEndpointAuth<\n EndpointAuth extends Record<string, string | null>,\n Endpoint extends keyof EndpointAuth,\n> = EndpointAuth[Endpoint];\n\n/**\n * Type helper to get all authenticated endpoints.\n */\nexport type AuthenticatedEndpoints<\n EndpointAuth extends Record<string, string | null>,\n> = {\n [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 EndpointAuth extends Record<string, string | null>,\n> = {\n [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never;\n}[keyof EndpointAuth];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"auth-fetcher.cjs","names":["options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n baseURL: string;\n }","TypedFetcher","endpoint: T","config?: FilteredRequestConfig<Paths, T>","authHeaders: Record<string, string>","strategy: AuthStrategy","scheme: SecuritySchemeObject"],"sources":["../src/auth-fetcher.ts"],"sourcesContent":["import { TypedFetcher } from './fetcher';\nimport type {\n ExtractEndpointResponse,\n FetcherOptions,\n FilteredRequestConfig,\n TypedApiFunction,\n TypedEndpoint,\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 type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [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 EndpointAuth 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 /**\n * Get a valid access token, refreshing if necessary.\n */\n getValidAccessToken(): Promise<string | null>;\n\n /**\n * Create Authorization headers from the current token.\n */\n createValidAuthHeaders(): Promise<Record<string, string>>;\n}\n\n/**\n * Interface for API key providers.\n */\nexport interface ApiKeyProvider {\n /**\n * Get the API key value.\n */\n getApiKey(): Promise<string> | string;\n}\n\n/**\n * Interface for AWS SigV4 request signing.\n */\nexport interface AwsSigner {\n /**\n * Sign a request with AWS SigV4.\n * @param url - The request URL\n * @param init - The request init object\n * @returns Headers to add to the request\n */\n sign(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 | { type: 'bearer'; tokenProvider: TokenProvider }\n | { type: 'apiKey'; apiKeyProvider: ApiKeyProvider; headerName?: string }\n | { type: 'iam'; signer: AwsSigner }\n | { 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 EndpointAuth extends Record<string, string | null>,\n SecuritySchemes extends Record<string, SecuritySchemeObject>,\n> extends Omit<FetcherOptions, 'onRequest'> {\n /**\n * Runtime map of endpoints to their required auth scheme.\n * Generated by `gkm openapi --ts`.\n */\n endpointAuth: EndpointAuth;\n\n /**\n * Security scheme definitions.\n * Generated by `gkm openapi --ts`.\n */\n securitySchemes: SecuritySchemes;\n\n /**\n * Auth strategies for security schemes that are actually used.\n * Only schemes referenced in endpointAuth are required.\n *\n * @example\n * ```typescript\n * // If endpointAuth has: { 'GET /users': 'jwt', 'POST /data': 'iam', 'GET /public': null }\n * // Then authStrategies must include strategies for 'jwt' and 'iam'\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * iam: { type: 'iam', signer: awsSigner },\n * }\n * ```\n */\n authStrategies: Record<UsedSecuritySchemes<EndpointAuth>, AuthStrategy>;\n\n /**\n * Optional request interceptor (runs after auth headers are added).\n */\n onRequest?: (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 Paths,\n EndpointAuth extends Record<string, string | null> = Record<\n string,\n string | null\n >,\n SecuritySchemes extends Record<string, SecuritySchemeObject> = Record<\n string,\n SecuritySchemeObject\n >,\n>(\n options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n baseURL: string;\n },\n): TypedApiFunction<Paths> {\n const {\n endpointAuth,\n securitySchemes,\n authStrategies,\n onRequest: userOnRequest,\n ...fetcherOptions\n } = options;\n\n // Create base fetcher with user's onRequest if provided\n const baseFetcher = new TypedFetcher<Paths>({\n ...fetcherOptions,\n onRequest: userOnRequest,\n });\n\n const fetcher = async <T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ): Promise<ExtractEndpointResponse<Paths, T>> => {\n // Look up auth requirement for this endpoint\n const schemeName = endpointAuth[endpoint as keyof EndpointAuth] as\n | string\n | null;\n\n let authHeaders: Record<string, string> = {};\n\n if (schemeName) {\n const scheme = securitySchemes[schemeName as keyof SecuritySchemes];\n // Since authStrategies is now required to have all used schemes,\n // we can safely access it - TypeScript ensures the strategy exists\n const strategy =\n authStrategies[schemeName as UsedSecuritySchemes<EndpointAuth>];\n\n if (strategy) {\n authHeaders = await resolveAuthHeaders(strategy, scheme);\n }\n }\n\n // Merge auth headers with config headers\n const existingHeaders =\n config && 'headers' in config && config.headers\n ? (config.headers as Record<string, string>)\n : {};\n\n const mergedConfig = {\n ...config,\n headers: {\n ...authHeaders,\n ...existingHeaders,\n },\n } as unknown as FilteredRequestConfig<Paths, T>;\n\n return baseFetcher.request(endpoint, mergedConfig);\n };\n\n return fetcher as TypedApiFunction<Paths>;\n}\n\n/**\n * Resolves auth headers based on the strategy and scheme.\n */\nasync function resolveAuthHeaders(\n strategy: AuthStrategy,\n scheme: SecuritySchemeObject,\n): Promise<Record<string, string>> {\n switch (strategy.type) {\n case 'bearer': {\n return strategy.tokenProvider.createValidAuthHeaders();\n }\n\n case 'apiKey': {\n const apiKey = await strategy.apiKeyProvider.getApiKey();\n const headerName = strategy.headerName || scheme.name || 'X-API-Key';\n\n if (scheme.in === 'header' || !scheme.in) {\n return { [headerName]: apiKey };\n }\n // Note: query and cookie API keys are handled differently\n // For now, we only support header-based API keys\n return {};\n }\n\n case 'iam': {\n // IAM signing requires the full URL and request config\n // This is a simplified version - full implementation would need\n // access to the complete request\n // For now, return empty - the actual signing should be done\n // in a custom onRequest interceptor if needed\n return {};\n }\n\n case 'none':\n default:\n return {};\n }\n}\n\n/**\n * Type helper to extract the security scheme ID from an endpoint.\n */\nexport type GetEndpointAuth<\n EndpointAuth extends Record<string, string | null>,\n Endpoint extends keyof EndpointAuth,\n> = EndpointAuth[Endpoint];\n\n/**\n * Type helper to get all authenticated endpoints.\n */\nexport type AuthenticatedEndpoints<\n EndpointAuth extends Record<string, string | null>,\n> = {\n [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 EndpointAuth extends Record<string, string | null>,\n> = {\n [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never;\n}[keyof EndpointAuth];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0JA,SAAgB,uBAWdA,SAGyB;CACzB,MAAM,EACJ,cACA,iBACA,gBACA,WAAW,cACX,GAAG,gBACJ,GAAG;CAGJ,MAAM,cAAc,IAAIC,6BAAoB;EAC1C,GAAG;EACH,WAAW;CACZ;CAED,MAAM,UAAU,OACdC,UACAC,WAC+C;EAE/C,MAAM,aAAa,aAAa;EAIhC,IAAIC,cAAsC,CAAE;AAE5C,MAAI,YAAY;GACd,MAAM,SAAS,gBAAgB;GAG/B,MAAM,WACJ,eAAe;AAEjB,OAAI,SACF,eAAc,MAAM,mBAAmB,UAAU,OAAO;EAE3D;EAGD,MAAM,kBACJ,UAAU,aAAa,UAAU,OAAO,UACnC,OAAO,UACR,CAAE;EAER,MAAM,eAAe;GACnB,GAAG;GACH,SAAS;IACP,GAAG;IACH,GAAG;GACJ;EACF;AAED,SAAO,YAAY,QAAQ,UAAU,aAAa;CACnD;AAED,QAAO;AACR;;;;AAKD,eAAe,mBACbC,UACAC,QACiC;AACjC,SAAQ,SAAS,MAAjB;EACE,KAAK,SACH,QAAO,SAAS,cAAc,wBAAwB;EAGxD,KAAK,UAAU;GACb,MAAM,SAAS,MAAM,SAAS,eAAe,WAAW;GACxD,MAAM,aAAa,SAAS,cAAc,OAAO,QAAQ;AAEzD,OAAI,OAAO,OAAO,aAAa,OAAO,GACpC,QAAO,GAAG,aAAa,OAAQ;AAIjC,UAAO,CAAE;EACV;EAED,KAAK,MAMH,QAAO,CAAE;EAGX,KAAK;EACL,QACE,QAAO,CAAE;CACZ;AACF"}
|
package/dist/auth-fetcher.d.cts
CHANGED
|
@@ -153,5 +153,5 @@ type AuthenticatedEndpoints<EndpointAuth extends Record<string, string | null>>
|
|
|
153
153
|
*/
|
|
154
154
|
type PublicEndpoints<EndpointAuth extends Record<string, string | null>> = { [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never }[keyof EndpointAuth];
|
|
155
155
|
//#endregion
|
|
156
|
-
export { ApiKeyProvider, AuthFetcherOptions, AuthStrategy, AuthenticatedEndpoints, AwsSigner, GetEndpointAuth, PublicEndpoints, SecuritySchemeObject, TokenProvider, UsedSecuritySchemes, createAuthAwareFetcher };
|
|
156
|
+
export { ApiKeyProvider, AuthFetcherOptions, AuthStrategy, AuthenticatedEndpoints, AwsSigner, FetcherOptions, GetEndpointAuth, PublicEndpoints, SecuritySchemeObject, TokenProvider, UsedSecuritySchemes, createAuthAwareFetcher };
|
|
157
157
|
//# sourceMappingURL=auth-fetcher.d.cts.map
|
package/dist/auth-fetcher.d.mts
CHANGED
|
@@ -153,5 +153,5 @@ type AuthenticatedEndpoints<EndpointAuth extends Record<string, string | null>>
|
|
|
153
153
|
*/
|
|
154
154
|
type PublicEndpoints<EndpointAuth extends Record<string, string | null>> = { [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never }[keyof EndpointAuth];
|
|
155
155
|
//#endregion
|
|
156
|
-
export { ApiKeyProvider, AuthFetcherOptions, AuthStrategy, AuthenticatedEndpoints, AwsSigner, GetEndpointAuth, PublicEndpoints, SecuritySchemeObject, TokenProvider, UsedSecuritySchemes, createAuthAwareFetcher };
|
|
156
|
+
export { ApiKeyProvider, AuthFetcherOptions, AuthStrategy, AuthenticatedEndpoints, AwsSigner, FetcherOptions, GetEndpointAuth, PublicEndpoints, SecuritySchemeObject, TokenProvider, UsedSecuritySchemes, createAuthAwareFetcher };
|
|
157
157
|
//# sourceMappingURL=auth-fetcher.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-fetcher.mjs","names":["options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n baseURL: string;\n }","endpoint: T","config?: FilteredRequestConfig<Paths, T>","authHeaders: Record<string, string>","strategy: AuthStrategy","scheme: SecuritySchemeObject"],"sources":["../src/auth-fetcher.ts"],"sourcesContent":["import { TypedFetcher } from './fetcher';\nimport type {\n ExtractEndpointResponse,\n FetcherOptions,\n FilteredRequestConfig,\n TypedApiFunction,\n TypedEndpoint,\n} from './types';\n\n/**\n * Security scheme object matching OpenAPI 3.1 specification.\n */\nexport interface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [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 EndpointAuth 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 /**\n * Get a valid access token, refreshing if necessary.\n */\n getValidAccessToken(): Promise<string | null>;\n\n /**\n * Create Authorization headers from the current token.\n */\n createValidAuthHeaders(): Promise<Record<string, string>>;\n}\n\n/**\n * Interface for API key providers.\n */\nexport interface ApiKeyProvider {\n /**\n * Get the API key value.\n */\n getApiKey(): Promise<string> | string;\n}\n\n/**\n * Interface for AWS SigV4 request signing.\n */\nexport interface AwsSigner {\n /**\n * Sign a request with AWS SigV4.\n * @param url - The request URL\n * @param init - The request init object\n * @returns Headers to add to the request\n */\n sign(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 | { type: 'bearer'; tokenProvider: TokenProvider }\n | { type: 'apiKey'; apiKeyProvider: ApiKeyProvider; headerName?: string }\n | { type: 'iam'; signer: AwsSigner }\n | { 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 EndpointAuth extends Record<string, string | null>,\n SecuritySchemes extends Record<string, SecuritySchemeObject>,\n> extends Omit<FetcherOptions, 'onRequest'> {\n /**\n * Runtime map of endpoints to their required auth scheme.\n * Generated by `gkm openapi --ts`.\n */\n endpointAuth: EndpointAuth;\n\n /**\n * Security scheme definitions.\n * Generated by `gkm openapi --ts`.\n */\n securitySchemes: SecuritySchemes;\n\n /**\n * Auth strategies for security schemes that are actually used.\n * Only schemes referenced in endpointAuth are required.\n *\n * @example\n * ```typescript\n * // If endpointAuth has: { 'GET /users': 'jwt', 'POST /data': 'iam', 'GET /public': null }\n * // Then authStrategies must include strategies for 'jwt' and 'iam'\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * iam: { type: 'iam', signer: awsSigner },\n * }\n * ```\n */\n authStrategies: Record<UsedSecuritySchemes<EndpointAuth>, AuthStrategy>;\n\n /**\n * Optional request interceptor (runs after auth headers are added).\n */\n onRequest?: (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 Paths,\n EndpointAuth extends Record<string, string | null> = Record<\n string,\n string | null\n >,\n SecuritySchemes extends Record<string, SecuritySchemeObject> = Record<\n string,\n SecuritySchemeObject\n >,\n>(\n options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n baseURL: string;\n },\n): TypedApiFunction<Paths> {\n const {\n endpointAuth,\n securitySchemes,\n authStrategies,\n onRequest: userOnRequest,\n ...fetcherOptions\n } = options;\n\n // Create base fetcher with user's onRequest if provided\n const baseFetcher = new TypedFetcher<Paths>({\n ...fetcherOptions,\n onRequest: userOnRequest,\n });\n\n const fetcher = async <T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ): Promise<ExtractEndpointResponse<Paths, T>> => {\n // Look up auth requirement for this endpoint\n const schemeName = endpointAuth[endpoint as keyof EndpointAuth] as\n | string\n | null;\n\n let authHeaders: Record<string, string> = {};\n\n if (schemeName) {\n const scheme = securitySchemes[schemeName as keyof SecuritySchemes];\n // Since authStrategies is now required to have all used schemes,\n // we can safely access it - TypeScript ensures the strategy exists\n const strategy =\n authStrategies[schemeName as UsedSecuritySchemes<EndpointAuth>];\n\n if (strategy) {\n authHeaders = await resolveAuthHeaders(strategy, scheme);\n }\n }\n\n // Merge auth headers with config headers\n const existingHeaders =\n config && 'headers' in config && config.headers\n ? (config.headers as Record<string, string>)\n : {};\n\n const mergedConfig = {\n ...config,\n headers: {\n ...authHeaders,\n ...existingHeaders,\n },\n } as unknown as FilteredRequestConfig<Paths, T>;\n\n return baseFetcher.request(endpoint, mergedConfig);\n };\n\n return fetcher as TypedApiFunction<Paths>;\n}\n\n/**\n * Resolves auth headers based on the strategy and scheme.\n */\nasync function resolveAuthHeaders(\n strategy: AuthStrategy,\n scheme: SecuritySchemeObject,\n): Promise<Record<string, string>> {\n switch (strategy.type) {\n case 'bearer': {\n return strategy.tokenProvider.createValidAuthHeaders();\n }\n\n case 'apiKey': {\n const apiKey = await strategy.apiKeyProvider.getApiKey();\n const headerName = strategy.headerName || scheme.name || 'X-API-Key';\n\n if (scheme.in === 'header' || !scheme.in) {\n return { [headerName]: apiKey };\n }\n // Note: query and cookie API keys are handled differently\n // For now, we only support header-based API keys\n return {};\n }\n\n case 'iam': {\n // IAM signing requires the full URL and request config\n // This is a simplified version - full implementation would need\n // access to the complete request\n // For now, return empty - the actual signing should be done\n // in a custom onRequest interceptor if needed\n return {};\n }\n\n case 'none':\n default:\n return {};\n }\n}\n\n/**\n * Type helper to extract the security scheme ID from an endpoint.\n */\nexport type GetEndpointAuth<\n EndpointAuth extends Record<string, string | null>,\n Endpoint extends keyof EndpointAuth,\n> = EndpointAuth[Endpoint];\n\n/**\n * Type helper to get all authenticated endpoints.\n */\nexport type AuthenticatedEndpoints<\n EndpointAuth extends Record<string, string | null>,\n> = {\n [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 EndpointAuth extends Record<string, string | null>,\n> = {\n [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never;\n}[keyof EndpointAuth];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"auth-fetcher.mjs","names":["options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n baseURL: string;\n }","endpoint: T","config?: FilteredRequestConfig<Paths, T>","authHeaders: Record<string, string>","strategy: AuthStrategy","scheme: SecuritySchemeObject"],"sources":["../src/auth-fetcher.ts"],"sourcesContent":["import { TypedFetcher } from './fetcher';\nimport type {\n ExtractEndpointResponse,\n FetcherOptions,\n FilteredRequestConfig,\n TypedApiFunction,\n TypedEndpoint,\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 type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [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 EndpointAuth 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 /**\n * Get a valid access token, refreshing if necessary.\n */\n getValidAccessToken(): Promise<string | null>;\n\n /**\n * Create Authorization headers from the current token.\n */\n createValidAuthHeaders(): Promise<Record<string, string>>;\n}\n\n/**\n * Interface for API key providers.\n */\nexport interface ApiKeyProvider {\n /**\n * Get the API key value.\n */\n getApiKey(): Promise<string> | string;\n}\n\n/**\n * Interface for AWS SigV4 request signing.\n */\nexport interface AwsSigner {\n /**\n * Sign a request with AWS SigV4.\n * @param url - The request URL\n * @param init - The request init object\n * @returns Headers to add to the request\n */\n sign(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 | { type: 'bearer'; tokenProvider: TokenProvider }\n | { type: 'apiKey'; apiKeyProvider: ApiKeyProvider; headerName?: string }\n | { type: 'iam'; signer: AwsSigner }\n | { 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 EndpointAuth extends Record<string, string | null>,\n SecuritySchemes extends Record<string, SecuritySchemeObject>,\n> extends Omit<FetcherOptions, 'onRequest'> {\n /**\n * Runtime map of endpoints to their required auth scheme.\n * Generated by `gkm openapi --ts`.\n */\n endpointAuth: EndpointAuth;\n\n /**\n * Security scheme definitions.\n * Generated by `gkm openapi --ts`.\n */\n securitySchemes: SecuritySchemes;\n\n /**\n * Auth strategies for security schemes that are actually used.\n * Only schemes referenced in endpointAuth are required.\n *\n * @example\n * ```typescript\n * // If endpointAuth has: { 'GET /users': 'jwt', 'POST /data': 'iam', 'GET /public': null }\n * // Then authStrategies must include strategies for 'jwt' and 'iam'\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * iam: { type: 'iam', signer: awsSigner },\n * }\n * ```\n */\n authStrategies: Record<UsedSecuritySchemes<EndpointAuth>, AuthStrategy>;\n\n /**\n * Optional request interceptor (runs after auth headers are added).\n */\n onRequest?: (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 Paths,\n EndpointAuth extends Record<string, string | null> = Record<\n string,\n string | null\n >,\n SecuritySchemes extends Record<string, SecuritySchemeObject> = Record<\n string,\n SecuritySchemeObject\n >,\n>(\n options: AuthFetcherOptions<EndpointAuth, SecuritySchemes> & {\n baseURL: string;\n },\n): TypedApiFunction<Paths> {\n const {\n endpointAuth,\n securitySchemes,\n authStrategies,\n onRequest: userOnRequest,\n ...fetcherOptions\n } = options;\n\n // Create base fetcher with user's onRequest if provided\n const baseFetcher = new TypedFetcher<Paths>({\n ...fetcherOptions,\n onRequest: userOnRequest,\n });\n\n const fetcher = async <T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ): Promise<ExtractEndpointResponse<Paths, T>> => {\n // Look up auth requirement for this endpoint\n const schemeName = endpointAuth[endpoint as keyof EndpointAuth] as\n | string\n | null;\n\n let authHeaders: Record<string, string> = {};\n\n if (schemeName) {\n const scheme = securitySchemes[schemeName as keyof SecuritySchemes];\n // Since authStrategies is now required to have all used schemes,\n // we can safely access it - TypeScript ensures the strategy exists\n const strategy =\n authStrategies[schemeName as UsedSecuritySchemes<EndpointAuth>];\n\n if (strategy) {\n authHeaders = await resolveAuthHeaders(strategy, scheme);\n }\n }\n\n // Merge auth headers with config headers\n const existingHeaders =\n config && 'headers' in config && config.headers\n ? (config.headers as Record<string, string>)\n : {};\n\n const mergedConfig = {\n ...config,\n headers: {\n ...authHeaders,\n ...existingHeaders,\n },\n } as unknown as FilteredRequestConfig<Paths, T>;\n\n return baseFetcher.request(endpoint, mergedConfig);\n };\n\n return fetcher as TypedApiFunction<Paths>;\n}\n\n/**\n * Resolves auth headers based on the strategy and scheme.\n */\nasync function resolveAuthHeaders(\n strategy: AuthStrategy,\n scheme: SecuritySchemeObject,\n): Promise<Record<string, string>> {\n switch (strategy.type) {\n case 'bearer': {\n return strategy.tokenProvider.createValidAuthHeaders();\n }\n\n case 'apiKey': {\n const apiKey = await strategy.apiKeyProvider.getApiKey();\n const headerName = strategy.headerName || scheme.name || 'X-API-Key';\n\n if (scheme.in === 'header' || !scheme.in) {\n return { [headerName]: apiKey };\n }\n // Note: query and cookie API keys are handled differently\n // For now, we only support header-based API keys\n return {};\n }\n\n case 'iam': {\n // IAM signing requires the full URL and request config\n // This is a simplified version - full implementation would need\n // access to the complete request\n // For now, return empty - the actual signing should be done\n // in a custom onRequest interceptor if needed\n return {};\n }\n\n case 'none':\n default:\n return {};\n }\n}\n\n/**\n * Type helper to extract the security scheme ID from an endpoint.\n */\nexport type GetEndpointAuth<\n EndpointAuth extends Record<string, string | null>,\n Endpoint extends keyof EndpointAuth,\n> = EndpointAuth[Endpoint];\n\n/**\n * Type helper to get all authenticated endpoints.\n */\nexport type AuthenticatedEndpoints<\n EndpointAuth extends Record<string, string | null>,\n> = {\n [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 EndpointAuth extends Record<string, string | null>,\n> = {\n [K in keyof EndpointAuth]: EndpointAuth[K] extends null ? K : never;\n}[keyof EndpointAuth];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0JA,SAAgB,uBAWdA,SAGyB;CACzB,MAAM,EACJ,cACA,iBACA,gBACA,WAAW,cACX,GAAG,gBACJ,GAAG;CAGJ,MAAM,cAAc,IAAI,aAAoB;EAC1C,GAAG;EACH,WAAW;CACZ;CAED,MAAM,UAAU,OACdC,UACAC,WAC+C;EAE/C,MAAM,aAAa,aAAa;EAIhC,IAAIC,cAAsC,CAAE;AAE5C,MAAI,YAAY;GACd,MAAM,SAAS,gBAAgB;GAG/B,MAAM,WACJ,eAAe;AAEjB,OAAI,SACF,eAAc,MAAM,mBAAmB,UAAU,OAAO;EAE3D;EAGD,MAAM,kBACJ,UAAU,aAAa,UAAU,OAAO,UACnC,OAAO,UACR,CAAE;EAER,MAAM,eAAe;GACnB,GAAG;GACH,SAAS;IACP,GAAG;IACH,GAAG;GACJ;EACF;AAED,SAAO,YAAY,QAAQ,UAAU,aAAa;CACnD;AAED,QAAO;AACR;;;;AAKD,eAAe,mBACbC,UACAC,QACiC;AACjC,SAAQ,SAAS,MAAjB;EACE,KAAK,SACH,QAAO,SAAS,cAAc,wBAAwB;EAGxD,KAAK,UAAU;GACb,MAAM,SAAS,MAAM,SAAS,eAAe,WAAW;GACxD,MAAM,aAAa,SAAS,cAAc,OAAO,QAAQ;AAEzD,OAAI,OAAO,OAAO,aAAa,OAAO,GACpC,QAAO,GAAG,aAAa,OAAQ;AAIjC,UAAO,CAAE;EACV;EAED,KAAK,MAMH,QAAO,CAAE;EAGX,KAAK;EACL,QACE,QAAO,CAAE;CACZ;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetcher-DLDD_7Sa.mjs","names":["fn?: FetchFn","options: FetcherOptions","endpoint: T","config?: FilteredRequestConfig<Paths, T>","prefix: string","value: unknown","requestConfig: RequestInit","options?: FetcherOptions"],"sources":["../src/fetcher.ts"],"sourcesContent":["import type {\n EndpointString,\n ExtractEndpointResponse,\n FetcherOptions,\n FilteredRequestConfig,\n ParseEndpoint,\n TypedEndpoint,\n} from './types';\n\nexport class TypedFetcher<Paths> {\n private baseURL: string;\n private defaultHeaders: Record<string, string>;\n private options: FetcherOptions;\n private fetchFn: FetchFn;\n\n static getFetchFn(fn?: FetchFn): FetchFn {\n if (fn) {\n return fn;\n }\n\n if (typeof window !== 'undefined' && typeof window.fetch === 'function') {\n return window.fetch.bind(window);\n }\n\n if (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch === 'function'\n ) {\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new Error('No fetch implementation found');\n }\n\n constructor(options: FetcherOptions = {}) {\n this.baseURL = options.baseURL || '';\n this.defaultHeaders = options.headers || {};\n this.options = options;\n this.fetchFn = TypedFetcher.getFetchFn(options.fetch);\n }\n\n async request<T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ): Promise<ExtractEndpointResponse<Paths, T>> {\n const { method, route } = this.parseEndpoint(endpoint);\n\n // Replace path parameters\n let url = route;\n if (config && 'params' in config && config.params) {\n Object.entries(config.params as Record<string, unknown>).forEach(\n ([key, value]) => {\n url = url.replace(`{${key}}`, encodeURIComponent(String(value)));\n },\n );\n }\n\n // Add query parameters\n if (config && 'query' in config && config.query) {\n const queryParams = new URLSearchParams();\n\n // Recursive function to handle nested objects and arrays\n const appendQueryParam = (prefix: string, value: unknown) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (Array.isArray(value)) {\n // Handle arrays by appending multiple values with the same key\n value.forEach((item) => {\n queryParams.append(prefix, String(item));\n });\n } else if (typeof value === 'object') {\n // For objects, recursively flatten into dot notation\n Object.entries(value as Record<string, unknown>).forEach(\n ([subKey, subValue]) => {\n appendQueryParam(`${prefix}.${subKey}`, subValue);\n },\n );\n } else {\n queryParams.append(prefix, String(value));\n }\n };\n\n // Process all query parameters\n Object.entries(config.query as Record<string, unknown>).forEach(\n ([key, value]) => {\n appendQueryParam(key, value);\n },\n );\n\n const queryString = queryParams.toString();\n if (queryString) {\n url += `?${queryString}`;\n }\n }\n\n // Build request configuration\n let requestConfig: RequestInit = {\n method: method.toUpperCase(),\n headers: {\n ...this.defaultHeaders,\n ...((config && 'headers' in config && config.headers) || {}),\n },\n };\n\n // Add body if present\n if (config && 'body' in config && config.body) {\n requestConfig.body = JSON.stringify(config.body);\n requestConfig.headers = {\n ...requestConfig.headers,\n 'Content-Type': 'application/json',\n };\n }\n\n // Apply request interceptor\n if (this.options.onRequest) {\n requestConfig = await this.options.onRequest(requestConfig);\n }\n\n try {\n // Make the request\n let response = await this.fetchFn(`${this.baseURL}${url}`, requestConfig);\n\n // Apply response interceptor\n if (this.options.onResponse) {\n response = await this.options.onResponse(response);\n }\n\n // Handle errors\n if (!response.ok) {\n throw response;\n }\n\n // Handle empty responses (204 No Content, etc.)\n if (\n response.status === 204 ||\n response.headers.get('content-length') === '0'\n ) {\n return undefined as ExtractEndpointResponse<Paths, T>;\n }\n\n // Parse JSON response\n const data = await response.json();\n return data as ExtractEndpointResponse<Paths, T>;\n } catch (error) {\n // Apply error handler\n if (this.options.onError) {\n // @ts-ignore\n await this.options.onError(error);\n }\n throw error;\n }\n }\n\n private parseEndpoint<T extends EndpointString>(\n endpoint: T,\n ): ParseEndpoint<T> {\n const [method, ...routeParts] = endpoint.split(' ');\n const route = routeParts.join(' ');\n return { method: method.toLowerCase(), route } as ParseEndpoint<T>;\n }\n}\n\nexport function createTypedFetcher<Paths>(options?: FetcherOptions) {\n const fetcher = new TypedFetcher<Paths>(options);\n return <T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ) => fetcher.request(endpoint, config);\n}\n\nexport type FetchFn = typeof fetch;\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"fetcher-DLDD_7Sa.mjs","names":["fn?: FetchFn","options: FetcherOptions","endpoint: T","config?: FilteredRequestConfig<Paths, T>","prefix: string","value: unknown","requestConfig: RequestInit","options?: FetcherOptions"],"sources":["../src/fetcher.ts"],"sourcesContent":["import type {\n EndpointString,\n ExtractEndpointResponse,\n FetcherOptions,\n FilteredRequestConfig,\n ParseEndpoint,\n TypedEndpoint,\n} from './types';\n\nexport type { FetcherOptions } from './types';\n\nexport class TypedFetcher<Paths> {\n private baseURL: string;\n private defaultHeaders: Record<string, string>;\n private options: FetcherOptions;\n private fetchFn: FetchFn;\n\n static getFetchFn(fn?: FetchFn): FetchFn {\n if (fn) {\n return fn;\n }\n\n if (typeof window !== 'undefined' && typeof window.fetch === 'function') {\n return window.fetch.bind(window);\n }\n\n if (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch === 'function'\n ) {\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new Error('No fetch implementation found');\n }\n\n constructor(options: FetcherOptions = {}) {\n this.baseURL = options.baseURL || '';\n this.defaultHeaders = options.headers || {};\n this.options = options;\n this.fetchFn = TypedFetcher.getFetchFn(options.fetch);\n }\n\n async request<T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ): Promise<ExtractEndpointResponse<Paths, T>> {\n const { method, route } = this.parseEndpoint(endpoint);\n\n // Replace path parameters\n let url = route;\n if (config && 'params' in config && config.params) {\n Object.entries(config.params as Record<string, unknown>).forEach(\n ([key, value]) => {\n url = url.replace(`{${key}}`, encodeURIComponent(String(value)));\n },\n );\n }\n\n // Add query parameters\n if (config && 'query' in config && config.query) {\n const queryParams = new URLSearchParams();\n\n // Recursive function to handle nested objects and arrays\n const appendQueryParam = (prefix: string, value: unknown) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (Array.isArray(value)) {\n // Handle arrays by appending multiple values with the same key\n value.forEach((item) => {\n queryParams.append(prefix, String(item));\n });\n } else if (typeof value === 'object') {\n // For objects, recursively flatten into dot notation\n Object.entries(value as Record<string, unknown>).forEach(\n ([subKey, subValue]) => {\n appendQueryParam(`${prefix}.${subKey}`, subValue);\n },\n );\n } else {\n queryParams.append(prefix, String(value));\n }\n };\n\n // Process all query parameters\n Object.entries(config.query as Record<string, unknown>).forEach(\n ([key, value]) => {\n appendQueryParam(key, value);\n },\n );\n\n const queryString = queryParams.toString();\n if (queryString) {\n url += `?${queryString}`;\n }\n }\n\n // Build request configuration\n let requestConfig: RequestInit = {\n method: method.toUpperCase(),\n headers: {\n ...this.defaultHeaders,\n ...((config && 'headers' in config && config.headers) || {}),\n },\n };\n\n // Add body if present\n if (config && 'body' in config && config.body) {\n requestConfig.body = JSON.stringify(config.body);\n requestConfig.headers = {\n ...requestConfig.headers,\n 'Content-Type': 'application/json',\n };\n }\n\n // Apply request interceptor\n if (this.options.onRequest) {\n requestConfig = await this.options.onRequest(requestConfig);\n }\n\n try {\n // Make the request\n let response = await this.fetchFn(`${this.baseURL}${url}`, requestConfig);\n\n // Apply response interceptor\n if (this.options.onResponse) {\n response = await this.options.onResponse(response);\n }\n\n // Handle errors\n if (!response.ok) {\n throw response;\n }\n\n // Handle empty responses (204 No Content, etc.)\n if (\n response.status === 204 ||\n response.headers.get('content-length') === '0'\n ) {\n return undefined as ExtractEndpointResponse<Paths, T>;\n }\n\n // Parse JSON response\n const data = await response.json();\n return data as ExtractEndpointResponse<Paths, T>;\n } catch (error) {\n // Apply error handler\n if (this.options.onError) {\n // @ts-ignore\n await this.options.onError(error);\n }\n throw error;\n }\n }\n\n private parseEndpoint<T extends EndpointString>(\n endpoint: T,\n ): ParseEndpoint<T> {\n const [method, ...routeParts] = endpoint.split(' ');\n const route = routeParts.join(' ');\n return { method: method.toLowerCase(), route } as ParseEndpoint<T>;\n }\n}\n\nexport function createTypedFetcher<Paths>(options?: FetcherOptions) {\n const fetcher = new TypedFetcher<Paths>(options);\n return <T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ) => fetcher.request(endpoint, config);\n}\n\nexport type FetchFn = typeof fetch;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetcher-KdwHgdAl.cjs","names":["fn?: FetchFn","options: FetcherOptions","endpoint: T","config?: FilteredRequestConfig<Paths, T>","prefix: string","value: unknown","requestConfig: RequestInit","options?: FetcherOptions"],"sources":["../src/fetcher.ts"],"sourcesContent":["import type {\n EndpointString,\n ExtractEndpointResponse,\n FetcherOptions,\n FilteredRequestConfig,\n ParseEndpoint,\n TypedEndpoint,\n} from './types';\n\nexport class TypedFetcher<Paths> {\n private baseURL: string;\n private defaultHeaders: Record<string, string>;\n private options: FetcherOptions;\n private fetchFn: FetchFn;\n\n static getFetchFn(fn?: FetchFn): FetchFn {\n if (fn) {\n return fn;\n }\n\n if (typeof window !== 'undefined' && typeof window.fetch === 'function') {\n return window.fetch.bind(window);\n }\n\n if (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch === 'function'\n ) {\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new Error('No fetch implementation found');\n }\n\n constructor(options: FetcherOptions = {}) {\n this.baseURL = options.baseURL || '';\n this.defaultHeaders = options.headers || {};\n this.options = options;\n this.fetchFn = TypedFetcher.getFetchFn(options.fetch);\n }\n\n async request<T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ): Promise<ExtractEndpointResponse<Paths, T>> {\n const { method, route } = this.parseEndpoint(endpoint);\n\n // Replace path parameters\n let url = route;\n if (config && 'params' in config && config.params) {\n Object.entries(config.params as Record<string, unknown>).forEach(\n ([key, value]) => {\n url = url.replace(`{${key}}`, encodeURIComponent(String(value)));\n },\n );\n }\n\n // Add query parameters\n if (config && 'query' in config && config.query) {\n const queryParams = new URLSearchParams();\n\n // Recursive function to handle nested objects and arrays\n const appendQueryParam = (prefix: string, value: unknown) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (Array.isArray(value)) {\n // Handle arrays by appending multiple values with the same key\n value.forEach((item) => {\n queryParams.append(prefix, String(item));\n });\n } else if (typeof value === 'object') {\n // For objects, recursively flatten into dot notation\n Object.entries(value as Record<string, unknown>).forEach(\n ([subKey, subValue]) => {\n appendQueryParam(`${prefix}.${subKey}`, subValue);\n },\n );\n } else {\n queryParams.append(prefix, String(value));\n }\n };\n\n // Process all query parameters\n Object.entries(config.query as Record<string, unknown>).forEach(\n ([key, value]) => {\n appendQueryParam(key, value);\n },\n );\n\n const queryString = queryParams.toString();\n if (queryString) {\n url += `?${queryString}`;\n }\n }\n\n // Build request configuration\n let requestConfig: RequestInit = {\n method: method.toUpperCase(),\n headers: {\n ...this.defaultHeaders,\n ...((config && 'headers' in config && config.headers) || {}),\n },\n };\n\n // Add body if present\n if (config && 'body' in config && config.body) {\n requestConfig.body = JSON.stringify(config.body);\n requestConfig.headers = {\n ...requestConfig.headers,\n 'Content-Type': 'application/json',\n };\n }\n\n // Apply request interceptor\n if (this.options.onRequest) {\n requestConfig = await this.options.onRequest(requestConfig);\n }\n\n try {\n // Make the request\n let response = await this.fetchFn(`${this.baseURL}${url}`, requestConfig);\n\n // Apply response interceptor\n if (this.options.onResponse) {\n response = await this.options.onResponse(response);\n }\n\n // Handle errors\n if (!response.ok) {\n throw response;\n }\n\n // Handle empty responses (204 No Content, etc.)\n if (\n response.status === 204 ||\n response.headers.get('content-length') === '0'\n ) {\n return undefined as ExtractEndpointResponse<Paths, T>;\n }\n\n // Parse JSON response\n const data = await response.json();\n return data as ExtractEndpointResponse<Paths, T>;\n } catch (error) {\n // Apply error handler\n if (this.options.onError) {\n // @ts-ignore\n await this.options.onError(error);\n }\n throw error;\n }\n }\n\n private parseEndpoint<T extends EndpointString>(\n endpoint: T,\n ): ParseEndpoint<T> {\n const [method, ...routeParts] = endpoint.split(' ');\n const route = routeParts.join(' ');\n return { method: method.toLowerCase(), route } as ParseEndpoint<T>;\n }\n}\n\nexport function createTypedFetcher<Paths>(options?: FetcherOptions) {\n const fetcher = new TypedFetcher<Paths>(options);\n return <T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ) => fetcher.request(endpoint, config);\n}\n\nexport type FetchFn = typeof fetch;\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"fetcher-KdwHgdAl.cjs","names":["fn?: FetchFn","options: FetcherOptions","endpoint: T","config?: FilteredRequestConfig<Paths, T>","prefix: string","value: unknown","requestConfig: RequestInit","options?: FetcherOptions"],"sources":["../src/fetcher.ts"],"sourcesContent":["import type {\n EndpointString,\n ExtractEndpointResponse,\n FetcherOptions,\n FilteredRequestConfig,\n ParseEndpoint,\n TypedEndpoint,\n} from './types';\n\nexport type { FetcherOptions } from './types';\n\nexport class TypedFetcher<Paths> {\n private baseURL: string;\n private defaultHeaders: Record<string, string>;\n private options: FetcherOptions;\n private fetchFn: FetchFn;\n\n static getFetchFn(fn?: FetchFn): FetchFn {\n if (fn) {\n return fn;\n }\n\n if (typeof window !== 'undefined' && typeof window.fetch === 'function') {\n return window.fetch.bind(window);\n }\n\n if (\n typeof globalThis !== 'undefined' &&\n typeof globalThis.fetch === 'function'\n ) {\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new Error('No fetch implementation found');\n }\n\n constructor(options: FetcherOptions = {}) {\n this.baseURL = options.baseURL || '';\n this.defaultHeaders = options.headers || {};\n this.options = options;\n this.fetchFn = TypedFetcher.getFetchFn(options.fetch);\n }\n\n async request<T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ): Promise<ExtractEndpointResponse<Paths, T>> {\n const { method, route } = this.parseEndpoint(endpoint);\n\n // Replace path parameters\n let url = route;\n if (config && 'params' in config && config.params) {\n Object.entries(config.params as Record<string, unknown>).forEach(\n ([key, value]) => {\n url = url.replace(`{${key}}`, encodeURIComponent(String(value)));\n },\n );\n }\n\n // Add query parameters\n if (config && 'query' in config && config.query) {\n const queryParams = new URLSearchParams();\n\n // Recursive function to handle nested objects and arrays\n const appendQueryParam = (prefix: string, value: unknown) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (Array.isArray(value)) {\n // Handle arrays by appending multiple values with the same key\n value.forEach((item) => {\n queryParams.append(prefix, String(item));\n });\n } else if (typeof value === 'object') {\n // For objects, recursively flatten into dot notation\n Object.entries(value as Record<string, unknown>).forEach(\n ([subKey, subValue]) => {\n appendQueryParam(`${prefix}.${subKey}`, subValue);\n },\n );\n } else {\n queryParams.append(prefix, String(value));\n }\n };\n\n // Process all query parameters\n Object.entries(config.query as Record<string, unknown>).forEach(\n ([key, value]) => {\n appendQueryParam(key, value);\n },\n );\n\n const queryString = queryParams.toString();\n if (queryString) {\n url += `?${queryString}`;\n }\n }\n\n // Build request configuration\n let requestConfig: RequestInit = {\n method: method.toUpperCase(),\n headers: {\n ...this.defaultHeaders,\n ...((config && 'headers' in config && config.headers) || {}),\n },\n };\n\n // Add body if present\n if (config && 'body' in config && config.body) {\n requestConfig.body = JSON.stringify(config.body);\n requestConfig.headers = {\n ...requestConfig.headers,\n 'Content-Type': 'application/json',\n };\n }\n\n // Apply request interceptor\n if (this.options.onRequest) {\n requestConfig = await this.options.onRequest(requestConfig);\n }\n\n try {\n // Make the request\n let response = await this.fetchFn(`${this.baseURL}${url}`, requestConfig);\n\n // Apply response interceptor\n if (this.options.onResponse) {\n response = await this.options.onResponse(response);\n }\n\n // Handle errors\n if (!response.ok) {\n throw response;\n }\n\n // Handle empty responses (204 No Content, etc.)\n if (\n response.status === 204 ||\n response.headers.get('content-length') === '0'\n ) {\n return undefined as ExtractEndpointResponse<Paths, T>;\n }\n\n // Parse JSON response\n const data = await response.json();\n return data as ExtractEndpointResponse<Paths, T>;\n } catch (error) {\n // Apply error handler\n if (this.options.onError) {\n // @ts-ignore\n await this.options.onError(error);\n }\n throw error;\n }\n }\n\n private parseEndpoint<T extends EndpointString>(\n endpoint: T,\n ): ParseEndpoint<T> {\n const [method, ...routeParts] = endpoint.split(' ');\n const route = routeParts.join(' ');\n return { method: method.toLowerCase(), route } as ParseEndpoint<T>;\n }\n}\n\nexport function createTypedFetcher<Paths>(options?: FetcherOptions) {\n const fetcher = new TypedFetcher<Paths>(options);\n return <T extends TypedEndpoint<Paths>>(\n endpoint: T,\n config?: FilteredRequestConfig<Paths, T>,\n ) => fetcher.request(endpoint, config);\n}\n\nexport type FetchFn = typeof fetch;\n"],"mappings":";;AAWA,IAAa,eAAb,MAAa,aAAoB;CAC/B,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,OAAO,WAAWA,IAAuB;AACvC,MAAI,GACF,QAAO;AAGT,aAAW,WAAW,sBAAsB,OAAO,UAAU,WAC3D,QAAO,OAAO,MAAM,KAAK,OAAO;AAGlC,aACS,eAAe,sBACf,WAAW,UAAU,WAE5B,QAAO,WAAW,MAAM,KAAK,WAAW;AAG1C,QAAM,IAAI,MAAM;CACjB;CAED,YAAYC,UAA0B,CAAE,GAAE;AACxC,OAAK,UAAU,QAAQ,WAAW;AAClC,OAAK,iBAAiB,QAAQ,WAAW,CAAE;AAC3C,OAAK,UAAU;AACf,OAAK,UAAU,aAAa,WAAW,QAAQ,MAAM;CACtD;CAED,MAAM,QACJC,UACAC,QAC4C;EAC5C,MAAM,EAAE,QAAQ,OAAO,GAAG,KAAK,cAAc,SAAS;EAGtD,IAAI,MAAM;AACV,MAAI,UAAU,YAAY,UAAU,OAAO,OACzC,QAAO,QAAQ,OAAO,OAAkC,CAAC,QACvD,CAAC,CAAC,KAAK,MAAM,KAAK;AAChB,SAAM,IAAI,SAAS,GAAG,IAAI,IAAI,mBAAmB,OAAO,MAAM,CAAC,CAAC;EACjE,EACF;AAIH,MAAI,UAAU,WAAW,UAAU,OAAO,OAAO;GAC/C,MAAM,cAAc,IAAI;GAGxB,MAAM,mBAAmB,CAACC,QAAgBC,UAAmB;AAC3D,QAAI,oBAAuB,UAAU,KACnC;AAGF,QAAI,MAAM,QAAQ,MAAM,CAEtB,OAAM,QAAQ,CAAC,SAAS;AACtB,iBAAY,OAAO,QAAQ,OAAO,KAAK,CAAC;IACzC,EAAC;oBACc,UAAU,SAE1B,QAAO,QAAQ,MAAiC,CAAC,QAC/C,CAAC,CAAC,QAAQ,SAAS,KAAK;AACtB,uBAAkB,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS;IAClD,EACF;QAED,aAAY,OAAO,QAAQ,OAAO,MAAM,CAAC;GAE5C;AAGD,UAAO,QAAQ,OAAO,MAAiC,CAAC,QACtD,CAAC,CAAC,KAAK,MAAM,KAAK;AAChB,qBAAiB,KAAK,MAAM;GAC7B,EACF;GAED,MAAM,cAAc,YAAY,UAAU;AAC1C,OAAI,YACF,SAAQ,GAAG,YAAY;EAE1B;EAGD,IAAIC,gBAA6B;GAC/B,QAAQ,OAAO,aAAa;GAC5B,SAAS;IACP,GAAG,KAAK;IACR,GAAK,UAAU,aAAa,UAAU,OAAO,WAAY,CAAE;GAC5D;EACF;AAGD,MAAI,UAAU,UAAU,UAAU,OAAO,MAAM;AAC7C,iBAAc,OAAO,KAAK,UAAU,OAAO,KAAK;AAChD,iBAAc,UAAU;IACtB,GAAG,cAAc;IACjB,gBAAgB;GACjB;EACF;AAGD,MAAI,KAAK,QAAQ,UACf,iBAAgB,MAAM,KAAK,QAAQ,UAAU,cAAc;AAG7D,MAAI;GAEF,IAAI,WAAW,MAAM,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,IAAI,GAAG,cAAc;AAGzE,OAAI,KAAK,QAAQ,WACf,YAAW,MAAM,KAAK,QAAQ,WAAW,SAAS;AAIpD,QAAK,SAAS,GACZ,OAAM;AAIR,OACE,SAAS,WAAW,OACpB,SAAS,QAAQ,IAAI,iBAAiB,KAAK,IAE3C;GAIF,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,UAAO;EACR,SAAQ,OAAO;AAEd,OAAI,KAAK,QAAQ,QAEf,OAAM,KAAK,QAAQ,QAAQ,MAAM;AAEnC,SAAM;EACP;CACF;CAED,AAAQ,cACNJ,UACkB;EAClB,MAAM,CAAC,QAAQ,GAAG,WAAW,GAAG,SAAS,MAAM,IAAI;EACnD,MAAM,QAAQ,WAAW,KAAK,IAAI;AAClC,SAAO;GAAE,QAAQ,OAAO,aAAa;GAAE;EAAO;CAC/C;AACF;AAED,SAAgB,mBAA0BK,SAA0B;CAClE,MAAM,UAAU,IAAI,aAAoB;AACxC,QAAO,CACLL,UACAC,WACG,QAAQ,QAAQ,UAAU,OAAO;AACvC"}
|
package/dist/fetcher.d.cts
CHANGED
|
@@ -14,5 +14,5 @@ declare class TypedFetcher<Paths> {
|
|
|
14
14
|
declare function createTypedFetcher<Paths>(options?: FetcherOptions): <T extends TypedEndpoint<Paths>>(endpoint: T, config?: FilteredRequestConfig<Paths, T>) => Promise<ExtractEndpointResponse<Paths, T>>;
|
|
15
15
|
type FetchFn = typeof fetch;
|
|
16
16
|
//#endregion
|
|
17
|
-
export { FetchFn, TypedFetcher, createTypedFetcher };
|
|
17
|
+
export { FetchFn, FetcherOptions, TypedFetcher, createTypedFetcher };
|
|
18
18
|
//# sourceMappingURL=fetcher.d.cts.map
|
package/dist/fetcher.d.mts
CHANGED
|
@@ -14,5 +14,5 @@ declare class TypedFetcher<Paths> {
|
|
|
14
14
|
declare function createTypedFetcher<Paths>(options?: FetcherOptions): <T extends TypedEndpoint<Paths>>(endpoint: T, config?: FilteredRequestConfig<Paths, T>) => Promise<ExtractEndpointResponse<Paths, T>>;
|
|
15
15
|
type FetchFn = typeof fetch;
|
|
16
16
|
//#endregion
|
|
17
|
-
export { FetchFn, TypedFetcher, createTypedFetcher };
|
|
17
|
+
export { FetchFn, FetcherOptions, TypedFetcher, createTypedFetcher };
|
|
18
18
|
//# sourceMappingURL=fetcher.d.mts.map
|
package/dist/openapi-hooks.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FetcherOptions } from "./types-D4OSWveN.cjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _tanstack_react_query0 from "@tanstack/react-query";
|
|
3
3
|
import { UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
|
|
4
4
|
|
|
5
5
|
//#region src/openapi-hooks.d.ts
|
|
@@ -91,8 +91,8 @@ interface OperationRegistry {
|
|
|
91
91
|
declare function createOpenAPIHooks<Paths>(options?: FetcherOptions & {
|
|
92
92
|
operations?: OperationRegistry;
|
|
93
93
|
}): {
|
|
94
|
-
useQuery: <OpId extends OperationsByMethod<Paths, "get">>(operationId: OpId, config?: RemoveNever<OperationParams<Paths, OpId>>, options?: Omit<UseQueryOptions<OperationResponse<Paths, OpId>, Error>, "queryKey" | "queryFn">) =>
|
|
95
|
-
useMutation: <OpId extends Exclude<OperationId<Paths>, OperationsByMethod<Paths, "get">>>(operationId: OpId, options?: Omit<UseMutationOptions<OperationResponse<Paths, OpId>, Error, RemoveNever<OperationParams<Paths, OpId>>>, "mutationFn">) =>
|
|
94
|
+
useQuery: <OpId extends OperationsByMethod<Paths, "get">>(operationId: OpId, config?: RemoveNever<OperationParams<Paths, OpId>>, options?: Omit<UseQueryOptions<OperationResponse<Paths, OpId>, Error>, "queryKey" | "queryFn">) => _tanstack_react_query0.UseQueryResult<_tanstack_react_query0.NoInfer<OperationResponse<Paths, OpId>>, Error>;
|
|
95
|
+
useMutation: <OpId extends Exclude<OperationId<Paths>, OperationsByMethod<Paths, "get">>>(operationId: OpId, options?: Omit<UseMutationOptions<OperationResponse<Paths, OpId>, Error, RemoveNever<OperationParams<Paths, OpId>>>, "mutationFn">) => _tanstack_react_query0.UseMutationResult<OperationResponse<Paths, OpId>, Error, RemoveNever<OperationParams<Paths, OpId>>, unknown>;
|
|
96
96
|
};
|
|
97
97
|
//#endregion
|
|
98
98
|
export { createOpenAPIHooks };
|
package/dist/react-query.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExtractEndpointResponse, FetcherOptions, FilteredRequestConfig, MutationEndpoint, QueryEndpoint, TypedEndpoint } from "./types-D4OSWveN.cjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _tanstack_react_query3 from "@tanstack/react-query";
|
|
3
3
|
import { QueryClient, UseInfiniteQueryOptions, UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
|
|
4
4
|
|
|
5
5
|
//#region src/react-query.d.ts
|
|
@@ -10,15 +10,15 @@ declare class TypedQueryClient<Paths> {
|
|
|
10
10
|
private fetcher;
|
|
11
11
|
private queryClient?;
|
|
12
12
|
constructor(options?: TypedQueryClientOptions);
|
|
13
|
-
useQuery<T extends QueryEndpoint<Paths>>(endpoint: T, config?: FilteredRequestConfig<Paths, T>, options?: Omit<UseQueryOptions<ExtractEndpointResponse<Paths, T>, Response>, 'queryKey' | 'queryFn'>):
|
|
14
|
-
useMutation<T extends MutationEndpoint<Paths>>(endpoint: T, options?: Omit<UseMutationOptions<ExtractEndpointResponse<Paths, T>, Response, FilteredRequestConfig<Paths, T>>, 'mutationFn'>):
|
|
13
|
+
useQuery<T extends QueryEndpoint<Paths>>(endpoint: T, config?: FilteredRequestConfig<Paths, T>, options?: Omit<UseQueryOptions<ExtractEndpointResponse<Paths, T>, Response>, 'queryKey' | 'queryFn'>): _tanstack_react_query3.UseQueryResult<_tanstack_react_query3.NoInfer<ExtractEndpointResponse<Paths, T>>, Response>;
|
|
14
|
+
useMutation<T extends MutationEndpoint<Paths>>(endpoint: T, options?: Omit<UseMutationOptions<ExtractEndpointResponse<Paths, T>, Response, FilteredRequestConfig<Paths, T>>, 'mutationFn'>): _tanstack_react_query3.UseMutationResult<ExtractEndpointResponse<Paths, T>, Response, FilteredRequestConfig<Paths, T>, unknown>;
|
|
15
15
|
useInfiniteQuery<T extends QueryEndpoint<Paths>, TPageData = ExtractEndpointResponse<Paths, T>, TPageParam = unknown>(endpoint: T, options: Omit<UseInfiniteQueryOptions<TPageData, Response, {
|
|
16
16
|
pages: TPageData[];
|
|
17
17
|
pageParams: TPageParam[];
|
|
18
18
|
}, unknown[], TPageParam>, 'queryKey' | 'queryFn' | 'getNextPageParam' | 'initialPageParam'> & {
|
|
19
19
|
getNextPageParam: (lastPage: TPageData, allPages: TPageData[], lastPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | undefined;
|
|
20
20
|
initialPageParam: TPageParam;
|
|
21
|
-
}, config?: FilteredRequestConfig<Paths, T>):
|
|
21
|
+
}, config?: FilteredRequestConfig<Paths, T>): _tanstack_react_query3.UseInfiniteQueryResult<{
|
|
22
22
|
pages: TPageData[];
|
|
23
23
|
pageParams: TPageParam[];
|
|
24
24
|
}, Response>;
|
|
@@ -47,15 +47,15 @@ declare class TypedQueryClient<Paths> {
|
|
|
47
47
|
setQueryClient(queryClient: QueryClient): void;
|
|
48
48
|
}
|
|
49
49
|
declare function createTypedQueryClient<Paths>(options?: TypedQueryClientOptions): TypedQueryClient<Paths>;
|
|
50
|
-
declare function useTypedQuery<Paths, T extends QueryEndpoint<Paths>>(client: TypedQueryClient<Paths>, endpoint: T, config?: FilteredRequestConfig<Paths, T>, options?: Omit<UseQueryOptions<ExtractEndpointResponse<Paths, T>, Response>, 'queryKey' | 'queryFn'>):
|
|
51
|
-
declare function useTypedMutation<Paths, T extends MutationEndpoint<Paths>>(client: TypedQueryClient<Paths>, endpoint: T, options?: Omit<UseMutationOptions<ExtractEndpointResponse<Paths, T>, Response, FilteredRequestConfig<Paths, T>>, 'mutationFn'>):
|
|
50
|
+
declare function useTypedQuery<Paths, T extends QueryEndpoint<Paths>>(client: TypedQueryClient<Paths>, endpoint: T, config?: FilteredRequestConfig<Paths, T>, options?: Omit<UseQueryOptions<ExtractEndpointResponse<Paths, T>, Response>, 'queryKey' | 'queryFn'>): _tanstack_react_query3.UseQueryResult<_tanstack_react_query3.NoInfer<ExtractEndpointResponse<Paths, T>>, Response>;
|
|
51
|
+
declare function useTypedMutation<Paths, T extends MutationEndpoint<Paths>>(client: TypedQueryClient<Paths>, endpoint: T, options?: Omit<UseMutationOptions<ExtractEndpointResponse<Paths, T>, Response, FilteredRequestConfig<Paths, T>>, 'mutationFn'>): _tanstack_react_query3.UseMutationResult<ExtractEndpointResponse<Paths, T>, Response, FilteredRequestConfig<Paths, T>, unknown>;
|
|
52
52
|
declare function useTypedInfiniteQuery<Paths, T extends QueryEndpoint<Paths>, TPageData = ExtractEndpointResponse<Paths, T>, TPageParam = unknown>(client: TypedQueryClient<Paths>, endpoint: T, options: Omit<UseInfiniteQueryOptions<TPageData, Response, {
|
|
53
53
|
pages: TPageData[];
|
|
54
54
|
pageParams: TPageParam[];
|
|
55
55
|
}, unknown[], TPageParam>, 'queryKey' | 'queryFn' | 'getNextPageParam' | 'initialPageParam'> & {
|
|
56
56
|
getNextPageParam: (lastPage: TPageData, allPages: TPageData[], lastPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | undefined;
|
|
57
57
|
initialPageParam: TPageParam;
|
|
58
|
-
}, config?: FilteredRequestConfig<Paths, T>):
|
|
58
|
+
}, config?: FilteredRequestConfig<Paths, T>): _tanstack_react_query3.UseInfiniteQueryResult<{
|
|
59
59
|
pages: TPageData[];
|
|
60
60
|
pageParams: TPageParam[];
|
|
61
61
|
}, Response>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -54,8 +54,7 @@
|
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@standard-schema/spec": "^1.0.0"
|
|
58
|
-
"@geekmidas/schema": "0.0.3"
|
|
57
|
+
"@standard-schema/spec": "^1.0.0"
|
|
59
58
|
},
|
|
60
59
|
"devDependencies": {
|
|
61
60
|
"@testing-library/jest-dom": "~6.6.3",
|
|
@@ -65,18 +64,24 @@
|
|
|
65
64
|
"@types/react": "~19.1.8",
|
|
66
65
|
"@types/react-dom": "~19.1.6",
|
|
67
66
|
"jsdom": "~26.1.0",
|
|
68
|
-
"msw": "~2.10.3"
|
|
67
|
+
"msw": "~2.10.3",
|
|
68
|
+
"@geekmidas/constructs": "^0.3.0",
|
|
69
|
+
"@geekmidas/schema": "^0.1.0"
|
|
69
70
|
},
|
|
70
71
|
"peerDependencies": {
|
|
71
72
|
"@tanstack/react-query": ">=5.0.0",
|
|
72
73
|
"react": ">=18.0.0",
|
|
73
74
|
"react-dom": ">=18.0.0",
|
|
74
75
|
"zod": "~4.1.13",
|
|
75
|
-
"@geekmidas/
|
|
76
|
+
"@geekmidas/schema": "^0.1.0",
|
|
77
|
+
"@geekmidas/constructs": "^0.3.0"
|
|
76
78
|
},
|
|
77
79
|
"peerDependenciesMeta": {
|
|
78
80
|
"@geekmidas/constructs": {
|
|
79
|
-
"optional":
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"@geekmidas/schema": {
|
|
84
|
+
"optional": true
|
|
80
85
|
},
|
|
81
86
|
"@tanstack/react-query": {
|
|
82
87
|
"optional": true
|
package/src/auth-fetcher.ts
CHANGED