@getopenpay/openpay-js 0.1.14 → 0.1.15-alpha.09caa9f

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/dist/index.d.ts CHANGED
@@ -1,6 +1,21 @@
1
1
  import { PaymentRequest as PaymentRequest_2 } from '@stripe/stripe-js';
2
+ import { Subject } from 'rxjs';
2
3
  import { z } from 'zod';
3
4
 
5
+ declare type AllCallbacks = {
6
+ onFocus?: (elementId: string, field: AllFieldNames) => void;
7
+ onBlur?: (elementId: string, field: AllFieldNames) => void;
8
+ onChange?: (elementId: string, field: AllFieldNames, errors?: string[]) => void;
9
+ onLoad?: (totalAmountAtoms?: number, currency?: string) => void;
10
+ onLoadError?: (message: string) => void;
11
+ onValidationError?: OnValidationError;
12
+ onCheckoutStarted?: OnCheckoutStarted;
13
+ onCheckoutSuccess?: OnCheckoutSuccess;
14
+ onSetupPaymentMethodSuccess?: OnSetupPaymentMethodSuccess;
15
+ onCheckoutError?: OnCheckoutError;
16
+ onPaymentRequestLoad?: (paymentRequests: PRStatuses) => void;
17
+ };
18
+
4
19
  declare const AllFieldNames = z.union([FieldNameEnum, PrivateFieldNameEnum]);
5
20
 
6
21
  declare type AllFieldNames = z.infer<typeof AllFieldNames>;
@@ -34,17 +49,9 @@ declare const CheckoutPaymentMethod = z.object({
34
49
 
35
50
  declare type CheckoutPaymentMethod = z.infer<typeof CheckoutPaymentMethod>;
36
51
 
37
- export declare type Config = ElementsFormProps & {
38
- _frameUrl?: URL;
39
- };
52
+ export declare type Config = ElementsFormProps & AllCallbacks;
40
53
 
41
- declare class ConnectionManager {
42
- private connections;
43
- constructor();
44
- addConnection(id: ElementType, connection: CdeConnection): void;
45
- getConnection(): CdeConnection;
46
- getAllConnections(): Map<ElementType, CdeConnection>;
47
- }
54
+ declare type CurrentStatus<T> = InitialStatus | SuccessStatus<T> | ErrorStatus;
48
55
 
49
56
  declare type CustomInitParams = {
50
57
  stripeLink?: {
@@ -78,19 +85,8 @@ declare type ElementProps<PlaceholderType extends z.ZodTypeAny = z.ZodString> =
78
85
  export declare type ElementsFormProps = {
79
86
  className?: string;
80
87
  checkoutSecureToken: string;
81
- onFocus?: (elementId: string, field: AllFieldNames) => void;
82
- onBlur?: (elementId: string, field: AllFieldNames) => void;
83
- onChange?: (elementId: string, field: AllFieldNames, errors?: string[]) => void;
84
- onLoad?: (totalAmountAtoms?: number, currency?: string) => void;
85
- onLoadError?: (message: string) => void;
86
- onValidationError?: (field: AllFieldNames, errors: string[], elementId?: string) => void;
87
- onCheckoutStarted?: () => void;
88
- onCheckoutSuccess?: (invoiceUrls: string[], subscriptionIds: string[], customerId: string) => void;
89
- onSetupPaymentMethodSuccess?: (paymentMethodId: string) => void;
90
- onCheckoutError?: (message: string) => void;
91
88
  baseUrl?: string;
92
89
  formTarget?: string;
93
- onPaymentRequestLoad?: (paymentRequests: Record<PaymentRequestProvider, PaymentRequestStatus>) => void;
94
90
  customInitParams?: CustomInitParams;
95
91
  };
96
92
 
@@ -124,6 +120,13 @@ declare enum ElementTypeEnum {
124
120
 
125
121
  declare type ElementTypeEnumValue = ElementTypeEnum[keyof ElementTypeEnum];
126
122
 
123
+ declare type ErrorStatus = {
124
+ status: 'error';
125
+ isSuccess: false;
126
+ error: unknown; // Anything can be thrown, so we don't want to be strict here
127
+ errMsg: string;
128
+ };
129
+
127
130
  /**
128
131
  * Expected input fields
129
132
  */
@@ -142,6 +145,41 @@ export declare enum FieldName {
142
145
  PROMOTION_CODE = 'promotionCode',
143
146
  }
144
147
 
148
+ declare class FormCallbacks {
149
+ private _callbacks: AllCallbacks = {};
150
+
151
+ static fromObject = (obj: unknown) => {
152
+ const instance = new FormCallbacks();
153
+ instance.setCallbacks(ZodFormCallbacks.parse(obj));
154
+ return instance;
155
+ };
156
+
157
+ /**
158
+ * Sets ALL form callbacks. Note that all old callbacks are removed.
159
+ */
160
+ setCallbacks = (rawCallbacks: AllCallbacks) => {
161
+ // Making sure to reinitialize
162
+ this._callbacks = {};
163
+ Object.entries(rawCallbacks).forEach(([key, rawCallback]) => {
164
+ const safeCallback = makeCallbackSafe(key, rawCallback ?? (() => {}), err__);
165
+ // @ts-expect-error - trust the process
166
+ this._callbacks[key] = safeCallback;
167
+ });
168
+ };
169
+
170
+ /**
171
+ * Returns a read-only version of the callbacks object.
172
+ */
173
+ get get() {
174
+ return { ...this._callbacks };
175
+ }
176
+ }
177
+
178
+ declare type InitialStatus = {
179
+ status: 'initial';
180
+ isSuccess: false;
181
+ };
182
+
145
183
  declare type InitOjsFlow<T extends InitOjsFlowResult> = (params: InitOjsFlowParams) => Promise<T>;
146
184
 
147
185
  declare type InitOjsFlowParams = {
@@ -154,13 +192,22 @@ declare type InitOjsFlowParams = {
154
192
  /**
155
193
  * Lifecycle callbacks for OJS flows.
156
194
  */
157
- flowCallbacks: OjsFlowCallbacks;
195
+ formCallbacks: FormCallbacks;
158
196
  };
159
197
 
160
198
  declare type InitOjsFlowResult = {
161
199
  isAvailable: boolean;
162
200
  };
163
201
 
202
+ declare type InitStripeLinkFlowResult =
203
+ | {
204
+ isAvailable: true;
205
+ controller: StripeLinkController;
206
+ }
207
+ | {
208
+ isAvailable: false;
209
+ };
210
+
164
211
  declare type InitStripePrFlowResult =
165
212
  | InitStripePrFlowSuccess
166
213
  | {
@@ -179,19 +226,6 @@ declare type InitStripePrFlowSuccess = {
179
226
  };
180
227
  };
181
228
 
182
- declare type Loadable<T> =
183
- | {
184
- status: 'loading';
185
- }
186
- | {
187
- status: 'loaded';
188
- result: T;
189
- }
190
- | {
191
- status: 'error';
192
- message: string;
193
- };
194
-
195
229
  declare const LoadedEventPayload = z.object({
196
230
  type: z.literal(EventType.enum.LOADED),
197
231
  sessionId: RequiredString,
@@ -202,6 +236,95 @@ declare const LoadedEventPayload = z.object({
202
236
 
203
237
  declare type LoadedEventPayload = z.infer<typeof LoadedEventPayload>;
204
238
 
239
+ declare class LoadedOncePublisher<T> {
240
+ private _current: CurrentStatus<T>;
241
+ private _subject: Subject<T>;
242
+
243
+ constructor() {
244
+ this._current = { status: 'initial', isSuccess: false };
245
+ this._subject = new Subject<T>();
246
+ }
247
+
248
+ set = (value: T) => {
249
+ if (this._current.status === 'success') {
250
+ throw new Error('LoadedOnce is already in success state');
251
+ }
252
+ this._current = { status: 'success', isSuccess: true, loadedValue: value };
253
+ this._subject.next(value);
254
+ this._subject.complete();
255
+ };
256
+
257
+ throw = (error: unknown, errMsg: string) => {
258
+ if (this._current.status === 'success') {
259
+ throw new Error('LoadedOnce is already in success state');
260
+ }
261
+ this._current = { status: 'error', isSuccess: false, error, errMsg };
262
+ this._subject.error(error);
263
+ // Do not complete the subject since a set() call might be made after this
264
+ };
265
+
266
+ get current() {
267
+ return this._current;
268
+ }
269
+
270
+ getValueIfLoadedElse = <T_ELSE>(valueIfNotLoaded: T_ELSE): T | T_ELSE => {
271
+ if (this._current.status === 'success') return this._current.loadedValue;
272
+ return valueIfNotLoaded;
273
+ };
274
+
275
+ subscribe = (fn: (value: Exclude<CurrentStatus<T>, InitialStatus>) => void) => {
276
+ if (this._current.status === 'success') {
277
+ fn(this._current);
278
+ return;
279
+ }
280
+
281
+ if (this._current.status === 'error') {
282
+ fn(this._current);
283
+ // Do not return, as we will still have the fn subscribed to the subject
284
+ }
285
+
286
+ const subscription = this._subject.subscribe({
287
+ next: () => {
288
+ if (this._current.status !== 'success') {
289
+ throw new Error('Invalid state (next): please make sure to update _current before the subject');
290
+ }
291
+ fn(this._current);
292
+ subscription.unsubscribe();
293
+ },
294
+ error: () => {
295
+ if (this._current.status !== 'error') {
296
+ throw new Error('Invalid state (error): please make sure to update _current before the subject');
297
+ }
298
+ fn(this._current);
299
+ // Do not unsubscribe
300
+ },
301
+ });
302
+ };
303
+
304
+ waitForLoad = (timeoutConfig: { timeoutSec: number; timeoutErrMsg: string }): Promise<T> => {
305
+ if (this._current.status === 'success') return Promise.resolve(this._current.loadedValue);
306
+ if (this._current.status === 'error') return Promise.reject(this._current.error);
307
+ if (this._current.status !== 'initial') assertNever(this._current);
308
+
309
+ const timeoutParams = {
310
+ first: timeoutConfig.timeoutSec * 1000,
311
+ with: () => throwError(() => new Error(timeoutConfig.timeoutErrMsg)),
312
+ };
313
+
314
+ /*
315
+ * Note: lastValueFrom converts the observable to a promise (https://rxjs.dev/api/index/function/lastValueFrom)
316
+ *
317
+ * We use lastValueFrom to wait for the observable to close successfully before resolving the Promise.
318
+ * To avoid hanging threads forever, we use timeoutParams to throw an error if it takes too long.
319
+ * firstValueFrom is theoretically also usable, but it might result in bugs
320
+ * if we do decide to emit more values in this Observable/Subject in the future.
321
+ *
322
+ * For more details, see: https://rxjs.dev/deprecations/to-promise
323
+ */
324
+ return lastValueFrom(this._subject.pipe(timeout(timeoutParams)));
325
+ };
326
+ }
327
+
205
328
  declare type OjsContext = {
206
329
  /**
207
330
  * The form element for the OJS form (non-CDE form).
@@ -221,7 +344,7 @@ declare type OjsContext = {
221
344
  /**
222
345
  * All the CDE connection objects (one for each CDE iframe).
223
346
  */
224
- cdeConnections: Map<ElementType, CdeConnection>;
347
+ anyCdeConnection: CdeConnection;
225
348
 
226
349
  /**
227
350
  * Custom init params for init flows.
@@ -239,14 +362,6 @@ declare type OjsFlow<T_PARAMS = unknown, T_INIT_RESULT extends InitOjsFlowResult
239
362
  run: RunOjsFlow<T_PARAMS, T_INIT_RESULT>;
240
363
  };
241
364
 
242
- declare type OjsFlowCallbacks = {
243
- onCheckoutError: OnCheckoutError;
244
- onCheckoutStarted: OnCheckoutStarted;
245
- onCheckoutSuccess: OnCheckoutSuccess;
246
- onSetupPaymentMethodSuccess: OnSetupPaymentMethodSuccess;
247
- onValidationError: OnValidationError;
248
- };
249
-
250
365
  declare type OjsFlowParams<T_PARAMS = void, T_INIT_RESULT = void> = {
251
366
  /**
252
367
  * Contains the context where OJS is run.
@@ -265,9 +380,9 @@ declare type OjsFlowParams<T_PARAMS = void, T_INIT_RESULT = void> = {
265
380
  nonCdeFormInputs: Record<string, unknown>;
266
381
 
267
382
  /**
268
- * Lifecycle callbacks for OJS flows.
383
+ * Form callbacks. Take note that these can be dynamically updated (but the object remains)
269
384
  */
270
- flowCallbacks: OjsFlowCallbacks;
385
+ formCallbacks: FormCallbacks;
271
386
 
272
387
  /**
273
388
  * Custom parameters for the flow.
@@ -285,6 +400,7 @@ declare const OjsFlows = {
285
400
 
286
401
  // Common
287
402
  commonCC: {
403
+ init: async () => {},
288
404
  run: runCommonCcFlow,
289
405
  },
290
406
 
@@ -314,53 +430,72 @@ declare type OnSetupPaymentMethodSuccess = (paymentMethodId: string) => void;
314
430
  declare type OnValidationError = (field: AllFieldNames, errors: string[], elementId?: string) => void;
315
431
 
316
432
  export declare class OpenPayForm {
317
- config: Config;
318
- formId: string;
319
- formTarget: string;
320
- checkoutFired: boolean;
321
- ojsVersion: string;
322
- ojsReleaseVersion: string;
323
- private referer;
433
+ readonly config: Config;
434
+ readonly formId: string;
435
+ readonly formTarget: string;
436
+ readonly ojsVersion: string;
437
+ readonly ojsReleaseVersion: string;
438
+ readonly formProperties: {
439
+ height: string;
440
+ };
441
+ readonly referrer: string;
442
+ readonly baseUrl: string;
443
+ readonly formCallbacks: FormCallbacks;
444
+ private registeredElements;
324
445
  private eventHandler;
325
- private formProperties;
326
446
  private connectionManager;
327
- private ojsFlowsInitialization;
328
- private cdeLoadedPayload;
329
- private elements;
330
447
  static ojsFlows: typeof OjsFlows;
448
+ private readonly cdeLoadEvent;
449
+ private readonly anyCdeConn;
450
+ private readonly context;
451
+ readonly initFlows: {
452
+ readonly stripePR: {
453
+ publisher: LoadedOncePublisher<InitStripePrFlowResult>;
454
+ initialize: (initParams: InitOjsFlowParams) => Promise<void>;
455
+ };
456
+ readonly stripeLink: {
457
+ publisher: LoadedOncePublisher<InitStripeLinkFlowResult>;
458
+ initialize: (initParams: InitOjsFlowParams) => Promise<void>;
459
+ };
460
+ };
331
461
  constructor(config: Config);
462
+ /**
463
+ * Starts the form initialization process
464
+ */
465
+ private startFormInit;
332
466
  /**
333
467
  * Assign the instance to the window as a singleton
334
- * @param form - The OpenPayForm instance
335
468
  */
336
- static assignAsSingleton(form: OpenPayForm): void;
469
+ private static assignAsSingleton;
337
470
  /**
338
471
  * Get the singleton instance of OpenPayForm
339
- * @returns The OpenPayForm instance
340
472
  */
341
- static getInstance(): OpenPayForm | null;
342
- getConnectionManager(): ConnectionManager;
343
- setFormHeight(height: string): void;
344
- tryInitOjsFlows: () => void;
473
+ static getInstance: () => OpenPayForm | null;
474
+ get checkoutSecureToken(): string;
475
+ setFormHeight: (height: string) => void;
345
476
  onCdeLoaded: (payload: LoadedEventPayload) => void;
346
- onStripePRStatusChange: (initStatus: Loadable<InitStripePrFlowResult>) => void;
347
- createElement(elementValue: ElementTypeEnumValue, options?: ElementProps): {
348
- type: ElementTypeEnum;
349
- node: HTMLIFrameElement;
350
- mount: (selector: string) => HTMLIFrameElement | undefined;
351
- };
477
+ onCdeLoadError: (errMsg: string) => void;
478
+ createElement: (elementValue: ElementTypeEnumValue, options?: ElementProps) => RegisteredElement;
479
+ registerIframe: (type: ElementTypeEnum, frame: HTMLIFrameElement) => RegisteredElement;
352
480
  private buildQueryString;
353
481
  private connectToElement;
354
482
  private getFormDiv;
355
- private createOjsFlowContext;
356
- private createOjsFlowCallbacks;
357
- submit(): void;
358
- submitPaymentRequest: (provider: PaymentRequestProvider, initResult: InitStripePrFlowSuccess, params?: PaymentRequestStartParams) => Promise<void>;
359
- onPaymentRequestError(errMsg: string): void;
360
- destroy(): void;
483
+ /**
484
+ * Builds the OJS context object. Take note that this is a pure function.
485
+ */
486
+ private static buildOjsFlowContext;
487
+ /**
488
+ * Runs the common credit card flow
489
+ */
490
+ submitCard: () => void;
491
+ /**
492
+ * Alias for submitCard
493
+ */
494
+ submit: () => void;
495
+ destroy: () => void;
361
496
  }
362
497
 
363
- declare const PaymentRequestProvider: z.ZodEnum<["apple_pay", "google_pay"]>;
498
+ declare const PaymentRequestProvider = z.enum(['apple_pay', 'google_pay']);
364
499
 
365
500
  declare type PaymentRequestProvider = z.infer<typeof PaymentRequestProvider>;
366
501
 
@@ -377,8 +512,28 @@ declare type PaymentRequestStatus = {
377
512
  startFlow: (params?: PaymentRequestStartParams) => Promise<void>;
378
513
  };
379
514
 
515
+ declare type PRStatuses = Record<PaymentRequestProvider, PaymentRequestStatus>;
516
+
517
+ declare type RegisteredElement = {
518
+ type: ElementType;
519
+ node: HTMLIFrameElement;
520
+ mount: (selector: string) => void;
521
+ };
522
+
380
523
  declare type RunOjsFlow<T_PARAMS = undefined, T_INIT_RESULT = undefined> = (
381
524
  params: OjsFlowParams<T_PARAMS, T_INIT_RESULT>
382
525
  ) => Promise<void>;
383
526
 
527
+ declare type StripeLinkController = {
528
+ mountButton: () => void;
529
+ dismountButton: () => void;
530
+ waitForButtonToMount: () => Promise<HTMLElement>;
531
+ };
532
+
533
+ declare type SuccessStatus<T> = {
534
+ status: 'success';
535
+ isSuccess: true;
536
+ loadedValue: T;
537
+ };
538
+
384
539
  export { }