@census-ai/census-sdk 0.2.0 → 0.4.1

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.
@@ -0,0 +1,3 @@
1
+ 'use strict';var l="https://api.census.ai",o=class{constructor(t){if(!t.apiKey)throw new Error("Census: apiKey is required");["cs_live_","cs_test_","op_live_","op_test_"].some(e=>t.apiKey.startsWith(e))||console.warn('Census: API key should start with "cs_live_" or "cs_test_"'),this.apiKey=t.apiKey,this.baseUrl=t.baseUrl||l,this.debug=t.debug||false,this.log("Server client initialized with base URL:",this.baseUrl);}async syncUser(t){if(!t.userId)throw new Error("Census: userId is required for syncUser()");let s=await this.request("/api/sdk/sync","POST",this.prepareUserData(t));return this.log("User synced:",t.userId),s}async syncUsers(t,s){if(!t||t.length===0)return {success:true,created:0,updated:0,skipped:0,failed:0};if(t.length>1e3)throw new Error("Census: Maximum 1000 users per syncUsers() call. Split into multiple calls.");let e=t.filter(r=>!r.userId);if(e.length>0)throw new Error(`Census: ${e.length} users missing userId`);let n=await this.request("/api/sdk/sync/bulk","POST",{users:t.map(r=>this.prepareUserData(r)),options:{onConflict:s?.onConflict||"update",batchSize:s?.batchSize}});return this.log("Bulk sync complete:",`${n.created} created,`,`${n.updated} updated,`,`${n.failed} failed`),n}prepareUserData(t){let s={userId:t.userId,email:t.email,name:t.name,avatarUrl:t.avatarUrl,metadata:t.metadata,organizationId:t.organizationId,organizationName:t.organizationName,organizationDomain:t.organizationDomain,organizationPlan:t.organizationPlan,planName:t.planName,subscriptionStatus:t.subscriptionStatus,billingCycle:t.billingCycle,mrr:t.mrr,loginCount:t.loginCount};return t.subscriptionStartedAt&&(s.subscriptionStartedAt=this.toISOString(t.subscriptionStartedAt)),t.subscriptionEndsAt&&(s.subscriptionEndsAt=this.toISOString(t.subscriptionEndsAt)),t.trialEndsAt&&(s.trialEndsAt=this.toISOString(t.trialEndsAt)),t.signupAt&&(s.signupAt=this.toISOString(t.signupAt)),t.lastLoginAt&&(s.lastLoginAt=this.toISOString(t.lastLoginAt)),Object.fromEntries(Object.entries(s).filter(([,e])=>e!==void 0))}toISOString(t){return t instanceof Date?t.toISOString():t}async request(t,s,e){let n=`${this.baseUrl}${t}`,r={"X-Census-Key":this.apiKey,"Content-Type":"application/json"};this.log(`${s} ${t}`,e);let i=await fetch(n,{method:s,headers:r,body:e?JSON.stringify(e):void 0});if(!i.ok){let a=`Request failed with status ${i.status}`;try{a=(await i.json()).error||a;}catch{}throw {error:a,status:i.status}}return i.json()}log(...t){this.debug&&console.log("[Census Server]",...t);}};function d(c){return new o(c)}
2
+ exports.CensusServerClient=o;exports.createCensusServer=d;//# sourceMappingURL=server.cjs.map
3
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server.ts"],"names":["DEFAULT_BASE_URL","CensusServerClient","config","prefix","user","response","users","options","invalidUsers","u","data","v","value","path","method","body","url","headers","errorMessage","args","createCensusServer"],"mappings":"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","file":"server.cjs","sourcesContent":["/**\n * @census-ai/census-sdk/server - Server-side Census SDK\n *\n * For backend use cases: sync users from your server, track subscription changes,\n * and bulk import users.\n *\n * @example\n * ```typescript\n * import { createCensusServer } from '@census-ai/census-sdk/server';\n *\n * const census = createCensusServer({ apiKey: 'cs_live_xxx' });\n *\n * // Sync a single user (e.g., on signup or subscription change)\n * await census.syncUser({\n * userId: 'user_123',\n * email: 'john@example.com',\n * planName: 'Pro',\n * subscriptionStatus: 'active',\n * mrr: 9900, // $99.00 in cents\n * signupAt: new Date(),\n * });\n *\n * // Bulk sync users (e.g., initial import)\n * const result = await census.syncUsers(allUsers, { batchSize: 100 });\n * console.log(`Created: ${result.created}, Updated: ${result.updated}`);\n * ```\n */\n\nimport type {\n CensusConfig,\n SyncUserData,\n SyncUsersOptions,\n SyncResult,\n SyncUsersResult,\n CensusError,\n} from './types';\n\n/**\n * Default API base URL\n */\nconst DEFAULT_BASE_URL = 'https://api.census.ai';\n\n/**\n * Census Server SDK Client\n *\n * A server-side client for syncing user data from your backend.\n * Use `createCensusServer()` to create an instance.\n *\n * This client is designed for:\n * - Backend services (Node.js, Bun, Deno, Edge runtimes)\n * - Syncing subscription/billing data from your payment processor\n * - Bulk importing users from your database\n * - Tracking server-side events\n *\n * For client-side usage, use `createCensus()` from '@census-ai/census-sdk'.\n */\nexport class CensusServerClient {\n private apiKey: string;\n private baseUrl: string;\n private debug: boolean;\n\n constructor(config: CensusConfig) {\n if (!config.apiKey) {\n throw new Error('Census: apiKey is required');\n }\n\n // Support both new (cs_) and legacy (op_) key prefixes\n const validPrefixes = ['cs_live_', 'cs_test_', 'op_live_', 'op_test_'];\n if (!validPrefixes.some(prefix => config.apiKey.startsWith(prefix))) {\n console.warn('Census: API key should start with \"cs_live_\" or \"cs_test_\"');\n }\n\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;\n this.debug = config.debug || false;\n\n this.log('Server client initialized with base URL:', this.baseUrl);\n }\n\n /**\n * Sync a single user's data to Census.\n *\n * Call this when:\n * - A user signs up\n * - Subscription status changes (upgrade, downgrade, cancel)\n * - User profile is updated\n * - Login activity should be recorded\n *\n * @param user - User data to sync\n * @returns Sync result with user ID\n *\n * @example\n * ```typescript\n * // On user signup\n * await census.syncUser({\n * userId: 'user_123',\n * email: 'john@example.com',\n * name: 'John Doe',\n * signupAt: new Date(),\n * subscriptionStatus: 'trial',\n * trialEndsAt: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000),\n * });\n *\n * // On subscription purchase\n * await census.syncUser({\n * userId: 'user_123',\n * planName: 'Pro',\n * subscriptionStatus: 'active',\n * billingCycle: 'monthly',\n * mrr: 9900, // $99.00 in cents\n * subscriptionStartedAt: new Date(),\n * });\n *\n * // On cancellation\n * await census.syncUser({\n * userId: 'user_123',\n * subscriptionStatus: 'canceled',\n * subscriptionEndsAt: new Date('2024-02-01'),\n * });\n * ```\n */\n async syncUser(user: SyncUserData): Promise<SyncResult> {\n if (!user.userId) {\n throw new Error('Census: userId is required for syncUser()');\n }\n\n const response = await this.request<SyncResult>(\n '/api/sdk/sync',\n 'POST',\n this.prepareUserData(user)\n );\n\n this.log('User synced:', user.userId);\n return response;\n }\n\n /**\n * Bulk sync multiple users to Census.\n *\n * Use this for:\n * - Initial import of existing users\n * - Periodic full sync from your database\n * - Batch updates after bulk operations\n *\n * @param users - Array of users to sync (max 1000 per request)\n * @param options - Sync options\n * @returns Bulk sync result with counts\n *\n * @example\n * ```typescript\n * // Initial import\n * const allUsers = await db.users.findAll();\n *\n * const result = await census.syncUsers(\n * allUsers.map(u => ({\n * userId: u.id,\n * email: u.email,\n * name: u.name,\n * planName: u.subscription?.plan,\n * subscriptionStatus: u.subscription?.status,\n * mrr: u.subscription?.mrr,\n * signupAt: u.createdAt,\n * lastLoginAt: u.lastLogin,\n * loginCount: u.loginCount,\n * })),\n * { batchSize: 100 }\n * );\n *\n * console.log(`Synced: ${result.created} created, ${result.updated} updated`);\n * if (result.errors?.length) {\n * console.error('Errors:', result.errors);\n * }\n * ```\n */\n async syncUsers(\n users: SyncUserData[],\n options?: SyncUsersOptions\n ): Promise<SyncUsersResult> {\n if (!users || users.length === 0) {\n return {\n success: true,\n created: 0,\n updated: 0,\n skipped: 0,\n failed: 0,\n };\n }\n\n if (users.length > 1000) {\n throw new Error('Census: Maximum 1000 users per syncUsers() call. Split into multiple calls.');\n }\n\n // Validate all users have userId\n const invalidUsers = users.filter(u => !u.userId);\n if (invalidUsers.length > 0) {\n throw new Error(`Census: ${invalidUsers.length} users missing userId`);\n }\n\n const response = await this.request<SyncUsersResult>(\n '/api/sdk/sync/bulk',\n 'POST',\n {\n users: users.map(u => this.prepareUserData(u)),\n options: {\n onConflict: options?.onConflict || 'update',\n batchSize: options?.batchSize,\n },\n }\n );\n\n this.log(\n 'Bulk sync complete:',\n `${response.created} created,`,\n `${response.updated} updated,`,\n `${response.failed} failed`\n );\n\n return response;\n }\n\n /**\n * Prepare user data for API request, converting dates to ISO strings\n */\n private prepareUserData(user: SyncUserData): Record<string, unknown> {\n const data: Record<string, unknown> = {\n userId: user.userId,\n email: user.email,\n name: user.name,\n avatarUrl: user.avatarUrl,\n metadata: user.metadata,\n organizationId: user.organizationId,\n organizationName: user.organizationName,\n organizationDomain: user.organizationDomain,\n organizationPlan: user.organizationPlan,\n planName: user.planName,\n subscriptionStatus: user.subscriptionStatus,\n billingCycle: user.billingCycle,\n mrr: user.mrr,\n loginCount: user.loginCount,\n };\n\n // Convert dates to ISO strings\n if (user.subscriptionStartedAt) {\n data.subscriptionStartedAt = this.toISOString(user.subscriptionStartedAt);\n }\n if (user.subscriptionEndsAt) {\n data.subscriptionEndsAt = this.toISOString(user.subscriptionEndsAt);\n }\n if (user.trialEndsAt) {\n data.trialEndsAt = this.toISOString(user.trialEndsAt);\n }\n if (user.signupAt) {\n data.signupAt = this.toISOString(user.signupAt);\n }\n if (user.lastLoginAt) {\n data.lastLoginAt = this.toISOString(user.lastLoginAt);\n }\n\n // Remove undefined values\n return Object.fromEntries(\n Object.entries(data).filter(([, v]) => v !== undefined)\n );\n }\n\n /**\n * Convert Date or string to ISO string\n */\n private toISOString(value: string | Date): string {\n if (value instanceof Date) {\n return value.toISOString();\n }\n return value;\n }\n\n /**\n * Make an API request\n */\n private async request<T>(\n path: string,\n method: string,\n body?: unknown\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n const headers: Record<string, string> = {\n 'X-Census-Key': this.apiKey,\n 'Content-Type': 'application/json',\n };\n\n this.log(`${method} ${path}`, body);\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n let errorMessage = `Request failed with status ${response.status}`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.error || errorMessage;\n } catch {\n // Use default error message\n }\n\n const error: CensusError = {\n error: errorMessage,\n status: response.status,\n };\n throw error;\n }\n\n return response.json();\n }\n\n /**\n * Log debug messages\n */\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.log('[Census Server]', ...args);\n }\n }\n}\n\n/**\n * Create a new Census Server SDK client.\n *\n * @param config - Configuration options\n * @returns Census server client instance\n *\n * @example\n * ```typescript\n * import { createCensusServer } from '@census-ai/census-sdk/server';\n *\n * const census = createCensusServer({\n * apiKey: 'cs_live_your_key_here',\n * debug: true, // Enable debug logging\n * });\n *\n * // Sync user on subscription change\n * await census.syncUser({\n * userId: 'user_123',\n * planName: 'Pro',\n * subscriptionStatus: 'active',\n * mrr: 9900,\n * });\n * ```\n */\nexport function createCensusServer(config: CensusConfig): CensusServerClient {\n return new CensusServerClient(config);\n}\n\n// Re-export types needed for server usage\nexport type {\n CensusConfig,\n SyncUserData,\n SyncUsersOptions,\n SyncResult,\n SyncUsersResult,\n CensusError,\n} from './types';\n"]}
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Configuration options for the Census SDK
3
+ */
4
+ interface CensusConfig {
5
+ /**
6
+ * Your Census API key (starts with cs_live_ or cs_test_)
7
+ */
8
+ apiKey: string;
9
+ /**
10
+ * Base URL for the Census API
11
+ * @default "https://api.census.ai" or your custom domain
12
+ */
13
+ baseUrl?: string;
14
+ /**
15
+ * Enable debug logging
16
+ * @default false
17
+ */
18
+ debug?: boolean;
19
+ }
20
+ /**
21
+ * User identity information for SDK tracking
22
+ */
23
+ interface UserIdentity {
24
+ /**
25
+ * Unique identifier for the user in your system
26
+ */
27
+ userId: string;
28
+ /**
29
+ * User's email address
30
+ */
31
+ email?: string;
32
+ /**
33
+ * User's display name
34
+ */
35
+ name?: string;
36
+ /**
37
+ * URL to user's avatar image
38
+ */
39
+ avatarUrl?: string;
40
+ /**
41
+ * Additional custom properties for the user
42
+ */
43
+ metadata?: Record<string, unknown>;
44
+ /**
45
+ * Organization ID if the user belongs to an organization
46
+ */
47
+ organizationId?: string;
48
+ /**
49
+ * Organization name
50
+ */
51
+ organizationName?: string;
52
+ /**
53
+ * Organization's domain
54
+ */
55
+ organizationDomain?: string;
56
+ /**
57
+ * Organization's plan/tier
58
+ */
59
+ organizationPlan?: string;
60
+ }
61
+ /**
62
+ * API error response
63
+ */
64
+ interface CensusError {
65
+ error: string;
66
+ status?: number;
67
+ }
68
+ /**
69
+ * Extended user data for server-side sync (includes subscription/activity fields)
70
+ */
71
+ interface SyncUserData extends UserIdentity {
72
+ /**
73
+ * User's plan name (e.g., "Pro", "Enterprise")
74
+ */
75
+ planName?: string;
76
+ /**
77
+ * Current subscription status
78
+ */
79
+ subscriptionStatus?: 'active' | 'canceled' | 'trial' | 'past_due' | 'paused' | 'free';
80
+ /**
81
+ * Billing cycle frequency
82
+ */
83
+ billingCycle?: 'monthly' | 'yearly' | 'quarterly' | 'lifetime' | 'custom';
84
+ /**
85
+ * Monthly recurring revenue in cents (e.g., 9900 = $99.00)
86
+ */
87
+ mrr?: number;
88
+ /**
89
+ * When the subscription started
90
+ */
91
+ subscriptionStartedAt?: string | Date;
92
+ /**
93
+ * When the subscription ends (for canceled subscriptions)
94
+ */
95
+ subscriptionEndsAt?: string | Date;
96
+ /**
97
+ * When the trial period ends
98
+ */
99
+ trialEndsAt?: string | Date;
100
+ /**
101
+ * When the user first signed up
102
+ */
103
+ signupAt?: string | Date;
104
+ /**
105
+ * Total number of logins
106
+ */
107
+ loginCount?: number;
108
+ /**
109
+ * Last login timestamp
110
+ */
111
+ lastLoginAt?: string | Date;
112
+ }
113
+ /**
114
+ * Options for bulk sync operations
115
+ */
116
+ interface SyncUsersOptions {
117
+ /**
118
+ * How to handle existing users
119
+ * - 'update': Update existing users with new data (default)
120
+ * - 'skip': Skip existing users
121
+ */
122
+ onConflict?: 'update' | 'skip';
123
+ /**
124
+ * Batch size for processing (default: 100, max: 100)
125
+ */
126
+ batchSize?: number;
127
+ }
128
+ /**
129
+ * Result from sync operations
130
+ */
131
+ interface SyncResult {
132
+ success: boolean;
133
+ userId?: string;
134
+ }
135
+ /**
136
+ * Result from bulk sync operation
137
+ */
138
+ interface SyncUsersResult {
139
+ success: boolean;
140
+ created: number;
141
+ updated: number;
142
+ skipped: number;
143
+ failed: number;
144
+ errors?: Array<{
145
+ userId: string;
146
+ error: string;
147
+ }>;
148
+ }
149
+
150
+ /**
151
+ * @census-ai/census-sdk/server - Server-side Census SDK
152
+ *
153
+ * For backend use cases: sync users from your server, track subscription changes,
154
+ * and bulk import users.
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * import { createCensusServer } from '@census-ai/census-sdk/server';
159
+ *
160
+ * const census = createCensusServer({ apiKey: 'cs_live_xxx' });
161
+ *
162
+ * // Sync a single user (e.g., on signup or subscription change)
163
+ * await census.syncUser({
164
+ * userId: 'user_123',
165
+ * email: 'john@example.com',
166
+ * planName: 'Pro',
167
+ * subscriptionStatus: 'active',
168
+ * mrr: 9900, // $99.00 in cents
169
+ * signupAt: new Date(),
170
+ * });
171
+ *
172
+ * // Bulk sync users (e.g., initial import)
173
+ * const result = await census.syncUsers(allUsers, { batchSize: 100 });
174
+ * console.log(`Created: ${result.created}, Updated: ${result.updated}`);
175
+ * ```
176
+ */
177
+
178
+ /**
179
+ * Census Server SDK Client
180
+ *
181
+ * A server-side client for syncing user data from your backend.
182
+ * Use `createCensusServer()` to create an instance.
183
+ *
184
+ * This client is designed for:
185
+ * - Backend services (Node.js, Bun, Deno, Edge runtimes)
186
+ * - Syncing subscription/billing data from your payment processor
187
+ * - Bulk importing users from your database
188
+ * - Tracking server-side events
189
+ *
190
+ * For client-side usage, use `createCensus()` from '@census-ai/census-sdk'.
191
+ */
192
+ declare class CensusServerClient {
193
+ private apiKey;
194
+ private baseUrl;
195
+ private debug;
196
+ constructor(config: CensusConfig);
197
+ /**
198
+ * Sync a single user's data to Census.
199
+ *
200
+ * Call this when:
201
+ * - A user signs up
202
+ * - Subscription status changes (upgrade, downgrade, cancel)
203
+ * - User profile is updated
204
+ * - Login activity should be recorded
205
+ *
206
+ * @param user - User data to sync
207
+ * @returns Sync result with user ID
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * // On user signup
212
+ * await census.syncUser({
213
+ * userId: 'user_123',
214
+ * email: 'john@example.com',
215
+ * name: 'John Doe',
216
+ * signupAt: new Date(),
217
+ * subscriptionStatus: 'trial',
218
+ * trialEndsAt: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000),
219
+ * });
220
+ *
221
+ * // On subscription purchase
222
+ * await census.syncUser({
223
+ * userId: 'user_123',
224
+ * planName: 'Pro',
225
+ * subscriptionStatus: 'active',
226
+ * billingCycle: 'monthly',
227
+ * mrr: 9900, // $99.00 in cents
228
+ * subscriptionStartedAt: new Date(),
229
+ * });
230
+ *
231
+ * // On cancellation
232
+ * await census.syncUser({
233
+ * userId: 'user_123',
234
+ * subscriptionStatus: 'canceled',
235
+ * subscriptionEndsAt: new Date('2024-02-01'),
236
+ * });
237
+ * ```
238
+ */
239
+ syncUser(user: SyncUserData): Promise<SyncResult>;
240
+ /**
241
+ * Bulk sync multiple users to Census.
242
+ *
243
+ * Use this for:
244
+ * - Initial import of existing users
245
+ * - Periodic full sync from your database
246
+ * - Batch updates after bulk operations
247
+ *
248
+ * @param users - Array of users to sync (max 1000 per request)
249
+ * @param options - Sync options
250
+ * @returns Bulk sync result with counts
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * // Initial import
255
+ * const allUsers = await db.users.findAll();
256
+ *
257
+ * const result = await census.syncUsers(
258
+ * allUsers.map(u => ({
259
+ * userId: u.id,
260
+ * email: u.email,
261
+ * name: u.name,
262
+ * planName: u.subscription?.plan,
263
+ * subscriptionStatus: u.subscription?.status,
264
+ * mrr: u.subscription?.mrr,
265
+ * signupAt: u.createdAt,
266
+ * lastLoginAt: u.lastLogin,
267
+ * loginCount: u.loginCount,
268
+ * })),
269
+ * { batchSize: 100 }
270
+ * );
271
+ *
272
+ * console.log(`Synced: ${result.created} created, ${result.updated} updated`);
273
+ * if (result.errors?.length) {
274
+ * console.error('Errors:', result.errors);
275
+ * }
276
+ * ```
277
+ */
278
+ syncUsers(users: SyncUserData[], options?: SyncUsersOptions): Promise<SyncUsersResult>;
279
+ /**
280
+ * Prepare user data for API request, converting dates to ISO strings
281
+ */
282
+ private prepareUserData;
283
+ /**
284
+ * Convert Date or string to ISO string
285
+ */
286
+ private toISOString;
287
+ /**
288
+ * Make an API request
289
+ */
290
+ private request;
291
+ /**
292
+ * Log debug messages
293
+ */
294
+ private log;
295
+ }
296
+ /**
297
+ * Create a new Census Server SDK client.
298
+ *
299
+ * @param config - Configuration options
300
+ * @returns Census server client instance
301
+ *
302
+ * @example
303
+ * ```typescript
304
+ * import { createCensusServer } from '@census-ai/census-sdk/server';
305
+ *
306
+ * const census = createCensusServer({
307
+ * apiKey: 'cs_live_your_key_here',
308
+ * debug: true, // Enable debug logging
309
+ * });
310
+ *
311
+ * // Sync user on subscription change
312
+ * await census.syncUser({
313
+ * userId: 'user_123',
314
+ * planName: 'Pro',
315
+ * subscriptionStatus: 'active',
316
+ * mrr: 9900,
317
+ * });
318
+ * ```
319
+ */
320
+ declare function createCensusServer(config: CensusConfig): CensusServerClient;
321
+
322
+ export { type CensusConfig, type CensusError, CensusServerClient, type SyncResult, type SyncUserData, type SyncUsersOptions, type SyncUsersResult, createCensusServer };
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Configuration options for the Census SDK
3
+ */
4
+ interface CensusConfig {
5
+ /**
6
+ * Your Census API key (starts with cs_live_ or cs_test_)
7
+ */
8
+ apiKey: string;
9
+ /**
10
+ * Base URL for the Census API
11
+ * @default "https://api.census.ai" or your custom domain
12
+ */
13
+ baseUrl?: string;
14
+ /**
15
+ * Enable debug logging
16
+ * @default false
17
+ */
18
+ debug?: boolean;
19
+ }
20
+ /**
21
+ * User identity information for SDK tracking
22
+ */
23
+ interface UserIdentity {
24
+ /**
25
+ * Unique identifier for the user in your system
26
+ */
27
+ userId: string;
28
+ /**
29
+ * User's email address
30
+ */
31
+ email?: string;
32
+ /**
33
+ * User's display name
34
+ */
35
+ name?: string;
36
+ /**
37
+ * URL to user's avatar image
38
+ */
39
+ avatarUrl?: string;
40
+ /**
41
+ * Additional custom properties for the user
42
+ */
43
+ metadata?: Record<string, unknown>;
44
+ /**
45
+ * Organization ID if the user belongs to an organization
46
+ */
47
+ organizationId?: string;
48
+ /**
49
+ * Organization name
50
+ */
51
+ organizationName?: string;
52
+ /**
53
+ * Organization's domain
54
+ */
55
+ organizationDomain?: string;
56
+ /**
57
+ * Organization's plan/tier
58
+ */
59
+ organizationPlan?: string;
60
+ }
61
+ /**
62
+ * API error response
63
+ */
64
+ interface CensusError {
65
+ error: string;
66
+ status?: number;
67
+ }
68
+ /**
69
+ * Extended user data for server-side sync (includes subscription/activity fields)
70
+ */
71
+ interface SyncUserData extends UserIdentity {
72
+ /**
73
+ * User's plan name (e.g., "Pro", "Enterprise")
74
+ */
75
+ planName?: string;
76
+ /**
77
+ * Current subscription status
78
+ */
79
+ subscriptionStatus?: 'active' | 'canceled' | 'trial' | 'past_due' | 'paused' | 'free';
80
+ /**
81
+ * Billing cycle frequency
82
+ */
83
+ billingCycle?: 'monthly' | 'yearly' | 'quarterly' | 'lifetime' | 'custom';
84
+ /**
85
+ * Monthly recurring revenue in cents (e.g., 9900 = $99.00)
86
+ */
87
+ mrr?: number;
88
+ /**
89
+ * When the subscription started
90
+ */
91
+ subscriptionStartedAt?: string | Date;
92
+ /**
93
+ * When the subscription ends (for canceled subscriptions)
94
+ */
95
+ subscriptionEndsAt?: string | Date;
96
+ /**
97
+ * When the trial period ends
98
+ */
99
+ trialEndsAt?: string | Date;
100
+ /**
101
+ * When the user first signed up
102
+ */
103
+ signupAt?: string | Date;
104
+ /**
105
+ * Total number of logins
106
+ */
107
+ loginCount?: number;
108
+ /**
109
+ * Last login timestamp
110
+ */
111
+ lastLoginAt?: string | Date;
112
+ }
113
+ /**
114
+ * Options for bulk sync operations
115
+ */
116
+ interface SyncUsersOptions {
117
+ /**
118
+ * How to handle existing users
119
+ * - 'update': Update existing users with new data (default)
120
+ * - 'skip': Skip existing users
121
+ */
122
+ onConflict?: 'update' | 'skip';
123
+ /**
124
+ * Batch size for processing (default: 100, max: 100)
125
+ */
126
+ batchSize?: number;
127
+ }
128
+ /**
129
+ * Result from sync operations
130
+ */
131
+ interface SyncResult {
132
+ success: boolean;
133
+ userId?: string;
134
+ }
135
+ /**
136
+ * Result from bulk sync operation
137
+ */
138
+ interface SyncUsersResult {
139
+ success: boolean;
140
+ created: number;
141
+ updated: number;
142
+ skipped: number;
143
+ failed: number;
144
+ errors?: Array<{
145
+ userId: string;
146
+ error: string;
147
+ }>;
148
+ }
149
+
150
+ /**
151
+ * @census-ai/census-sdk/server - Server-side Census SDK
152
+ *
153
+ * For backend use cases: sync users from your server, track subscription changes,
154
+ * and bulk import users.
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * import { createCensusServer } from '@census-ai/census-sdk/server';
159
+ *
160
+ * const census = createCensusServer({ apiKey: 'cs_live_xxx' });
161
+ *
162
+ * // Sync a single user (e.g., on signup or subscription change)
163
+ * await census.syncUser({
164
+ * userId: 'user_123',
165
+ * email: 'john@example.com',
166
+ * planName: 'Pro',
167
+ * subscriptionStatus: 'active',
168
+ * mrr: 9900, // $99.00 in cents
169
+ * signupAt: new Date(),
170
+ * });
171
+ *
172
+ * // Bulk sync users (e.g., initial import)
173
+ * const result = await census.syncUsers(allUsers, { batchSize: 100 });
174
+ * console.log(`Created: ${result.created}, Updated: ${result.updated}`);
175
+ * ```
176
+ */
177
+
178
+ /**
179
+ * Census Server SDK Client
180
+ *
181
+ * A server-side client for syncing user data from your backend.
182
+ * Use `createCensusServer()` to create an instance.
183
+ *
184
+ * This client is designed for:
185
+ * - Backend services (Node.js, Bun, Deno, Edge runtimes)
186
+ * - Syncing subscription/billing data from your payment processor
187
+ * - Bulk importing users from your database
188
+ * - Tracking server-side events
189
+ *
190
+ * For client-side usage, use `createCensus()` from '@census-ai/census-sdk'.
191
+ */
192
+ declare class CensusServerClient {
193
+ private apiKey;
194
+ private baseUrl;
195
+ private debug;
196
+ constructor(config: CensusConfig);
197
+ /**
198
+ * Sync a single user's data to Census.
199
+ *
200
+ * Call this when:
201
+ * - A user signs up
202
+ * - Subscription status changes (upgrade, downgrade, cancel)
203
+ * - User profile is updated
204
+ * - Login activity should be recorded
205
+ *
206
+ * @param user - User data to sync
207
+ * @returns Sync result with user ID
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * // On user signup
212
+ * await census.syncUser({
213
+ * userId: 'user_123',
214
+ * email: 'john@example.com',
215
+ * name: 'John Doe',
216
+ * signupAt: new Date(),
217
+ * subscriptionStatus: 'trial',
218
+ * trialEndsAt: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000),
219
+ * });
220
+ *
221
+ * // On subscription purchase
222
+ * await census.syncUser({
223
+ * userId: 'user_123',
224
+ * planName: 'Pro',
225
+ * subscriptionStatus: 'active',
226
+ * billingCycle: 'monthly',
227
+ * mrr: 9900, // $99.00 in cents
228
+ * subscriptionStartedAt: new Date(),
229
+ * });
230
+ *
231
+ * // On cancellation
232
+ * await census.syncUser({
233
+ * userId: 'user_123',
234
+ * subscriptionStatus: 'canceled',
235
+ * subscriptionEndsAt: new Date('2024-02-01'),
236
+ * });
237
+ * ```
238
+ */
239
+ syncUser(user: SyncUserData): Promise<SyncResult>;
240
+ /**
241
+ * Bulk sync multiple users to Census.
242
+ *
243
+ * Use this for:
244
+ * - Initial import of existing users
245
+ * - Periodic full sync from your database
246
+ * - Batch updates after bulk operations
247
+ *
248
+ * @param users - Array of users to sync (max 1000 per request)
249
+ * @param options - Sync options
250
+ * @returns Bulk sync result with counts
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * // Initial import
255
+ * const allUsers = await db.users.findAll();
256
+ *
257
+ * const result = await census.syncUsers(
258
+ * allUsers.map(u => ({
259
+ * userId: u.id,
260
+ * email: u.email,
261
+ * name: u.name,
262
+ * planName: u.subscription?.plan,
263
+ * subscriptionStatus: u.subscription?.status,
264
+ * mrr: u.subscription?.mrr,
265
+ * signupAt: u.createdAt,
266
+ * lastLoginAt: u.lastLogin,
267
+ * loginCount: u.loginCount,
268
+ * })),
269
+ * { batchSize: 100 }
270
+ * );
271
+ *
272
+ * console.log(`Synced: ${result.created} created, ${result.updated} updated`);
273
+ * if (result.errors?.length) {
274
+ * console.error('Errors:', result.errors);
275
+ * }
276
+ * ```
277
+ */
278
+ syncUsers(users: SyncUserData[], options?: SyncUsersOptions): Promise<SyncUsersResult>;
279
+ /**
280
+ * Prepare user data for API request, converting dates to ISO strings
281
+ */
282
+ private prepareUserData;
283
+ /**
284
+ * Convert Date or string to ISO string
285
+ */
286
+ private toISOString;
287
+ /**
288
+ * Make an API request
289
+ */
290
+ private request;
291
+ /**
292
+ * Log debug messages
293
+ */
294
+ private log;
295
+ }
296
+ /**
297
+ * Create a new Census Server SDK client.
298
+ *
299
+ * @param config - Configuration options
300
+ * @returns Census server client instance
301
+ *
302
+ * @example
303
+ * ```typescript
304
+ * import { createCensusServer } from '@census-ai/census-sdk/server';
305
+ *
306
+ * const census = createCensusServer({
307
+ * apiKey: 'cs_live_your_key_here',
308
+ * debug: true, // Enable debug logging
309
+ * });
310
+ *
311
+ * // Sync user on subscription change
312
+ * await census.syncUser({
313
+ * userId: 'user_123',
314
+ * planName: 'Pro',
315
+ * subscriptionStatus: 'active',
316
+ * mrr: 9900,
317
+ * });
318
+ * ```
319
+ */
320
+ declare function createCensusServer(config: CensusConfig): CensusServerClient;
321
+
322
+ export { type CensusConfig, type CensusError, CensusServerClient, type SyncResult, type SyncUserData, type SyncUsersOptions, type SyncUsersResult, createCensusServer };
@@ -0,0 +1,3 @@
1
+ var l="https://api.census.ai",o=class{constructor(t){if(!t.apiKey)throw new Error("Census: apiKey is required");["cs_live_","cs_test_","op_live_","op_test_"].some(e=>t.apiKey.startsWith(e))||console.warn('Census: API key should start with "cs_live_" or "cs_test_"'),this.apiKey=t.apiKey,this.baseUrl=t.baseUrl||l,this.debug=t.debug||false,this.log("Server client initialized with base URL:",this.baseUrl);}async syncUser(t){if(!t.userId)throw new Error("Census: userId is required for syncUser()");let s=await this.request("/api/sdk/sync","POST",this.prepareUserData(t));return this.log("User synced:",t.userId),s}async syncUsers(t,s){if(!t||t.length===0)return {success:true,created:0,updated:0,skipped:0,failed:0};if(t.length>1e3)throw new Error("Census: Maximum 1000 users per syncUsers() call. Split into multiple calls.");let e=t.filter(r=>!r.userId);if(e.length>0)throw new Error(`Census: ${e.length} users missing userId`);let n=await this.request("/api/sdk/sync/bulk","POST",{users:t.map(r=>this.prepareUserData(r)),options:{onConflict:s?.onConflict||"update",batchSize:s?.batchSize}});return this.log("Bulk sync complete:",`${n.created} created,`,`${n.updated} updated,`,`${n.failed} failed`),n}prepareUserData(t){let s={userId:t.userId,email:t.email,name:t.name,avatarUrl:t.avatarUrl,metadata:t.metadata,organizationId:t.organizationId,organizationName:t.organizationName,organizationDomain:t.organizationDomain,organizationPlan:t.organizationPlan,planName:t.planName,subscriptionStatus:t.subscriptionStatus,billingCycle:t.billingCycle,mrr:t.mrr,loginCount:t.loginCount};return t.subscriptionStartedAt&&(s.subscriptionStartedAt=this.toISOString(t.subscriptionStartedAt)),t.subscriptionEndsAt&&(s.subscriptionEndsAt=this.toISOString(t.subscriptionEndsAt)),t.trialEndsAt&&(s.trialEndsAt=this.toISOString(t.trialEndsAt)),t.signupAt&&(s.signupAt=this.toISOString(t.signupAt)),t.lastLoginAt&&(s.lastLoginAt=this.toISOString(t.lastLoginAt)),Object.fromEntries(Object.entries(s).filter(([,e])=>e!==void 0))}toISOString(t){return t instanceof Date?t.toISOString():t}async request(t,s,e){let n=`${this.baseUrl}${t}`,r={"X-Census-Key":this.apiKey,"Content-Type":"application/json"};this.log(`${s} ${t}`,e);let i=await fetch(n,{method:s,headers:r,body:e?JSON.stringify(e):void 0});if(!i.ok){let a=`Request failed with status ${i.status}`;try{a=(await i.json()).error||a;}catch{}throw {error:a,status:i.status}}return i.json()}log(...t){this.debug&&console.log("[Census Server]",...t);}};function d(c){return new o(c)}
2
+ export{o as CensusServerClient,d as createCensusServer};//# sourceMappingURL=server.js.map
3
+ //# sourceMappingURL=server.js.map