@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.
Files changed (103) hide show
  1. package/README.md +186 -0
  2. package/docs/ASSISTANT.md +138 -0
  3. package/docs/GENERATION.md +29 -2
  4. package/docs/NATIVE_PUSH.md +56 -0
  5. package/lib/actions/alfredFaq.d.ts +80 -0
  6. package/lib/actions/alfredFaq.js +206 -0
  7. package/lib/actions/contentGeneration.d.ts +4 -1
  8. package/lib/actions/contentGeneration.js +83 -27
  9. package/lib/actions/contentGenerationErrors.js +1 -1
  10. package/lib/actions/conversations.d.ts +1 -1
  11. package/lib/actions/conversations.js +19 -9
  12. package/lib/actions/crud.js +26 -1
  13. package/lib/actions/index.d.ts +2 -0
  14. package/lib/actions/index.js +3 -1
  15. package/lib/actions/messages.js +23 -7
  16. package/lib/actions/phoneSupport.d.ts +18 -0
  17. package/lib/actions/phoneSupport.js +170 -0
  18. package/lib/actions/users.js +57 -4
  19. package/lib/assistant/core.d.ts +53 -0
  20. package/lib/assistant/core.js +123 -0
  21. package/lib/assistant/faq.d.ts +26 -0
  22. package/lib/assistant/faq.js +238 -0
  23. package/lib/assistant/faqCore.d.ts +23 -0
  24. package/lib/assistant/faqCore.js +20 -0
  25. package/lib/assistant/index.d.ts +7 -0
  26. package/lib/assistant/index.js +5 -0
  27. package/lib/assistant/service.d.ts +35 -0
  28. package/lib/assistant/service.js +201 -0
  29. package/lib/config.js +3 -2
  30. package/lib/durableChat/conversations.d.ts +62 -0
  31. package/lib/durableChat/conversations.js +729 -0
  32. package/lib/durableChat/errors.d.ts +6 -0
  33. package/lib/durableChat/errors.js +11 -0
  34. package/lib/durableChat/events.d.ts +22 -0
  35. package/lib/durableChat/events.js +50 -0
  36. package/lib/durableChat/index.d.ts +8 -0
  37. package/lib/durableChat/index.js +10 -0
  38. package/lib/durableChat/membership.d.ts +24 -0
  39. package/lib/durableChat/membership.js +85 -0
  40. package/lib/durableChat/messageTypes.d.ts +76 -0
  41. package/lib/durableChat/messageTypes.js +3 -0
  42. package/lib/durableChat/messages.d.ts +16 -0
  43. package/lib/durableChat/messages.js +257 -0
  44. package/lib/durableChat/transaction.d.ts +10 -0
  45. package/lib/durableChat/transaction.js +53 -0
  46. package/lib/durableChat/types.d.ts +81 -0
  47. package/lib/durableChat/types.js +3 -0
  48. package/lib/index.d.ts +4 -4
  49. package/lib/index.js +5 -3
  50. package/lib/lambdas/actions/websockets.js +4 -4
  51. package/lib/nativePush/graphql.d.ts +14 -0
  52. package/lib/nativePush/graphql.js +105 -0
  53. package/lib/nativePush/index.d.ts +7 -0
  54. package/lib/nativePush/index.js +9 -0
  55. package/lib/nativePush/migrations.d.ts +2 -0
  56. package/lib/nativePush/migrations.js +36 -0
  57. package/lib/nativePush/nativePushContract.fixture.d.ts +22 -0
  58. package/lib/nativePush/nativePushContract.fixture.js +27 -0
  59. package/lib/nativePush/payload.d.ts +2 -0
  60. package/lib/nativePush/payload.js +106 -0
  61. package/lib/nativePush/repository.d.ts +9 -0
  62. package/lib/nativePush/repository.js +120 -0
  63. package/lib/nativePush/service.d.ts +2 -0
  64. package/lib/nativePush/service.js +110 -0
  65. package/lib/nativePush/snsProvider.d.ts +17 -0
  66. package/lib/nativePush/snsProvider.js +165 -0
  67. package/lib/nativePush/types.d.ts +89 -0
  68. package/lib/nativePush/types.js +3 -0
  69. package/lib/organizations/accountLifecycle.d.ts +7 -0
  70. package/lib/organizations/accountLifecycle.js +106 -0
  71. package/lib/organizations/authorization.d.ts +9 -0
  72. package/lib/organizations/authorization.js +40 -0
  73. package/lib/organizations/billing.d.ts +38 -0
  74. package/lib/organizations/billing.js +277 -0
  75. package/lib/organizations/billingProvider.d.ts +4 -0
  76. package/lib/organizations/billingProvider.js +287 -0
  77. package/lib/organizations/billingUpdates.d.ts +9 -0
  78. package/lib/organizations/billingUpdates.js +388 -0
  79. package/lib/organizations/index.d.ts +10 -0
  80. package/lib/organizations/index.js +12 -0
  81. package/lib/organizations/mail.d.ts +10 -0
  82. package/lib/organizations/mail.js +60 -0
  83. package/lib/organizations/memberDirectory.d.ts +15 -0
  84. package/lib/organizations/memberDirectory.js +28 -0
  85. package/lib/organizations/membership.d.ts +19 -0
  86. package/lib/organizations/membership.js +248 -0
  87. package/lib/organizations/passwordRecovery.d.ts +9 -0
  88. package/lib/organizations/passwordRecovery.js +50 -0
  89. package/lib/organizations/plans.d.ts +6 -0
  90. package/lib/organizations/plans.js +40 -0
  91. package/lib/organizations/providerPagination.d.ts +6 -0
  92. package/lib/organizations/providerPagination.js +23 -0
  93. package/lib/organizations/reconciliation.d.ts +11 -0
  94. package/lib/organizations/reconciliation.js +400 -0
  95. package/lib/organizations/signup.d.ts +25 -0
  96. package/lib/organizations/signup.js +169 -0
  97. package/lib/organizations/store.d.ts +25 -0
  98. package/lib/organizations/store.js +167 -0
  99. package/lib/organizations/types.d.ts +138 -0
  100. package/lib/organizations/types.js +3 -0
  101. package/lib/organizations/verification.d.ts +3 -0
  102. package/lib/organizations/verification.js +51 -0
  103. 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+IHRvdGFsICsgbGluZS5hbW91bnQsIDApO1xuICAgIH0sXG4gICAgcmV0cmlldmUsXG4gICAgdXBkYXRlOiBjcmVhdGVPcmdhbml6YXRpb25CaWxsaW5nVXBkYXRlcihzdHJpcGUsIHByaWNlcyksXG4gICAgdmVyaWZ5OiAoYm9keSwgc2lnbmF0dXJlKSA9PiB2ZXJpZnlFdmVudChzdHJpcGUsIGJvZHksIHNpZ25hdHVyZSlcbiAgfTtcbn07XG4iXSwibmFtZXMiOlsiU3RyaXBlIiwic3RyaXBlQXBpVmVyc2lvbiIsImNyZWF0ZU9yZ2FuaXphdGlvbkJpbGxpbmdVcGRhdGVyIiwiZ2V0T3JnYW5pemF0aW9uUGxhbiIsImxpc3RBbGxQcm92aWRlclJlY29yZHMiLCJsaXN0QWxsIiwib3JnYW5pemF0aW9uS2V5Iiwib3JnYW5pemF0aW9uQmlsbGluZ01vZGUiLCJtb2RlIiwicHJvY2VzcyIsImVudiIsIk9SR0FOSVpBVElPTl9CSUxMSU5HX01PREUiLCJpbmNsdWRlcyIsIkVycm9yIiwib3JnYW5pemF0aW9uU3RyaXBlQ2xpZW50Iiwia2V5IiwiT1JHQU5JWkFUSU9OX1NUUklQRV9TRUNSRVRfS0VZIiwidGVzdCIsImFwaVZlcnNpb24iLCJtYXhOZXR3b3JrUmV0cmllcyIsInRpbWVvdXQiLCJ0eXBlc2NyaXB0IiwidmVyaWZ5RXZlbnQiLCJzdHJpcGUiLCJib2R5Iiwic2lnbmF0dXJlIiwic2VjcmV0IiwiT1JHQU5JWkFUSU9OX1NUUklQRV9XRUJIT09LX1NFQ1JFVCIsInN0YXJ0c1dpdGgiLCJldmVudCIsIndlYmhvb2tzIiwiY29uc3RydWN0RXZlbnQiLCJvYmplY3QiLCJkYXRhIiwiY3VzdG9tZXJJZCIsImN1c3RvbWVyIiwiaWQiLCJsaXZlbW9kZSIsImV2ZW50SWQiLCJ0eXBlIiwidmVyaWZ5T3JnYW5pemF0aW9uQmlsbGluZ0V2ZW50IiwiZ2V0T3JnYW5pemF0aW9uQmlsbGluZ1Byb3ZpZGVyIiwib3JpZ2luIiwiT1JHQU5JWkFUSU9OX1NJVEVfT1JJR0lOIiwicGFyc2VkIiwiVVJMIiwicHJvdG9jb2wiLCJ1c2VybmFtZSIsInBhc3N3b3JkIiwicHJpY2VzIiwicHJvIiwiT1JHQU5JWkFUSU9OX1NUUklQRV9QUk9fUFJJQ0VfSUQiLCJzZWF0IiwiT1JHQU5JWkFUSU9OX1NUUklQRV9TRUFUX1BSSUNFX0lEIiwic3RhcnRlciIsIk9SR0FOSVpBVElPTl9TVFJJUEVfU1RBUlRFUl9QUklDRV9JRCIsIlByb21pc2UiLCJhbGwiLCJPYmplY3QiLCJlbnRyaWVzIiwibWFwIiwibmFtZSIsImV4cGVjdGVkIiwiYmFzZUNlbnRzIiwicHJpY2UiLCJyZXRyaWV2ZSIsImFjdGl2ZSIsImN1cnJlbmN5IiwidW5pdF9hbW91bnQiLCJyZWN1cnJpbmciLCJpbnRlcnZhbCIsImludGVydmFsX2NvdW50IiwidXNhZ2VfdHlwZSIsInN1YnNjcmlwdGlvbklkIiwic3RhcnRpbmdBZnRlciIsInN1YnNjcmlwdGlvbnMiLCJsaXN0IiwibGltaXQiLCJzdGFydGluZ19hZnRlciIsInN0YXR1cyIsImxpdmUiLCJmaWx0ZXIiLCJzdWJzY3JpcHRpb24iLCJsZW5ndGgiLCJpdGVtcyIsImJhc2UiLCJmaW5kIiwiaXRlbSIsImhhc19tb3JlIiwicXVhbnRpdHkiLCJOdW1iZXIiLCJCb29sZWFuIiwiaXNTYWZlSW50ZWdlciIsImN1cnJlbnRfcGVyaW9kX2VuZCIsImN1cnJlbnRfcGVyaW9kX3N0YXJ0IiwiaW52b2ljZXMiLCJ1bnNldHRsZWQiLCJpbnZvaWNlIiwibWV0YWRhdGEiLCJvcmdhbml6YXRpb25CaWxsaW5nSm9iIiwiYW1vdW50X3JlbWFpbmluZyIsInNvbWUiLCJhdHRlbXB0ZWQiLCJiYXNlSXRlbUlkIiwiY2FuY2VsQXRQZXJpb2RFbmQiLCJjYW5jZWxfYXRfcGVyaW9kX2VuZCIsImV4dHJhU2VhdHMiLCJsYXN0Sm9iSWQiLCJwZW5kaW5nUGxhbiIsIm9yZ2FuaXphdGlvblBlbmRpbmdQbGFuIiwicGVyaW9kRW5kIiwicGVyaW9kU3RhcnQiLCJwbGFuIiwic2VhdEl0ZW1JZCIsInN0YXJ0ZWRBdCIsInN0YXJ0X2RhdGUiLCJzZXNzaW9uUmVzdWx0Iiwic2Vzc2lvbiIsInVybCIsImV4cGlyZXNBdCIsImV4cGlyZXNfYXQiLCJjaGVja291dCIsInNlc3Npb25zIiwibWF0Y2hpbmciLCJvcmdhbml6YXRpb25DaGVja291dEtleSIsIkRhdGUiLCJub3ciLCJsaW5lSXRlbXMiLCJjcmVhdGUiLCJjYW5jZWxfdXJsIiwiY2xpZW50X3JlZmVyZW5jZV9pZCIsImxpbmVfaXRlbXMiLCJwcmljZVZlcnNpb24iLCJzdWJzY3JpcHRpb25fZGF0YSIsInN1Y2Nlc3NfdXJsIiwiaWRlbXBvdGVuY3lLZXkiLCJvcmdhbml6YXRpb25JZCIsImVtYWlsIiwiY3VzdG9tZXJzIiwicG9ydGFsIiwiY29uZmlndXJhdGlvbiIsIk9SR0FOSVpBVElPTl9TVFJJUEVfUE9SVEFMX0NPTkZJR1VSQVRJT05fSUQiLCJjb25maWciLCJiaWxsaW5nUG9ydGFsIiwiY29uZmlndXJhdGlvbnMiLCJmZWF0dXJlcyIsInN1YnNjcmlwdGlvbl9jYW5jZWwiLCJlbmFibGVkIiwic3Vic2NyaXB0aW9uX3VwZGF0ZSIsInBheW1lbnRfbWV0aG9kX3VwZGF0ZSIsImludm9pY2VfaGlzdG9yeSIsInJldHVybl91cmwiLCJwcmV2aWV3Iiwic2VhdHMiLCJlZmZlY3RpdmVBdCIsInNlYXRJdGVtcyIsImNyZWF0ZVByZXZpZXciLCJzdWJzY3JpcHRpb25fZGV0YWlscyIsInByb3JhdGlvbl9kYXRlIiwiTWF0aCIsImZsb29yIiwibGluZXMiLCJsaW5lIiwicGFyZW50Iiwic3Vic2NyaXB0aW9uX2l0ZW1fZGV0YWlscyIsInByb3JhdGlvbiIsInJlZHVjZSIsInRvdGFsIiwiYW1vdW50IiwidXBkYXRlIiwidmVyaWZ5Il0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFZLFNBQVM7QUFFNUIsU0FBUUMsZ0JBQWdCLFFBQU8sMEJBQTBCO0FBQ3pELFNBQVFDLGdDQUFnQyxRQUFPLHNCQUFzQjtBQUNyRSxTQUFRQyxtQkFBbUIsUUFBTyxhQUFhO0FBQy9DLFNBQVFDLDBCQUEwQkMsT0FBTyxRQUFPLDBCQUEwQjtBQUMxRSxTQUFRQyxlQUFlLFFBQU8sYUFBYTtBQVczQyxPQUFPLE1BQU1DLDBCQUEwQjtJQUNyQyxNQUFNQyxPQUFPQyxRQUFRQyxHQUFHLENBQUNDLHlCQUF5QixJQUFJO0lBQ3RELElBQUcsQ0FBQztRQUFDO1FBQVk7S0FBTyxDQUFDQyxRQUFRLENBQUNKLE9BQU87UUFDdkMsTUFBTSxJQUFJSyxNQUFNO0lBQ2xCO0lBQ0EsT0FBT0w7QUFDVCxFQUFFO0FBQ0YsTUFBTU0sMkJBQTJCO0lBQy9CLElBQUdQLDhCQUE4QixRQUFRO1FBQ3ZDLE1BQU0sSUFBSU0sTUFBTTtJQUNsQjtJQUNBLE1BQU1FLE1BQU1OLFFBQVFDLEdBQUcsQ0FBQ00sOEJBQThCLElBQUk7SUFDMUQsSUFBRyxDQUFDLDhCQUE4QkMsSUFBSSxDQUFDRixNQUFNO1FBQzNDLE1BQU0sSUFBSUYsTUFBTTtJQUNsQjtJQUNBLE9BQU8sSUFBSWIsT0FBT2UsS0FBSztRQUFDRyxZQUFZakI7UUFBa0JrQixtQkFBbUI7UUFBR0MsU0FBUztRQUFPQyxZQUFZO0lBQUk7QUFDOUc7QUFDQSxNQUFNQyxjQUFjLENBQUNDLFFBQWdCQyxNQUF1QkM7SUFDMUQsTUFBTUMsU0FBU2pCLFFBQVFDLEdBQUcsQ0FBQ2lCLGtDQUFrQyxJQUFJO0lBQ2pFLElBQUcsQ0FBQ0QsT0FBT0UsVUFBVSxDQUFDLGFBQWEsQ0FBQ0gsV0FBVztRQUM3QyxNQUFNLElBQUlaLE1BQU07SUFDbEI7SUFDQSxNQUFNZ0IsUUFBUU4sT0FBT08sUUFBUSxDQUFDQyxjQUFjLENBQUNQLE1BQU1DLFdBQVdDO0lBQzlELE1BQU1NLFNBQVNILE1BQU1JLElBQUksQ0FBQ0QsTUFBTTtJQUNoQyxNQUFNRSxhQUFhLE9BQU9GLE9BQU9HLFFBQVEsS0FBSyxXQUFXSCxPQUFPRyxRQUFRLEdBQUdILE9BQU9HLFFBQVEsRUFBRUM7SUFDNUYsSUFBR1AsTUFBTVEsUUFBUSxJQUFJLENBQUNILGNBQWMsQ0FBQyxxQkFBcUJqQixJQUFJLENBQUNpQixhQUFhO1FBQzFFLE1BQU0sSUFBSXJCLE1BQU07SUFDbEI7SUFDQSxPQUFPO1FBQUNxQjtRQUFZSSxTQUFTVCxNQUFNTyxFQUFFO1FBQUVHLE1BQU1WLE1BQU1VLElBQUk7SUFBQTtBQUN6RDtBQUNBLE9BQU8sTUFBTUMsaUNBQWlDLENBQzVDaEIsTUFDQUMsWUFDeUJILFlBQVlSLDRCQUE0QlUsTUFBTUMsV0FBVztBQUVwRixPQUFPLE1BQU1nQixpQ0FBaUM7SUFDNUMsTUFBTWxCLFNBQVNUO0lBQ2YsTUFBTTRCLFNBQVNqQyxRQUFRQyxHQUFHLENBQUNpQyx3QkFBd0IsSUFBSTtJQUN2RCxJQUFJQztJQUNKLElBQUk7UUFDRkEsU0FBUyxJQUFJQyxJQUFJSDtJQUNuQixFQUFFLE9BQUs7UUFDTCxNQUFNLElBQUk3QixNQUFNO0lBQ2xCO0lBQ0EsSUFBRytCLE9BQU9FLFFBQVEsS0FBSyxZQUFZRixPQUFPRixNQUFNLEtBQUtBLFVBQVVFLE9BQU9HLFFBQVEsSUFBSUgsT0FBT0ksUUFBUSxFQUFFO1FBQ2pHLE1BQU0sSUFBSW5DLE1BQU07SUFDbEI7SUFDQSxNQUFNb0MsU0FBUztRQUNiQyxLQUFLekMsUUFBUUMsR0FBRyxDQUFDeUMsZ0NBQWdDLElBQUk7UUFDckRDLE1BQU0zQyxRQUFRQyxHQUFHLENBQUMyQyxpQ0FBaUMsSUFBSTtRQUN2REMsU0FBUzdDLFFBQVFDLEdBQUcsQ0FBQzZDLG9DQUFvQyxJQUFJO0lBQy9EO0lBQ0EsTUFBTUMsUUFBUUMsR0FBRyxDQUNmQyxPQUFPQyxPQUFPLENBQUNWLFFBQVFXLEdBQUcsQ0FBQyxPQUFPLENBQUNDLE1BQU16QixHQUFHO1FBQzFDLElBQUcsQ0FBQyx1QkFBdUJuQixJQUFJLENBQUNtQixLQUFLO1lBQ25DLE1BQU0sSUFBSXZCLE1BQU07UUFDbEI7UUFDQSxNQUFNaUQsV0FBV0QsU0FBUyxTQUFTLE1BQU0xRCxvQkFBb0IwRCxNQUFpQkUsU0FBUztRQUN2RixNQUFNQyxRQUFRLE1BQU16QyxPQUFPMEIsTUFBTSxDQUFDZ0IsUUFBUSxDQUFDN0I7UUFDM0MsSUFDRTRCLE1BQU0zQixRQUFRLElBQ2QsQ0FBQzJCLE1BQU1FLE1BQU0sSUFDYkYsTUFBTUcsUUFBUSxLQUFLLFNBQ25CSCxNQUFNSSxXQUFXLEtBQUtOLFlBQ3RCRSxNQUFNSyxTQUFTLEVBQUVDLGFBQWEsV0FDOUJOLE1BQU1LLFNBQVMsQ0FBQ0UsY0FBYyxLQUFLLEtBQ25DUCxNQUFNSyxTQUFTLENBQUNHLFVBQVUsS0FBSyxZQUMvQjtZQUNBLE1BQU0sSUFBSTNELE1BQU07UUFDbEI7SUFDRjtJQUVGLE1BQU1vRCxXQUFXLE9BQU8vQixZQUFvQnVDO1FBQzFDLE1BQU1oQixNQUFNLE1BQU1wRCxRQUFRLENBQUNxRSxnQkFDekJuRCxPQUFPb0QsYUFBYSxDQUFDQyxJQUFJLENBQUM7Z0JBQUN6QyxVQUFVRDtnQkFBWTJDLE9BQU87Z0JBQUtDLGdCQUFnQko7Z0JBQWVLLFFBQVE7WUFBSztRQUUzRyxNQUFNQyxPQUFPdkIsSUFBSXdCLE1BQU0sQ0FDckIsQ0FBQ0MsZUFBaUIsQ0FBQztnQkFBQztnQkFBWTthQUFxQixDQUFDdEUsUUFBUSxDQUFDc0UsYUFBYUgsTUFBTTtRQUVwRixJQUFHQyxLQUFLRyxNQUFNLEdBQUcsR0FBRztZQUNsQixNQUFNLElBQUl0RSxNQUFNO1FBQ2xCO1FBQ0EsTUFBTXFFLGVBQWVULGlCQUFpQixNQUFNbEQsT0FBT29ELGFBQWEsQ0FBQ1YsUUFBUSxDQUFDUSxrQkFBa0JPLElBQUksQ0FBQyxFQUFFLElBQUk7UUFDdkcsSUFBRyxDQUFDRSxjQUFjO1lBQ2hCLE9BQU87UUFDVDtRQUNBLE1BQU0vQyxXQUNKLE9BQU8rQyxhQUFhL0MsUUFBUSxLQUFLLFdBQVcrQyxhQUFhL0MsUUFBUSxHQUFHK0MsYUFBYS9DLFFBQVEsQ0FBQ0MsRUFBRTtRQUM5RixNQUFNZ0QsUUFBUUYsYUFBYUUsS0FBSyxDQUFDbkQsSUFBSTtRQUNyQyxNQUFNb0QsT0FBT0QsTUFBTUUsSUFBSSxDQUFDLENBQUNDLE9BQVM7Z0JBQUN0QyxPQUFPQyxHQUFHO2dCQUFFRCxPQUFPSyxPQUFPO2FBQUMsQ0FBQzFDLFFBQVEsQ0FBQzJFLEtBQUt2QixLQUFLLENBQUM1QixFQUFFO1FBQ3JGLE1BQU1nQixPQUFPZ0MsTUFBTUUsSUFBSSxDQUFDLENBQUNDLE9BQVNBLEtBQUt2QixLQUFLLENBQUM1QixFQUFFLEtBQUthLE9BQU9HLElBQUk7UUFDL0QsSUFDRThCLGFBQWE3QyxRQUFRLElBQ3JCRixhQUFhRCxjQUNiZ0QsYUFBYUUsS0FBSyxDQUFDSSxRQUFRLElBQzNCLENBQUNILFFBQ0RBLEtBQUtJLFFBQVEsS0FBSyxLQUNsQkwsTUFBTUQsTUFBTSxLQUFLLElBQUlPLE9BQU9DLFFBQVF2QyxVQUNwQyxDQUFDc0MsT0FBT0UsYUFBYSxDQUFDeEMsTUFBTXFDLFlBQVksTUFDeEMsQUFBQ3JDLENBQUFBLE1BQU1xQyxZQUFZLENBQUEsSUFBSyxLQUN2QnJDLFFBQ0VBLENBQUFBLEtBQUt5QyxrQkFBa0IsS0FBS1IsS0FBS1Esa0JBQWtCLElBQ2xEekMsS0FBSzBDLG9CQUFvQixLQUFLVCxLQUFLUyxvQkFBb0IsQUFBRCxHQUMxRDtZQUNBLE1BQU0sSUFBSWpGLE1BQU07UUFDbEI7UUFDQSxNQUFNa0YsV0FBVyxNQUFNMUYsUUFBUSxDQUFDcUUsZ0JBQzlCbkQsT0FBT3dFLFFBQVEsQ0FBQ25CLElBQUksQ0FBQztnQkFBQ3pDLFVBQVVEO2dCQUFZMkMsT0FBTztnQkFBS0MsZ0JBQWdCSjtZQUFhO1FBRXZGLE1BQU1zQixZQUFZRCxTQUFTZCxNQUFNLENBQUMsQ0FBQ2dCLFVBQVlBLFFBQVFDLFFBQVEsRUFBRUMsMEJBQzVERixRQUFRbEIsTUFBTSxLQUFLLFVBQVVrQixRQUFRRyxnQkFBZ0IsR0FBRztRQUM3RCxJQUFJLEVBQUNyQixNQUFNLEVBQUMsR0FBR0c7UUFDZixJQUFHQSxhQUFhSCxNQUFNLEtBQUssWUFBWWlCLFVBQVViLE1BQU0sRUFBRTtZQUN2REosU0FBU2lCLFVBQVVLLElBQUksQ0FBQyxDQUFDSixVQUFZQSxRQUFRSyxTQUFTLElBQUksYUFBYTtRQUN6RTtRQUNBLE9BQU87WUFDTEMsWUFBWWxCLEtBQUtqRCxFQUFFO1lBQ25Cb0UsbUJBQW1CdEIsYUFBYXVCLG9CQUFvQjtZQUNwRHZFO1lBQ0F3RSxZQUFZdEQsTUFBTXFDLFlBQVk7WUFDOUJyRCxJQUFJOEMsYUFBYTlDLEVBQUU7WUFDbkJ1RSxXQUFXekIsYUFBYWdCLFFBQVEsRUFBRUMsMEJBQTBCO1lBQzVEUyxhQUFhMUIsYUFBYWdCLFFBQVEsRUFBRVcsNEJBQTRCLGFBQWF4QixLQUFLckIsS0FBSyxDQUFDNUIsRUFBRSxLQUFLYSxPQUFPSyxPQUFPLEdBQUcsWUFBWTtZQUM1SHdELFdBQVd6QixLQUFLUSxrQkFBa0IsR0FBRztZQUNyQ2tCLGFBQWExQixLQUFLUyxvQkFBb0IsR0FBRztZQUN6Q2tCLE1BQU0zQixLQUFLckIsS0FBSyxDQUFDNUIsRUFBRSxLQUFLYSxPQUFPQyxHQUFHLEdBQUcsUUFBUTtZQUM3QytELFlBQVk3RCxNQUFNaEIsTUFBTTtZQUN4QjhFLFdBQVcsQUFBQ2hDLENBQUFBLGFBQWFpQyxVQUFVLElBQUk5QixLQUFLUyxvQkFBb0IsQUFBRCxJQUFLO1lBQ3BFZjtRQUNGO0lBQ0Y7SUFDQSxNQUFNcUMsZ0JBQWdCLENBQUNDO1FBQ3JCLElBQUdBLFFBQVFoRixRQUFRLEVBQUU7WUFDbkIsTUFBTSxJQUFJeEIsTUFBTTtRQUNsQjtRQUNBLElBQUd3RyxRQUFRdEMsTUFBTSxLQUFLLFlBQVk7WUFDaEMsTUFBTSxJQUFJbEUsTUFBTTtRQUNsQjtRQUNBLElBQUd3RyxRQUFRQyxHQUFHLElBQUksQ0FBQ0QsUUFBUUMsR0FBRyxDQUFDMUYsVUFBVSxDQUFDLGlDQUFpQztZQUN6RSxNQUFNLElBQUlmLE1BQU07UUFDbEI7UUFDQSxPQUFPO1lBQUMwRyxXQUFXRixRQUFRRyxVQUFVLEdBQUc7WUFBTXBGLElBQUlpRixRQUFRakYsRUFBRTtZQUFFa0YsS0FBS0QsUUFBUUMsR0FBRyxJQUFJO1FBQUU7SUFDdEY7SUFDQSxPQUFPO1FBQ0xHLFVBQVUsT0FBT3ZGLFlBQVk4RSxNQUFNTixZQUFZM0Y7WUFDN0NaLG9CQUFvQjZHO1lBQ3BCLElBQUcsQ0FBQ3RCLE9BQU9FLGFBQWEsQ0FBQ2MsZUFBZUEsYUFBYSxHQUFHO2dCQUN0RCxNQUFNLElBQUk3RixNQUFNO1lBQ2xCO1lBQ0EsTUFBTTZHLFdBQVcsTUFBTXJILFFBQVEsQ0FBQ3FFLGdCQUM5Qm5ELE9BQU9rRyxRQUFRLENBQUNDLFFBQVEsQ0FBQzlDLElBQUksQ0FBQztvQkFBQ3pDLFVBQVVEO29CQUFZMkMsT0FBTztvQkFBS0MsZ0JBQWdCSjtnQkFBYTtZQUVoRyxNQUFNaUQsV0FBV0QsU0FBU3pDLE1BQU0sQ0FBQyxDQUFDb0MsVUFBWUEsUUFBUW5CLFFBQVEsRUFBRTBCLDRCQUE0QjdHO1lBQzVGLElBQUc0RyxTQUFTeEMsTUFBTSxHQUFHLEdBQUc7Z0JBQ3RCLE1BQU0sSUFBSXRFLE1BQU07WUFDbEI7WUFDQSxJQUFHOEcsUUFBUSxDQUFDLEVBQUUsRUFBRTtnQkFDZCxPQUFPUCxjQUFjTyxRQUFRLENBQUMsRUFBRTtZQUNsQztZQUNBLElBQUdELFNBQVNyQixJQUFJLENBQUMsQ0FBQ2dCLFVBQVlBLFFBQVF0QyxNQUFNLEtBQUssVUFBVXNDLFFBQVFHLFVBQVUsR0FBRyxPQUFPSyxLQUFLQyxHQUFHLEtBQUs7Z0JBQ2xHLE1BQU0sSUFBSWpILE1BQU07WUFDbEI7WUFDQSxJQUFHLE1BQU1vRCxTQUFTL0IsYUFBYTtnQkFDN0IsTUFBTSxJQUFJckIsTUFBTTtZQUNsQjtZQUNBLE1BQU1rSCxZQUFZO2dCQUNoQjtvQkFBQy9ELE9BQU9mLE1BQU0sQ0FBQytELEtBQUs7b0JBQUV2QixVQUFVO2dCQUFDO21CQUM3QmlCLGFBQWE7b0JBQUM7d0JBQUMxQyxPQUFPZixPQUFPRyxJQUFJO3dCQUFFcUMsVUFBVWlCO29CQUFVO2lCQUFFLEdBQUcsRUFBRTthQUNuRTtZQUNELE1BQU1XLFVBQVUsTUFBTTlGLE9BQU9rRyxRQUFRLENBQUNDLFFBQVEsQ0FBQ00sTUFBTSxDQUNuRDtnQkFDRUMsWUFBWSxHQUFHdkYsT0FBTyxpQkFBaUIsQ0FBQztnQkFDeEN3RixxQkFBcUJuSDtnQkFDckJvQixVQUFVRDtnQkFDVmlHLFlBQVlKO2dCQUNaN0IsVUFBVTtvQkFBQzBCLHlCQUF5QjdHO29CQUFLcUgsY0FBYztnQkFBWTtnQkFDbkU1SCxNQUFNO2dCQUNONkgsbUJBQW1CO29CQUFDbkMsVUFBVTt3QkFBQzBCLHlCQUF5QjdHO3dCQUFLcUgsY0FBYztvQkFBWTtnQkFBQztnQkFDeEZFLGFBQWEsR0FBRzVGLE9BQU8sc0NBQXNDLENBQUM7WUFDaEUsR0FDQTtnQkFBQzZGLGdCQUFnQnhIO1lBQUc7WUFFdEIsT0FBT3FHLGNBQWNDO1FBQ3ZCO1FBQ0FsRixVQUFVLE9BQU9xRyxnQkFBZ0JDO1lBQy9CLDZGQUE2RjtZQUM3RixNQUFNQyxZQUFZLE1BQU1ySSxRQUFRLENBQUNxRSxnQkFDL0JuRCxPQUFPbUgsU0FBUyxDQUFDOUQsSUFBSSxDQUFDO29CQUFDQyxPQUFPO29CQUFLQyxnQkFBZ0JKO2dCQUFhO1lBRWxFLE1BQU1pRCxXQUFXZSxVQUFVekQsTUFBTSxDQUFDLENBQUM5QyxXQUFhQSxTQUFTK0QsUUFBUSxDQUFDc0MsY0FBYyxLQUFLQTtZQUNyRixJQUFHYixTQUFTeEMsTUFBTSxHQUFHLEdBQUc7Z0JBQ3RCLE1BQU0sSUFBSXRFLE1BQU07WUFDbEI7WUFDQSxNQUFNc0IsV0FDSndGLFFBQVEsQ0FBQyxFQUFFLElBQ1YsTUFBTXBHLE9BQU9tSCxTQUFTLENBQUNWLE1BQU0sQ0FDNUI7Z0JBQUNTO2dCQUFPdkMsVUFBVTtvQkFBQ3NDO2dCQUFjO1lBQUMsR0FDbEM7Z0JBQUNELGdCQUFnQmpJLGdCQUFnQix5QkFBeUJrSTtZQUFlO1lBRTdFLElBQUdyRyxTQUFTRSxRQUFRLEVBQUU7Z0JBQ3BCLE1BQU0sSUFBSXhCLE1BQU07WUFDbEI7WUFDQSxPQUFPc0IsU0FBU0MsRUFBRTtRQUNwQjtRQUNBdUcsUUFBUSxPQUFPekc7WUFDYixNQUFNMEcsZ0JBQWdCbkksUUFBUUMsR0FBRyxDQUFDbUksMkNBQTJDLElBQUk7WUFDakYsSUFBRyxDQUFDLHFCQUFxQjVILElBQUksQ0FBQzJILGdCQUFnQjtnQkFDNUMsTUFBTSxJQUFJL0gsTUFBTTtZQUNsQjtZQUNBLE1BQU1pSSxTQUFTLE1BQU12SCxPQUFPd0gsYUFBYSxDQUFDQyxjQUFjLENBQUMvRSxRQUFRLENBQUMyRTtZQUNsRSxJQUNFRSxPQUFPekcsUUFBUSxJQUNmLENBQUN5RyxPQUFPNUUsTUFBTSxJQUNkNEUsT0FBT0csUUFBUSxDQUFDQyxtQkFBbUIsQ0FBQ0MsT0FBTyxJQUMzQ0wsT0FBT0csUUFBUSxDQUFDRyxtQkFBbUIsQ0FBQ0QsT0FBTyxJQUMzQyxDQUFDTCxPQUFPRyxRQUFRLENBQUNJLHFCQUFxQixDQUFDRixPQUFPLElBQzlDLENBQUNMLE9BQU9HLFFBQVEsQ0FBQ0ssZUFBZSxDQUFDSCxPQUFPLEVBQ3hDO2dCQUNBLE1BQU0sSUFBSXRJLE1BQU07WUFDbEI7WUFDQSxPQUFPLEFBQ0wsQ0FBQSxNQUFNVSxPQUFPd0gsYUFBYSxDQUFDckIsUUFBUSxDQUFDTSxNQUFNLENBQUM7Z0JBQ3pDWTtnQkFDQXpHLFVBQVVEO2dCQUNWcUgsWUFBWSxHQUFHN0csT0FBTyxzQkFBc0IsQ0FBQztZQUMvQyxFQUFDLEVBQ0Q0RSxHQUFHO1FBQ1A7UUFDQWtDLFNBQVMsT0FBT3RFLGNBQWM4QixNQUFNeUMsT0FBT0M7WUFDekN2SixvQkFBb0I2RztZQUNwQixJQUFHLENBQUN0QixPQUFPRSxhQUFhLENBQUM2RCxVQUFVQSxRQUFRLEtBQUssQ0FBQy9ELE9BQU9FLGFBQWEsQ0FBQzhELGNBQWM7Z0JBQ2xGLE1BQU0sSUFBSTdJLE1BQU07WUFDbEI7WUFDQSxNQUFNOEksWUFBWUYsUUFBUTtnQkFBQztvQkFBQ3pGLE9BQU9mLE9BQU9HLElBQUk7b0JBQUVxQyxVQUFVZ0U7Z0JBQUs7YUFBRSxHQUFHLEVBQUU7WUFDdEUsTUFBTXJFLFFBQVE7Z0JBQ1o7b0JBQUNoRCxJQUFJOEMsYUFBYXFCLFVBQVU7b0JBQUV2QyxPQUFPZixNQUFNLENBQUMrRCxLQUFLO29CQUFFdkIsVUFBVTtnQkFBQzttQkFDMURQLGFBQWErQixVQUFVLEdBQ3ZCO29CQUFDO3dCQUFDN0UsSUFBSThDLGFBQWErQixVQUFVO3dCQUFFakQsT0FBT2YsT0FBT0csSUFBSTt3QkFBRXFDLFVBQVVnRTtvQkFBSztpQkFBRSxHQUNwRUU7YUFDTDtZQUNELE1BQU0xRCxVQUFVLE1BQU0xRSxPQUFPd0UsUUFBUSxDQUFDNkQsYUFBYSxDQUFDO2dCQUNsRHpILFVBQVUrQyxhQUFhaEQsVUFBVTtnQkFDakNnRCxjQUFjQSxhQUFhOUMsRUFBRTtnQkFDN0J5SCxzQkFBc0I7b0JBQUN6RTtvQkFBTzBFLGdCQUFnQkMsS0FBS0MsS0FBSyxDQUFDTixjQUFjO2dCQUFLO1lBQzlFO1lBQ0EsSUFBR3pELFFBQVE1RCxRQUFRLElBQUk0RCxRQUFRZ0UsS0FBSyxDQUFDekUsUUFBUSxFQUFFO2dCQUM3QyxNQUFNLElBQUkzRSxNQUFNO1lBQ2xCO1lBQ0EsT0FBT29GLFFBQVFnRSxLQUFLLENBQUNoSSxJQUFJLENBQ3RCZ0QsTUFBTSxDQUFDLENBQUNpRixPQUFTQSxLQUFLQyxNQUFNLEVBQUVDLDJCQUEyQkMsV0FDekRDLE1BQU0sQ0FBQyxDQUFDQyxPQUFPTCxPQUFTSyxRQUFRTCxLQUFLTSxNQUFNLEVBQUU7UUFDbEQ7UUFDQXZHO1FBQ0F3RyxRQUFRdkssaUNBQWlDcUIsUUFBUTBCO1FBQ2pEeUgsUUFBUSxDQUFDbEosTUFBTUMsWUFBY0gsWUFBWUMsUUFBUUMsTUFBTUM7SUFDekQ7QUFDRixFQUFFIn0=
@@ -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 {};