@coinlist-co/react 0.3.0 → 0.4.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/{RequirementItem-BvwsFu9e.d.cts → RequirementItem-B-MvcxSr.d.cts} +3 -3
- package/dist/{RequirementItem-BpkJQep8.d.ts → RequirementItem-DcYot2uC.d.ts} +3 -3
- package/dist/{chunk-IDCROXPS.js → chunk-EHZ6PIGN.js} +6 -4
- package/dist/chunk-EHZ6PIGN.js.map +1 -0
- package/dist/chunk-NC45IO63.js +777 -0
- package/dist/chunk-NC45IO63.js.map +1 -0
- package/dist/chunk-RIFATQB5.js +257 -0
- package/dist/chunk-RIFATQB5.js.map +1 -0
- package/dist/chunk-UGJUTRXC.js +304 -0
- package/dist/chunk-UGJUTRXC.js.map +1 -0
- package/dist/client/components/index.cjs +60 -59
- package/dist/client/components/index.cjs.map +1 -1
- package/dist/client/components/index.d.cts +40 -22
- package/dist/client/components/index.d.ts +40 -22
- package/dist/client/components/index.js +34 -62
- package/dist/client/components/index.js.map +1 -1
- package/dist/client/core/index.cjs +308 -222
- package/dist/client/core/index.cjs.map +1 -1
- package/dist/client/core/index.d.cts +4 -4
- package/dist/client/core/index.d.ts +4 -4
- package/dist/client/core/index.js +14 -14
- package/dist/client/hooks/index.cjs +87 -13
- package/dist/client/hooks/index.cjs.map +1 -1
- package/dist/client/hooks/index.d.cts +102 -9
- package/dist/client/hooks/index.d.ts +102 -9
- package/dist/client/hooks/index.js +9 -9
- package/dist/client/index.cjs +465 -237
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +7 -8
- package/dist/client/index.d.ts +7 -8
- package/dist/client/index.js +24 -18
- package/dist/{coinlist-client-B_dJkbwB.d.ts → coinlist-client-BSxpqylo.d.ts} +13 -138
- package/dist/{coinlist-client-DBKa6j3f.d.cts → coinlist-client-Cah5c_aF.d.cts} +13 -138
- package/dist/participation-DMMEDxON.d.cts +185 -0
- package/dist/participation-E-bT-GXJ.d.ts +185 -0
- package/dist/{requirement-CxbdY8l4.d.cts → requirement-XWT0T_zO.d.cts} +5 -2
- package/dist/{requirement-fJsQ3f9_.d.ts → requirement-XWT0T_zO.d.ts} +5 -2
- package/dist/server/index.cjs +519 -14
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +73 -4
- package/dist/server/index.d.ts +73 -4
- package/dist/server/index.js +116 -20
- package/dist/server/index.js.map +1 -1
- package/dist/useCoinListRequirements-B5-ZPOMz.d.ts +80 -0
- package/dist/useCoinListRequirements-Cuc32Tqw.d.cts +80 -0
- package/package.json +1 -1
- package/dist/chunk-GRVV7NLV.js +0 -282
- package/dist/chunk-GRVV7NLV.js.map +0 -1
- package/dist/chunk-IADBIDY6.js +0 -76
- package/dist/chunk-IADBIDY6.js.map +0 -1
- package/dist/chunk-IDCROXPS.js.map +0 -1
- package/dist/chunk-P4DTIPEX.js +0 -623
- package/dist/chunk-P4DTIPEX.js.map +0 -1
- package/dist/chunk-V5M7SA3C.js +0 -161
- package/dist/chunk-V5M7SA3C.js.map +0 -1
- package/dist/newtype-yKTvFdg_.d.cts +0 -6
- package/dist/newtype-yKTvFdg_.d.ts +0 -6
- package/dist/oauth-session-DgItaMKN.d.cts +0 -56
- package/dist/oauth-session-DnKDI5ou.d.ts +0 -56
- package/dist/useCoinListOffers-C5lBlzcC.d.ts +0 -27
- package/dist/useCoinListOffers-CguwXaCX.d.cts +0 -27
- package/dist/useCoinListRequirements-BECx1cIw.d.ts +0 -31
- package/dist/useCoinListRequirements-CX2gV9gJ.d.cts +0 -31
- package/dist/useCompleteCoinListOAuth-BRhAqD4_.d.cts +0 -55
- package/dist/useCompleteCoinListOAuth-DEZpHjd6.d.ts +0 -55
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/api/api.server.ts","../../src/server/coinlist.server.ts"],"sourcesContent":["import {\n type HttpClientConfig,\n HttpError,\n type HttpRequest,\n} from '@/shared/api/http';\nimport { HttpClient } from '@/shared/api/http-client';\nimport { requestRetryMiddleware } from '@/shared/api/middleware/request-retry';\n\nexport class Api {\n private readonly httpClient: HttpClient;\n\n constructor(private readonly config: HttpClientConfig) {\n this.httpClient = new HttpClient(this.config, {\n beforeRequest: [],\n afterRequest: [requestRetryMiddleware],\n });\n }\n\n async send<TResponse>(request: HttpRequest): Promise<TResponse> {\n const response = await this.httpClient.send<TResponse>(request);\n if (response.status >= 200 && response.status < 300) {\n return response.body as TResponse;\n } else {\n throw new HttpError(response);\n }\n }\n}\n","import { Api } from '@/server/api/api.server';\nimport { API_VERSION, PUBLIC_API_BASE_URL } from '@/shared/api/frontline';\nimport { HttpError } from '@/shared/api/http';\nimport type { Config } from '@/shared/types/config';\nimport type { OAuthSessionDto } from '@/shared/types/dto/oauth-session';\nimport type {\n AuthorizationCode,\n ClientSecret,\n CodeVerifier,\n} from '@/shared/types/oauth';\nimport {\n type OAuthAccessToken,\n OAuthSession,\n} from '@/shared/types/oauth-session';\n\n/** Buffer in seconds before expiry to consider token expired for refresh. */\nconst ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS = 60;\n\nexport interface SessionStore {\n getSession(): Promise<OAuthSession | null>;\n setSession(session: OAuthSession | null): Promise<void>;\n}\n\nexport interface ServerConfig extends Config {\n readonly clientSecret: ClientSecret;\n readonly sessionStore: SessionStore;\n /** Buffer in seconds before expiry to consider token expired for refresh. */\n readonly accessTokenExpiryBufferSeconds?: number;\n /**\n * Whether SDK will throw an exception in cases it can be silent.\n * For example, if token revokation on logout fails.\n */\n readonly strict?: boolean;\n}\n\nexport interface CoinListServer {\n completeOAuth(\n code: AuthorizationCode,\n codeVerifier: CodeVerifier\n ): Promise<OAuthSession>;\n\n /**\n * Responsible for:\n * 1. Returning a securely stored access token from Cookies\n * 2. Renewing the session if it's expired (or about to expire)\n *\n * @returns a valid access token or null if the user is not authentication.\n * On error rejects the Promise and throws.\n */\n accessToken(): Promise<OAuthAccessToken | null>;\n\n /**\n * Revokes the current token via POST /oauth/revoke and clears the session.\n */\n logout(): Promise<void>;\n}\n\nclass CoinListServerImpl implements CoinListServer {\n private readonly api: Api;\n private readonly baseUrl: string;\n\n private readonly accessTokenExpiryBufferSeconds: number;\n private readonly strict: boolean;\n\n constructor(private readonly _config: ServerConfig) {\n this.baseUrl = _config.baseUrl ?? PUBLIC_API_BASE_URL;\n this.accessTokenExpiryBufferSeconds =\n _config.accessTokenExpiryBufferSeconds ??\n ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS;\n this.strict = _config.strict ?? false;\n this.api = new Api({\n baseUrl: this.baseUrl,\n xApiVersion: API_VERSION,\n });\n }\n\n async completeOAuth(\n code: AuthorizationCode,\n codeVerifier: CodeVerifier\n ): Promise<OAuthSession> {\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'authorization_code',\n code,\n redirect_uri: this._config.redirectUri,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n code_verifier: codeVerifier,\n },\n });\n const session = OAuthSession.fromDto(sessionDto);\n this._config.sessionStore.setSession(session);\n return session;\n }\n\n async accessToken(): Promise<OAuthAccessToken | null> {\n const session = await this._config.sessionStore.getSession();\n if (session == null) return null;\n\n const now = Date.now();\n const expiresAt = session.accessToken.expiresAt.getTime();\n const bufferMs = this.accessTokenExpiryBufferSeconds * 1000;\n if (expiresAt > now + bufferMs) {\n return session.accessToken;\n }\n\n const refreshToken = session?.refreshToken;\n if (!refreshToken) {\n await this._config.sessionStore.setSession(null);\n return null;\n }\n\n try {\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n const newSession = OAuthSession.fromDto(sessionDto);\n await this._config.sessionStore.setSession(newSession);\n return newSession.accessToken;\n } catch {\n await this._config.sessionStore.setSession(null);\n return null;\n }\n }\n\n async logout(): Promise<void> {\n const session = await this._config.sessionStore.getSession();\n if (session != null) {\n const tokenToRevoke = session.accessToken.value;\n try {\n await this.api.send({\n method: 'POST',\n url: `/oauth/revoke`,\n body: {\n token: tokenToRevoke,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n } catch (err) {\n if (err instanceof HttpError) {\n if (this.strict) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n await this._config.sessionStore.setSession(null);\n }\n }\n}\n\nexport function createCoinListServer(config: ServerConfig): CoinListServer {\n return new CoinListServerImpl(config);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/api/api.server.ts","../../src/server/coinlist.server.ts"],"sourcesContent":["import { AuthenticatedApiClient } from '@/shared/api/authenticated-api-client';\nimport type { HttpClientConfig, HttpRequest } from '@/shared/api/http';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\nexport class Api {\n private readonly client: AuthenticatedApiClient;\n\n constructor(\n config: HttpClientConfig,\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>\n ) {\n this.client = new AuthenticatedApiClient(config, fetchAccessToken);\n }\n\n async send<TResponse>(request: HttpRequest): Promise<TResponse> {\n return this.client.send<TResponse>(request);\n }\n}\n","import { Api } from '@/server/api/api.server';\nimport { API_VERSION, PUBLIC_API_BASE_URL } from '@/shared/api/frontline';\nimport * as offersApi from '@/shared/api/frontline/offers';\nimport * as participationsApi from '@/shared/api/frontline/participations';\nimport * as requirementsApi from '@/shared/api/frontline/requirements';\nimport { HttpError } from '@/shared/api/http';\nimport type {\n PaginatedResponse,\n PaginationParams,\n} from '@/shared/api/pagination';\nimport type { Config } from '@/shared/types/config';\nimport type { OAuthSessionDto } from '@/shared/types/dto/oauth-session';\nimport { NotAuthenticatedError } from '@/shared/types/errors';\nimport type {\n AuthorizationCode,\n ClientSecret,\n CodeVerifier,\n} from '@/shared/types/oauth';\nimport {\n type OAuthAccessToken,\n OAuthSession,\n} from '@/shared/types/oauth-session';\nimport type { Offer, OfferId } from '@/shared/types/offer';\nimport type { OfferDetail, OfferOptionId } from '@/shared/types/offer-detail';\nimport type {\n CreateParticipationParams,\n Participation,\n ParticipationId,\n ParticipationsPaginationParams,\n} from '@/shared/types/participation';\nimport type {\n Requirement,\n RequirementStatusInfo,\n} from '@/shared/types/requirement';\n\n/** Buffer in seconds before expiry to consider token expired for refresh. */\nconst ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS = 60;\n\nexport interface SessionStore {\n getSession(): Promise<OAuthSession | null>;\n setSession(session: OAuthSession | null): Promise<void>;\n}\n\nexport interface ServerConfig extends Config {\n readonly clientSecret: ClientSecret;\n readonly sessionStore: SessionStore;\n /** Buffer in seconds before expiry to consider token expired for refresh. */\n readonly accessTokenExpiryBufferSeconds?: number;\n /**\n * Whether SDK will throw an exception in cases it can be silent.\n * For example, if token revokation on logout fails.\n */\n readonly strict?: boolean;\n}\n\nexport interface CoinListServer {\n completeOAuth(\n code: AuthorizationCode,\n codeVerifier: CodeVerifier\n ): Promise<OAuthSession>;\n\n /**\n * Responsible for:\n * 1. Returning a securely stored access token from Cookies\n * 2. Renewing the session if it's expired (or about to expire)\n *\n * @returns a valid access token or null if the user is not authentication.\n * On error rejects the Promise and throws.\n */\n accessToken(): Promise<OAuthAccessToken | null>;\n\n /**\n * Revokes the current token via POST /oauth/revoke and clears the session.\n */\n logout(): Promise<void>;\n\n /**\n * Fetches all offers by iterating through every paginated response.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchAllOffers(): Promise<Offer[]>;\n\n /**\n * Fetches a single page of offers.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchOffersPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;\n\n /**\n * Fetches details for a given offer by its id.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchOfferDetails(id: OfferId): Promise<OfferDetail>;\n\n /**\n * Fetches all participations by iterating through every paginated response.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchAllParticipations(offerId?: OfferId): Promise<Participation[]>;\n\n /**\n * Fetches a single page of participations, optionally filtered by offer.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchParticipationsPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>>;\n\n /**\n * Fetches a participation by id.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchParticipation(id: ParticipationId): Promise<Participation>;\n\n /**\n * Creates a participation.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation>;\n\n /**\n * Fetches the requirements for all options of a given offer, grouped by option ID.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchOfferRequirements(\n offerId: OfferId\n ): Promise<Record<OfferOptionId, Requirement[]>>;\n\n /**\n * Fetches the user's requirement statuses for a given offer.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchRequirementStatuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;\n}\n\nclass CoinListServerImpl implements CoinListServer {\n private readonly api: Api;\n private readonly baseUrl: string;\n\n private readonly accessTokenExpiryBufferSeconds: number;\n private readonly strict: boolean;\n\n constructor(private readonly _config: ServerConfig) {\n this.baseUrl = _config.baseUrl ?? PUBLIC_API_BASE_URL;\n this.accessTokenExpiryBufferSeconds =\n _config.accessTokenExpiryBufferSeconds ??\n ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS;\n this.strict = _config.strict ?? false;\n this.api = new Api(\n {\n baseUrl: this.baseUrl,\n xApiVersion: API_VERSION,\n },\n (_refresh) => this.accessToken()\n );\n }\n\n async completeOAuth(\n code: AuthorizationCode,\n codeVerifier: CodeVerifier\n ): Promise<OAuthSession> {\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'authorization_code',\n code,\n redirect_uri: this._config.redirectUri,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n code_verifier: codeVerifier,\n },\n });\n const session = OAuthSession.fromDto(sessionDto);\n this._config.sessionStore.setSession(session);\n return session;\n }\n\n async accessToken(): Promise<OAuthAccessToken | null> {\n const session = await this._config.sessionStore.getSession();\n if (session == null) return null;\n\n const now = Date.now();\n const expiresAt = session.accessToken.expiresAt.getTime();\n const bufferMs = this.accessTokenExpiryBufferSeconds * 1000;\n if (expiresAt > now + bufferMs) {\n return session.accessToken;\n }\n\n const refreshToken = session?.refreshToken;\n if (!refreshToken) {\n await this._config.sessionStore.setSession(null);\n return null;\n }\n\n try {\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n const newSession = OAuthSession.fromDto(sessionDto);\n await this._config.sessionStore.setSession(newSession);\n return newSession.accessToken;\n } catch {\n await this._config.sessionStore.setSession(null);\n return null;\n }\n }\n\n async logout(): Promise<void> {\n const session = await this._config.sessionStore.getSession();\n if (session != null) {\n const tokenToRevoke = session.accessToken.value;\n try {\n await this.api.send({\n method: 'POST',\n url: `/oauth/revoke`,\n body: {\n token: tokenToRevoke,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n } catch (err) {\n if (err instanceof HttpError) {\n if (this.strict) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n await this._config.sessionStore.setSession(null);\n }\n }\n\n private async ensureAuthenticated(): Promise<void> {\n const token = await this.accessToken();\n if (token === null) {\n throw new NotAuthenticatedError();\n }\n }\n\n async fetchAllOffers(): Promise<Offer[]> {\n await this.ensureAuthenticated();\n return offersApi.fetchAllOffers(this.api);\n }\n\n async fetchOffersPage(\n params: PaginationParams\n ): Promise<PaginatedResponse<Offer>> {\n await this.ensureAuthenticated();\n return offersApi.fetchOffersPage(this.api, params);\n }\n\n async fetchOfferDetails(id: OfferId): Promise<OfferDetail> {\n await this.ensureAuthenticated();\n return offersApi.fetchOfferDetails(this.api, id);\n }\n\n async fetchAllParticipations(offerId?: OfferId): Promise<Participation[]> {\n await this.ensureAuthenticated();\n return participationsApi.fetchAllParticipations(this.api, offerId);\n }\n\n async fetchParticipationsPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>> {\n await this.ensureAuthenticated();\n return participationsApi.fetchParticipationsPage(this.api, params);\n }\n\n async fetchParticipation(id: ParticipationId): Promise<Participation> {\n await this.ensureAuthenticated();\n return participationsApi.fetchParticipation(this.api, id);\n }\n\n async createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation> {\n await this.ensureAuthenticated();\n return participationsApi.createParticipation(this.api, params);\n }\n\n async fetchOfferRequirements(\n offerId: OfferId\n ): Promise<Record<OfferOptionId, Requirement[]>> {\n await this.ensureAuthenticated();\n return requirementsApi.fetchOfferRequirements(this.api, offerId);\n }\n\n async fetchRequirementStatuses(\n offerId: OfferId\n ): Promise<RequirementStatusInfo[]> {\n await this.ensureAuthenticated();\n return requirementsApi.fetchRequirementStatuses(this.api, offerId);\n }\n}\n\nexport function createCoinListServer(config: ServerConfig): CoinListServer {\n return new CoinListServerImpl(config);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { O as Offer, d as OfferOptionId, R as Requirement, h as RequirementStatusInfo, b as OfferId } from './requirement-XWT0T_zO.js';
|
|
2
|
+
|
|
3
|
+
type LoadOffersReason = 'not-authenticated' | 'generic-error';
|
|
4
|
+
type LoadOffersState = {
|
|
5
|
+
type: 'LOADING';
|
|
6
|
+
} | {
|
|
7
|
+
type: 'ERROR';
|
|
8
|
+
reason: LoadOffersReason;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'CONTENT';
|
|
11
|
+
offers: Offer[];
|
|
12
|
+
};
|
|
13
|
+
interface UseCoinListOffersOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Offers pre-fetched on the server (e.g. via `CoinListServer.fetchAllOffers()`).
|
|
16
|
+
* When provided, the hook uses this data as-is and skips the client-side fetch entirely.
|
|
17
|
+
*/
|
|
18
|
+
serverOffers?: Offer[];
|
|
19
|
+
}
|
|
20
|
+
interface UseCoinListOffersResult {
|
|
21
|
+
offersState: LoadOffersState;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Loads all CoinList offers for the current user and exposes a UI-friendly state.
|
|
25
|
+
*
|
|
26
|
+
* Pass `serverOffers` (pre-fetched server-side) to use that data as-is and skip
|
|
27
|
+
* the client-side fetch entirely.
|
|
28
|
+
*
|
|
29
|
+
* Returns `LOADING` while CoinList is initializing or while offers are being fetched.
|
|
30
|
+
* Returns `CONTENT` with all offers when `fetchAllOffers()` succeeds.
|
|
31
|
+
* Returns `ERROR` with:
|
|
32
|
+
* - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
|
|
33
|
+
* - `generic-error` for any other failure
|
|
34
|
+
*/
|
|
35
|
+
declare function useCoinListOffers(options?: UseCoinListOffersOptions): UseCoinListOffersResult;
|
|
36
|
+
|
|
37
|
+
type LoadRequirementsReason = 'not-authenticated' | 'generic-error';
|
|
38
|
+
type LoadRequirementsState = {
|
|
39
|
+
type: 'LOADING';
|
|
40
|
+
} | {
|
|
41
|
+
type: 'ERROR';
|
|
42
|
+
reason: LoadRequirementsReason;
|
|
43
|
+
} | {
|
|
44
|
+
type: 'CONTENT';
|
|
45
|
+
requirementsByOptionId: Record<OfferOptionId, Requirement[]>;
|
|
46
|
+
statuses: RequirementStatusInfo[];
|
|
47
|
+
};
|
|
48
|
+
interface UseCoinListRequirementsOptions {
|
|
49
|
+
/**
|
|
50
|
+
* Requirements data pre-fetched on the server (e.g. via
|
|
51
|
+
* `CoinListServer.fetchOfferRequirements()` + `fetchRequirementStatuses()`).
|
|
52
|
+
* When provided, the hook uses this data as-is and skips the initial client-side fetch.
|
|
53
|
+
* Calling `refetch()` will still trigger a fresh fetch.
|
|
54
|
+
*/
|
|
55
|
+
serverData?: {
|
|
56
|
+
requirementsByOptionId: Record<OfferOptionId, Requirement[]>;
|
|
57
|
+
statuses: RequirementStatusInfo[];
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
interface UseCoinListRequirementsResult {
|
|
61
|
+
requirementsState: LoadRequirementsState;
|
|
62
|
+
/** Triggers a re-fetch of requirements and statuses. */
|
|
63
|
+
refetch: () => void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Loads requirements (grouped by option ID) and requirement statuses for a
|
|
67
|
+
* given offer, then exposes them via a state machine.
|
|
68
|
+
*
|
|
69
|
+
* Pass `serverData` (pre-fetched server-side) to use that data as-is and skip
|
|
70
|
+
* the initial client-side fetch. Calling `refetch()` will still trigger a fresh fetch.
|
|
71
|
+
*
|
|
72
|
+
* Returns `LOADING` while CoinList is initializing or while data is being fetched.
|
|
73
|
+
* Returns `CONTENT` with requirementsByOptionId and statuses on success.
|
|
74
|
+
* Returns `ERROR` with:
|
|
75
|
+
* - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
|
|
76
|
+
* - `generic-error` for any other failure
|
|
77
|
+
*/
|
|
78
|
+
declare function useCoinListRequirements(offerId: OfferId, options?: UseCoinListRequirementsOptions): UseCoinListRequirementsResult;
|
|
79
|
+
|
|
80
|
+
export { type LoadOffersReason as L, type UseCoinListOffersOptions as U, type LoadOffersState as a, type LoadRequirementsReason as b, type LoadRequirementsState as c, type UseCoinListOffersResult as d, type UseCoinListRequirementsOptions as e, type UseCoinListRequirementsResult as f, useCoinListRequirements as g, useCoinListOffers as u };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { O as Offer, d as OfferOptionId, R as Requirement, h as RequirementStatusInfo, b as OfferId } from './requirement-XWT0T_zO.cjs';
|
|
2
|
+
|
|
3
|
+
type LoadOffersReason = 'not-authenticated' | 'generic-error';
|
|
4
|
+
type LoadOffersState = {
|
|
5
|
+
type: 'LOADING';
|
|
6
|
+
} | {
|
|
7
|
+
type: 'ERROR';
|
|
8
|
+
reason: LoadOffersReason;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'CONTENT';
|
|
11
|
+
offers: Offer[];
|
|
12
|
+
};
|
|
13
|
+
interface UseCoinListOffersOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Offers pre-fetched on the server (e.g. via `CoinListServer.fetchAllOffers()`).
|
|
16
|
+
* When provided, the hook uses this data as-is and skips the client-side fetch entirely.
|
|
17
|
+
*/
|
|
18
|
+
serverOffers?: Offer[];
|
|
19
|
+
}
|
|
20
|
+
interface UseCoinListOffersResult {
|
|
21
|
+
offersState: LoadOffersState;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Loads all CoinList offers for the current user and exposes a UI-friendly state.
|
|
25
|
+
*
|
|
26
|
+
* Pass `serverOffers` (pre-fetched server-side) to use that data as-is and skip
|
|
27
|
+
* the client-side fetch entirely.
|
|
28
|
+
*
|
|
29
|
+
* Returns `LOADING` while CoinList is initializing or while offers are being fetched.
|
|
30
|
+
* Returns `CONTENT` with all offers when `fetchAllOffers()` succeeds.
|
|
31
|
+
* Returns `ERROR` with:
|
|
32
|
+
* - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
|
|
33
|
+
* - `generic-error` for any other failure
|
|
34
|
+
*/
|
|
35
|
+
declare function useCoinListOffers(options?: UseCoinListOffersOptions): UseCoinListOffersResult;
|
|
36
|
+
|
|
37
|
+
type LoadRequirementsReason = 'not-authenticated' | 'generic-error';
|
|
38
|
+
type LoadRequirementsState = {
|
|
39
|
+
type: 'LOADING';
|
|
40
|
+
} | {
|
|
41
|
+
type: 'ERROR';
|
|
42
|
+
reason: LoadRequirementsReason;
|
|
43
|
+
} | {
|
|
44
|
+
type: 'CONTENT';
|
|
45
|
+
requirementsByOptionId: Record<OfferOptionId, Requirement[]>;
|
|
46
|
+
statuses: RequirementStatusInfo[];
|
|
47
|
+
};
|
|
48
|
+
interface UseCoinListRequirementsOptions {
|
|
49
|
+
/**
|
|
50
|
+
* Requirements data pre-fetched on the server (e.g. via
|
|
51
|
+
* `CoinListServer.fetchOfferRequirements()` + `fetchRequirementStatuses()`).
|
|
52
|
+
* When provided, the hook uses this data as-is and skips the initial client-side fetch.
|
|
53
|
+
* Calling `refetch()` will still trigger a fresh fetch.
|
|
54
|
+
*/
|
|
55
|
+
serverData?: {
|
|
56
|
+
requirementsByOptionId: Record<OfferOptionId, Requirement[]>;
|
|
57
|
+
statuses: RequirementStatusInfo[];
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
interface UseCoinListRequirementsResult {
|
|
61
|
+
requirementsState: LoadRequirementsState;
|
|
62
|
+
/** Triggers a re-fetch of requirements and statuses. */
|
|
63
|
+
refetch: () => void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Loads requirements (grouped by option ID) and requirement statuses for a
|
|
67
|
+
* given offer, then exposes them via a state machine.
|
|
68
|
+
*
|
|
69
|
+
* Pass `serverData` (pre-fetched server-side) to use that data as-is and skip
|
|
70
|
+
* the initial client-side fetch. Calling `refetch()` will still trigger a fresh fetch.
|
|
71
|
+
*
|
|
72
|
+
* Returns `LOADING` while CoinList is initializing or while data is being fetched.
|
|
73
|
+
* Returns `CONTENT` with requirementsByOptionId and statuses on success.
|
|
74
|
+
* Returns `ERROR` with:
|
|
75
|
+
* - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
|
|
76
|
+
* - `generic-error` for any other failure
|
|
77
|
+
*/
|
|
78
|
+
declare function useCoinListRequirements(offerId: OfferId, options?: UseCoinListRequirementsOptions): UseCoinListRequirementsResult;
|
|
79
|
+
|
|
80
|
+
export { type LoadOffersReason as L, type UseCoinListOffersOptions as U, type LoadOffersState as a, type LoadRequirementsReason as b, type LoadRequirementsState as c, type UseCoinListOffersResult as d, type UseCoinListRequirementsOptions as e, type UseCoinListRequirementsResult as f, useCoinListRequirements as g, useCoinListOffers as u };
|
package/package.json
CHANGED
package/dist/chunk-GRVV7NLV.js
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
// src/shared/types/oauth.ts
|
|
2
|
-
var AuthorizationCode = (value) => value;
|
|
3
|
-
var CodeVerifier = (value) => value;
|
|
4
|
-
var CodeChallenge = (value) => value;
|
|
5
|
-
var RedirectUri = (value) => value;
|
|
6
|
-
var ClientId = (value) => value;
|
|
7
|
-
var ClientSecret = (value) => value;
|
|
8
|
-
|
|
9
|
-
// src/shared/api/http-attributes.ts
|
|
10
|
-
var empty = {};
|
|
11
|
-
var concat = (left, right) => ({
|
|
12
|
-
...left,
|
|
13
|
-
...right
|
|
14
|
-
});
|
|
15
|
-
var concatAll = (...items) => {
|
|
16
|
-
let result = empty;
|
|
17
|
-
for (const item of items) {
|
|
18
|
-
result = concat(result, item);
|
|
19
|
-
}
|
|
20
|
-
return result;
|
|
21
|
-
};
|
|
22
|
-
var protectedRequest = () => ({ protected: true });
|
|
23
|
-
var userAgent = () => ({ userAgent: true });
|
|
24
|
-
var idempotencyKey = () => ({
|
|
25
|
-
idempotencyKey: true
|
|
26
|
-
});
|
|
27
|
-
var retryAttempt = (attempt) => ({
|
|
28
|
-
retryAttempt: attempt
|
|
29
|
-
});
|
|
30
|
-
var renewAttempted = (value) => ({
|
|
31
|
-
renewAttempted: value
|
|
32
|
-
});
|
|
33
|
-
var isProtected = (attrs) => attrs?.protected === true;
|
|
34
|
-
var needUserAgent = (attrs) => attrs?.userAgent === true;
|
|
35
|
-
var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
|
|
36
|
-
var getRetryAttempt = (attrs) => attrs?.retryAttempt ?? 0;
|
|
37
|
-
var wasRenewAttempted = (attrs) => attrs?.renewAttempted === true;
|
|
38
|
-
var Attributes = {
|
|
39
|
-
empty,
|
|
40
|
-
concat,
|
|
41
|
-
concatAll,
|
|
42
|
-
protected: protectedRequest,
|
|
43
|
-
isProtected,
|
|
44
|
-
userAgent,
|
|
45
|
-
needUserAgent,
|
|
46
|
-
idempotencyKey,
|
|
47
|
-
isIdempotent,
|
|
48
|
-
retryAttempt,
|
|
49
|
-
getRetryAttempt,
|
|
50
|
-
renewAttempted,
|
|
51
|
-
wasRenewAttempted
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// src/shared/api/http.ts
|
|
55
|
-
var HttpError = class extends Error {
|
|
56
|
-
constructor(response) {
|
|
57
|
-
super(`Request failed with ${response.status} status`);
|
|
58
|
-
this.name = "HttpError";
|
|
59
|
-
this.response = response;
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
async function makeRequest(request) {
|
|
63
|
-
const headers = {
|
|
64
|
-
Accept: "application/json",
|
|
65
|
-
...request.method === "POST" && request.body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
66
|
-
...request.headers ?? {}
|
|
67
|
-
};
|
|
68
|
-
const init = {
|
|
69
|
-
method: request.method,
|
|
70
|
-
headers,
|
|
71
|
-
...request.redirect !== void 0 ? { redirect: request.redirect } : {}
|
|
72
|
-
};
|
|
73
|
-
if (request.method === "POST" && request.body !== void 0) {
|
|
74
|
-
init.body = JSON.stringify(request.body);
|
|
75
|
-
}
|
|
76
|
-
const response = await fetch(
|
|
77
|
-
buildUrlWithQueryParams(request.url, request.queryParams),
|
|
78
|
-
init
|
|
79
|
-
);
|
|
80
|
-
const responseHeaders = headersToRecord(response.headers);
|
|
81
|
-
if (response.status === 204 || response.status === 205) {
|
|
82
|
-
return {
|
|
83
|
-
status: response.status,
|
|
84
|
-
body: null,
|
|
85
|
-
headers: responseHeaders
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
if (response.status >= 300 && response.status < 400) {
|
|
89
|
-
await response.text();
|
|
90
|
-
return {
|
|
91
|
-
status: response.status,
|
|
92
|
-
body: null,
|
|
93
|
-
headers: responseHeaders
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
const text = await response.text();
|
|
97
|
-
const body = text ? JSON.parse(text) : null;
|
|
98
|
-
return {
|
|
99
|
-
status: response.status,
|
|
100
|
-
body,
|
|
101
|
-
headers: responseHeaders
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function buildUrlWithQueryParams(url, queryParams) {
|
|
105
|
-
if (!queryParams) {
|
|
106
|
-
return url;
|
|
107
|
-
}
|
|
108
|
-
const searchParams = new URLSearchParams();
|
|
109
|
-
for (const [key, value] of Object.entries(queryParams)) {
|
|
110
|
-
if (value === void 0 || value === null) {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
if (Array.isArray(value)) {
|
|
114
|
-
for (const item of value) {
|
|
115
|
-
if (item === void 0 || item === null) {
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
searchParams.append(key, String(item));
|
|
119
|
-
}
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
searchParams.append(key, String(value));
|
|
123
|
-
}
|
|
124
|
-
const queryString = searchParams.toString();
|
|
125
|
-
if (!queryString) {
|
|
126
|
-
return url;
|
|
127
|
-
}
|
|
128
|
-
return url.includes("?") ? `${url}&${queryString}` : `${url}?${queryString}`;
|
|
129
|
-
}
|
|
130
|
-
function headersToRecord(headers) {
|
|
131
|
-
const record = {};
|
|
132
|
-
headers.forEach((value, key) => {
|
|
133
|
-
record[key.toLowerCase()] = value;
|
|
134
|
-
});
|
|
135
|
-
return record;
|
|
136
|
-
}
|
|
137
|
-
function concatAttributes(request, attrs) {
|
|
138
|
-
const nextAttributes = Attributes.concat(
|
|
139
|
-
request.attributes ?? Attributes.empty,
|
|
140
|
-
attrs
|
|
141
|
-
);
|
|
142
|
-
const nextRequest = {
|
|
143
|
-
...request,
|
|
144
|
-
attributes: nextAttributes
|
|
145
|
-
};
|
|
146
|
-
return nextRequest;
|
|
147
|
-
}
|
|
148
|
-
var Request = {
|
|
149
|
-
concatAttributes
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
// src/shared/api/frontline.ts
|
|
153
|
-
var PUBLIC_API_BASE_URL = "https://api.coinlist.co";
|
|
154
|
-
var HEADER_API_VERSION = "X-API-Version";
|
|
155
|
-
var HEADER_USER_AGENT = "User-Agent";
|
|
156
|
-
var HEADER_IDEMPOTENCY_KEY = "Idempotency-Key";
|
|
157
|
-
var API_VERSION = "2025-10-17";
|
|
158
|
-
var COINLIST_OAUTH_PAGE_URL = "https://coinlist.co/oauth/authorize";
|
|
159
|
-
|
|
160
|
-
// src/shared/api/http-client.ts
|
|
161
|
-
var HttpClient = class {
|
|
162
|
-
constructor(config, middleware = {}) {
|
|
163
|
-
this.config = config;
|
|
164
|
-
this.middleware = middleware;
|
|
165
|
-
}
|
|
166
|
-
async send(request) {
|
|
167
|
-
return this.runRequestWithAfterMiddleware(request);
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Runs beforeRequest, executeRequest, then the full afterRequest middleware
|
|
171
|
-
* chain. Used by send() and by the retry() callback so that when a
|
|
172
|
-
* middleware calls retry(), the retried response also goes through all
|
|
173
|
-
* afterRequest middleware (e.g. session renewal, retry). Middleware
|
|
174
|
-
* must use request.attributes.retryAttempt (or similar) to avoid infinite
|
|
175
|
-
* recursion when they trigger retries.
|
|
176
|
-
*/
|
|
177
|
-
async runRequestWithAfterMiddleware(request) {
|
|
178
|
-
const preparedRequest = await this.runBeforeRequestMiddleware(
|
|
179
|
-
this.withClientDefaults(request)
|
|
180
|
-
);
|
|
181
|
-
let response = await this.executeRequest(preparedRequest);
|
|
182
|
-
for (const middleware of this.middleware.afterRequest ?? []) {
|
|
183
|
-
response = await middleware({
|
|
184
|
-
request: preparedRequest,
|
|
185
|
-
response,
|
|
186
|
-
retry: (nextRequest = preparedRequest) => this.runRequestWithAfterMiddleware(nextRequest)
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
return response;
|
|
190
|
-
}
|
|
191
|
-
withClientDefaults(request) {
|
|
192
|
-
const url = this.resolveUrl(request.url);
|
|
193
|
-
const headers = {
|
|
194
|
-
...request.headers ?? {},
|
|
195
|
-
[HEADER_API_VERSION]: this.config.xApiVersion
|
|
196
|
-
};
|
|
197
|
-
return {
|
|
198
|
-
...request,
|
|
199
|
-
url,
|
|
200
|
-
headers
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Resolves a request URL against the client's baseUrl.
|
|
205
|
-
*
|
|
206
|
-
* @internal Public only for testing. Do not use in application code; use
|
|
207
|
-
* {@link HttpClient.send} with a path and the client will resolve the URL.
|
|
208
|
-
*/
|
|
209
|
-
resolveUrl(url) {
|
|
210
|
-
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
211
|
-
return url;
|
|
212
|
-
}
|
|
213
|
-
const base = this.config.baseUrl.replace(/\/$/, "");
|
|
214
|
-
const path = url.startsWith("/") ? url : `/${url}`;
|
|
215
|
-
return base + path;
|
|
216
|
-
}
|
|
217
|
-
async runBeforeRequestMiddleware(initialRequest) {
|
|
218
|
-
let request = initialRequest;
|
|
219
|
-
for (const middleware of this.middleware.beforeRequest ?? []) {
|
|
220
|
-
request = await middleware(request);
|
|
221
|
-
}
|
|
222
|
-
return request;
|
|
223
|
-
}
|
|
224
|
-
executeRequest(request) {
|
|
225
|
-
return makeRequest(request);
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
// src/shared/api/middleware/request-retry.ts
|
|
230
|
-
var MAX_ATTEMPTS = 3;
|
|
231
|
-
var INITIAL_DELAY_MS = 300;
|
|
232
|
-
var MAX_DELAY_MS = 2e3;
|
|
233
|
-
var RETRYABLE_4XX = /* @__PURE__ */ new Set([408, 409, 429]);
|
|
234
|
-
function isRetryableStatus(status) {
|
|
235
|
-
return status >= 500 && status < 600 || RETRYABLE_4XX.has(status);
|
|
236
|
-
}
|
|
237
|
-
function getRetryDelayMs(attempt) {
|
|
238
|
-
return Math.min(INITIAL_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);
|
|
239
|
-
}
|
|
240
|
-
function createRequestRetryMiddleware(options = {}) {
|
|
241
|
-
const delayFn = options.delayFn ?? defaultDelay;
|
|
242
|
-
return async ({ request, response, retry }) => {
|
|
243
|
-
if (!isRetryableStatus(response.status)) {
|
|
244
|
-
return response;
|
|
245
|
-
}
|
|
246
|
-
const currentAttempt = Attributes.getRetryAttempt(request.attributes);
|
|
247
|
-
if (currentAttempt >= MAX_ATTEMPTS - 1) {
|
|
248
|
-
return response;
|
|
249
|
-
}
|
|
250
|
-
const nextAttempt = currentAttempt + 1;
|
|
251
|
-
await delayFn(getRetryDelayMs(nextAttempt));
|
|
252
|
-
const nextRequest = Request.concatAttributes(
|
|
253
|
-
request,
|
|
254
|
-
Attributes.retryAttempt(nextAttempt)
|
|
255
|
-
);
|
|
256
|
-
return retry(nextRequest);
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
function defaultDelay(ms) {
|
|
260
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
261
|
-
}
|
|
262
|
-
var requestRetryMiddleware = createRequestRetryMiddleware();
|
|
263
|
-
|
|
264
|
-
export {
|
|
265
|
-
Attributes,
|
|
266
|
-
HttpError,
|
|
267
|
-
Request,
|
|
268
|
-
PUBLIC_API_BASE_URL,
|
|
269
|
-
HEADER_USER_AGENT,
|
|
270
|
-
HEADER_IDEMPOTENCY_KEY,
|
|
271
|
-
API_VERSION,
|
|
272
|
-
COINLIST_OAUTH_PAGE_URL,
|
|
273
|
-
HttpClient,
|
|
274
|
-
requestRetryMiddleware,
|
|
275
|
-
AuthorizationCode,
|
|
276
|
-
CodeVerifier,
|
|
277
|
-
CodeChallenge,
|
|
278
|
-
RedirectUri,
|
|
279
|
-
ClientId,
|
|
280
|
-
ClientSecret
|
|
281
|
-
};
|
|
282
|
-
//# sourceMappingURL=chunk-GRVV7NLV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/types/oauth.ts","../src/shared/api/http-attributes.ts","../src/shared/api/http.ts","../src/shared/api/frontline.ts","../src/shared/api/http-client.ts","../src/shared/api/middleware/request-retry.ts"],"sourcesContent":["import type { Newtype } from '@/shared/types/newtype';\n\nexport type AuthorizationCode = Newtype<string, 'AuthorizationCode'>;\nexport const AuthorizationCode = (value: string): AuthorizationCode =>\n value as AuthorizationCode;\n\nexport type CodeVerifier = Newtype<string, 'CodeVerifier'>;\nexport const CodeVerifier = (value: string): CodeVerifier =>\n value as CodeVerifier;\n\nexport type CodeChallenge = Newtype<string, 'CodeChallenge'>;\nexport const CodeChallenge = (value: string): CodeChallenge =>\n value as CodeChallenge;\n\nexport type RedirectUri = Newtype<string, 'RedirectUri'>;\nexport const RedirectUri = (value: string): RedirectUri => value as RedirectUri;\n\nexport type ClientId = Newtype<string, 'ClientId'>;\nexport const ClientId = (value: string): ClientId => value as ClientId;\n\nexport type ClientSecret = Newtype<string, 'ClientSecret'>;\nexport const ClientSecret = (value: string): ClientSecret =>\n value as ClientSecret;\n","export type HttpRequestAttributes = {\n protected?: boolean;\n userAgent?: boolean;\n idempotencyKey?: boolean;\n /** Zero-based attempt index: 0 = first request, 1 = first retry, etc. */\n retryAttempt?: number;\n renewAttempted?: boolean;\n};\n\nexport type Attributes = Readonly<HttpRequestAttributes>;\n\nconst empty: Attributes = {};\n\nconst concat = (left: Attributes, right: Attributes): Attributes => ({\n ...left,\n ...right,\n});\n\nconst concatAll = (...items: Attributes[]): Attributes => {\n let result = empty;\n for (const item of items) {\n result = concat(result, item);\n }\n return result;\n};\n\nconst protectedRequest = (): Attributes => ({ protected: true });\nconst userAgent = (): Attributes => ({ userAgent: true });\nconst idempotencyKey = (): Attributes => ({\n idempotencyKey: true,\n});\n\n/** Returns attributes with the given retry attempt (zero-based). */\nconst retryAttempt = (attempt: number): Attributes => ({\n retryAttempt: attempt,\n});\nconst renewAttempted = (value: boolean): Attributes => ({\n renewAttempted: value,\n});\n\nconst isProtected = (attrs?: HttpRequestAttributes): boolean =>\n attrs?.protected === true;\nconst needUserAgent = (attrs?: HttpRequestAttributes): boolean =>\n attrs?.userAgent === true;\nconst isIdempotent = (attrs?: HttpRequestAttributes): boolean =>\n attrs?.idempotencyKey === true;\nconst getRetryAttempt = (attrs?: HttpRequestAttributes): number =>\n attrs?.retryAttempt ?? 0;\nconst wasRenewAttempted = (attrs?: HttpRequestAttributes): boolean =>\n attrs?.renewAttempted === true;\n\nexport const Attributes = {\n empty,\n concat,\n concatAll,\n protected: protectedRequest,\n isProtected,\n userAgent,\n needUserAgent,\n idempotencyKey,\n isIdempotent,\n retryAttempt,\n getRetryAttempt,\n renewAttempted,\n wasRenewAttempted,\n} as const;\n","import {\n Attributes,\n type HttpRequestAttributes,\n} from '@/shared/api/http-attributes';\n\nexport type HttpClientConfig = {\n baseUrl: string;\n xApiVersion: string;\n};\n\nexport type QueryParamValue = string | number | boolean | null | undefined;\nexport type QueryParamValues = QueryParamValue | QueryParamValue[];\n\nexport type HttpRequest<TBody = unknown> =\n | {\n method: 'GET';\n url: string;\n queryParams?: Record<string, QueryParamValues>;\n headers?: Record<string, string>;\n attributes?: HttpRequestAttributes;\n redirect?: RequestRedirect;\n }\n | {\n method: 'POST';\n url: string;\n queryParams?: Record<string, QueryParamValues>;\n headers?: Record<string, string>;\n body: TBody;\n attributes?: HttpRequestAttributes;\n redirect?: RequestRedirect;\n };\nexport type HttpResponse<TBody = unknown> = {\n status: number;\n headers?: Record<string, string>;\n body: TBody | null;\n};\n\nexport class HttpError<TBody = unknown> extends Error {\n readonly response: HttpResponse<TBody>;\n\n constructor(response: HttpResponse<TBody>) {\n super(`Request failed with ${response.status} status`);\n this.name = 'HttpError';\n this.response = response;\n }\n}\n\nexport async function makeRequest<TResponse = unknown>(\n request: HttpRequest\n): Promise<HttpResponse<TResponse>> {\n const headers: Record<string, string> = {\n Accept: 'application/json',\n ...(request.method === 'POST' && request.body !== undefined\n ? { 'Content-Type': 'application/json' }\n : {}),\n ...(request.headers ?? {}),\n };\n\n const init: RequestInit = {\n method: request.method,\n headers,\n ...(request.redirect !== undefined ? { redirect: request.redirect } : {}),\n };\n\n if (request.method === 'POST' && request.body !== undefined) {\n init.body = JSON.stringify(request.body);\n }\n\n const response = await fetch(\n buildUrlWithQueryParams(request.url, request.queryParams),\n init\n );\n const responseHeaders = headersToRecord(response.headers);\n\n if (response.status === 204 || response.status === 205) {\n return {\n status: response.status,\n body: null,\n headers: responseHeaders,\n };\n }\n\n if (response.status >= 300 && response.status < 400) {\n await response.text();\n return {\n status: response.status,\n body: null,\n headers: responseHeaders,\n };\n }\n\n const text = await response.text();\n const body = text ? (JSON.parse(text) as TResponse) : null;\n\n return {\n status: response.status,\n body,\n headers: responseHeaders,\n };\n}\n\nfunction buildUrlWithQueryParams(\n url: string,\n queryParams?: Record<string, QueryParamValues>\n): string {\n if (!queryParams) {\n return url;\n }\n\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(queryParams)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item === undefined || item === null) {\n continue;\n }\n searchParams.append(key, String(item));\n }\n continue;\n }\n\n searchParams.append(key, String(value));\n }\n\n const queryString = searchParams.toString();\n if (!queryString) {\n return url;\n }\n\n return url.includes('?') ? `${url}&${queryString}` : `${url}?${queryString}`;\n}\n\nfunction headersToRecord(headers: Headers): Record<string, string> {\n const record: Record<string, string> = {};\n headers.forEach((value, key) => {\n record[key.toLowerCase()] = value;\n });\n return record;\n}\n\nfunction concatAttributes(\n request: HttpRequest,\n attrs: Attributes\n): HttpRequest {\n const nextAttributes = Attributes.concat(\n request.attributes ?? Attributes.empty,\n attrs\n );\n const nextRequest: typeof request = {\n ...request,\n attributes: nextAttributes,\n };\n return nextRequest;\n}\n\nexport const Request = {\n concatAttributes,\n};\n","export const PUBLIC_API_BASE_URL = 'https://api.coinlist.co';\nexport const HEADER_API_VERSION = 'X-API-Version';\nexport const HEADER_USER_AGENT = 'User-Agent';\nexport const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';\nexport const API_VERSION = '2025-10-17';\n\nexport const COINLIST_OAUTH_PAGE_URL = 'https://coinlist.co/oauth/authorize';\n","import { HEADER_API_VERSION } from '@/shared/api/frontline';\nimport type {\n HttpClientConfig,\n HttpRequest,\n HttpResponse,\n} from '@/shared/api/http';\nimport { makeRequest } from '@/shared/api/http';\n\nexport type BeforeRequestMiddleware = (\n request: HttpRequest\n) => Promise<HttpRequest>;\n\nexport type AfterRequestMiddleware = (args: {\n request: HttpRequest;\n response: HttpResponse<unknown>;\n retry: (request?: HttpRequest) => Promise<HttpResponse<unknown>>;\n}) => Promise<HttpResponse<unknown>>;\n\nexport type HttpClientMiddleware = {\n beforeRequest?: BeforeRequestMiddleware[];\n afterRequest?: AfterRequestMiddleware[];\n};\n\nexport class HttpClient {\n constructor(\n readonly config: HttpClientConfig,\n readonly middleware: HttpClientMiddleware = {}\n ) {}\n\n async send<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n return this.runRequestWithAfterMiddleware<TResponse>(request);\n }\n\n /**\n * Runs beforeRequest, executeRequest, then the full afterRequest middleware\n * chain. Used by send() and by the retry() callback so that when a\n * middleware calls retry(), the retried response also goes through all\n * afterRequest middleware (e.g. session renewal, retry). Middleware\n * must use request.attributes.retryAttempt (or similar) to avoid infinite\n * recursion when they trigger retries.\n */\n private async runRequestWithAfterMiddleware<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n const preparedRequest = await this.runBeforeRequestMiddleware(\n this.withClientDefaults(request)\n );\n let response = await this.executeRequest<TResponse>(preparedRequest);\n\n for (const middleware of this.middleware.afterRequest ?? []) {\n response = (await middleware({\n request: preparedRequest,\n response,\n retry: (nextRequest = preparedRequest) =>\n this.runRequestWithAfterMiddleware(nextRequest) as Promise<\n HttpResponse<TResponse>\n >,\n })) as HttpResponse<TResponse>;\n }\n\n return response;\n }\n\n private withClientDefaults(request: HttpRequest): HttpRequest {\n const url = this.resolveUrl(request.url);\n const headers = {\n ...(request.headers ?? {}),\n [HEADER_API_VERSION]: this.config.xApiVersion,\n };\n\n return {\n ...request,\n url,\n headers,\n };\n }\n\n /**\n * Resolves a request URL against the client's baseUrl.\n *\n * @internal Public only for testing. Do not use in application code; use\n * {@link HttpClient.send} with a path and the client will resolve the URL.\n */\n resolveUrl(url: string): string {\n // If already absolute, use as-is.\n if (url.startsWith('http://') || url.startsWith('https://')) {\n return url;\n }\n // Otherwise append path to baseUrl so base path (e.g. /api) is preserved.\n const base = this.config.baseUrl.replace(/\\/$/, '');\n const path = url.startsWith('/') ? url : `/${url}`;\n return base + path;\n }\n\n private async runBeforeRequestMiddleware(\n initialRequest: HttpRequest\n ): Promise<HttpRequest> {\n let request = initialRequest;\n for (const middleware of this.middleware.beforeRequest ?? []) {\n request = await middleware(request);\n }\n\n return request;\n }\n\n private executeRequest<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n return makeRequest<TResponse>(request);\n }\n}\n","import { Request } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { AfterRequestMiddleware } from '@/shared/api/http-client';\n\nconst MAX_ATTEMPTS = 3;\nconst INITIAL_DELAY_MS = 300;\nconst MAX_DELAY_MS = 2000;\n\nconst RETRYABLE_4XX = new Set([408, 409, 429]);\n\nexport function isRetryableStatus(status: number): boolean {\n return (status >= 500 && status < 600) || RETRYABLE_4XX.has(status);\n}\n\nfunction getRetryDelayMs(attempt: number): number {\n return Math.min(INITIAL_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);\n}\n\nexport type RequestRetryMiddlewareOptions = {\n /**\n * Optional delay function. Defaults to real setTimeout-based delay.\n * Use a no-op (e.g. () => Promise.resolve()) in tests to avoid slow tests.\n */\n delayFn?: (ms: number) => Promise<void>;\n};\n\n/**\n * Creates the request retry after-request middleware. Inject a no-op delayFn\n * in tests to avoid real delays (unit testing best practice).\n */\nexport function createRequestRetryMiddleware(\n options: RequestRetryMiddlewareOptions = {}\n): AfterRequestMiddleware {\n const delayFn = options.delayFn ?? defaultDelay;\n\n return async ({ request, response, retry }) => {\n if (!isRetryableStatus(response.status)) {\n return response;\n }\n\n const currentAttempt = Attributes.getRetryAttempt(request.attributes);\n if (currentAttempt >= MAX_ATTEMPTS - 1) {\n return response;\n }\n\n const nextAttempt = currentAttempt + 1;\n await delayFn(getRetryDelayMs(nextAttempt));\n\n const nextRequest = Request.concatAttributes(\n request,\n Attributes.retryAttempt(nextAttempt)\n );\n return retry(nextRequest);\n };\n}\n\nfunction defaultDelay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retries the request up to 3 times with exponential backoff when the response\n * has a retryable status (5xx server errors). Uses request.attributes.retryAttempt\n * to decide delay and whether to retry, so the middleware does not loop when\n * retry() runs the full HTTP middleware chain again.\n */\nexport const requestRetryMiddleware: AfterRequestMiddleware =\n createRequestRetryMiddleware();\n"],"mappings":"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","names":[]}
|
package/dist/chunk-IADBIDY6.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useCoinList
|
|
3
|
-
} from "./chunk-V5M7SA3C.js";
|
|
4
|
-
import {
|
|
5
|
-
NotAuthenticatedError
|
|
6
|
-
} from "./chunk-P4DTIPEX.js";
|
|
7
|
-
|
|
8
|
-
// src/client/hooks/useCoinListOfferDetails.ts
|
|
9
|
-
import { useEffect, useState } from "react";
|
|
10
|
-
var LOADING_STATE = { type: "LOADING" };
|
|
11
|
-
function useCoinListOfferDetails(offerId) {
|
|
12
|
-
const { coinlist, isReady } = useCoinList();
|
|
13
|
-
const [offerDetailsState, setOfferDetailsState] = useState(LOADING_STATE);
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
let isCancelled = false;
|
|
16
|
-
if (!isReady) {
|
|
17
|
-
setOfferDetailsState(LOADING_STATE);
|
|
18
|
-
return () => {
|
|
19
|
-
isCancelled = true;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
setOfferDetailsState(LOADING_STATE);
|
|
23
|
-
coinlist.fetchOfferDetails(offerId).then((offerDetail) => {
|
|
24
|
-
if (!isCancelled) {
|
|
25
|
-
setOfferDetailsState({ type: "CONTENT", offerDetail });
|
|
26
|
-
}
|
|
27
|
-
}).catch((error) => {
|
|
28
|
-
if (!isCancelled) {
|
|
29
|
-
const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
|
|
30
|
-
setOfferDetailsState({ type: "ERROR", reason });
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
return () => {
|
|
34
|
-
isCancelled = true;
|
|
35
|
-
};
|
|
36
|
-
}, [coinlist, isReady, offerId]);
|
|
37
|
-
return { offerDetailsState };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// src/client/hooks/useCoinListOffers.ts
|
|
41
|
-
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
42
|
-
var LOADING_STATE2 = { type: "LOADING" };
|
|
43
|
-
function useCoinListOffers() {
|
|
44
|
-
const { coinlist, isReady } = useCoinList();
|
|
45
|
-
const [offersState, setOffersState] = useState2(LOADING_STATE2);
|
|
46
|
-
useEffect2(() => {
|
|
47
|
-
let isCancelled = false;
|
|
48
|
-
if (!isReady) {
|
|
49
|
-
setOffersState(LOADING_STATE2);
|
|
50
|
-
return () => {
|
|
51
|
-
isCancelled = true;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
setOffersState(LOADING_STATE2);
|
|
55
|
-
coinlist.fetchAllOffers().then((offers) => {
|
|
56
|
-
if (!isCancelled) {
|
|
57
|
-
setOffersState({ type: "CONTENT", offers });
|
|
58
|
-
}
|
|
59
|
-
}).catch((error) => {
|
|
60
|
-
if (!isCancelled) {
|
|
61
|
-
const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
|
|
62
|
-
setOffersState({ type: "ERROR", reason });
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
return () => {
|
|
66
|
-
isCancelled = true;
|
|
67
|
-
};
|
|
68
|
-
}, [coinlist, isReady]);
|
|
69
|
-
return { offersState };
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export {
|
|
73
|
-
useCoinListOfferDetails,
|
|
74
|
-
useCoinListOffers
|
|
75
|
-
};
|
|
76
|
-
//# sourceMappingURL=chunk-IADBIDY6.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/hooks/useCoinListOfferDetails.ts","../src/client/hooks/useCoinListOffers.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useCoinList } from '@/client/hooks/useCoinList';\nimport { NotAuthenticatedError } from '@/shared/types/errors';\nimport type { OfferId } from '@/shared/types/offer';\nimport type { OfferDetail } from '@/shared/types/offer-detail';\n\nexport type LoadOfferDetailsReason = 'not-authenticated' | 'generic-error';\n\nexport type LoadOfferDetailsState =\n | {\n type: 'LOADING';\n }\n | {\n type: 'ERROR';\n reason: LoadOfferDetailsReason;\n }\n | {\n type: 'CONTENT';\n offerDetail: OfferDetail;\n };\n\nexport interface UseCoinListOfferDetailsResult {\n offerDetailsState: LoadOfferDetailsState;\n}\n\nconst LOADING_STATE: LoadOfferDetailsState = { type: 'LOADING' };\n\n/**\n * Loads CoinList offer details for a given offer id and exposes a UI-friendly state.\n *\n * Returns `LOADING` while CoinList is initializing or while details are being fetched.\n * Returns `CONTENT` with the offer when `fetchOfferDetails()` succeeds.\n * Returns `ERROR` with:\n * - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}\n * - `generic-error` for any other failure\n */\nexport function useCoinListOfferDetails(\n offerId: OfferId\n): UseCoinListOfferDetailsResult {\n const { coinlist, isReady } = useCoinList();\n const [offerDetailsState, setOfferDetailsState] =\n useState<LoadOfferDetailsState>(LOADING_STATE);\n\n useEffect(() => {\n let isCancelled = false;\n\n if (!isReady) {\n setOfferDetailsState(LOADING_STATE);\n return () => {\n isCancelled = true;\n };\n }\n\n setOfferDetailsState(LOADING_STATE);\n coinlist\n .fetchOfferDetails(offerId)\n .then((offerDetail) => {\n if (!isCancelled) {\n setOfferDetailsState({ type: 'CONTENT', offerDetail });\n }\n })\n .catch((error: unknown) => {\n if (!isCancelled) {\n const reason: LoadOfferDetailsReason =\n error instanceof NotAuthenticatedError\n ? 'not-authenticated'\n : 'generic-error';\n setOfferDetailsState({ type: 'ERROR', reason });\n }\n });\n\n return () => {\n isCancelled = true;\n };\n }, [coinlist, isReady, offerId]);\n\n return { offerDetailsState };\n}\n","import { useEffect, useState } from 'react';\nimport { useCoinList } from '@/client/hooks/useCoinList';\nimport { NotAuthenticatedError } from '@/shared/types/errors';\nimport type { Offer } from '@/shared/types/offer';\n\nexport type LoadOffersReason = 'not-authenticated' | 'generic-error';\n\nexport type LoadOffersState =\n | {\n type: 'LOADING';\n }\n | {\n type: 'ERROR';\n reason: LoadOffersReason;\n }\n | {\n type: 'CONTENT';\n offers: Offer[];\n };\n\nexport interface UseCoinListOffersResult {\n offersState: LoadOffersState;\n}\n\nconst LOADING_STATE: LoadOffersState = { type: 'LOADING' };\n\n/**\n * Loads all CoinList offers for the current user and exposes a UI-friendly state.\n *\n * Returns `LOADING` while CoinList is initializing or while offers are being fetched.\n * Returns `CONTENT` with all offers when `fetchAllOffers()` succeeds.\n * Returns `ERROR` with:\n * - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}\n * - `generic-error` for any other failure\n */\nexport function useCoinListOffers(): UseCoinListOffersResult {\n const { coinlist, isReady } = useCoinList();\n const [offersState, setOffersState] =\n useState<LoadOffersState>(LOADING_STATE);\n\n useEffect(() => {\n let isCancelled = false;\n\n // Wait until CoinListProvider finishes auth initialization.\n if (!isReady) {\n setOffersState(LOADING_STATE);\n return () => {\n isCancelled = true;\n };\n }\n\n setOffersState(LOADING_STATE);\n coinlist\n .fetchAllOffers()\n .then((offers) => {\n if (!isCancelled) {\n setOffersState({ type: 'CONTENT', offers });\n }\n })\n .catch((error: unknown) => {\n if (!isCancelled) {\n const reason: LoadOffersReason =\n error instanceof NotAuthenticatedError\n ? 'not-authenticated'\n : 'generic-error';\n setOffersState({ type: 'ERROR', reason });\n }\n });\n\n return () => {\n isCancelled = true;\n };\n }, [coinlist, isReady]);\n\n return { offersState };\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,WAAW,gBAAgB;AAyBpC,IAAM,gBAAuC,EAAE,MAAM,UAAU;AAWxD,SAAS,wBACd,SAC+B;AAC/B,QAAM,EAAE,UAAU,QAAQ,IAAI,YAAY;AAC1C,QAAM,CAAC,mBAAmB,oBAAoB,IAC5C,SAAgC,aAAa;AAE/C,YAAU,MAAM;AACd,QAAI,cAAc;AAElB,QAAI,CAAC,SAAS;AACZ,2BAAqB,aAAa;AAClC,aAAO,MAAM;AACX,sBAAc;AAAA,MAChB;AAAA,IACF;AAEA,yBAAqB,aAAa;AAClC,aACG,kBAAkB,OAAO,EACzB,KAAK,CAAC,gBAAgB;AACrB,UAAI,CAAC,aAAa;AAChB,6BAAqB,EAAE,MAAM,WAAW,YAAY,CAAC;AAAA,MACvD;AAAA,IACF,CAAC,EACA,MAAM,CAAC,UAAmB;AACzB,UAAI,CAAC,aAAa;AAChB,cAAM,SACJ,iBAAiB,wBACb,sBACA;AACN,6BAAqB,EAAE,MAAM,SAAS,OAAO,CAAC;AAAA,MAChD;AAAA,IACF,CAAC;AAEH,WAAO,MAAM;AACX,oBAAc;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,UAAU,SAAS,OAAO,CAAC;AAE/B,SAAO,EAAE,kBAAkB;AAC7B;;;AC7EA,SAAS,aAAAA,YAAW,YAAAC,iBAAgB;AAwBpC,IAAMC,iBAAiC,EAAE,MAAM,UAAU;AAWlD,SAAS,oBAA6C;AAC3D,QAAM,EAAE,UAAU,QAAQ,IAAI,YAAY;AAC1C,QAAM,CAAC,aAAa,cAAc,IAChCC,UAA0BD,cAAa;AAEzC,EAAAE,WAAU,MAAM;AACd,QAAI,cAAc;AAGlB,QAAI,CAAC,SAAS;AACZ,qBAAeF,cAAa;AAC5B,aAAO,MAAM;AACX,sBAAc;AAAA,MAChB;AAAA,IACF;AAEA,mBAAeA,cAAa;AAC5B,aACG,eAAe,EACf,KAAK,CAAC,WAAW;AAChB,UAAI,CAAC,aAAa;AAChB,uBAAe,EAAE,MAAM,WAAW,OAAO,CAAC;AAAA,MAC5C;AAAA,IACF,CAAC,EACA,MAAM,CAAC,UAAmB;AACzB,UAAI,CAAC,aAAa;AAChB,cAAM,SACJ,iBAAiB,wBACb,sBACA;AACN,uBAAe,EAAE,MAAM,SAAS,OAAO,CAAC;AAAA,MAC1C;AAAA,IACF,CAAC;AAEH,WAAO,MAAM;AACX,oBAAc;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,SAAO,EAAE,YAAY;AACvB;","names":["useEffect","useState","LOADING_STATE","useState","useEffect"]}
|