@revolugo/common 7.4.2-alpha.2 → 7.4.2-alpha.21

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.4.2-alpha.2",
3
+ "version": "7.4.2-alpha.21",
4
4
  "private": false,
5
5
  "description": "Revolugo common",
6
6
  "author": "Revolugo",
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable camelcase */
2
- import z from 'zod'
2
+ import { z } from 'zod'
3
3
 
4
4
  import { PayLaterStatusEnum } from '../types/booking.ts'
5
5
  import { BookingStatusEnum } from '../types/index.ts'
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable camelcase */
2
- import z from 'zod'
2
+ import { z } from 'zod'
3
3
 
4
4
  import { CountryIso2Code } from '../countries/constants.ts'
5
5
  import { ContactPersonSalutationEnum } from '../types/index.ts'
@@ -1,4 +1,4 @@
1
- import z from 'zod'
1
+ import { z } from 'zod'
2
2
 
3
3
  export const EVENT_SCHEMA = z
4
4
  .object({
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable camelcase */
2
- import z from 'zod'
2
+ import { z } from 'zod'
3
3
 
4
4
  import { HOTEL_ROOM_SCHEMA } from './hotel-room.ts'
5
5
 
@@ -1,4 +1,4 @@
1
- import z from 'zod'
1
+ import { z } from 'zod'
2
2
 
3
3
  import { InvoiceApiTypeEnum } from '../types/index.ts'
4
4
 
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable camelcase */
2
- import z from 'zod'
2
+ import { z } from 'zod'
3
3
 
4
4
  import {
5
5
  BookingStatusEnum,
@@ -166,5 +166,4 @@ export interface HotelOfferRequestCreate {
166
166
  latitude?: HotelOfferRequest['latitude']
167
167
  longitude?: HotelOfferRequest['longitude']
168
168
  roomCount: HotelOfferRequest['roomCount']
169
- sourceMarket: HotelOfferRequest['sourceMarket']
170
169
  }
@@ -135,7 +135,6 @@ export interface HotelRoomOfferRequestCreate {
135
135
  eventMetadata?: HotelRoomOfferRequest['eventMetadata']
136
136
  hotelId: HotelRoomOfferRequest['hotelId']
137
137
  roomCount: HotelRoomOfferRequest['roomCount']
138
- sourceMarket: HotelRoomOfferRequest['sourceMarket']
139
138
  }
140
139
  export interface HotelRoomOfferRequestsCreatePayload {
141
140
  hotelRoomOfferRequestCreateApi?: HotelRoomOfferRequestCreate
@@ -13,12 +13,12 @@ import timezone from 'dayjs/plugin/timezone.js'
13
13
  import utc from 'dayjs/plugin/utc.js'
14
14
  /* eslint-enable no-restricted-imports, no-restricted-syntax */
15
15
 
16
- /* eslint-disable no-restricted-syntax, import/no-unassigned-import */
16
+ /* eslint-disable no-restricted-syntax, import-x/no-unassigned-import */
17
17
  import 'dayjs/locale/fr.js'
18
18
  import 'dayjs/locale/en.js'
19
- /* eslint-enable no-restricted-syntax, import/no-unassigned-import */
19
+ /* eslint-enable no-restricted-syntax, import-x/no-unassigned-import */
20
20
 
21
- /* eslint-disable import/no-named-as-default-member */
21
+ /* eslint-disable import-x/no-named-as-default-member */
22
22
  dayjs.extend(advancedFormat)
23
23
  dayjs.extend(customParseFormat)
24
24
  dayjs.extend(isBetween)
@@ -30,7 +30,7 @@ dayjs.extend(minMax)
30
30
  dayjs.extend(relativeTime)
31
31
  dayjs.extend(timezone)
32
32
  dayjs.extend(utc)
33
- /* eslint-enable import/no-named-as-default-member */
33
+ /* eslint-enable import-x/no-named-as-default-member */
34
34
 
35
35
  export { dayjs }
36
36
 
@@ -0,0 +1,62 @@
1
+ import { describe, expect, test } from 'vitest'
2
+
3
+ import { getUserIpAddress } from './get-user-ip-address.ts'
4
+
5
+ describe('getUserIpAddress', () => {
6
+ test('UT-1a: extracts first IP from x-forwarded-for (comma-separated)', () => {
7
+ const headers = new Headers({
8
+ 'x-forwarded-for': '203.0.113.1, 70.41.3.18, 150.172.238.178',
9
+ })
10
+ expect(getUserIpAddress(headers)).toBe('203.0.113.1')
11
+ })
12
+
13
+ test('UT-1a: extracts single IP from x-forwarded-for', () => {
14
+ const headers = new Headers({ 'x-forwarded-for': '203.0.113.1' })
15
+ expect(getUserIpAddress(headers)).toBe('203.0.113.1')
16
+ })
17
+
18
+ test('UT-1b: extracts IP from cf-connecting-ip', () => {
19
+ const headers = new Headers({ 'cf-connecting-ip': '198.51.100.1' })
20
+ expect(getUserIpAddress(headers)).toBe('198.51.100.1')
21
+ })
22
+
23
+ test('UT-1c: extracts IP from x-real-ip', () => {
24
+ const headers = new Headers({ 'x-real-ip': '198.51.100.2' })
25
+ expect(getUserIpAddress(headers)).toBe('198.51.100.2')
26
+ })
27
+
28
+ test('UT-1c: extracts IP from true-client-ip', () => {
29
+ const headers = new Headers({ 'true-client-ip': '198.51.100.3' })
30
+ expect(getUserIpAddress(headers)).toBe('198.51.100.3')
31
+ })
32
+
33
+ test('UT-1c: extracts IP from x-client-ip', () => {
34
+ const headers = new Headers({ 'x-client-ip': '198.51.100.4' })
35
+ expect(getUserIpAddress(headers)).toBe('198.51.100.4')
36
+ })
37
+
38
+ test('UT-1a: x-forwarded-for takes priority over other headers', () => {
39
+ const headers = new Headers({
40
+ 'cf-connecting-ip': '198.51.100.1',
41
+ 'x-forwarded-for': '203.0.113.1',
42
+ })
43
+ expect(getUserIpAddress(headers)).toBe('203.0.113.1')
44
+ })
45
+
46
+ test('UT-1d: returns null when no IP headers present', () => {
47
+ const headers = new Headers({ 'content-type': 'application/json' })
48
+ expect(getUserIpAddress(headers)).toBeNull()
49
+ })
50
+
51
+ test('UT-1e: extracts IP from Forwarded header (RFC 7239)', () => {
52
+ const headers = new Headers({
53
+ forwarded: 'for=192.0.2.60;proto=http;by=203.0.113.43',
54
+ })
55
+ expect(getUserIpAddress(headers)).toBe('192.0.2.60')
56
+ })
57
+
58
+ test('UT-1e: extracts quoted IP from Forwarded header', () => {
59
+ const headers = new Headers({ forwarded: 'for="192.0.2.60"' })
60
+ expect(getUserIpAddress(headers)).toBe('192.0.2.60')
61
+ })
62
+ })
@@ -0,0 +1,28 @@
1
+ const IP_HEADERS = [
2
+ 'x-forwarded-for',
3
+ 'cf-connecting-ip',
4
+ 'x-real-ip',
5
+ 'true-client-ip',
6
+ 'x-client-ip',
7
+ ] as const
8
+
9
+ export function getUserIpAddress(headers: Headers): string | null {
10
+ for (const header of IP_HEADERS) {
11
+ const value = headers.get(header)
12
+ if (value) {
13
+ return header === 'x-forwarded-for'
14
+ ? (value.split(',')[0]?.trim() ?? null)
15
+ : value
16
+ }
17
+ }
18
+
19
+ const forwarded = headers.get('forwarded')
20
+ if (forwarded) {
21
+ const match = /for=["']?([^;"',\s]+)/u.exec(forwarded)
22
+ if (match?.[1]) {
23
+ return match[1]
24
+ }
25
+ }
26
+
27
+ return null
28
+ }
@@ -26,6 +26,7 @@ export * from './get-random-element-from-array.ts'
26
26
  export * from './get-random-hex-color.ts'
27
27
  export * from './get-random-int.ts'
28
28
  export * from './get-sanitized-room-count.ts'
29
+ export * from './get-user-ip-address.ts'
29
30
  export * from './group-by.ts'
30
31
  export * from './images.ts'
31
32
  export * from './is-empty.ts'