Skip to content

Commit 61a81dd

Browse files
committed
add rudder-compat
1 parent 75f6ac5 commit 61a81dd

File tree

6 files changed

+292
-17
lines changed

6 files changed

+292
-17
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,5 @@ For now, it reads Segment cookies and uses if they exist. Also checks RudderStac
4949
- [ ] Store traits to localstorage?
5050
- [ ] Explore adding queue to localstorage (for durability)
5151
- [ ] Probably should prepend cookies with something
52-
- [ ] Need to decrypt and decode both RS cookies (don't want to include in core library)
52+
- [ ] Need to decrypt and decode both RS cookies (don't want to include in core library)
53+
- [ ] Actually manage sendEvent failures

package-lock.json

Lines changed: 131 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,20 @@
55
"scripts": {
66
"build": "rollup -c --bundleConfigAsCjs",
77
"watch": "rollup -c -w",
8-
"deploy": "aws s3 cp build/tt.js s3://tiny-tag/tt.js --content-encoding gzip",
9-
"release": "npm run build && gzip -9 build/tt.js && mv build/tt.js.gz build/tt.js && npm run deploy",
8+
"deploy": "aws s3 cp build/tt.js s3://tiny-tag/tinytag/tt.js --content-encoding gzip && aws s3 cp build/tt-rudder-compat.js s3://tiny-tag/tinytag/tt-rudder-compat.js --content-encoding gzip",
9+
"release": "npm run build && gzip -9 build/tt.js && mv build/tt.js.gz build/tt.js && gzip -9 build/tt-rudder-compat.js && mv build/tt-rudder-compat.js.gz build/tt-rudder-compat.js && npm run deploy",
1010
"test": "jest",
1111
"test:coverage": "jest --coverage"
1212
},
1313
"devDependencies": {
1414
"@babel/core": "^7.26.9",
1515
"@babel/preset-env": "^7.26.9",
16+
"@rollup/plugin-commonjs": "^28.0.2",
1617
"@rollup/plugin-json": "^6.1.0",
18+
"@rollup/plugin-node-resolve": "^16.0.0",
1719
"@rollup/plugin-terser": "^0.4.4",
1820
"babel-jest": "^29.7.0",
21+
"crypto-js": "^4.2.0",
1922
"jest": "^29.7.0",
2023
"jest-environment-jsdom": "^29.7.0",
2124
"rollup": "^3.0.0"

rollup.config.js

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
import terser from '@rollup/plugin-terser';
22
import json from '@rollup/plugin-json';
3+
import { nodeResolve } from '@rollup/plugin-node-resolve'; // Resolve node_modules
4+
import commonjs from '@rollup/plugin-commonjs'; // Handle UMD/CommonJS
35

4-
export default {
5-
input: 'src/index.js',
6-
output: {
7-
file: 'build/tt.js',
8-
format: 'iife',
9-
name: 'TinyTag', // Changed to avoid overriding window.tt
10-
sourcemap: false
11-
},
12-
plugins: [
13-
json(),
14-
terser({
6+
export default [
7+
{
8+
input: 'src/index.js',
9+
output: {
10+
file: 'build/tt.js',
11+
format: 'iife',
12+
name: 'TinyTag', // Changed to avoid overriding window.tt
13+
sourcemap: false
14+
},
15+
plugins: [
16+
json(),
17+
terser({
1518
compress: {
1619
drop_console: true,
1720
pure_funcs: ['console.log'],
@@ -24,6 +27,27 @@ export default {
2427
},
2528
mangle: { toplevel: true },
2629
output: { comments: false }
27-
})
28-
]
29-
};
30+
})
31+
]
32+
},
33+
{
34+
input: 'src/rudder-compat.js',
35+
output: {
36+
file: 'build/tt-rudder-compat.js',
37+
format: 'iife',
38+
name: 'TinyTagRudderCompat',
39+
sourcemap: false
40+
},
41+
plugins: [
42+
nodeResolve({
43+
browser: true // Resolve for browser environment
44+
}),
45+
commonjs(),
46+
terser({
47+
compress: { drop_console: true, pure_funcs: ['console.log'], passes: 3 },
48+
mangle: { toplevel: true },
49+
output: { comments: false }
50+
})
51+
]
52+
}
53+
];

src/rudder-compat.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// import CryptoJS from 'crypto-js'; // For v1 decryption
2+
import { AES } from 'crypto-js';
3+
import { getCookie } from './cookie.js'; // Reuse TinyTag's getCookie
4+
5+
// RudderStack v1 decryption key (placeholder, needs actual key)
6+
const V1_ENCRYPTION_KEY = 'Rudder'; // Replace with real key from RudderStack
7+
8+
// Decode v3 encoded cookie (base64 JSON)
9+
function decodeV3Cookie(value) {
10+
if (value && value.startsWith('RS_ENC_v3_')) {
11+
const encoded = value.replace('RS_ENC_v3_', '');
12+
try {
13+
return JSON.parse(atob(encoded));
14+
} catch (e) {
15+
return null; // Invalid encoding
16+
}
17+
}
18+
return value; // Not v3, return as-is
19+
}
20+
21+
// Decrypt v1 encrypted cookie
22+
function decryptV1Cookie(value) {
23+
if (value && !value.startsWith('RS_ENC_v3_')) {
24+
try {
25+
const bytes = AES.decrypt(value, V1_ENCRYPTION_KEY);
26+
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
27+
return decrypted || value; // Return original if decryption fails or is empty
28+
} catch (e) {
29+
return 'whoa'; // Return original on exception
30+
}
31+
}
32+
return value; // Not v3 or encrypted, return as-is
33+
}
34+
35+
// Enhance window.tt methods with RudderStack compatibility
36+
const originalGetUserId = window.tt.getUserId;
37+
window.tt.getUserId = function () {
38+
const value = getCookie('rl_user_id');
39+
return decodeV3Cookie(decryptV1Cookie(value)) || originalGetUserId();
40+
};
41+
42+
const originalGetAnonymousId = window.tt.getAnonymousId;
43+
window.tt.getAnonymousId = function () {
44+
const value = getCookie('rl_anonymous_id');
45+
return decodeV3Cookie(decryptV1Cookie(value)) || originalGetAnonymousId();
46+
};
47+
48+
const originalGetTraits = window.tt.getTraits;
49+
window.tt.getTraits = function () {
50+
const value = getCookie('rl_trait');
51+
const decoded = decodeV3Cookie(decryptV1Cookie(value));
52+
return decoded ? JSON.parse(decoded) : originalGetTraits();
53+
};
54+
55+
// Export for testing (optional, not used in IIFE)
56+
export { decodeV3Cookie, decryptV1Cookie };

0 commit comments

Comments
 (0)