Skip to content

Commit c42c43a

Browse files
authored
Merge branch 'main' into renovate/react-monorepo
2 parents 3c2af9b + 9dc9923 commit c42c43a

File tree

12 files changed

+262
-323
lines changed

12 files changed

+262
-323
lines changed

.changeset/hip-carrots-reply.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@scaleway/use-analytics": patch
3+
---
4+
5+
Add normalize id on anonymousId, userId, groupId

packages/use-analytics/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@
4040
"build": "vite build --config vite.config.ts && pnpm run type:generate",
4141
"build:profile": "npx vite-bundle-visualizer -c vite.config.ts",
4242
"lint": "eslint --report-unused-disable-directives --cache --cache-strategy content --ext ts,tsx .",
43-
"lintpublish": "publint"
43+
"lintpublish": "publint",
44+
"test:unit": "vitest --run --config vite.config.ts",
45+
"test:unit:coverage": "pnpm test:unit --coverage"
4446
},
4547
"repository": {
4648
"type": "git",

packages/use-analytics/src/__tests__/AnalyticsProvider.test.tsx

Lines changed: 0 additions & 160 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// use-analytics/src/__tests__/normalizeId.test.ts
2+
import { normalizeId } from '../analytics/normalizeId'
3+
4+
describe('normalizeId', () => {
5+
it('should return undefined for null or undefined input', () => {
6+
expect(normalizeId(null)).toBeUndefined()
7+
expect(normalizeId(undefined)).toBeUndefined()
8+
})
9+
10+
it('should return the same string for non-JSON inputs', () => {
11+
expect(normalizeId('user123')).toBe('user123')
12+
expect(normalizeId('hello world!')).toBe('hello world!')
13+
})
14+
15+
it('should parse valid JSON strings to string', () => {
16+
expect(normalizeId('"user123"')).toBe('user123')
17+
expect(normalizeId('"12345"')).toBe('12345')
18+
expect(normalizeId('"\\"nested\\" string"')).toBe('"nested" string')
19+
})
20+
21+
it('should ignore JSON strings that decode to non-strings', () => {
22+
expect(normalizeId('{"id": "user123"}')).toBe('{"id": "user123"}')
23+
expect(normalizeId('[1, 2, 3]')).toBe('[1, 2, 3]')
24+
expect(normalizeId('123')).toBe('123')
25+
expect(normalizeId('true')).toBe('true')
26+
})
27+
28+
it('should convert numbers to strings', () => {
29+
expect(normalizeId(12345)).toBe('12345')
30+
expect(normalizeId(123e45)).toBe('1.23e+47') // Might vary based on the string conversion
31+
})
32+
33+
it('should handle string inputs with special characters', () => {
34+
expect(normalizeId('user!@#$%^&*()')).toBe('user!@#$%^&*()')
35+
expect(normalizeId('user"123"')).toBe('user"123"')
36+
})
37+
})

packages/use-analytics/src/analytics/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export type {
99
export { userMigrationsTraits } from './segments/userMigrationsTraits'
1010
export { defaultLoadOptions } from './constants'
1111
export { useDestinations } from './useDestinations'
12+
export { normalizeId } from './normalizeId'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
type ID = string | number | undefined | null
2+
3+
export const normalizeId = (id: ID) => {
4+
if (id === null || id === undefined) return undefined
5+
6+
// Already a string but possibly JSON-encoded
7+
if (typeof id === 'string') {
8+
try {
9+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
10+
const parsed = JSON.parse(id)
11+
// Only use parsed if it’s a string too
12+
13+
if (typeof parsed === 'string') {
14+
return parsed
15+
}
16+
} catch {
17+
// not JSON, keep original
18+
}
19+
20+
return id
21+
}
22+
23+
return String(id)
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { RudderAnalytics } from '@rudderstack/analytics-js'
2+
import { normalizeId } from './normalizeId'
3+
4+
export const normalizeIdsMigration = (rudderAnalytics: RudderAnalytics) => {
5+
// normalize id issue with segment migration
6+
const anonymousId = rudderAnalytics.getAnonymousId()
7+
const normalizeAnonymousId = normalizeId(anonymousId)
8+
if (normalizeAnonymousId !== anonymousId) {
9+
rudderAnalytics.setAnonymousId(normalizeAnonymousId)
10+
}
11+
12+
const userId = rudderAnalytics.getUserId()
13+
const normalizeUserId = userId ? normalizeId(userId) : null
14+
15+
if (userId !== normalizeUserId && normalizeUserId) {
16+
rudderAnalytics.identify(normalizeUserId)
17+
}
18+
19+
const groupId = rudderAnalytics.getGroupId()
20+
const normalizeGroupId = groupId ? normalizeId(groupId) : null
21+
22+
if (userId !== normalizeGroupId && normalizeGroupId) {
23+
rudderAnalytics.group(normalizeGroupId)
24+
}
25+
}

packages/use-analytics/src/analytics/segments/userMigrationsTraits.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { RudderAnalytics } from '@rudderstack/analytics-js'
2+
import { normalizeId } from '../normalizeId'
23

34
const SEGMENT_COOKIES_KEY = {
45
ANONYMOUS_ID: 'ajs_anonymous_id',
@@ -16,14 +17,20 @@ export const userMigrationsTraits = (rudderAnalytics: RudderAnalytics) => {
1617
const rudderGroupId = rudderAnalytics.getGroupId()
1718

1819
if (segmentAnonymousId) {
19-
rudderAnalytics.setAnonymousId(segmentAnonymousId)
20+
rudderAnalytics.setAnonymousId(normalizeId(segmentAnonymousId))
2021
}
2122

2223
if (segmentUserId && (!rudderUserId || rudderUserId !== segmentUserId)) {
23-
rudderAnalytics.identify(segmentUserId)
24+
const normalizedUserId = normalizeId(segmentUserId)
25+
if (normalizedUserId) {
26+
rudderAnalytics.identify(normalizedUserId)
27+
}
2428
}
2529

2630
if (segmentGroupId && (!rudderGroupId || rudderGroupId !== segmentGroupId)) {
27-
rudderAnalytics.group(segmentGroupId)
31+
const normalizedGroupId = normalizeId(segmentGroupId)
32+
if (normalizedGroupId) {
33+
rudderAnalytics.group(normalizedGroupId)
34+
}
2835
}
2936
}

packages/use-analytics/src/analytics/useAnalytics.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useDeepCompareEffectNoCheck } from 'use-deep-compare-effect'
66
import { destSDKBaseURL, pluginsSDKBaseURL } from '../constants'
77
import type { CategoryKind } from '../types'
88
import { defaultConsentOptions, defaultLoadOptions } from './constants'
9+
import { normalizeIdsMigration } from './normalizeIdsMigration'
910
import { userMigrationsTraits } from './segments/userMigrationsTraits'
1011

1112
type Analytics = RudderAnalytics
@@ -130,6 +131,7 @@ export function AnalyticsProvider<T extends Events>({
130131
pluginsSDKBaseURL: pluginsSDKBaseURL(settings.cdnURL),
131132
onLoaded: (rudderAnalytics: Analytics) => {
132133
userMigrationsTraits(rudderAnalytics)
134+
normalizeIdsMigration(rudderAnalytics)
133135

134136
rudderAnalytics.consent({
135137
...defaultConsentOptions,

0 commit comments

Comments
 (0)