Skip to content

Commit 4adea5b

Browse files
authored
Fix identifyUser wasCreated (#654)
## Motivation / Description We were incorrectly obtaining the was_created field from the response. We should have used the response code instead. This fixes that and should deal with RevenueCat/purchases-flutter#1539 ## Changes introduced ## Linear ticket (if any) ## Additional comments
1 parent a5e6d94 commit 4adea5b

File tree

5 files changed

+69
-20
lines changed

5 files changed

+69
-20
lines changed

src/networking/backend.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type OfferingsResponse } from "./responses/offerings-response";
2-
import { performRequest } from "./http-client";
2+
import { performRequest, performRequestWithStatus } from "./http-client";
33
import {
44
CheckoutCalculateTaxEndpoint,
55
CheckoutCompleteEndpoint,
@@ -87,14 +87,22 @@ export class Backend {
8787
new_app_user_id: newAppUserId,
8888
};
8989

90-
return await performRequest<IdentifyRequestBody, IdentifyResponse>(
91-
new IdentifyEndpoint(),
92-
{
93-
apiKey: this.API_KEY,
94-
body: body,
95-
httpConfig: this.httpConfig,
96-
},
97-
);
90+
const result = await performRequestWithStatus<
91+
IdentifyRequestBody,
92+
SubscriberResponse
93+
>(new IdentifyEndpoint(), {
94+
apiKey: this.API_KEY,
95+
body: body,
96+
httpConfig: this.httpConfig,
97+
});
98+
99+
// HTTP 201 indicates the user was created, 200 indicates it already existed
100+
const was_created = result.statusCode === 201;
101+
102+
return {
103+
...result.data,
104+
was_created,
105+
};
98106
}
99107

100108
async getProducts(

src/networking/http-client.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,29 @@ interface HttpRequestConfig<RequestBody> {
1414
httpConfig?: HttpConfig;
1515
}
1616

17+
export interface ResponseWithStatus<ResponseType> {
18+
data: ResponseType;
19+
statusCode: number;
20+
}
21+
1722
export async function performRequest<RequestBody, ResponseType>(
1823
endpoint: SupportedEndpoint,
1924
config: HttpRequestConfig<RequestBody>,
2025
signal?: AbortSignal | null,
2126
): Promise<ResponseType> {
27+
const result = await performRequestWithStatus<RequestBody, ResponseType>(
28+
endpoint,
29+
config,
30+
signal,
31+
);
32+
return result.data;
33+
}
34+
35+
export async function performRequestWithStatus<RequestBody, ResponseType>(
36+
endpoint: SupportedEndpoint,
37+
config: HttpRequestConfig<RequestBody>,
38+
signal?: AbortSignal | null,
39+
): Promise<ResponseWithStatus<ResponseType>> {
2240
const { apiKey, body, headers, httpConfig } = config;
2341
const baseUrl = httpConfig?.proxyURL ?? RC_ENDPOINT;
2442
const url = `${baseUrl}${endpoint.urlPath()}`;
@@ -33,7 +51,10 @@ export async function performRequest<RequestBody, ResponseType>(
3351

3452
await handleErrors(response, endpoint);
3553

36-
return (await response.json()) as ResponseType; // TODO: Validate response is correct.
54+
const statusCode = response.status;
55+
const data = (await response.json()) as ResponseType;
56+
57+
return { data, statusCode };
3758
} catch (error) {
3859
if (error instanceof TypeError) {
3960
throw new PurchasesError(
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import type { SubscriberResponse } from "./subscriber-response";
22

3+
/**
4+
* Response from the identify endpoint.
5+
* Note: The backend returns a standard SubscriberResponse without a was_created field.
6+
* The was_created field is derived client-side from the HTTP status code:
7+
* - 201: User was created (was_created = true)
8+
* - 200: User already existed (was_created = false)
9+
*/
310
export interface IdentifyResponse extends SubscriberResponse {
411
was_created: boolean;
512
}

src/tests/networking/backend.test.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
productsResponse,
1010
getVirtualCurrenciesResponseWith3Currencies,
1111
getVirtualCurrenciesResponseWithNoCurrencies,
12-
identifyResponse,
1312
} from "../test-responses";
1413
import { Backend } from "../../networking/backend";
1514
import { StatusCodes } from "http-status-codes";
@@ -240,13 +239,32 @@ describe("identify request", () => {
240239
);
241240
}
242241

243-
test("can get customer info successfully", async () => {
244-
setIdentifyResponse(HttpResponse.json(identifyResponse, { status: 200 }));
242+
test("returns was_created: false when backend returns 200", async () => {
243+
setIdentifyResponse(
244+
HttpResponse.json(customerInfoResponse, { status: 200 }),
245+
);
246+
const backendResponse = await backend.identify(
247+
"oldAppUserId",
248+
"newAppUserId",
249+
);
250+
expect(backendResponse).toEqual({
251+
...customerInfoResponse,
252+
was_created: false,
253+
});
254+
});
255+
256+
test("returns was_created: true when backend returns 201", async () => {
257+
setIdentifyResponse(
258+
HttpResponse.json(customerInfoResponse, { status: 201 }),
259+
);
245260
const backendResponse = await backend.identify(
246261
"oldAppUserId",
247262
"newAppUserId",
248263
);
249-
expect(backendResponse).toEqual(identifyResponse);
264+
expect(backendResponse).toEqual({
265+
...customerInfoResponse,
266+
was_created: true,
267+
});
250268
});
251269

252270
test("throws an error if the backend returns a server error", async () => {

src/tests/test-responses.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -286,11 +286,6 @@ export const customerInfoResponse: SubscriberResponse = {
286286
},
287287
};
288288

289-
export const identifyResponse = {
290-
...customerInfoResponse,
291-
was_created: true,
292-
};
293-
294289
export const newAppUserIdCustomerInfoResponse = {
295290
request_date: "2024-01-22T13:23:07Z",
296291
request_date_ms: 1705929787636,
@@ -528,7 +523,7 @@ export function getRequestHandlers(): RequestHandler[] {
528523
http.post(identify, async ({ request }) => {
529524
const json = await request.json();
530525
APIPostRequest({ url: identify, json });
531-
return HttpResponse.json(identifyResponse, { status: 200 });
526+
return HttpResponse.json(customerInfoResponse, { status: 200 });
532527
}),
533528
);
534529

0 commit comments

Comments
 (0)