Skip to content

Typescript CreatePaymentMethodLambda #7017

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jun 9, 2025

Conversation

rupertbates
Copy link
Member

@rupertbates rupertbates commented May 12, 2025

What are you doing in this PR?

This PR migrates the CreatePaymentMethod lambda to Typescript it follows on from #7008 and is part of the work to fully migrate support-workers from Scala to Typescript.

Trello Card

Why are you doing this?

Things to test

  • Make sure FailureHandler understands the errors thrown from TS
  • Stripe payment in US, UK & AU
  • Stripe hosted payment
  • PayPal payment
  • GoCardless payment

Copy link
Contributor

github-actions bot commented May 12, 2025

Copy link
Contributor

github-actions bot commented May 12, 2025

Size Change: 0 B

Total Size: 1.49 MB

ℹ️ View Unchanged
Filename Size
./support-frontend/public/compiled-assets/javascripts/[countryGroupId]/events/router.js 95.4 kB
./support-frontend/public/compiled-assets/javascripts/[countryGroupId]/router.js 104 kB
./support-frontend/public/compiled-assets/javascripts/ausMomentMap.js 108 kB
./support-frontend/public/compiled-assets/javascripts/contributionsRedirectStyles.js 20 B
./support-frontend/public/compiled-assets/javascripts/downForMaintenancePage.js 72 kB
./support-frontend/public/compiled-assets/javascripts/error404Page.js 72 kB
./support-frontend/public/compiled-assets/javascripts/error500Page.js 71.9 kB
./support-frontend/public/compiled-assets/javascripts/favicons.js 618 B
./support-frontend/public/compiled-assets/javascripts/paperSubscriptionLandingPage.js 92.8 kB
./support-frontend/public/compiled-assets/javascripts/payPalErrorPage.js 70.1 kB
./support-frontend/public/compiled-assets/javascripts/payPalErrorPageStyles.js 20 B
./support-frontend/public/compiled-assets/javascripts/promotionTerms.js 78.4 kB
./support-frontend/public/compiled-assets/javascripts/subscriptionsLandingPage.js 102 kB
./support-frontend/public/compiled-assets/javascripts/unsupportedBrowserStyles.js 20 B
./support-frontend/public/compiled-assets/javascripts/weeklySubscriptionCheckoutPage.js 162 kB
./support-frontend/public/compiled-assets/javascripts/weeklySubscriptionLandingPage.js 95.7 kB
./support-frontend/public/compiled-assets/webpack/128.js 7.12 kB
./support-frontend/public/compiled-assets/webpack/167.js 24.5 kB
./support-frontend/public/compiled-assets/webpack/230.js 28.6 kB
./support-frontend/public/compiled-assets/webpack/249.js 34 kB
./support-frontend/public/compiled-assets/webpack/286.js 14.6 kB
./support-frontend/public/compiled-assets/webpack/340.js 5 kB
./support-frontend/public/compiled-assets/webpack/709.js 109 kB
./support-frontend/public/compiled-assets/webpack/760.js 5.79 kB
./support-frontend/public/compiled-assets/webpack/774.js 7 kB
./support-frontend/public/compiled-assets/webpack/793.js 4.35 kB
./support-frontend/public/compiled-assets/webpack/8.js 20.1 kB
./support-frontend/public/compiled-assets/webpack/801.js 2.18 kB
./support-frontend/public/compiled-assets/webpack/916.js 8.9 kB
./support-frontend/public/compiled-assets/webpack/948.js 3.5 kB
./support-frontend/public/compiled-assets/webpack/checkout.js 18.6 kB
./support-frontend/public/compiled-assets/webpack/GuardianAdLiteLanding.js 8.43 kB
./support-frontend/public/compiled-assets/webpack/LandingPage.js 15.3 kB
./support-frontend/public/compiled-assets/webpack/oneTimeCheckout.js 7.33 kB
./support-frontend/public/compiled-assets/webpack/ThankYou.js 43.2 kB

compressed-size-action

Copy link
Contributor

github-actions bot commented May 12, 2025

@rupertbates rupertbates force-pushed the rb/typescript-support-workers-createPaymentMethod branch 5 times, most recently from 8a9088b to 62d4075 Compare June 3, 2025 14:34
@@ -6,13 +6,14 @@
"scripts": {
"test": "jest --group=-integration",
"it-test": "jest --group=integration",
"lint": "eslint src/typescript/**/*.ts",
"lint:check": "eslint src/typescript/**/*.ts",
"lint:fix": "eslint src/typescript/**/*.ts --fix",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These match the commands in support-frontend now for consistency

@rupertbates rupertbates force-pushed the rb/typescript-support-workers-createPaymentMethod branch 3 times, most recently from 6269470 to 192a611 Compare June 4, 2025 09:49
@rupertbates rupertbates force-pushed the rb/typescript-support-workers-createPaymentMethod branch from 477bf45 to 83d7d70 Compare June 5, 2025 13:09
@@ -9,10 +9,11 @@
"lint": "eslint src/typescript/**/*.ts",
"check-formatting": "prettier --check **.ts",
"build": "tsc",
"bundle": "esbuild src/typescript/lambdas/*.ts --bundle --platform=node --target=node22 --outdir=target/typescript",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have introduced esbuild as a bundler because it was very difficult to get pnpm to produce a flat set of dependencies for deployment. It should also produce a smaller deployment artifact.

@rupertbates rupertbates force-pushed the rb/typescript-support-workers-createPaymentMethod branch from 630469d to 6e8fe30 Compare June 6, 2025 09:48
import { z } from 'zod';

export const billingPeriodSchema = z.union([
z.literal('Monthly'), //TODO: share this with support-frontend
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've decided to do all the TODOs around sharing models in a follow up PR because it will probably involve some quite extensive changes

@rupertbates rupertbates force-pushed the rb/typescript-support-workers-createPaymentMethod branch from 5f409ee to df65194 Compare June 6, 2025 15:19
Copy link
Member

@tjmw tjmw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good, nice work! 👏

I've left a few comments / questions, all minor stuff.

"install-runtime-dependencies": "pnpm install --ignore-scripts --modules-dir target/typescript/node_modules --production",
"build-and-zip": "pnpm clean-target && pnpm build && pnpm install-runtime-dependencies && cd target/typescript && zip -r support-workers.zip ./* -x \".*\" -x \"__MACOSX\"",
"package": "pnpm check-formatting && pnpm lint && pnpm test && pnpm build-and-zip"
"zip": "cd target/typescript && zip -r support-workers.zip ./* -x \".*\" -x \"__MACOSX\"",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this exclude doing? -x \".*\" I'm finding it hard to parse!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's dotfiles, probably not needed now that we are using esbuild actually

"package": "pnpm check-formatting && pnpm lint && pnpm test && pnpm build-and-zip"
"zip": "cd target/typescript && zip -r support-workers.zip ./* -x \".*\" -x \"__MACOSX\"",
"bundle-and-zip": "pnpm clean-target && pnpm bundle && pnpm zip",
"package": "pnpm check-formatting && pnpm lint:check && pnpm test && pnpm bundle-and-zip"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does type checking happening implicitly in one of these commands? If not should it be added?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it needs to be added 👍

Comment on lines 14 to 15
z.literal('StripeApplePay'),
z.literal('StripePaymentRequestButton'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to extract these out to named consts like the others?

directDebitPaymentGatewaySchema,
z.literal('Amazon Pay - Contributions USA'),
])
.or(stripePaymentGatewaySchema);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the .or do here? Is the result the same as adding stripePaymentGatewaySchema to the union?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes in this case it actually is, although it isn't in all cases 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If fact this schema wasn't actually used

Comment on lines +19 to +25
const supporterPlus = createPaymentMethodStateSchema.parse(
createPaymentSupporterPlus,
);
expect(supporterPlus.product.currency).toBe('EUR');
expect(supporterPlus.acquisitionData?.ophanIds.pageviewId).toBe(
'9999999999999',
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about splitting each of these product/payment method tests out to their own test/it block? I think it's helpful as it makes it clearer what's going on if there are failures.

),
);
}
return Promise.reject(new Error('Unknown payment method type'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth including the unknown type in the error? Might be helpful to know what it was if we ever reach this line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually unreachable code, I'm surprised it wasn't being flagged by lint

@rupertbates rupertbates merged commit 5a04958 into main Jun 9, 2025
18 checks passed
@rupertbates rupertbates deleted the rb/typescript-support-workers-createPaymentMethod branch June 9, 2025 13:30
@prout-bot
Copy link

Seen on PROD (merged by @rupertbates 8 minutes and 47 seconds ago)

Sentry Release: support-client-side, support

Comment on lines +9 to +15
"lint:check": "eslint src/typescript/**/*.ts",
"lint:fix": "eslint --fix src/typescript/**/*.ts",
"check-formatting": "prettier --check **.ts",
"build": "tsc",
"bundle": "esbuild src/typescript/lambdas/*.ts --bundle --platform=node --target=node22 --outdir=target/typescript",
"clean-target": "rm -rf target && mkdir -p target",
"install-runtime-dependencies": "pnpm install --ignore-scripts --modules-dir target/typescript/node_modules --production",
"build-and-zip": "pnpm clean-target && pnpm build && pnpm install-runtime-dependencies && cd target/typescript && zip -r support-workers.zip ./* -x \".*\" -x \"__MACOSX\"",
"package": "pnpm check-formatting && pnpm lint && pnpm test && pnpm build-and-zip"
"zip": "cd target/typescript && zip -r support-workers.zip ./* -x \".*\" -x \"__MACOSX\"",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a standard for what these commands should be?

in support service-lambdas we use type-check, lint or lint --fix and check-formatting or fix-formatting
Obviously I'm not working on support-workers much now, but it is already a bit of a pain to remember the commands so it would be nice if they could be consistent across projects

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I agree, I might make a health card to standardise them

Name: `/${stage}/support/support-workers/${configKeyName}`,
WithDecryption: true,
};
const command = new GetParameterCommand(params);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually doing a PR in support-service-lambdas (following the threads on chat) to add a module to retrieve all the separate config keys under a /stage/stack/app/* in one go and parse it as json as a whole.
It's interesting that you've gone for storing the whole config as JSON in a single key though, is that preferred over individual keys? As the idea is the module would encourage our standard supporter revenue way.

Comment on lines +6 to +10
export async function getConfig<I, O, T extends z.ZodType<O, z.ZodTypeDef, I>>(
stage: Stage,
configKeyName: string,
schema: T,
): Promise<O> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why <I, O, T extends z.ZodType<O, z.ZodTypeDef, I>>
with schema: T,
and not <O>
with schema: z.ZodType<O, z.ZodTypeDef, any>
? ( @tjmw and I were looking at similar code and wondering this morning )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants