userplex 1.0.0 → 1.0.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.
- package/README.md +7 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,9 +13,14 @@ npm install userplex
|
|
|
13
13
|
```javascript
|
|
14
14
|
import Userplex from 'userplex';
|
|
15
15
|
|
|
16
|
-
// Initialize with your API key
|
|
16
|
+
// Initialize with your API key (connects to userplex.vercel.app by default)
|
|
17
17
|
const userplex = new Userplex('upx_your_api_key_here');
|
|
18
18
|
|
|
19
|
+
// Or use your own Userplex instance
|
|
20
|
+
const customUserplex = new Userplex('upx_your_api_key_here', {
|
|
21
|
+
baseUrl: 'https://your-userplex-instance.com'
|
|
22
|
+
});
|
|
23
|
+
|
|
19
24
|
// Track events
|
|
20
25
|
await userplex.track('user123', 'button_clicked', {
|
|
21
26
|
button: 'signup',
|
|
@@ -49,7 +54,7 @@ Create a new Userplex instance.
|
|
|
49
54
|
|
|
50
55
|
- `apiKey` - Your Userplex API key (required)
|
|
51
56
|
- `options` - Optional configuration
|
|
52
|
-
- `baseUrl` - Your Userplex server URL (default: `
|
|
57
|
+
- `baseUrl` - Your Userplex server URL (default: `https://userplex.vercel.app`)
|
|
53
58
|
- `timeout` - Request timeout in ms (default: `10000`)
|
|
54
59
|
- `debug` - Enable debug logging (default: `false`)
|
|
55
60
|
|
package/dist/index.d.mts
CHANGED
|
@@ -29,7 +29,7 @@ interface ConversationMessage {
|
|
|
29
29
|
content: string;
|
|
30
30
|
}
|
|
31
31
|
interface UserplexOptions {
|
|
32
|
-
/** Your Userplex instance URL (default:
|
|
32
|
+
/** Your Userplex instance URL (default: https://userplex.vercel.app) */
|
|
33
33
|
baseUrl?: string;
|
|
34
34
|
/** Request timeout in ms (default: 10000) */
|
|
35
35
|
timeout?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ interface ConversationMessage {
|
|
|
29
29
|
content: string;
|
|
30
30
|
}
|
|
31
31
|
interface UserplexOptions {
|
|
32
|
-
/** Your Userplex instance URL (default:
|
|
32
|
+
/** Your Userplex instance URL (default: https://userplex.vercel.app) */
|
|
33
33
|
baseUrl?: string;
|
|
34
34
|
/** Request timeout in ms (default: 10000) */
|
|
35
35
|
timeout?: number;
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ var Userplex = class {
|
|
|
20
20
|
throw new Error('Userplex: API key must start with "upx_"');
|
|
21
21
|
}
|
|
22
22
|
this.apiKey = apiKey;
|
|
23
|
-
this.baseUrl = (options.baseUrl || "
|
|
23
|
+
this.baseUrl = (options.baseUrl || "https://userplex.vercel.app").replace(/\/$/, "");
|
|
24
24
|
this.timeout = options.timeout || 1e4;
|
|
25
25
|
this.debug = options.debug || false;
|
|
26
26
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts"],"names":[],"mappings":";;;;;AAyCO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EACvC,WAAA,CACE,OAAA,EACO,UAAA,EACA,QAAA,EACP;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAHN,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAGP,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEA,IAAM,WAAN,MAAe;AAAA,EAMb,WAAA,CAAY,MAAA,EAAgB,OAAA,GAA2B,EAAC,EAAG;AACzD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,IACjD;AACA,IAAA,IAAI,CAAC,MAAA,CAAO,UAAA,CAAW,MAAM,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,IAC5D;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,OAAA,IAAW,
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Userplex - Simple Analytics SDK\n * \n * Just install and use. No complex setup required.\n * \n * @example\n * ```ts\n * import Userplex from 'userplex';\n * \n * const userplex = new Userplex('upx_your_api_key');\n * \n * // Track events\n * await userplex.track('user123', 'button_clicked', { button: 'signup' });\n * \n * // Identify users\n * await userplex.identify('user123', { email: 'user@example.com' });\n * \n * // Log conversations\n * await userplex.logConversation({\n * messages: [\n * { role: 'user', content: 'Hello' },\n * { role: 'assistant', content: 'Hi there!' }\n * ]\n * });\n * ```\n */\n\nexport interface ConversationMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n}\n\nexport interface UserplexOptions {\n /** Your Userplex instance URL (default: https://userplex.vercel.app) */\n baseUrl?: string;\n /** Request timeout in ms (default: 10000) */\n timeout?: number;\n /** Enable debug logging (default: false) */\n debug?: boolean;\n}\n\nexport class UserplexError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: any\n ) {\n super(message);\n this.name = 'UserplexError';\n }\n}\n\nclass Userplex {\n private apiKey: string;\n private baseUrl: string;\n private timeout: number;\n private debug: boolean;\n\n constructor(apiKey: string, options: UserplexOptions = {}) {\n if (!apiKey) {\n throw new Error('Userplex: API key is required');\n }\n if (!apiKey.startsWith('upx_')) {\n throw new Error('Userplex: API key must start with \"upx_\"');\n }\n\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl || 'https://userplex.vercel.app').replace(/\\/$/, '');\n this.timeout = options.timeout || 10000;\n this.debug = options.debug || false;\n }\n\n /**\n * Track an event\n */\n async track(userId: string, event: string, properties?: Record<string, any>) {\n if (!userId || !event) {\n throw new Error('userId and event are required');\n }\n\n return this.request('/api/events', {\n userId,\n event,\n properties: properties || {}\n });\n }\n\n /**\n * Identify a user\n */\n async identify(externalId: string, properties?: Record<string, any>) {\n if (!externalId) {\n throw new Error('externalId is required');\n }\n\n return this.request('/api/identify', {\n externalId,\n ...properties\n }, {\n 'x-api-key': this.apiKey // identify endpoint uses this header too\n });\n }\n\n /**\n * Log a conversation\n */\n async logConversation(options: {\n messages: ConversationMessage[];\n userId?: string;\n conversationId?: string;\n conversationName?: string;\n }) {\n if (!options.messages || options.messages.length === 0) {\n throw new Error('messages array is required and cannot be empty');\n }\n\n return this.request('/api/conversations', {\n externalUserId: options.userId,\n conversationId: options.conversationId,\n conversationName: options.conversationName,\n messages: options.messages\n });\n }\n\n /**\n * Batch track multiple events\n */\n async trackBatch(events: Array<{\n userId: string;\n event: string;\n properties?: Record<string, any>;\n }>) {\n if (!events || events.length === 0) {\n throw new Error('events array is required and cannot be empty');\n }\n\n const promises = events.map(e => this.track(e.userId, e.event, e.properties));\n return Promise.all(promises);\n }\n\n private async request(endpoint: string, data: any, additionalHeaders?: Record<string, string>) {\n const url = `${this.baseUrl}${endpoint}`;\n \n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n if (this.debug) {\n console.log(`[Userplex] POST ${url}`, JSON.stringify(data, null, 2));\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...additionalHeaders\n },\n body: JSON.stringify(data),\n signal: controller.signal\n });\n\n clearTimeout(timeoutId);\n\n const responseData = await response.json() as any;\n\n if (this.debug) {\n console.log(`[Userplex] Response:`, JSON.stringify(responseData, null, 2));\n }\n\n if (!response.ok) {\n throw new UserplexError(\n responseData.error || `Request failed with status ${response.status}`,\n response.status,\n responseData\n );\n }\n\n return responseData;\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n if (error.name === 'AbortError') {\n throw new UserplexError('Request timeout', 408);\n }\n\n if (error instanceof UserplexError) {\n throw error;\n }\n\n throw new UserplexError(\n error.message || 'An unexpected error occurred',\n undefined,\n error\n );\n }\n }\n}\n\nexport default Userplex;\n\n// For environments that need it separate\nexport { Userplex };\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -16,7 +16,7 @@ var Userplex = class {
|
|
|
16
16
|
throw new Error('Userplex: API key must start with "upx_"');
|
|
17
17
|
}
|
|
18
18
|
this.apiKey = apiKey;
|
|
19
|
-
this.baseUrl = (options.baseUrl || "
|
|
19
|
+
this.baseUrl = (options.baseUrl || "https://userplex.vercel.app").replace(/\/$/, "");
|
|
20
20
|
this.timeout = options.timeout || 1e4;
|
|
21
21
|
this.debug = options.debug || false;
|
|
22
22
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts"],"names":[],"mappings":";AAyCO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EACvC,WAAA,CACE,OAAA,EACO,UAAA,EACA,QAAA,EACP;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAHN,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAGP,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEA,IAAM,WAAN,MAAe;AAAA,EAMb,WAAA,CAAY,MAAA,EAAgB,OAAA,GAA2B,EAAC,EAAG;AACzD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,IACjD;AACA,IAAA,IAAI,CAAC,MAAA,CAAO,UAAA,CAAW,MAAM,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,IAC5D;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,OAAA,IAAW,
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Userplex - Simple Analytics SDK\n * \n * Just install and use. No complex setup required.\n * \n * @example\n * ```ts\n * import Userplex from 'userplex';\n * \n * const userplex = new Userplex('upx_your_api_key');\n * \n * // Track events\n * await userplex.track('user123', 'button_clicked', { button: 'signup' });\n * \n * // Identify users\n * await userplex.identify('user123', { email: 'user@example.com' });\n * \n * // Log conversations\n * await userplex.logConversation({\n * messages: [\n * { role: 'user', content: 'Hello' },\n * { role: 'assistant', content: 'Hi there!' }\n * ]\n * });\n * ```\n */\n\nexport interface ConversationMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n}\n\nexport interface UserplexOptions {\n /** Your Userplex instance URL (default: https://userplex.vercel.app) */\n baseUrl?: string;\n /** Request timeout in ms (default: 10000) */\n timeout?: number;\n /** Enable debug logging (default: false) */\n debug?: boolean;\n}\n\nexport class UserplexError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: any\n ) {\n super(message);\n this.name = 'UserplexError';\n }\n}\n\nclass Userplex {\n private apiKey: string;\n private baseUrl: string;\n private timeout: number;\n private debug: boolean;\n\n constructor(apiKey: string, options: UserplexOptions = {}) {\n if (!apiKey) {\n throw new Error('Userplex: API key is required');\n }\n if (!apiKey.startsWith('upx_')) {\n throw new Error('Userplex: API key must start with \"upx_\"');\n }\n\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl || 'https://userplex.vercel.app').replace(/\\/$/, '');\n this.timeout = options.timeout || 10000;\n this.debug = options.debug || false;\n }\n\n /**\n * Track an event\n */\n async track(userId: string, event: string, properties?: Record<string, any>) {\n if (!userId || !event) {\n throw new Error('userId and event are required');\n }\n\n return this.request('/api/events', {\n userId,\n event,\n properties: properties || {}\n });\n }\n\n /**\n * Identify a user\n */\n async identify(externalId: string, properties?: Record<string, any>) {\n if (!externalId) {\n throw new Error('externalId is required');\n }\n\n return this.request('/api/identify', {\n externalId,\n ...properties\n }, {\n 'x-api-key': this.apiKey // identify endpoint uses this header too\n });\n }\n\n /**\n * Log a conversation\n */\n async logConversation(options: {\n messages: ConversationMessage[];\n userId?: string;\n conversationId?: string;\n conversationName?: string;\n }) {\n if (!options.messages || options.messages.length === 0) {\n throw new Error('messages array is required and cannot be empty');\n }\n\n return this.request('/api/conversations', {\n externalUserId: options.userId,\n conversationId: options.conversationId,\n conversationName: options.conversationName,\n messages: options.messages\n });\n }\n\n /**\n * Batch track multiple events\n */\n async trackBatch(events: Array<{\n userId: string;\n event: string;\n properties?: Record<string, any>;\n }>) {\n if (!events || events.length === 0) {\n throw new Error('events array is required and cannot be empty');\n }\n\n const promises = events.map(e => this.track(e.userId, e.event, e.properties));\n return Promise.all(promises);\n }\n\n private async request(endpoint: string, data: any, additionalHeaders?: Record<string, string>) {\n const url = `${this.baseUrl}${endpoint}`;\n \n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n if (this.debug) {\n console.log(`[Userplex] POST ${url}`, JSON.stringify(data, null, 2));\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...additionalHeaders\n },\n body: JSON.stringify(data),\n signal: controller.signal\n });\n\n clearTimeout(timeoutId);\n\n const responseData = await response.json() as any;\n\n if (this.debug) {\n console.log(`[Userplex] Response:`, JSON.stringify(responseData, null, 2));\n }\n\n if (!response.ok) {\n throw new UserplexError(\n responseData.error || `Request failed with status ${response.status}`,\n response.status,\n responseData\n );\n }\n\n return responseData;\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n if (error.name === 'AbortError') {\n throw new UserplexError('Request timeout', 408);\n }\n\n if (error instanceof UserplexError) {\n throw error;\n }\n\n throw new UserplexError(\n error.message || 'An unexpected error occurred',\n undefined,\n error\n );\n }\n }\n}\n\nexport default Userplex;\n\n// For environments that need it separate\nexport { Userplex };\n"]}
|