Skip to content

Commit 07cb66b

Browse files
committed
feat: databuddy node SDK
1 parent 43f13ab commit 07cb66b

File tree

18 files changed

+1678
-10
lines changed

18 files changed

+1678
-10
lines changed

.github/workflows/test.yml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [main, staging]
6+
pull_request:
7+
branches: [main, staging]
8+
9+
jobs:
10+
test:
11+
name: Run Tests
12+
runs-on: ubuntu-latest
13+
14+
services:
15+
postgres:
16+
image: postgres:16
17+
env:
18+
POSTGRES_USER: postgres
19+
POSTGRES_PASSWORD: postgres
20+
POSTGRES_DB: databuddy_test
21+
ports:
22+
- 5432:5432
23+
options: >-
24+
--health-cmd pg_isready
25+
--health-interval 10s
26+
--health-timeout 5s
27+
--health-retries 5
28+
29+
redis:
30+
image: redis:7-alpine
31+
ports:
32+
- 6379:6379
33+
options: >-
34+
--health-cmd "redis-cli ping"
35+
--health-interval 10s
36+
--health-timeout 5s
37+
--health-retries 5
38+
39+
clickhouse:
40+
image: clickhouse/clickhouse-server:latest
41+
ports:
42+
- 8123:8123
43+
- 9000:9000
44+
env:
45+
CLICKHOUSE_DB: databuddy_test
46+
options: >-
47+
--health-cmd "clickhouse-client --query 'SELECT 1'"
48+
--health-interval 10s
49+
--health-timeout 5s
50+
--health-retries 5
51+
52+
steps:
53+
- name: Checkout repository
54+
uses: actions/checkout@v4
55+
56+
- name: Setup Bun
57+
uses: oven-sh/setup-bun@v2
58+
with:
59+
bun-version: latest
60+
61+
- name: Install dependencies
62+
run: bun install --frozen-lockfile
63+
64+
- name: Run tests
65+
env:
66+
# Database URLs
67+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/databuddy_test
68+
POSTGRES_URL: postgresql://postgres:postgres@localhost:5432/databuddy_test
69+
70+
# Redis URL
71+
REDIS_URL: redis://localhost:6379
72+
REDIS_HOST: localhost
73+
REDIS_PORT: 6379
74+
75+
# ClickHouse URLs
76+
CLICKHOUSE_URL: http://localhost:8123
77+
CLICKHOUSE_HOST: localhost
78+
CLICKHOUSE_PORT: 8123
79+
CLICKHOUSE_DATABASE: databuddy_test
80+
81+
# Test environment
82+
NODE_ENV: test
83+
84+
# Auth secrets (use dummy values for tests)
85+
AUTH_SECRET: test-auth-secret-for-ci-testing-only
86+
NEXTAUTH_SECRET: test-auth-secret-for-ci-testing-only
87+
88+
# API keys (use dummy values for tests)
89+
EMAIL_API_KEY: test-email-api-key
90+
IP_HASH_SALT: test-ip-hash-salt
91+
92+
run: bun test
93+
94+
- name: Upload coverage reports
95+
if: always()
96+
uses: codecov/codecov-action@v4
97+
with:
98+
files: ./coverage/coverage-final.json
99+
fail_ci_if_error: false
100+
token: ${{ secrets.CODECOV_TOKEN }}
101+

apps/api/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@databuddy/redis": "workspace:*",
2121
"@databuddy/rpc": "workspace:*",
2222
"@databuddy/shared": "workspace:*",
23+
"@databuddy/sdk": "workspace:*",
2324
"@elysiajs/cors": "^1.3.3",
2425
"@elysiajs/trpc": "^1.1.0",
2526
"@logtail/edge": "^0.5.5",

apps/api/src/lib/databuddy.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Databuddy } from '@databuddy/sdk/node';
2+
3+
const databuddy = new Databuddy({
4+
clientId: '3ed1fce1-5a56-4cb6-a977-66864f6d18e3',
5+
});
6+
7+
export { databuddy };

apps/api/src/routes/query.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
DynamicQueryRequestSchema,
1414
type DynamicQueryRequestType,
1515
} from '../schemas';
16+
import { databuddy } from '../lib/databuddy';
1617

1718
interface QueryParams {
1819
start_date?: string;
@@ -213,6 +214,13 @@ export const query = new Elysia({ prefix: '/v1/query' })
213214
: null;
214215

215216
const result = compileQuery(body as QueryRequest, websiteDomain);
217+
databuddy.track({
218+
name: 'compile_query',
219+
properties: {
220+
website_id,
221+
website_domain: websiteDomain,
222+
},
223+
});
216224
return {
217225
success: true,
218226
...result,

apps/api/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"compilerOptions": {
33
"lib": ["ESNext"],
44
"target": "ESNext",
5-
"module": "Preserve",
5+
"module": "esnext",
66
"moduleDetection": "force",
77
"jsx": "react-jsx",
88
"allowJs": true,

apps/basket/src/routes/basket.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,12 @@ async function insertCustomEvent(
351351
typeof customData.timestamp === 'number' ? customData.timestamp : now,
352352
};
353353

354+
console.log('🔍 INSERTING CUSTOM EVENT TO DATABASE:');
355+
console.log('📥 Raw input properties:', JSON.stringify(customData.properties, null, 2));
356+
console.log('📤 Final stored properties:', customEvent.properties);
357+
console.log('📊 Full event object:', JSON.stringify(customEvent, null, 2));
358+
console.log('---');
359+
354360
try {
355361
await clickHouse.insert({
356362
table: 'analytics.custom_events',
@@ -801,6 +807,12 @@ const app = new Elysia()
801807
}
802808

803809
if (eventType === 'custom') {
810+
console.log('📨 RECEIVED SINGLE CUSTOM EVENT:');
811+
console.log('🎯 Event name:', body.name);
812+
console.log('📋 Properties:', JSON.stringify(body.properties, null, 2));
813+
console.log('📏 Properties count:', Object.keys(body.properties || {}).length);
814+
console.log('---');
815+
804816
const parseResult = customEventSchema.safeParse(body);
805817
if (!parseResult.success) {
806818
console.error(
@@ -1101,6 +1113,12 @@ const app = new Elysia()
11011113
}
11021114
}
11031115
if (eventType === 'custom') {
1116+
console.log('📦 RECEIVED BATCH CUSTOM EVENT:');
1117+
console.log('🎯 Event name:', event.name);
1118+
console.log('📋 Properties:', JSON.stringify(event.properties, null, 2));
1119+
console.log('📏 Properties count:', Object.keys(event.properties || {}).length);
1120+
console.log('---');
1121+
11041122
const parseResult = customEventSchema.safeParse(event);
11051123
if (!parseResult.success) {
11061124
console.error(

bun.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@databuddy/db": "workspace:*",
2424
"@databuddy/redis": "workspace:*",
2525
"@databuddy/rpc": "workspace:*",
26+
"@databuddy/sdk": "workspace:*",
2627
"@databuddy/shared": "workspace:*",
2728
"@elysiajs/cors": "^1.3.3",
2829
"@elysiajs/trpc": "^1.1.0",
@@ -392,6 +393,9 @@
392393
"typescript": "catalog:",
393394
"unbuild": "^3.6.1",
394395
},
396+
"optionalDependencies": {
397+
"pino": "^9.0.0",
398+
},
395399
"peerDependencies": {
396400
"react": ">=18",
397401
"vue": ">=3",
@@ -1432,7 +1436,7 @@
14321436

14331437
"autumn": ["[email protected]", "", { "dependencies": { "ansi": "~0.3.0", "request": "~2.40.0" }, "bin": { "autumn": "./autumn.js" } }, "sha512-fMgmg5YHd5Kj/l7M5OxvDaTo13EBgL6rgSTS5maqq9kjU3Z4p+4nxjb1gJsREHk7x8B6/PoP4QdvoSuFC65w8w=="],
14341438

1435-
"autumn-js": ["[email protected].32", "", { "dependencies": { "query-string": "^9.2.2", "rou3": "^0.6.1", "swr": "^2.3.3", "zod": "^4.0.0" }, "peerDependencies": { "better-auth": "^1.3.4", "better-call": "^1.0.12", "convex": "^1.25.4" }, "optionalPeers": ["better-auth", "better-call"] }, "sha512-BZfLD2qwMEH7fREdOteS8idg0qYzq1S1HM2Dn2re89Q2K7FBS27eP1m0JdcpOw+ybsG8TWxO9y2Y3ziaYccaYA=="],
1439+
"autumn-js": ["[email protected].40", "", { "dependencies": { "query-string": "^9.2.2", "rou3": "^0.6.1", "swr": "^2.3.3", "zod": "^4.0.0" }, "peerDependencies": { "better-auth": "^1.3.17", "better-call": "^1.0.12", "convex": "^1.25.4" }, "optionalPeers": ["better-auth", "better-call"] }, "sha512-nAmyFJLOQqKosb8MHv09rB2pma8LyOHWsuYtrjXND+2LM51vToco1mweLIYIs/aX33iLAVUxfpXEEt8P3UYoxw=="],
14361440

14371441
"aws-sign2": ["[email protected]", "", {}, "sha512-oqUX0DM5j7aPWPCnpWebiyNIj2wiNI87ZxnOMoGv0aE4TGlBy2N+5iWc6dQ/NOKZaBD2W6PVz8jtOGkWzSC5EA=="],
14381442

@@ -3106,8 +3110,6 @@
31063110

31073111
"@databuddy/dashboard/@biomejs/biome": ["@biomejs/[email protected]", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.0.5", "@biomejs/cli-darwin-x64": "2.0.5", "@biomejs/cli-linux-arm64": "2.0.5", "@biomejs/cli-linux-arm64-musl": "2.0.5", "@biomejs/cli-linux-x64": "2.0.5", "@biomejs/cli-linux-x64-musl": "2.0.5", "@biomejs/cli-win32-arm64": "2.0.5", "@biomejs/cli-win32-x64": "2.0.5" }, "bin": { "biome": "bin/biome" } }, "sha512-MztFGhE6cVjf3QmomWu83GpTFyWY8KIcskgRf2AqVEMSH4qI4rNdBLdpAQ11TNK9pUfLGz3IIOC1ZYwgBePtig=="],
31083112

3109-
"@databuddy/dashboard/autumn-js": ["[email protected]", "", { "dependencies": { "query-string": "^9.2.2", "rou3": "^0.6.1", "swr": "^2.3.3", "zod": "^4.0.0" }, "peerDependencies": { "better-auth": "^1.3.17", "better-call": "^1.0.12", "convex": "^1.25.4" }, "optionalPeers": ["better-auth", "better-call"] }, "sha512-nAmyFJLOQqKosb8MHv09rB2pma8LyOHWsuYtrjXND+2LM51vToco1mweLIYIs/aX33iLAVUxfpXEEt8P3UYoxw=="],
3110-
31113113
"@databuddy/dashboard/ultracite": ["[email protected]", "", { "dependencies": { "@clack/prompts": "^0.11.0", "@trpc/server": "^11.5.1", "deepmerge": "^4.3.1", "jsonc-parser": "^3.3.1", "nypm": "^0.6.2", "trpc-cli": "^0.11.0", "zod": "^4.1.11" }, "bin": { "ultracite": "dist/index.js" } }, "sha512-RzfjJhCgTs3RbmZeAt7hTxvPxMtRFH/i3QeAm3HXX9FvAdoGW0U8dYvyAQALhQp6S5zGyuXEKft8lXz5Pq2u7A=="],
31123114

31133115
"@databuddy/docs/@biomejs/biome": ["@biomejs/[email protected]", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.1.2", "@biomejs/cli-darwin-x64": "2.1.2", "@biomejs/cli-linux-arm64": "2.1.2", "@biomejs/cli-linux-arm64-musl": "2.1.2", "@biomejs/cli-linux-x64": "2.1.2", "@biomejs/cli-linux-x64-musl": "2.1.2", "@biomejs/cli-win32-arm64": "2.1.2", "@biomejs/cli-win32-x64": "2.1.2" }, "bin": { "biome": "bin/biome" } }, "sha512-yq8ZZuKuBVDgAS76LWCfFKHSYIAgqkxVB3mGVVpOe2vSkUTs7xG46zXZeNPRNVjiJuw0SZ3+J2rXiYx0RUpfGg=="],
@@ -3196,8 +3198,6 @@
31963198

31973199
"accepts/negotiator": ["[email protected]", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
31983200

3199-
"autumn-js/zod": ["[email protected]", "", {}, "sha512-rcUUZqlLJgBC33IT3PNMgsCq6TzLQEG/Ei/KTCU0PedSWRMAXoOUN+4t/0H+Q8bdnLPdqUYnvboJT0bn/229qg=="],
3200-
32013201
"axios/form-data": ["[email protected]", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
32023202

32033203
"basket/autumn-js": ["[email protected]", "", { "dependencies": { "axios": "^1.10.0", "chalk": "^5.4.1", "commander": "^14.0.0", "ink": "^6.0.1", "jiti": "^2.4.2", "open": "^10.1.2", "rou3": "^0.6.1", "swr": "^2.3.3", "zod": "^3.24.1" }, "peerDependencies": { "better-auth": "^1.2.12", "better-call": "^1.0.12" }, "optionalPeers": ["better-auth", "better-call"] }, "sha512-Xmb6jvrr6EgN0UbHZZ0Er0OiLW/IbPPf02lbTNbTCuHePoSEaMQ3cxkvADpNRFf5NBo3Oos2rG2QVaDzkzIejg=="],

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
"build": "turbo run build",
2020
"dev": "dotenv -- turbo run dev",
2121
"start": "turbo run start",
22+
"test": "bun test",
23+
"test:watch": "bun test --watch",
24+
"test:coverage": "bun test --coverage",
2225
"lint": "npx ultracite@latest check",
2326
"format": "npx ultracite@latest fix",
2427
"check-types": "tsgo --noEmit --project .",

packages/db/src/clickhouse/schema.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ export interface CustomEvent {
656656
event_name: string;
657657
anonymous_id: string;
658658
session_id: string;
659-
properties: string;
659+
properties: Record<string, unknown>;
660660
timestamp: number;
661661
}
662662

@@ -667,7 +667,7 @@ export interface CustomOutgoingLink {
667667
session_id: string;
668668
href: string;
669669
text?: string;
670-
properties: string;
670+
properties: Record<string, unknown>;
671671
timestamp: number;
672672
}
673673

@@ -731,7 +731,7 @@ export interface AnalyticsEvent {
731731
redirect_time?: number;
732732
domain_lookup_time?: number;
733733

734-
properties: string;
734+
properties: Record<string, unknown>;
735735

736736
created_at: number;
737737
}

packages/sdk/build.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export default defineBuildConfig({
77
'./src/core/index.ts',
88
'./src/react/index.ts',
99
'./src/vue/index.ts',
10+
'./src/node/index.ts',
1011
],
1112
externals: ['react', 'react-dom', 'vue', 'jotai'],
1213
declaration: true,

0 commit comments

Comments
 (0)