@nlabs/reaktor 1.16.0 → 1.18.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/README.md +186 -0
- package/docs/ASSISTANT.md +138 -0
- package/docs/GENERATION.md +29 -2
- package/docs/NATIVE_PUSH.md +56 -0
- package/lib/actions/alfredFaq.d.ts +80 -0
- package/lib/actions/alfredFaq.js +206 -0
- package/lib/actions/contentGeneration.d.ts +4 -1
- package/lib/actions/contentGeneration.js +83 -27
- package/lib/actions/contentGenerationErrors.js +1 -1
- package/lib/actions/conversations.d.ts +1 -1
- package/lib/actions/conversations.js +19 -9
- package/lib/actions/crud.js +26 -1
- package/lib/actions/index.d.ts +2 -0
- package/lib/actions/index.js +3 -1
- package/lib/actions/messages.js +23 -7
- package/lib/actions/phoneSupport.d.ts +18 -0
- package/lib/actions/phoneSupport.js +170 -0
- package/lib/actions/users.js +57 -4
- package/lib/assistant/core.d.ts +53 -0
- package/lib/assistant/core.js +123 -0
- package/lib/assistant/faq.d.ts +26 -0
- package/lib/assistant/faq.js +238 -0
- package/lib/assistant/faqCore.d.ts +23 -0
- package/lib/assistant/faqCore.js +20 -0
- package/lib/assistant/index.d.ts +7 -0
- package/lib/assistant/index.js +5 -0
- package/lib/assistant/service.d.ts +35 -0
- package/lib/assistant/service.js +201 -0
- package/lib/config.js +3 -2
- package/lib/durableChat/conversations.d.ts +62 -0
- package/lib/durableChat/conversations.js +729 -0
- package/lib/durableChat/errors.d.ts +6 -0
- package/lib/durableChat/errors.js +11 -0
- package/lib/durableChat/events.d.ts +22 -0
- package/lib/durableChat/events.js +50 -0
- package/lib/durableChat/index.d.ts +8 -0
- package/lib/durableChat/index.js +10 -0
- package/lib/durableChat/membership.d.ts +24 -0
- package/lib/durableChat/membership.js +85 -0
- package/lib/durableChat/messageTypes.d.ts +76 -0
- package/lib/durableChat/messageTypes.js +3 -0
- package/lib/durableChat/messages.d.ts +16 -0
- package/lib/durableChat/messages.js +257 -0
- package/lib/durableChat/transaction.d.ts +10 -0
- package/lib/durableChat/transaction.js +53 -0
- package/lib/durableChat/types.d.ts +81 -0
- package/lib/durableChat/types.js +3 -0
- package/lib/index.d.ts +4 -4
- package/lib/index.js +5 -3
- package/lib/lambdas/actions/websockets.js +4 -4
- package/lib/nativePush/graphql.d.ts +14 -0
- package/lib/nativePush/graphql.js +105 -0
- package/lib/nativePush/index.d.ts +7 -0
- package/lib/nativePush/index.js +9 -0
- package/lib/nativePush/migrations.d.ts +2 -0
- package/lib/nativePush/migrations.js +36 -0
- package/lib/nativePush/nativePushContract.fixture.d.ts +22 -0
- package/lib/nativePush/nativePushContract.fixture.js +27 -0
- package/lib/nativePush/payload.d.ts +2 -0
- package/lib/nativePush/payload.js +106 -0
- package/lib/nativePush/repository.d.ts +9 -0
- package/lib/nativePush/repository.js +120 -0
- package/lib/nativePush/service.d.ts +2 -0
- package/lib/nativePush/service.js +110 -0
- package/lib/nativePush/snsProvider.d.ts +17 -0
- package/lib/nativePush/snsProvider.js +165 -0
- package/lib/nativePush/types.d.ts +89 -0
- package/lib/nativePush/types.js +3 -0
- package/lib/organizations/accountLifecycle.d.ts +7 -0
- package/lib/organizations/accountLifecycle.js +106 -0
- package/lib/organizations/authorization.d.ts +9 -0
- package/lib/organizations/authorization.js +40 -0
- package/lib/organizations/billing.d.ts +38 -0
- package/lib/organizations/billing.js +277 -0
- package/lib/organizations/billingProvider.d.ts +4 -0
- package/lib/organizations/billingProvider.js +287 -0
- package/lib/organizations/billingUpdates.d.ts +9 -0
- package/lib/organizations/billingUpdates.js +388 -0
- package/lib/organizations/index.d.ts +10 -0
- package/lib/organizations/index.js +12 -0
- package/lib/organizations/mail.d.ts +10 -0
- package/lib/organizations/mail.js +60 -0
- package/lib/organizations/memberDirectory.d.ts +15 -0
- package/lib/organizations/memberDirectory.js +28 -0
- package/lib/organizations/membership.d.ts +19 -0
- package/lib/organizations/membership.js +248 -0
- package/lib/organizations/passwordRecovery.d.ts +9 -0
- package/lib/organizations/passwordRecovery.js +50 -0
- package/lib/organizations/plans.d.ts +6 -0
- package/lib/organizations/plans.js +40 -0
- package/lib/organizations/providerPagination.d.ts +6 -0
- package/lib/organizations/providerPagination.js +23 -0
- package/lib/organizations/reconciliation.d.ts +11 -0
- package/lib/organizations/reconciliation.js +400 -0
- package/lib/organizations/signup.d.ts +25 -0
- package/lib/organizations/signup.js +169 -0
- package/lib/organizations/store.d.ts +25 -0
- package/lib/organizations/store.js +167 -0
- package/lib/organizations/types.d.ts +138 -0
- package/lib/organizations/types.js +3 -0
- package/lib/organizations/verification.d.ts +3 -0
- package/lib/organizations/verification.js +51 -0
- package/package.json +16 -3
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import Stripe from 'stripe';
|
|
2
|
+
import { stripeApiVersion } from '../utils/stripeUtils.js';
|
|
3
|
+
import { createOrganizationBillingUpdater } from './billingUpdates.js';
|
|
4
|
+
import { getOrganizationPlan } from './plans.js';
|
|
5
|
+
import { listAllProviderRecords as listAll } from './providerPagination.js';
|
|
6
|
+
import { organizationKey } from './store.js';
|
|
7
|
+
export const organizationBillingMode = ()=>{
|
|
8
|
+
const mode = process.env.ORGANIZATION_BILLING_MODE || 'disabled';
|
|
9
|
+
if (![
|
|
10
|
+
'disabled',
|
|
11
|
+
'test'
|
|
12
|
+
].includes(mode)) {
|
|
13
|
+
throw new Error('invalid_billing_mode');
|
|
14
|
+
}
|
|
15
|
+
return mode;
|
|
16
|
+
};
|
|
17
|
+
const organizationStripeClient = ()=>{
|
|
18
|
+
if (organizationBillingMode() !== 'test') {
|
|
19
|
+
throw new Error('billing_disabled');
|
|
20
|
+
}
|
|
21
|
+
const key = process.env.ORGANIZATION_STRIPE_SECRET_KEY || '';
|
|
22
|
+
if (!/^(sk|rk)_test_[A-Za-z0-9]+$/.test(key)) {
|
|
23
|
+
throw new Error('test_billing_key_required');
|
|
24
|
+
}
|
|
25
|
+
return new Stripe(key, {
|
|
26
|
+
apiVersion: stripeApiVersion,
|
|
27
|
+
maxNetworkRetries: 1,
|
|
28
|
+
timeout: 20000,
|
|
29
|
+
typescript: true
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
const verifyEvent = (stripe, body, signature)=>{
|
|
33
|
+
const secret = process.env.ORGANIZATION_STRIPE_WEBHOOK_SECRET || '';
|
|
34
|
+
if (!secret.startsWith('whsec_') || !signature) {
|
|
35
|
+
throw new Error('invalid_billing_event');
|
|
36
|
+
}
|
|
37
|
+
const event = stripe.webhooks.constructEvent(body, signature, secret);
|
|
38
|
+
const object = event.data.object;
|
|
39
|
+
const customerId = typeof object.customer === 'string' ? object.customer : object.customer?.id;
|
|
40
|
+
if (event.livemode || !customerId || !/^cus_[A-Za-z0-9]+$/.test(customerId)) {
|
|
41
|
+
throw new Error('invalid_billing_event');
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
customerId,
|
|
45
|
+
eventId: event.id,
|
|
46
|
+
type: event.type
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export const verifyOrganizationBillingEvent = (body, signature)=>verifyEvent(organizationStripeClient(), body, signature);
|
|
50
|
+
export const getOrganizationBillingProvider = async ()=>{
|
|
51
|
+
const stripe = organizationStripeClient();
|
|
52
|
+
const origin = process.env.ORGANIZATION_SITE_ORIGIN || '';
|
|
53
|
+
let parsed;
|
|
54
|
+
try {
|
|
55
|
+
parsed = new URL(origin);
|
|
56
|
+
} catch {
|
|
57
|
+
throw new Error('billing_origin_required');
|
|
58
|
+
}
|
|
59
|
+
if (parsed.protocol !== 'https:' || parsed.origin !== origin || parsed.username || parsed.password) {
|
|
60
|
+
throw new Error('billing_origin_required');
|
|
61
|
+
}
|
|
62
|
+
const prices = {
|
|
63
|
+
pro: process.env.ORGANIZATION_STRIPE_PRO_PRICE_ID || '',
|
|
64
|
+
seat: process.env.ORGANIZATION_STRIPE_SEAT_PRICE_ID || '',
|
|
65
|
+
starter: process.env.ORGANIZATION_STRIPE_STARTER_PRICE_ID || ''
|
|
66
|
+
};
|
|
67
|
+
await Promise.all(Object.entries(prices).map(async ([name, id])=>{
|
|
68
|
+
if (!/^price_[A-Za-z0-9]+$/.test(id)) {
|
|
69
|
+
throw new Error('billing_price_mismatch');
|
|
70
|
+
}
|
|
71
|
+
const expected = name === 'seat' ? 800 : getOrganizationPlan(name).baseCents;
|
|
72
|
+
const price = await stripe.prices.retrieve(id);
|
|
73
|
+
if (price.livemode || !price.active || price.currency !== 'usd' || price.unit_amount !== expected || price.recurring?.interval !== 'month' || price.recurring.interval_count !== 1 || price.recurring.usage_type !== 'licensed') {
|
|
74
|
+
throw new Error('billing_price_mismatch');
|
|
75
|
+
}
|
|
76
|
+
}));
|
|
77
|
+
const retrieve = async (customerId, subscriptionId)=>{
|
|
78
|
+
const all = await listAll((startingAfter)=>stripe.subscriptions.list({
|
|
79
|
+
customer: customerId,
|
|
80
|
+
limit: 100,
|
|
81
|
+
starting_after: startingAfter,
|
|
82
|
+
status: 'all'
|
|
83
|
+
}));
|
|
84
|
+
const live = all.filter((subscription)=>![
|
|
85
|
+
'canceled',
|
|
86
|
+
'incomplete_expired'
|
|
87
|
+
].includes(subscription.status));
|
|
88
|
+
if (live.length > 1) {
|
|
89
|
+
throw new Error('billing_subscription_conflict');
|
|
90
|
+
}
|
|
91
|
+
const subscription = subscriptionId ? await stripe.subscriptions.retrieve(subscriptionId) : live[0] || null;
|
|
92
|
+
if (!subscription) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
const customer = typeof subscription.customer === 'string' ? subscription.customer : subscription.customer.id;
|
|
96
|
+
const items = subscription.items.data;
|
|
97
|
+
const base = items.find((item)=>[
|
|
98
|
+
prices.pro,
|
|
99
|
+
prices.starter
|
|
100
|
+
].includes(item.price.id));
|
|
101
|
+
const seat = items.find((item)=>item.price.id === prices.seat);
|
|
102
|
+
if (subscription.livemode || customer !== customerId || subscription.items.has_more || !base || base.quantity !== 1 || items.length !== 1 + Number(Boolean(seat)) || !Number.isSafeInteger(seat?.quantity || 0) || (seat?.quantity || 0) < 0 || seat && (seat.current_period_end !== base.current_period_end || seat.current_period_start !== base.current_period_start)) {
|
|
103
|
+
throw new Error('billing_subscription_mismatch');
|
|
104
|
+
}
|
|
105
|
+
const invoices = await listAll((startingAfter)=>stripe.invoices.list({
|
|
106
|
+
customer: customerId,
|
|
107
|
+
limit: 100,
|
|
108
|
+
starting_after: startingAfter
|
|
109
|
+
}));
|
|
110
|
+
const unsettled = invoices.filter((invoice)=>invoice.metadata?.organizationBillingJob && invoice.status === 'open' && invoice.amount_remaining > 0);
|
|
111
|
+
let { status } = subscription;
|
|
112
|
+
if (subscription.status === 'active' && unsettled.length) {
|
|
113
|
+
status = unsettled.some((invoice)=>invoice.attempted) ? 'past_due' : 'payment_pending';
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
baseItemId: base.id,
|
|
117
|
+
cancelAtPeriodEnd: subscription.cancel_at_period_end,
|
|
118
|
+
customerId,
|
|
119
|
+
extraSeats: seat?.quantity || 0,
|
|
120
|
+
id: subscription.id,
|
|
121
|
+
lastJobId: subscription.metadata?.organizationBillingJob || '',
|
|
122
|
+
pendingPlan: subscription.metadata?.organizationPendingPlan === 'starter' && base.price.id !== prices.starter ? 'starter' : null,
|
|
123
|
+
periodEnd: base.current_period_end * 1000,
|
|
124
|
+
periodStart: base.current_period_start * 1000,
|
|
125
|
+
plan: base.price.id === prices.pro ? 'pro' : 'starter',
|
|
126
|
+
seatItemId: seat?.id || '',
|
|
127
|
+
startedAt: (subscription.start_date || base.current_period_start) * 1000,
|
|
128
|
+
status
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
const sessionResult = (session)=>{
|
|
132
|
+
if (session.livemode) {
|
|
133
|
+
throw new Error('invalid_billing_event');
|
|
134
|
+
}
|
|
135
|
+
if (session.status === 'complete') {
|
|
136
|
+
throw new Error('subscription_exists');
|
|
137
|
+
}
|
|
138
|
+
if (session.url && !session.url.startsWith('https://checkout.stripe.com/')) {
|
|
139
|
+
throw new Error('billing_redirect_invalid');
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
expiresAt: session.expires_at * 1000,
|
|
143
|
+
id: session.id,
|
|
144
|
+
url: session.url || ''
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
return {
|
|
148
|
+
checkout: async (customerId, plan, extraSeats, key)=>{
|
|
149
|
+
getOrganizationPlan(plan);
|
|
150
|
+
if (!Number.isSafeInteger(extraSeats) || extraSeats < 0) {
|
|
151
|
+
throw new Error('invalid_member_count');
|
|
152
|
+
}
|
|
153
|
+
const sessions = await listAll((startingAfter)=>stripe.checkout.sessions.list({
|
|
154
|
+
customer: customerId,
|
|
155
|
+
limit: 100,
|
|
156
|
+
starting_after: startingAfter
|
|
157
|
+
}));
|
|
158
|
+
const matching = sessions.filter((session)=>session.metadata?.organizationCheckoutKey === key);
|
|
159
|
+
if (matching.length > 1) {
|
|
160
|
+
throw new Error('billing_checkout_conflict');
|
|
161
|
+
}
|
|
162
|
+
if (matching[0]) {
|
|
163
|
+
return sessionResult(matching[0]);
|
|
164
|
+
}
|
|
165
|
+
if (sessions.some((session)=>session.status === 'open' && session.expires_at * 1000 > Date.now())) {
|
|
166
|
+
throw new Error('checkout_in_progress');
|
|
167
|
+
}
|
|
168
|
+
if (await retrieve(customerId)) {
|
|
169
|
+
throw new Error('subscription_exists');
|
|
170
|
+
}
|
|
171
|
+
const lineItems = [
|
|
172
|
+
{
|
|
173
|
+
price: prices[plan],
|
|
174
|
+
quantity: 1
|
|
175
|
+
},
|
|
176
|
+
...extraSeats ? [
|
|
177
|
+
{
|
|
178
|
+
price: prices.seat,
|
|
179
|
+
quantity: extraSeats
|
|
180
|
+
}
|
|
181
|
+
] : []
|
|
182
|
+
];
|
|
183
|
+
const session = await stripe.checkout.sessions.create({
|
|
184
|
+
cancel_url: `${origin}/subscription/new`,
|
|
185
|
+
client_reference_id: key,
|
|
186
|
+
customer: customerId,
|
|
187
|
+
line_items: lineItems,
|
|
188
|
+
metadata: {
|
|
189
|
+
organizationCheckoutKey: key,
|
|
190
|
+
priceVersion: '2026-10-v1'
|
|
191
|
+
},
|
|
192
|
+
mode: 'subscription',
|
|
193
|
+
subscription_data: {
|
|
194
|
+
metadata: {
|
|
195
|
+
organizationCheckoutKey: key,
|
|
196
|
+
priceVersion: '2026-10-v1'
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
success_url: `${origin}/settings/subscription?checkout=return`
|
|
200
|
+
}, {
|
|
201
|
+
idempotencyKey: key
|
|
202
|
+
});
|
|
203
|
+
return sessionResult(session);
|
|
204
|
+
},
|
|
205
|
+
customer: async (organizationId, email)=>{
|
|
206
|
+
// Search the full customer inventory: ownership/email can change after an ambiguous request.
|
|
207
|
+
const customers = await listAll((startingAfter)=>stripe.customers.list({
|
|
208
|
+
limit: 100,
|
|
209
|
+
starting_after: startingAfter
|
|
210
|
+
}));
|
|
211
|
+
const matching = customers.filter((customer)=>customer.metadata.organizationId === organizationId);
|
|
212
|
+
if (matching.length > 1) {
|
|
213
|
+
throw new Error('billing_customer_conflict');
|
|
214
|
+
}
|
|
215
|
+
const customer = matching[0] || await stripe.customers.create({
|
|
216
|
+
email,
|
|
217
|
+
metadata: {
|
|
218
|
+
organizationId
|
|
219
|
+
}
|
|
220
|
+
}, {
|
|
221
|
+
idempotencyKey: organizationKey('organization-customer', organizationId)
|
|
222
|
+
});
|
|
223
|
+
if (customer.livemode) {
|
|
224
|
+
throw new Error('invalid_billing_event');
|
|
225
|
+
}
|
|
226
|
+
return customer.id;
|
|
227
|
+
},
|
|
228
|
+
portal: async (customerId)=>{
|
|
229
|
+
const configuration = process.env.ORGANIZATION_STRIPE_PORTAL_CONFIGURATION_ID || '';
|
|
230
|
+
if (!/^bpc_[A-Za-z0-9]+$/.test(configuration)) {
|
|
231
|
+
throw new Error('unsafe_billing_portal');
|
|
232
|
+
}
|
|
233
|
+
const config = await stripe.billingPortal.configurations.retrieve(configuration);
|
|
234
|
+
if (config.livemode || !config.active || config.features.subscription_cancel.enabled || config.features.subscription_update.enabled || !config.features.payment_method_update.enabled || !config.features.invoice_history.enabled) {
|
|
235
|
+
throw new Error('unsafe_billing_portal');
|
|
236
|
+
}
|
|
237
|
+
return (await stripe.billingPortal.sessions.create({
|
|
238
|
+
configuration,
|
|
239
|
+
customer: customerId,
|
|
240
|
+
return_url: `${origin}/settings/subscription`
|
|
241
|
+
})).url;
|
|
242
|
+
},
|
|
243
|
+
preview: async (subscription, plan, seats, effectiveAt)=>{
|
|
244
|
+
getOrganizationPlan(plan);
|
|
245
|
+
if (!Number.isSafeInteger(seats) || seats < 0 || !Number.isSafeInteger(effectiveAt)) {
|
|
246
|
+
throw new Error('invalid_member_count');
|
|
247
|
+
}
|
|
248
|
+
const seatItems = seats ? [
|
|
249
|
+
{
|
|
250
|
+
price: prices.seat,
|
|
251
|
+
quantity: seats
|
|
252
|
+
}
|
|
253
|
+
] : [];
|
|
254
|
+
const items = [
|
|
255
|
+
{
|
|
256
|
+
id: subscription.baseItemId,
|
|
257
|
+
price: prices[plan],
|
|
258
|
+
quantity: 1
|
|
259
|
+
},
|
|
260
|
+
...subscription.seatItemId ? [
|
|
261
|
+
{
|
|
262
|
+
id: subscription.seatItemId,
|
|
263
|
+
price: prices.seat,
|
|
264
|
+
quantity: seats
|
|
265
|
+
}
|
|
266
|
+
] : seatItems
|
|
267
|
+
];
|
|
268
|
+
const invoice = await stripe.invoices.createPreview({
|
|
269
|
+
customer: subscription.customerId,
|
|
270
|
+
subscription: subscription.id,
|
|
271
|
+
subscription_details: {
|
|
272
|
+
items,
|
|
273
|
+
proration_date: Math.floor(effectiveAt / 1000)
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
if (invoice.livemode || invoice.lines.has_more) {
|
|
277
|
+
throw new Error('billing_lookup_incomplete');
|
|
278
|
+
}
|
|
279
|
+
return invoice.lines.data.filter((line)=>line.parent?.subscription_item_details?.proration).reduce((total, line)=>total + line.amount, 0);
|
|
280
|
+
},
|
|
281
|
+
retrieve,
|
|
282
|
+
update: createOrganizationBillingUpdater(stripe, prices),
|
|
283
|
+
verify: (body, signature)=>verifyEvent(stripe, body, signature)
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvb3JnYW5pemF0aW9ucy9iaWxsaW5nUHJvdmlkZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFN0cmlwZSBmcm9tICdzdHJpcGUnO1xuXG5pbXBvcnQge3N0cmlwZUFwaVZlcnNpb259IGZyb20gJy4uL3V0aWxzL3N0cmlwZVV0aWxzLmpzJztcbmltcG9ydCB7Y3JlYXRlT3JnYW5pemF0aW9uQmlsbGluZ1VwZGF0ZXJ9IGZyb20gJy4vYmlsbGluZ1VwZGF0ZXMuanMnO1xuaW1wb3J0IHtnZXRPcmdhbml6YXRpb25QbGFufSBmcm9tICcuL3BsYW5zLmpzJztcbmltcG9ydCB7bGlzdEFsbFByb3ZpZGVyUmVjb3JkcyBhcyBsaXN0QWxsfSBmcm9tICcuL3Byb3ZpZGVyUGFnaW5hdGlvbi5qcyc7XG5pbXBvcnQge29yZ2FuaXphdGlvbktleX0gZnJvbSAnLi9zdG9yZS5qcyc7XG5cbmltcG9ydCB0eXBlIHtcbiAgQmlsbGluZ01vZGUsXG4gIEJpbGxpbmdQcm92aWRlcixcbiAgQ2hlY2tvdXRSZXN1bHQsXG4gIFBsYW5LZXksXG4gIFByb3ZpZGVyU3Vic2NyaXB0aW9uLFxuICBWZXJpZmllZEJpbGxpbmdFdmVudFxufSBmcm9tICcuL3R5cGVzLmpzJztcblxuZXhwb3J0IGNvbnN0IG9yZ2FuaXphdGlvbkJpbGxpbmdNb2RlID0gKCk6IEJpbGxpbmdNb2RlID0+IHtcbiAgY29uc3QgbW9kZSA9IHByb2Nlc3MuZW52Lk9SR0FOSVpBVElPTl9CSUxMSU5HX01PREUgfHwgJ2Rpc2FibGVkJztcbiAgaWYoIVsnZGlzYWJsZWQnLCAndGVzdCddLmluY2x1ZGVzKG1vZGUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2JpbGxpbmdfbW9kZScpO1xuICB9XG4gIHJldHVybiBtb2RlIGFzIEJpbGxpbmdNb2RlO1xufTtcbmNvbnN0IG9yZ2FuaXphdGlvblN0cmlwZUNsaWVudCA9ICgpOiBTdHJpcGUgPT4ge1xuICBpZihvcmdhbml6YXRpb25CaWxsaW5nTW9kZSgpICE9PSAndGVzdCcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpbGxpbmdfZGlzYWJsZWQnKTtcbiAgfVxuICBjb25zdCBrZXkgPSBwcm9jZXNzLmVudi5PUkdBTklaQVRJT05fU1RSSVBFX1NFQ1JFVF9LRVkgfHwgJyc7XG4gIGlmKCEvXihza3xyaylfdGVzdF9bQS1aYS16MC05XSskLy50ZXN0KGtleSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Rlc3RfYmlsbGluZ19rZXlfcmVxdWlyZWQnKTtcbiAgfVxuICByZXR1cm4gbmV3IFN0cmlwZShrZXksIHthcGlWZXJzaW9uOiBzdHJpcGVBcGlWZXJzaW9uLCBtYXhOZXR3b3JrUmV0cmllczogMSwgdGltZW91dDogMjAwMDAsIHR5cGVzY3JpcHQ6IHRydWV9KTtcbn07XG5jb25zdCB2ZXJpZnlFdmVudCA9IChzdHJpcGU6IFN0cmlwZSwgYm9keTogc3RyaW5nIHwgQnVmZmVyLCBzaWduYXR1cmU6IHN0cmluZyk6IFZlcmlmaWVkQmlsbGluZ0V2ZW50ID0+IHtcbiAgY29uc3Qgc2VjcmV0ID0gcHJvY2Vzcy5lbnYuT1JHQU5JWkFUSU9OX1NUUklQRV9XRUJIT09LX1NFQ1JFVCB8fCAnJztcbiAgaWYoIXNlY3JldC5zdGFydHNXaXRoKCd3aHNlY18nKSB8fCAhc2lnbmF0dXJlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2JpbGxpbmdfZXZlbnQnKTtcbiAgfVxuICBjb25zdCBldmVudCA9IHN0cmlwZS53ZWJob29rcy5jb25zdHJ1Y3RFdmVudChib2R5LCBzaWduYXR1cmUsIHNlY3JldCk7XG4gIGNvbnN0IG9iamVjdCA9IGV2ZW50LmRhdGEub2JqZWN0IGFzIHtjdXN0b21lcj86IHN0cmluZyB8IHtpZDogc3RyaW5nfX07XG4gIGNvbnN0IGN1c3RvbWVySWQgPSB0eXBlb2Ygb2JqZWN0LmN1c3RvbWVyID09PSAnc3RyaW5nJyA/IG9iamVjdC5jdXN0b21lciA6IG9iamVjdC5jdXN0b21lcj8uaWQ7XG4gIGlmKGV2ZW50LmxpdmVtb2RlIHx8ICFjdXN0b21lcklkIHx8ICEvXmN1c19bQS1aYS16MC05XSskLy50ZXN0KGN1c3RvbWVySWQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2JpbGxpbmdfZXZlbnQnKTtcbiAgfVxuICByZXR1cm4ge2N1c3RvbWVySWQsIGV2ZW50SWQ6IGV2ZW50LmlkLCB0eXBlOiBldmVudC50eXBlfTtcbn07XG5leHBvcnQgY29uc3QgdmVyaWZ5T3JnYW5pemF0aW9uQmlsbGluZ0V2ZW50ID0gKFxuICBib2R5OiBzdHJpbmcgfCBCdWZmZXIsXG4gIHNpZ25hdHVyZTogc3RyaW5nXG4pOiBWZXJpZmllZEJpbGxpbmdFdmVudCA9PiB2ZXJpZnlFdmVudChvcmdhbml6YXRpb25TdHJpcGVDbGllbnQoKSwgYm9keSwgc2lnbmF0dXJlKTtcblxuZXhwb3J0IGNvbnN0IGdldE9yZ2FuaXphdGlvbkJpbGxpbmdQcm92aWRlciA9IGFzeW5jICgpOiBQcm9taXNlPEJpbGxpbmdQcm92aWRlcj4gPT4ge1xuICBjb25zdCBzdHJpcGUgPSBvcmdhbml6YXRpb25TdHJpcGVDbGllbnQoKTtcbiAgY29uc3Qgb3JpZ2luID0gcHJvY2Vzcy5lbnYuT1JHQU5JWkFUSU9OX1NJVEVfT1JJR0lOIHx8ICcnO1xuICBsZXQgcGFyc2VkOiBVUkw7XG4gIHRyeSB7XG4gICAgcGFyc2VkID0gbmV3IFVSTChvcmlnaW4pO1xuICB9IGNhdGNoe1xuICAgIHRocm93IG5ldyBFcnJvcignYmlsbGluZ19vcmlnaW5fcmVxdWlyZWQnKTtcbiAgfVxuICBpZihwYXJzZWQucHJvdG9jb2wgIT09ICdodHRwczonIHx8IHBhcnNlZC5vcmlnaW4gIT09IG9yaWdpbiB8fCBwYXJzZWQudXNlcm5hbWUgfHwgcGFyc2VkLnBhc3N3b3JkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdiaWxsaW5nX29yaWdpbl9yZXF1aXJlZCcpO1xuICB9XG4gIGNvbnN0IHByaWNlcyA9IHtcbiAgICBwcm86IHByb2Nlc3MuZW52Lk9SR0FOSVpBVElPTl9TVFJJUEVfUFJPX1BSSUNFX0lEIHx8ICcnLFxuICAgIHNlYXQ6IHByb2Nlc3MuZW52Lk9SR0FOSVpBVElPTl9TVFJJUEVfU0VBVF9QUklDRV9JRCB8fCAnJyxcbiAgICBzdGFydGVyOiBwcm9jZXNzLmVudi5PUkdBTklaQVRJT05fU1RSSVBFX1NUQVJURVJfUFJJQ0VfSUQgfHwgJydcbiAgfTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgT2JqZWN0LmVudHJpZXMocHJpY2VzKS5tYXAoYXN5bmMgKFtuYW1lLCBpZF0pID0+IHtcbiAgICAgIGlmKCEvXnByaWNlX1tBLVphLXowLTldKyQvLnRlc3QoaWQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYmlsbGluZ19wcmljZV9taXNtYXRjaCcpO1xuICAgICAgfVxuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBuYW1lID09PSAnc2VhdCcgPyA4MDAgOiBnZXRPcmdhbml6YXRpb25QbGFuKG5hbWUgYXMgUGxhbktleSkuYmFzZUNlbnRzO1xuICAgICAgY29uc3QgcHJpY2UgPSBhd2FpdCBzdHJpcGUucHJpY2VzLnJldHJpZXZlKGlkKTtcbiAgICAgIGlmKFxuICAgICAgICBwcmljZS5saXZlbW9kZSB8fFxuICAgICAgICAhcHJpY2UuYWN0aXZlIHx8XG4gICAgICAgIHByaWNlLmN1cnJlbmN5ICE9PSAndXNkJyB8fFxuICAgICAgICBwcmljZS51bml0X2Ftb3VudCAhPT0gZXhwZWN0ZWQgfHxcbiAgICAgICAgcHJpY2UucmVjdXJyaW5nPy5pbnRlcnZhbCAhPT0gJ21vbnRoJyB8fFxuICAgICAgICBwcmljZS5yZWN1cnJpbmcuaW50ZXJ2YWxfY291bnQgIT09IDEgfHxcbiAgICAgICAgcHJpY2UucmVjdXJyaW5nLnVzYWdlX3R5cGUgIT09ICdsaWNlbnNlZCdcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpbGxpbmdfcHJpY2VfbWlzbWF0Y2gnKTtcbiAgICAgIH1cbiAgICB9KVxuICApO1xuICBjb25zdCByZXRyaWV2ZSA9IGFzeW5jIChjdXN0b21lcklkOiBzdHJpbmcsIHN1YnNjcmlwdGlvbklkPzogc3RyaW5nKTogUHJvbWlzZTxQcm92aWRlclN1YnNjcmlwdGlvbiB8IG51bGw+ID0+IHtcbiAgICBjb25zdCBhbGwgPSBhd2FpdCBsaXN0QWxsKChzdGFydGluZ0FmdGVyKSA9PlxuICAgICAgc3RyaXBlLnN1YnNjcmlwdGlvbnMubGlzdCh7Y3VzdG9tZXI6IGN1c3RvbWVySWQsIGxpbWl0OiAxMDAsIHN0YXJ0aW5nX2FmdGVyOiBzdGFydGluZ0FmdGVyLCBzdGF0dXM6ICdhbGwnfSlcbiAgICApO1xuICAgIGNvbnN0IGxpdmUgPSBhbGwuZmlsdGVyKFxuICAgICAgKHN1YnNjcmlwdGlvbikgPT4gIVsnY2FuY2VsZWQnLCAnaW5jb21wbGV0ZV9leHBpcmVkJ10uaW5jbHVkZXMoc3Vic2NyaXB0aW9uLnN0YXR1cylcbiAgICApO1xuICAgIGlmKGxpdmUubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdiaWxsaW5nX3N1YnNjcmlwdGlvbl9jb25mbGljdCcpO1xuICAgIH1cbiAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBzdWJzY3JpcHRpb25JZCA/IGF3YWl0IHN0cmlwZS5zdWJzY3JpcHRpb25zLnJldHJpZXZlKHN1YnNjcmlwdGlvbklkKSA6IGxpdmVbMF0gfHwgbnVsbDtcbiAgICBpZighc3Vic2NyaXB0aW9uKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgY3VzdG9tZXIgPVxuICAgICAgdHlwZW9mIHN1YnNjcmlwdGlvbi5jdXN0b21lciA9PT0gJ3N0cmluZycgPyBzdWJzY3JpcHRpb24uY3VzdG9tZXIgOiBzdWJzY3JpcHRpb24uY3VzdG9tZXIuaWQ7XG4gICAgY29uc3QgaXRlbXMgPSBzdWJzY3JpcHRpb24uaXRlbXMuZGF0YTtcbiAgICBjb25zdCBiYXNlID0gaXRlbXMuZmluZCgoaXRlbSkgPT4gW3ByaWNlcy5wcm8sIHByaWNlcy5zdGFydGVyXS5pbmNsdWRlcyhpdGVtLnByaWNlLmlkKSk7XG4gICAgY29uc3Qgc2VhdCA9IGl0ZW1zLmZpbmQoKGl0ZW0pID0+IGl0ZW0ucHJpY2UuaWQgPT09IHByaWNlcy5zZWF0KTtcbiAgICBpZihcbiAgICAgIHN1YnNjcmlwdGlvbi5saXZlbW9kZSB8fFxuICAgICAgY3VzdG9tZXIgIT09IGN1c3RvbWVySWQgfHxcbiAgICAgIHN1YnNjcmlwdGlvbi5pdGVtcy5oYXNfbW9yZSB8fFxuICAgICAgIWJhc2UgfHxcbiAgICAgIGJhc2UucXVhbnRpdHkgIT09IDEgfHxcbiAgICAgIGl0ZW1zLmxlbmd0aCAhPT0gMSArIE51bWJlcihCb29sZWFuKHNlYXQpKSB8fFxuICAgICAgIU51bWJlci5pc1NhZmVJbnRlZ2VyKHNlYXQ/LnF1YW50aXR5IHx8IDApIHx8XG4gICAgICAoc2VhdD8ucXVhbnRpdHkgfHwgMCkgPCAwIHx8XG4gICAgICAoc2VhdCAmJlxuICAgICAgICAoc2VhdC5jdXJyZW50X3BlcmlvZF9lbmQgIT09IGJhc2UuY3VycmVudF9wZXJpb2RfZW5kIHx8XG4gICAgICAgICAgc2VhdC5jdXJyZW50X3BlcmlvZF9zdGFydCAhPT0gYmFzZS5jdXJyZW50X3BlcmlvZF9zdGFydCkpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpbGxpbmdfc3Vic2NyaXB0aW9uX21pc21hdGNoJyk7XG4gICAgfVxuICAgIGNvbnN0IGludm9pY2VzID0gYXdhaXQgbGlzdEFsbCgoc3RhcnRpbmdBZnRlcikgPT5cbiAgICAgIHN0cmlwZS5pbnZvaWNlcy5saXN0KHtjdXN0b21lcjogY3VzdG9tZXJJZCwgbGltaXQ6IDEwMCwgc3RhcnRpbmdfYWZ0ZXI6IHN0YXJ0aW5nQWZ0ZXJ9KVxuICAgICk7XG4gICAgY29uc3QgdW5zZXR0bGVkID0gaW52b2ljZXMuZmlsdGVyKChpbnZvaWNlKSA9PiBpbnZvaWNlLm1ldGFkYXRhPy5vcmdhbml6YXRpb25CaWxsaW5nSm9iXG4gICAgICAmJiBpbnZvaWNlLnN0YXR1cyA9PT0gJ29wZW4nICYmIGludm9pY2UuYW1vdW50X3JlbWFpbmluZyA+IDApO1xuICAgIGxldCB7c3RhdHVzfSA9IHN1YnNjcmlwdGlvbjtcbiAgICBpZihzdWJzY3JpcHRpb24uc3RhdHVzID09PSAnYWN0aXZlJyAmJiB1bnNldHRsZWQubGVuZ3RoKSB7XG4gICAgICBzdGF0dXMgPSB1bnNldHRsZWQuc29tZSgoaW52b2ljZSkgPT4gaW52b2ljZS5hdHRlbXB0ZWQpID8gJ3Bhc3RfZHVlJyA6ICdwYXltZW50X3BlbmRpbmcnO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgYmFzZUl0ZW1JZDogYmFzZS5pZCxcbiAgICAgIGNhbmNlbEF0UGVyaW9kRW5kOiBzdWJzY3JpcHRpb24uY2FuY2VsX2F0X3BlcmlvZF9lbmQsXG4gICAgICBjdXN0b21lcklkLFxuICAgICAgZXh0cmFTZWF0czogc2VhdD8ucXVhbnRpdHkgfHwgMCxcbiAgICAgIGlkOiBzdWJzY3JpcHRpb24uaWQsXG4gICAgICBsYXN0Sm9iSWQ6IHN1YnNjcmlwdGlvbi5tZXRhZGF0YT8ub3JnYW5pemF0aW9uQmlsbGluZ0pvYiB8fCAnJyxcbiAgICAgIHBlbmRpbmdQbGFuOiBzdWJzY3JpcHRpb24ubWV0YWRhdGE/Lm9yZ2FuaXphdGlvblBlbmRpbmdQbGFuID09PSAnc3RhcnRlcicgJiYgYmFzZS5wcmljZS5pZCAhPT0gcHJpY2VzLnN0YXJ0ZXIgPyAnc3RhcnRlcicgOiBudWxsLFxuICAgICAgcGVyaW9kRW5kOiBiYXNlLmN1cnJlbnRfcGVyaW9kX2VuZCAqIDEwMDAsXG4gICAgICBwZXJpb2RTdGFydDogYmFzZS5jdXJyZW50X3BlcmlvZF9zdGFydCAqIDEwMDAsXG4gICAgICBwbGFuOiBiYXNlLnByaWNlLmlkID09PSBwcmljZXMucHJvID8gJ3BybycgOiAnc3RhcnRlcicsXG4gICAgICBzZWF0SXRlbUlkOiBzZWF0Py5pZCB8fCAnJyxcbiAgICAgIHN0YXJ0ZWRBdDogKHN1YnNjcmlwdGlvbi5zdGFydF9kYXRlIHx8IGJhc2UuY3VycmVudF9wZXJpb2Rfc3RhcnQpICogMTAwMCxcbiAgICAgIHN0YXR1c1xuICAgIH07XG4gIH07XG4gIGNvbnN0IHNlc3Npb25SZXN1bHQgPSAoc2Vzc2lvbjogU3RyaXBlLkNoZWNrb3V0LlNlc3Npb24pOiBDaGVja291dFJlc3VsdCA9PiB7XG4gICAgaWYoc2Vzc2lvbi5saXZlbW9kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2JpbGxpbmdfZXZlbnQnKTtcbiAgICB9XG4gICAgaWYoc2Vzc2lvbi5zdGF0dXMgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc3Vic2NyaXB0aW9uX2V4aXN0cycpO1xuICAgIH1cbiAgICBpZihzZXNzaW9uLnVybCAmJiAhc2Vzc2lvbi51cmwuc3RhcnRzV2l0aCgnaHR0cHM6Ly9jaGVja291dC5zdHJpcGUuY29tLycpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpbGxpbmdfcmVkaXJlY3RfaW52YWxpZCcpO1xuICAgIH1cbiAgICByZXR1cm4ge2V4cGlyZXNBdDogc2Vzc2lvbi5leHBpcmVzX2F0ICogMTAwMCwgaWQ6IHNlc3Npb24uaWQsIHVybDogc2Vzc2lvbi51cmwgfHwgJyd9O1xuICB9O1xuICByZXR1cm4ge1xuICAgIGNoZWNrb3V0OiBhc3luYyAoY3VzdG9tZXJJZCwgcGxhbiwgZXh0cmFTZWF0cywga2V5KSA9PiB7XG4gICAgICBnZXRPcmdhbml6YXRpb25QbGFuKHBsYW4pO1xuICAgICAgaWYoIU51bWJlci5pc1NhZmVJbnRlZ2VyKGV4dHJhU2VhdHMpIHx8IGV4dHJhU2VhdHMgPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZF9tZW1iZXJfY291bnQnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHNlc3Npb25zID0gYXdhaXQgbGlzdEFsbCgoc3RhcnRpbmdBZnRlcikgPT5cbiAgICAgICAgc3RyaXBlLmNoZWNrb3V0LnNlc3Npb25zLmxpc3Qoe2N1c3RvbWVyOiBjdXN0b21lcklkLCBsaW1pdDogMTAwLCBzdGFydGluZ19hZnRlcjogc3RhcnRpbmdBZnRlcn0pXG4gICAgICApO1xuICAgICAgY29uc3QgbWF0Y2hpbmcgPSBzZXNzaW9ucy5maWx0ZXIoKHNlc3Npb24pID0+IHNlc3Npb24ubWV0YWRhdGE/Lm9yZ2FuaXphdGlvbkNoZWNrb3V0S2V5ID09PSBrZXkpO1xuICAgICAgaWYobWF0Y2hpbmcubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpbGxpbmdfY2hlY2tvdXRfY29uZmxpY3QnKTtcbiAgICAgIH1cbiAgICAgIGlmKG1hdGNoaW5nWzBdKSB7XG4gICAgICAgIHJldHVybiBzZXNzaW9uUmVzdWx0KG1hdGNoaW5nWzBdKTtcbiAgICAgIH1cbiAgICAgIGlmKHNlc3Npb25zLnNvbWUoKHNlc3Npb24pID0+IHNlc3Npb24uc3RhdHVzID09PSAnb3BlbicgJiYgc2Vzc2lvbi5leHBpcmVzX2F0ICogMTAwMCA+IERhdGUubm93KCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY2hlY2tvdXRfaW5fcHJvZ3Jlc3MnKTtcbiAgICAgIH1cbiAgICAgIGlmKGF3YWl0IHJldHJpZXZlKGN1c3RvbWVySWQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignc3Vic2NyaXB0aW9uX2V4aXN0cycpO1xuICAgICAgfVxuICAgICAgY29uc3QgbGluZUl0ZW1zID0gW1xuICAgICAgICB7cHJpY2U6IHByaWNlc1twbGFuXSwgcXVhbnRpdHk6IDF9LFxuICAgICAgICAuLi4oZXh0cmFTZWF0cyA/IFt7cHJpY2U6IHByaWNlcy5zZWF0LCBxdWFudGl0eTogZXh0cmFTZWF0c31dIDogW10pXG4gICAgICBdO1xuICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IHN0cmlwZS5jaGVja291dC5zZXNzaW9ucy5jcmVhdGUoXG4gICAgICAgIHtcbiAgICAgICAgICBjYW5jZWxfdXJsOiBgJHtvcmlnaW59L3N1YnNjcmlwdGlvbi9uZXdgLFxuICAgICAgICAgIGNsaWVudF9yZWZlcmVuY2VfaWQ6IGtleSxcbiAgICAgICAgICBjdXN0b21lcjogY3VzdG9tZXJJZCxcbiAgICAgICAgICBsaW5lX2l0ZW1zOiBsaW5lSXRlbXMsXG4gICAgICAgICAgbWV0YWRhdGE6IHtvcmdhbml6YXRpb25DaGVja291dEtleToga2V5LCBwcmljZVZlcnNpb246ICcyMDI2LTEwLXYxJ30sXG4gICAgICAgICAgbW9kZTogJ3N1YnNjcmlwdGlvbicsXG4gICAgICAgICAgc3Vic2NyaXB0aW9uX2RhdGE6IHttZXRhZGF0YToge29yZ2FuaXphdGlvbkNoZWNrb3V0S2V5OiBrZXksIHByaWNlVmVyc2lvbjogJzIwMjYtMTAtdjEnfX0sXG4gICAgICAgICAgc3VjY2Vzc191cmw6IGAke29yaWdpbn0vc2V0dGluZ3Mvc3Vic2NyaXB0aW9uP2NoZWNrb3V0PXJldHVybmBcbiAgICAgICAgfSxcbiAgICAgICAge2lkZW1wb3RlbmN5S2V5OiBrZXl9XG4gICAgICApO1xuICAgICAgcmV0dXJuIHNlc3Npb25SZXN1bHQoc2Vzc2lvbik7XG4gICAgfSxcbiAgICBjdXN0b21lcjogYXN5bmMgKG9yZ2FuaXphdGlvbklkLCBlbWFpbCkgPT4ge1xuICAgICAgLy8gU2VhcmNoIHRoZSBmdWxsIGN1c3RvbWVyIGludmVudG9yeTogb3duZXJzaGlwL2VtYWlsIGNhbiBjaGFuZ2UgYWZ0ZXIgYW4gYW1iaWd1b3VzIHJlcXVlc3QuXG4gICAgICBjb25zdCBjdXN0b21lcnMgPSBhd2FpdCBsaXN0QWxsKChzdGFydGluZ0FmdGVyKSA9PlxuICAgICAgICBzdHJpcGUuY3VzdG9tZXJzLmxpc3Qoe2xpbWl0OiAxMDAsIHN0YXJ0aW5nX2FmdGVyOiBzdGFydGluZ0FmdGVyfSlcbiAgICAgICk7XG4gICAgICBjb25zdCBtYXRjaGluZyA9IGN1c3RvbWVycy5maWx0ZXIoKGN1c3RvbWVyKSA9PiBjdXN0b21lci5tZXRhZGF0YS5vcmdhbml6YXRpb25JZCA9PT0gb3JnYW5pemF0aW9uSWQpO1xuICAgICAgaWYobWF0Y2hpbmcubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpbGxpbmdfY3VzdG9tZXJfY29uZmxpY3QnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGN1c3RvbWVyID1cbiAgICAgICAgbWF0Y2hpbmdbMF0gfHxcbiAgICAgICAgKGF3YWl0IHN0cmlwZS5jdXN0b21lcnMuY3JlYXRlKFxuICAgICAgICAgIHtlbWFpbCwgbWV0YWRhdGE6IHtvcmdhbml6YXRpb25JZH19LFxuICAgICAgICAgIHtpZGVtcG90ZW5jeUtleTogb3JnYW5pemF0aW9uS2V5KCdvcmdhbml6YXRpb24tY3VzdG9tZXInLCBvcmdhbml6YXRpb25JZCl9XG4gICAgICAgICkpO1xuICAgICAgaWYoY3VzdG9tZXIubGl2ZW1vZGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2JpbGxpbmdfZXZlbnQnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjdXN0b21lci5pZDtcbiAgICB9LFxuICAgIHBvcnRhbDogYXN5bmMgKGN1c3RvbWVySWQpID0+IHtcbiAgICAgIGNvbnN0IGNvbmZpZ3VyYXRpb24gPSBwcm9jZXNzLmVudi5PUkdBTklaQVRJT05fU1RSSVBFX1BPUlRBTF9DT05GSUdVUkFUSU9OX0lEIHx8ICcnO1xuICAgICAgaWYoIS9eYnBjX1tBLVphLXowLTldKyQvLnRlc3QoY29uZmlndXJhdGlvbikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bnNhZmVfYmlsbGluZ19wb3J0YWwnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbmZpZyA9IGF3YWl0IHN0cmlwZS5iaWxsaW5nUG9ydGFsLmNvbmZpZ3VyYXRpb25zLnJldHJpZXZlKGNvbmZpZ3VyYXRpb24pO1xuICAgICAgaWYoXG4gICAgICAgIGNvbmZpZy5saXZlbW9kZSB8fFxuICAgICAgICAhY29uZmlnLmFjdGl2ZSB8fFxuICAgICAgICBjb25maWcuZmVhdHVyZXMuc3Vic2NyaXB0aW9uX2NhbmNlbC5lbmFibGVkIHx8XG4gICAgICAgIGNvbmZpZy5mZWF0dXJlcy5zdWJzY3JpcHRpb25fdXBkYXRlLmVuYWJsZWQgfHxcbiAgICAgICAgIWNvbmZpZy5mZWF0dXJlcy5wYXltZW50X21ldGhvZF91cGRhdGUuZW5hYmxlZCB8fFxuICAgICAgICAhY29uZmlnLmZlYXR1cmVzLmludm9pY2VfaGlzdG9yeS5lbmFibGVkXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bnNhZmVfYmlsbGluZ19wb3J0YWwnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAoXG4gICAgICAgIGF3YWl0IHN0cmlwZS5iaWxsaW5nUG9ydGFsLnNlc3Npb25zLmNyZWF0ZSh7XG4gICAgICAgICAgY29uZmlndXJhdGlvbixcbiAgICAgICAgICBjdXN0b21lcjogY3VzdG9tZXJJZCxcbiAgICAgICAgICByZXR1cm5fdXJsOiBgJHtvcmlnaW59L3NldHRpbmdzL3N1YnNjcmlwdGlvbmBcbiAgICAgICAgfSlcbiAgICAgICkudXJsO1xuICAgIH0sXG4gICAgcHJldmlldzogYXN5bmMgKHN1YnNjcmlwdGlvbiwgcGxhbiwgc2VhdHMsIGVmZmVjdGl2ZUF0KSA9PiB7XG4gICAgICBnZXRPcmdhbml6YXRpb25QbGFuKHBsYW4pO1xuICAgICAgaWYoIU51bWJlci5pc1NhZmVJbnRlZ2VyKHNlYXRzKSB8fCBzZWF0cyA8IDAgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKGVmZmVjdGl2ZUF0KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWRfbWVtYmVyX2NvdW50Jyk7XG4gICAgICB9XG4gICAgICBjb25zdCBzZWF0SXRlbXMgPSBzZWF0cyA/IFt7cHJpY2U6IHByaWNlcy5zZWF0LCBxdWFudGl0eTogc2VhdHN9XSA6IFtdO1xuICAgICAgY29uc3QgaXRlbXMgPSBbXG4gICAgICAgIHtpZDogc3Vic2NyaXB0aW9uLmJhc2VJdGVtSWQsIHByaWNlOiBwcmljZXNbcGxhbl0sIHF1YW50aXR5OiAxfSxcbiAgICAgICAgLi4uKHN1YnNjcmlwdGlvbi5zZWF0SXRlbUlkXG4gICAgICAgICAgPyBbe2lkOiBzdWJzY3JpcHRpb24uc2VhdEl0ZW1JZCwgcHJpY2U6IHByaWNlcy5zZWF0LCBxdWFudGl0eTogc2VhdHN9XVxuICAgICAgICAgIDogc2VhdEl0ZW1zKVxuICAgICAgXTtcbiAgICAgIGNvbnN0IGludm9pY2UgPSBhd2FpdCBzdHJpcGUuaW52b2ljZXMuY3JlYXRlUHJldmlldyh7XG4gICAgICAgIGN1c3RvbWVyOiBzdWJzY3JpcHRpb24uY3VzdG9tZXJJZCxcbiAgICAgICAgc3Vic2NyaXB0aW9uOiBzdWJzY3JpcHRpb24uaWQsXG4gICAgICAgIHN1YnNjcmlwdGlvbl9kZXRhaWxzOiB7aXRlbXMsIHByb3JhdGlvbl9kYXRlOiBNYXRoLmZsb29yKGVmZmVjdGl2ZUF0IC8gMTAwMCl9XG4gICAgICB9KTtcbiAgICAgIGlmKGludm9pY2UubGl2ZW1vZGUgfHwgaW52b2ljZS5saW5lcy5oYXNfbW9yZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpbGxpbmdfbG9va3VwX2luY29tcGxldGUnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpbnZvaWNlLmxpbmVzLmRhdGFcbiAgICAgICAgLmZpbHRlcigobGluZSkgPT4gbGluZS5wYXJlbnQ/LnN1YnNjcmlwdGlvbl9pdGVtX2RldGFpbHM/LnByb3JhdGlvbilcbiAgICAgICAgLnJlZHVjZSgodG90YWwsIGxpbmUpID0+IHRvdGFsICsgbGluZS5hbW91bnQsIDApO1xuICAgIH0sXG4gICAgcmV0cmlldmUsXG4gICAgdXBkYXRlOiBjcmVhdGVPcmdhbml6YXRpb25CaWxsaW5nVXBkYXRlcihzdHJpcGUsIHByaWNlcyksXG4gICAgdmVyaWZ5OiAoYm9keSwgc2lnbmF0dXJlKSA9PiB2ZXJpZnlFdmVudChzdHJpcGUsIGJvZHksIHNpZ25hdHVyZSlcbiAgfTtcbn07XG4iXSwibmFtZXMiOlsiU3RyaXBlIiwic3RyaXBlQXBpVmVyc2lvbiIsImNyZWF0ZU9yZ2FuaXphdGlvbkJpbGxpbmdVcGRhdGVyIiwiZ2V0T3JnYW5pemF0aW9uUGxhbiIsImxpc3RBbGxQcm92aWRlclJlY29yZHMiLCJsaXN0QWxsIiwib3JnYW5pemF0aW9uS2V5Iiwib3JnYW5pemF0aW9uQmlsbGluZ01vZGUiLCJtb2RlIiwicHJvY2VzcyIsImVudiIsIk9SR0FOSVpBVElPTl9CSUxMSU5HX01PREUiLCJpbmNsdWRlcyIsIkVycm9yIiwib3JnYW5pemF0aW9uU3RyaXBlQ2xpZW50Iiwia2V5IiwiT1JHQU5JWkFUSU9OX1NUUklQRV9TRUNSRVRfS0VZIiwidGVzdCIsImFwaVZlcnNpb24iLCJtYXhOZXR3b3JrUmV0cmllcyIsInRpbWVvdXQiLCJ0eXBlc2NyaXB0IiwidmVyaWZ5RXZlbnQiLCJzdHJpcGUiLCJib2R5Iiwic2lnbmF0dXJlIiwic2VjcmV0IiwiT1JHQU5JWkFUSU9OX1NUUklQRV9XRUJIT09LX1NFQ1JFVCIsInN0YXJ0c1dpdGgiLCJldmVudCIsIndlYmhvb2tzIiwiY29uc3RydWN0RXZlbnQiLCJvYmplY3QiLCJkYXRhIiwiY3VzdG9tZXJJZCIsImN1c3RvbWVyIiwiaWQiLCJsaXZlbW9kZSIsImV2ZW50SWQiLCJ0eXBlIiwidmVyaWZ5T3JnYW5pemF0aW9uQmlsbGluZ0V2ZW50IiwiZ2V0T3JnYW5pemF0aW9uQmlsbGluZ1Byb3ZpZGVyIiwib3JpZ2luIiwiT1JHQU5JWkFUSU9OX1NJVEVfT1JJR0lOIiwicGFyc2VkIiwiVVJMIiwicHJvdG9jb2wiLCJ1c2VybmFtZSIsInBhc3N3b3JkIiwicHJpY2VzIiwicHJvIiwiT1JHQU5JWkFUSU9OX1NUUklQRV9QUk9fUFJJQ0VfSUQiLCJzZWF0IiwiT1JHQU5JWkFUSU9OX1NUUklQRV9TRUFUX1BSSUNFX0lEIiwic3RhcnRlciIsIk9SR0FOSVpBVElPTl9TVFJJUEVfU1RBUlRFUl9QUklDRV9JRCIsIlByb21pc2UiLCJhbGwiLCJPYmplY3QiLCJlbnRyaWVzIiwibWFwIiwibmFtZSIsImV4cGVjdGVkIiwiYmFzZUNlbnRzIiwicHJpY2UiLCJyZXRyaWV2ZSIsImFjdGl2ZSIsImN1cnJlbmN5IiwidW5pdF9hbW91bnQiLCJyZWN1cnJpbmciLCJpbnRlcnZhbCIsImludGVydmFsX2NvdW50IiwidXNhZ2VfdHlwZSIsInN1YnNjcmlwdGlvbklkIiwic3RhcnRpbmdBZnRlciIsInN1YnNjcmlwdGlvbnMiLCJsaXN0IiwibGltaXQiLCJzdGFydGluZ19hZnRlciIsInN0YXR1cyIsImxpdmUiLCJmaWx0ZXIiLCJzdWJzY3JpcHRpb24iLCJsZW5ndGgiLCJpdGVtcyIsImJhc2UiLCJmaW5kIiwiaXRlbSIsImhhc19tb3JlIiwicXVhbnRpdHkiLCJOdW1iZXIiLCJCb29sZWFuIiwiaXNTYWZlSW50ZWdlciIsImN1cnJlbnRfcGVyaW9kX2VuZCIsImN1cnJlbnRfcGVyaW9kX3N0YXJ0IiwiaW52b2ljZXMiLCJ1bnNldHRsZWQiLCJpbnZvaWNlIiwibWV0YWRhdGEiLCJvcmdhbml6YXRpb25CaWxsaW5nSm9iIiwiYW1vdW50X3JlbWFpbmluZyIsInNvbWUiLCJhdHRlbXB0ZWQiLCJiYXNlSXRlbUlkIiwiY2FuY2VsQXRQZXJpb2RFbmQiLCJjYW5jZWxfYXRfcGVyaW9kX2VuZCIsImV4dHJhU2VhdHMiLCJsYXN0Sm9iSWQiLCJwZW5kaW5nUGxhbiIsIm9yZ2FuaXphdGlvblBlbmRpbmdQbGFuIiwicGVyaW9kRW5kIiwicGVyaW9kU3RhcnQiLCJwbGFuIiwic2VhdEl0ZW1JZCIsInN0YXJ0ZWRBdCIsInN0YXJ0X2RhdGUiLCJzZXNzaW9uUmVzdWx0Iiwic2Vzc2lvbiIsInVybCIsImV4cGlyZXNBdCIsImV4cGlyZXNfYXQiLCJjaGVja291dCIsInNlc3Npb25zIiwibWF0Y2hpbmciLCJvcmdhbml6YXRpb25DaGVja291dEtleSIsIkRhdGUiLCJub3ciLCJsaW5lSXRlbXMiLCJjcmVhdGUiLCJjYW5jZWxfdXJsIiwiY2xpZW50X3JlZmVyZW5jZV9pZCIsImxpbmVfaXRlbXMiLCJwcmljZVZlcnNpb24iLCJzdWJzY3JpcHRpb25fZGF0YSIsInN1Y2Nlc3NfdXJsIiwiaWRlbXBvdGVuY3lLZXkiLCJvcmdhbml6YXRpb25JZCIsImVtYWlsIiwiY3VzdG9tZXJzIiwicG9ydGFsIiwiY29uZmlndXJhdGlvbiIsIk9SR0FOSVpBVElPTl9TVFJJUEVfUE9SVEFMX0NPTkZJR1VSQVRJT05fSUQiLCJjb25maWciLCJiaWxsaW5nUG9ydGFsIiwiY29uZmlndXJhdGlvbnMiLCJmZWF0dXJlcyIsInN1YnNjcmlwdGlvbl9jYW5jZWwiLCJlbmFibGVkIiwic3Vic2NyaXB0aW9uX3VwZGF0ZSIsInBheW1lbnRfbWV0aG9kX3VwZGF0ZSIsImludm9pY2VfaGlzdG9yeSIsInJldHVybl91cmwiLCJwcmV2aWV3Iiwic2VhdHMiLCJlZmZlY3RpdmVBdCIsInNlYXRJdGVtcyIsImNyZWF0ZVByZXZpZXciLCJzdWJzY3JpcHRpb25fZGV0YWlscyIsInByb3JhdGlvbl9kYXRlIiwiTWF0aCIsImZsb29yIiwibGluZXMiLCJsaW5lIiwicGFyZW50Iiwic3Vic2NyaXB0aW9uX2l0ZW1fZGV0YWlscyIsInByb3JhdGlvbiIsInJlZHVjZSIsInRvdGFsIiwiYW1vdW50IiwidXBkYXRlIiwidmVyaWZ5Il0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFZLFNBQVM7QUFFNUIsU0FBUUMsZ0JBQWdCLFFBQU8sMEJBQTBCO0FBQ3pELFNBQVFDLGdDQUFnQyxRQUFPLHNCQUFzQjtBQUNyRSxTQUFRQyxtQkFBbUIsUUFBTyxhQUFhO0FBQy9DLFNBQVFDLDBCQUEwQkMsT0FBTyxRQUFPLDBCQUEwQjtBQUMxRSxTQUFRQyxlQUFlLFFBQU8sYUFBYTtBQVczQyxPQUFPLE1BQU1DLDBCQUEwQjtJQUNyQyxNQUFNQyxPQUFPQyxRQUFRQyxHQUFHLENBQUNDLHlCQUF5QixJQUFJO0lBQ3RELElBQUcsQ0FBQztRQUFDO1FBQVk7S0FBTyxDQUFDQyxRQUFRLENBQUNKLE9BQU87UUFDdkMsTUFBTSxJQUFJSyxNQUFNO0lB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
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type Stripe from 'stripe';
|
|
2
|
+
import type { BillingProvider } from './types.js';
|
|
3
|
+
type Prices = Readonly<{
|
|
4
|
+
pro: string;
|
|
5
|
+
seat: string;
|
|
6
|
+
starter: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const createOrganizationBillingUpdater: (stripe: Stripe, prices: Prices) => BillingProvider['update'];
|
|
9
|
+
export {};
|