@revolugo/common 7.13.0 → 7.13.1-alpha.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revolugo/common",
3
- "version": "7.13.0",
3
+ "version": "7.13.1-alpha.0",
4
4
  "private": false,
5
5
  "description": "Revolugo common",
6
6
  "author": "Revolugo",
@@ -50,11 +50,9 @@ export enum ElementsEvent {
50
50
  export interface ElementsEventCallbacks {
51
51
  [ElementsEvent.BookingCreated]: Booking
52
52
  [ElementsEvent.BookingFlowStepUpdated]: BookingState
53
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
- [ElementsEvent.BookingManagerNewBooking]: any
53
+ [ElementsEvent.BookingManagerNewBooking]: undefined
55
54
  [ElementsEvent.BookingManagerRetrieve]: Booking
56
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
- [ElementsEvent.BookingManagerRetrieveFail]: any
55
+ [ElementsEvent.BookingManagerRetrieveFail]: undefined
58
56
  [ElementsEvent.BookingPolicyCreated]: BookingPolicies
59
57
  [ElementsEvent.CancellationPoliciesUpdated]: CancellationPolicy[]
60
58
  [ElementsEvent.CurrencyUpdated]: CurrencyType
@@ -67,8 +65,7 @@ export interface ElementsEventCallbacks {
67
65
  [ElementsEvent.HotelOffersItemClick]: HotelOffer | [HotelOffer, number]
68
66
  [ElementsEvent.HotelOffersMarkerClick]: HotelOffer | [HotelOffer, number]
69
67
  [ElementsEvent.HotelOffersOpenInNewTabClick]: string
70
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
- [ElementsEvent.HotelOffersPollingStarted]: any
68
+ [ElementsEvent.HotelOffersPollingStarted]: undefined
72
69
  [ElementsEvent.HotelOffersRetrieved]: HotelOffer[]
73
70
  [ElementsEvent.HotelRetrieved]: Hotel
74
71
  [ElementsEvent.HotelRoomOfferItemVisible]: [HotelRoomOffer, number]
@@ -1,5 +1,6 @@
1
1
  import type { CancellationPolicy } from './cancellation-policy.ts'
2
2
  import type { CurrencyType } from './currency.ts'
3
+ import type { Event } from './event.ts'
3
4
  import type { HotelRoomOfferPackageType } from './hotel-room-offer-package-type.ts'
4
5
  import type { HotelRoomOfferType } from './hotel-room-offer-type.ts'
5
6
  import type { HotelRoom } from './hotel-room.ts'
@@ -219,11 +220,10 @@ export interface HotelRoomOffersResponse {
219
220
  data: HotelRoomOffersDataResponse
220
221
  /**
221
222
  *
222
- * @type {any}
223
+ * @type {Event}
223
224
  * @memberof HotelRoomOffersApiResponse
224
225
  */
225
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
226
- event?: any | null
226
+ event?: Event | null
227
227
  /**
228
228
  *
229
229
  * @type {MetaApiPollingResponse}
@@ -53,34 +53,37 @@ function matches(patterns: (RegExp | string)[], value: string) {
53
53
  )
54
54
  }
55
55
 
56
- function isObject(o: unknown): boolean {
57
- return o === Object(o) && !Array.isArray(o) && typeof o !== 'function'
56
+ type PlainObject = Record<string, unknown>
57
+
58
+ function isPlainObject(value: unknown): value is PlainObject {
59
+ return (
60
+ value === Object(value) &&
61
+ !Array.isArray(value) &&
62
+ typeof value !== 'function'
63
+ )
58
64
  }
59
65
 
60
- /* eslint-disable @typescript-eslint/no-explicit-any */
61
- export function keysChangeCase<T = any>(
62
- obj: any[],
66
+ /** Infer `T` from input, or set `T` explicitly when output type differs (e.g. fixture → domain). */
67
+ export function keysChangeCase<T extends object | readonly unknown[]>(
68
+ obj: T | object | readonly unknown[],
63
69
  toCase: CaseTransformer,
64
-
65
70
  options?: { deep?: boolean; exclude?: (RegExp | string)[] },
66
- ): T[]
71
+ ): T
67
72
 
68
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
69
- export function keysChangeCase<T = any>(
73
+ /** Unknown input — `Record<string, unknown>` / `unknown[]` instead of `unknown`. */
74
+ export function keysChangeCase(
70
75
  obj: unknown,
71
76
  toCase: CaseTransformer,
72
77
  options?: { deep?: boolean; exclude?: (RegExp | string)[] },
73
- ): T
78
+ ): PlainObject | unknown[]
74
79
 
75
- export function keysChangeCase<T>(
76
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
77
- obj: any,
80
+ export function keysChangeCase(
81
+ obj: unknown,
78
82
  toCase: CaseTransformer,
79
-
80
83
  options: { deep?: boolean; exclude?: (RegExp | string)[] } = { deep: true },
81
- ): unknown {
82
- if (isObject(obj) && !(obj instanceof Date)) {
83
- return Object.keys(obj).reduce<any>((result, key) => {
84
+ ): PlainObject | unknown[] | unknown {
85
+ if (isPlainObject(obj) && !(obj instanceof Date)) {
86
+ return Object.keys(obj).reduce<PlainObject>((result, key) => {
84
87
  // Check if key should be excluded from the transformation
85
88
  const transformedKey =
86
89
  options?.exclude && matches(options.exclude, key)
@@ -94,12 +97,11 @@ export function keysChangeCase<T>(
94
97
  return result
95
98
  }, {})
96
99
  } else if (Array.isArray(obj)) {
97
- return obj.map(item => keysChangeCase(item, toCase, options)) as T[]
100
+ return obj.map(item => keysChangeCase(item, toCase, options))
98
101
  }
99
102
 
100
103
  return obj
101
104
  }
102
- /* eslint-enable @typescript-eslint/no-explicit-any */
103
105
 
104
106
  export function capitalize(value: string): string {
105
107
  return value.replace(/^\w/u, c => c.toUpperCase())
@@ -1,18 +1,11 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
1
  interface Options<Result> {
3
2
  isImmediate?: boolean
4
3
  maxWait?: number
5
4
  callback?: (data: Result) => void
6
5
  }
7
6
 
8
- export interface DebouncedFunction<
9
- Args extends any[],
10
- F extends (...args: Args) => any,
11
- > {
12
- (
13
- this: ThisParameterType<F>,
14
- ...args: Args & Parameters<F>
15
- ): Promise<Awaited<ReturnType<F>>>
7
+ export interface DebouncedFunction<Args extends unknown[], Return> {
8
+ (...args: Args): Promise<Awaited<Return>>
16
9
  cancel: (reason?: unknown) => void
17
10
  }
18
11
 
@@ -21,18 +14,18 @@ interface DebouncedPromise<FunctionReturn> {
21
14
  resolve: (result: FunctionReturn) => void
22
15
  }
23
16
 
24
- export function debounce<Args extends any[], F extends (...args: Args) => any>(
25
- func: F,
17
+ export function debounce<Args extends unknown[], Return>(
18
+ func: (...args: Args) => Return,
26
19
  waitMilliseconds = 50,
27
- options: Options<Awaited<ReturnType<F>>> = {},
28
- ): DebouncedFunction<Args, F> {
20
+ options: Options<Awaited<Return>> = {},
21
+ ): DebouncedFunction<Args, Return> {
29
22
  let timeoutId: ReturnType<typeof setTimeout> | undefined = undefined
30
23
  const isImmediate = options.isImmediate ?? false
31
24
  const callback = options.callback ?? false
32
25
  const { maxWait } = options
33
26
  let lastInvokeTime = Date.now()
34
27
 
35
- let promises: DebouncedPromise<ReturnType<F>>[] = []
28
+ let promises: DebouncedPromise<Awaited<Return>>[] = []
36
29
 
37
30
  function nextInvokeTimeout() {
38
31
  if (maxWait !== undefined) {
@@ -46,22 +39,19 @@ export function debounce<Args extends any[], F extends (...args: Args) => any>(
46
39
  return waitMilliseconds
47
40
  }
48
41
 
49
- function debouncedFunction(
50
- this: ThisParameterType<F>,
51
- ...args: Parameters<F>
52
- ) {
53
- // eslint-disable-next-line consistent-this, @typescript-eslint/no-this-alias
54
- const context = this
42
+ function debouncedFunction(...args: Args) {
55
43
  // eslint-disable-next-line consistent-return
56
- return new Promise<Awaited<ReturnType<F>>>((resolve, reject) => {
44
+ return new Promise<Awaited<Return>>((resolve, reject) => {
57
45
  function invokeFunction() {
58
46
  timeoutId = undefined
59
47
  lastInvokeTime = Date.now()
60
48
  if (!isImmediate) {
61
- const result = func.apply(context, args)
49
+ const result = func(...args)
62
50
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
63
- callback && callback(result)
64
- promises.forEach(({ resolve: resolveLoop }) => resolveLoop(result))
51
+ callback && callback(result as Awaited<Return>)
52
+ promises.forEach(({ resolve: resolveLoop }) =>
53
+ resolveLoop(result as Awaited<Return>),
54
+ )
65
55
  promises = []
66
56
  }
67
57
  }
@@ -75,11 +65,11 @@ export function debounce<Args extends any[], F extends (...args: Args) => any>(
75
65
  timeoutId = setTimeout(invokeFunction, nextInvokeTimeout())
76
66
 
77
67
  if (shouldCallNow) {
78
- const result = func.apply(context, args)
68
+ const result = func(...args)
79
69
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
80
- callback && callback(result)
70
+ callback && callback(result as Awaited<Return>)
81
71
  // eslint-disable-next-line no-promise-executor-return
82
- return resolve(result)
72
+ return resolve(result as Awaited<Return>)
83
73
  }
84
74
  promises.push({ reject, resolve })
85
75
  })
@@ -95,4 +85,3 @@ export function debounce<Args extends any[], F extends (...args: Args) => any>(
95
85
 
96
86
  return debouncedFunction
97
87
  }
98
- /* eslint-enable @typescript-eslint/no-explicit-any */
@@ -11,26 +11,22 @@
11
11
  * - Avoids infinite recursion for circular source structures.
12
12
  */
13
13
 
14
- /* eslint-disable @typescript-eslint/no-explicit-any */
15
- type AnyObject = Record<string, any>
14
+ type PlainObject = Record<string, unknown>
16
15
 
17
- function isObject(value: any): value is AnyObject {
16
+ function isObject(value: unknown): value is PlainObject {
18
17
  return value !== null && typeof value === 'object'
19
18
  }
20
19
 
21
- export function defaultsDeep<T>(
22
- object: T,
23
- ...sources: any[]
24
- ): T extends AnyObject ? T : any {
20
+ export function defaultsDeep<T>(object: T, ...sources: unknown[]): T {
25
21
  // Ensure we always return an object reference we can mutate (lodash creates/uses {} when target is falsy)
26
- const target: AnyObject = (
22
+ const target: PlainObject = (
27
23
  object === null || object === undefined ? {} : object
28
- ) as AnyObject
24
+ ) as PlainObject
29
25
 
30
26
  // WeakMap to track already-cloned source objects so circular refs won't blow the stack
31
27
  const seen = new WeakMap<object, object>()
32
28
 
33
- function applyDefaults(dst: AnyObject, src: any) {
29
+ function applyDefaults(dst: PlainObject, src: PlainObject) {
34
30
  // Only iterate string-keyed enumerable properties (own + inherited) => for...in
35
31
  for (const key in src) {
36
32
  if (Object.hasOwn(src, key)) {
@@ -49,12 +45,12 @@ export function defaultsDeep<T>(
49
45
  // Prepare new container (array vs object)
50
46
  const created = Array.isArray(srcVal)
51
47
  ? ([] as unknown[])
52
- : ({} as AnyObject)
48
+ : ({} as PlainObject)
53
49
  // remember mapping to handle circular refs
54
50
  seen.set(srcVal, created)
55
51
 
56
52
  // Recursively fill created from srcVal
57
- applyDefaults(created, srcVal)
53
+ applyDefaults(created as PlainObject, srcVal)
58
54
 
59
55
  // assign the created clone as the default
60
56
  dst[key] = created
@@ -75,11 +71,11 @@ export function defaultsDeep<T>(
75
71
  }
76
72
 
77
73
  for (const src of sources) {
78
- if (src !== null && src !== undefined) {
74
+ if (isObject(src)) {
79
75
  // If source itself has been seen (unlikely across top-level sources), we still traverse it
80
76
  applyDefaults(target, src)
81
77
  }
82
78
  }
83
79
 
84
- return target as any
80
+ return target as T
85
81
  }
package/src/utils/omit.ts CHANGED
@@ -10,8 +10,8 @@ export function omit<T extends object, K extends keyof T>(
10
10
  // eslint-disable-next-line no-restricted-syntax
11
11
  ): Omit<T, K> {
12
12
  if (object === null || object === undefined) {
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- return {} as any
13
+ // eslint-disable-next-line no-restricted-syntax
14
+ return {} as Omit<T, K>
15
15
  }
16
16
 
17
17
  const keysArray = (
@@ -24,16 +24,15 @@ export function omit<T extends object, K extends keyof T>(
24
24
  // Copy string/number keys
25
25
  for (const key in object) {
26
26
  if (Object.hasOwn(object, key) && !keysSet.has(key as keyof T)) {
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- ;(result as any)[key] = object[key as keyof T]
27
+ result[key as keyof T] = object[key as keyof T]
29
28
  }
30
29
  }
31
30
 
32
31
  // Copy symbol keys
32
+ const record = object as T & Record<PropertyKey, T[keyof T]>
33
33
  for (const sym of Object.getOwnPropertySymbols(object)) {
34
34
  if (!keysSet.has(sym as keyof T)) {
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- ;(result as any)[sym as unknown as keyof T] = (object as any)[sym]
35
+ result[sym as keyof T] = record[sym]
37
36
  }
38
37
  }
39
38
 
@@ -2,8 +2,7 @@ import { v4 as uuidv4 } from 'uuid'
2
2
 
3
3
  import { CaseTransformer, keysChangeCase } from './case-transformers.ts'
4
4
 
5
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
- export interface IPollerResponse<T = any> {
5
+ export interface IPollerResponse<T = unknown> {
7
6
  data?: T
8
7
  meta?: {
9
8
  status: 'COMPLETE' | 'IN_PROGRESS'
@@ -23,6 +22,20 @@ export type TPollerEvents<V extends IPollerResponse = IPollerResponse> = {
23
22
 
24
23
  const INTERVAL = 1500
25
24
 
25
+ function omitUndefined<T extends object>(obj: T): Partial<T> {
26
+ const out: Partial<T> = {}
27
+
28
+ for (const key of Object.keys(obj) as (keyof T)[]) {
29
+ const value = obj[key]
30
+
31
+ if (value !== undefined) {
32
+ out[key] = value
33
+ }
34
+ }
35
+
36
+ return out
37
+ }
38
+
26
39
  export interface IPollerOptions<U> {
27
40
  callCount?: number
28
41
  interval?: number
@@ -76,7 +89,10 @@ export class Poller<V extends IPollerResponse> {
76
89
  request()
77
90
  .then(result => this.onRequest(result, request, buildedOptions))
78
91
  .catch((error: unknown) => {
79
- this.dispatch('error', error as TPollerEventCallbackArg<V>)
92
+ const payload =
93
+ error instanceof Error ? error : new Error(String(error))
94
+
95
+ this.dispatch('error', payload)
80
96
  })
81
97
  }
82
98
 
@@ -91,21 +107,9 @@ export class Poller<V extends IPollerResponse> {
91
107
  }
92
108
 
93
109
  private buildPollerOptions(options: TOptions<V>): TOptions<V> {
94
- const compactedOptions = Object.entries(options).reduce<
95
- Record<string, unknown>
96
- >((acc, [key, value]) => {
97
- if (value !== undefined) {
98
- const tKey = key as keyof TOptions<V>
99
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
- acc[tKey] = value as any
101
- }
102
-
103
- return acc
104
- }, {}) as TOptions<V>
105
-
106
110
  return {
107
111
  ...this.defaultOptions,
108
- ...compactedOptions,
112
+ ...omitUndefined(options),
109
113
  }
110
114
  }
111
115
 
@@ -142,7 +146,7 @@ export class Poller<V extends IPollerResponse> {
142
146
  request: TRequest<V>,
143
147
  options: TOptions<V>,
144
148
  ): Promise<void> {
145
- const resultFormatted = keysChangeCase(result ?? {}, CaseTransformer.Camel)
149
+ const resultFormatted = keysChangeCase<V>(result, CaseTransformer.Camel)
146
150
 
147
151
  if (!this.isActivePoller(options)) {
148
152
  return
@@ -161,8 +165,10 @@ export class Poller<V extends IPollerResponse> {
161
165
  ) {
162
166
  // If not in progress but still need to meet minimum call count, set status to in progress
163
167
  if (!this.isInProgress(resultFormatted)) {
164
- resultFormatted.meta = resultFormatted.meta || {}
165
- resultFormatted.meta.status = 'IN_PROGRESS'
168
+ resultFormatted.meta = {
169
+ ...resultFormatted.meta,
170
+ status: 'IN_PROGRESS',
171
+ }
166
172
  }
167
173
 
168
174
  // Increment call count and dispatch data
@@ -180,8 +186,10 @@ export class Poller<V extends IPollerResponse> {
180
186
  // Handle the case when polling should complete
181
187
  } else if (this.isInProgress(resultFormatted)) {
182
188
  // Mark as complete if it was in progress
183
- resultFormatted.meta = resultFormatted.meta || {}
184
- resultFormatted.meta.status = 'COMPLETE'
189
+ resultFormatted.meta = {
190
+ ...resultFormatted.meta,
191
+ status: 'COMPLETE',
192
+ }
185
193
  this.onComplete(resultFormatted, options)
186
194
  // Handle the case when already complete
187
195
  } else {
@@ -221,8 +229,8 @@ export type TPollerCallback<T extends IPollerResponse = IPollerResponse> = (
221
229
  export function pollRequest<R extends IPollerResponse>(
222
230
  request: TRequest<R>,
223
231
  options: TOptions<R>,
224
- pollerCallback: TPollerCallback,
225
- ): Promise<PollerReturn>
232
+ pollerCallback: TPollerCallback<R>,
233
+ ): Promise<PollerReturn<R>>
226
234
 
227
235
  export function pollRequest<R extends IPollerResponse>(
228
236
  request: TRequest<R>,
@@ -4,21 +4,24 @@
4
4
  * by custom evaluation.
5
5
  */
6
6
  // eslint-disable-next-line no-restricted-syntax
7
- export function shake<RemovedKeys extends string, T>(
7
+ export function shake<RemovedKeys extends string, T extends object>(
8
8
  obj: T,
9
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
- filter: (value: any) => boolean = x => x === undefined,
9
+ filter: (value: unknown) => boolean = x => x === undefined,
11
10
  // eslint-disable-next-line no-restricted-syntax
12
11
  ): Omit<T, RemovedKeys> {
13
12
  if (!obj) {
14
- return {} as T
13
+ // eslint-disable-next-line no-restricted-syntax
14
+ return {} as Omit<T, RemovedKeys>
15
15
  }
16
- const keys = Object.keys(obj) as (keyof T)[]
17
- return keys.reduce((acc, key) => {
18
- if (filter(obj[key])) {
19
- return acc
16
+
17
+ const result: Partial<T> = {}
18
+
19
+ for (const key of Object.keys(obj) as (keyof T)[]) {
20
+ if (!filter(obj[key])) {
21
+ result[key] = obj[key]
20
22
  }
21
- acc[key] = obj[key]
22
- return acc
23
- }, {} as T)
23
+ }
24
+
25
+ // eslint-disable-next-line no-restricted-syntax
26
+ return result as Omit<T, RemovedKeys>
24
27
  }