()
| 69 | } |
| 70 | |
| 71 | async function main(): Promise<void> { |
| 72 | const args = parseArgs(process.argv); |
| 73 | |
| 74 | if (!process.env.STRIPE_SECRET_KEY) throw new Error('STRIPE_SECRET_KEY not set'); |
| 75 | if (!process.env.WORKOS_API_KEY) throw new Error('WORKOS_API_KEY not set'); |
| 76 | |
| 77 | const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); |
| 78 | const workos = new WorkOS(process.env.WORKOS_API_KEY); |
| 79 | const orgDb = new OrganizationDatabase(); |
| 80 | |
| 81 | const subscription = await stripe.subscriptions.retrieve(args.subscriptionId); |
| 82 | const customerId = typeof subscription.customer === 'string' |
| 83 | ? subscription.customer |
| 84 | : subscription.customer.id; |
| 85 | |
| 86 | const customer = await stripe.customers.retrieve(customerId); |
| 87 | if (customer.deleted) { |
| 88 | throw new Error(`Customer ${customerId} is deleted — cannot backfill.`); |
| 89 | } |
| 90 | |
| 91 | const orgIdFromMetadata = subscription.metadata?.workos_organization_id |
| 92 | || customer.metadata?.workos_organization_id; |
| 93 | if (!orgIdFromMetadata) { |
| 94 | throw new Error( |
| 95 | `No workos_organization_id found on subscription ${args.subscriptionId} or customer ${customerId} metadata. Cannot resolve org.`, |
| 96 | ); |
| 97 | } |
| 98 | |
| 99 | const org = await orgDb.getOrganization(orgIdFromMetadata); |
| 100 | if (!org) { |
| 101 | throw new Error(`Organization ${orgIdFromMetadata} not found in local DB.`); |
| 102 | } |
| 103 | |
| 104 | const workosUserId = args.workosUserId ?? org.pending_agreement_user_id; |
| 105 | if (!workosUserId) { |
| 106 | const memberships = await workos.userManagement.listOrganizationMemberships({ |
| 107 | organizationId: org.workos_organization_id, |
| 108 | }); |
| 109 | const lines = await Promise.all(memberships.data.map(async (m) => { |
| 110 | try { |
| 111 | const u = await workos.userManagement.getUser(m.userId); |
| 112 | return ` ${m.userId} ${u.email}${u.firstName ? ` (${u.firstName} ${u.lastName ?? ''})` : ''}`; |
| 113 | } catch { |
| 114 | return ` ${m.userId} (lookup failed)`; |
| 115 | } |
| 116 | })); |
| 117 | throw new Error( |
| 118 | `No user resolvable via --workos-user-id or org.pending_agreement_user_id. Pick from current members:\n${lines.join('\n')}\n\nRerun with --workos-user-id <id>.`, |
| 119 | ); |
| 120 | } |
| 121 | |
| 122 | const user = await workos.userManagement.getUser(workosUserId); |
| 123 | |
| 124 | const memberships = await workos.userManagement.listOrganizationMemberships({ |
| 125 | userId: workosUserId, |
| 126 | organizationId: org.workos_organization_id, |
| 127 | }); |
| 128 | if (memberships.data.length === 0) { |
no test coverage detected