@seriphxyz/core 0.1.2 → 0.1.7

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 ADDED
@@ -0,0 +1,277 @@
1
+ # @seriphxyz/core
2
+
3
+ > **Note:** This repo is a read-only mirror. Source lives in a private monorepo.
4
+ > For issues/PRs, please open them here and we'll sync changes back.
5
+
6
+ Framework-agnostic API client, types, and headless controllers for [Seriph](https://seriph.xyz) widgets.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @seriphxyz/core
12
+ ```
13
+
14
+ This is the base package used by `@seriphxyz/astro`, `@seriphxyz/react`, and `@seriphxyz/solid`. Use it directly when building custom integrations or with any JavaScript framework.
15
+
16
+ ## API Functions
17
+
18
+ ### Comments
19
+
20
+ ```ts
21
+ import { fetchComments, postComment } from "@seriphxyz/core";
22
+
23
+ // Fetch comments for a page
24
+ const comments = await fetchComments({
25
+ siteKey: "your-key",
26
+ pageId: "my-page",
27
+ });
28
+
29
+ // Post a new comment
30
+ await postComment({
31
+ siteKey: "your-key",
32
+ pageId: "my-page",
33
+ authorName: "John",
34
+ content: "Great post!",
35
+ authorEmail: "john@example.com", // optional
36
+ parentId: "comment-id", // optional, for replies
37
+ });
38
+ ```
39
+
40
+ ### Reactions
41
+
42
+ ```ts
43
+ import { fetchReactions, addReaction, removeReaction } from "@seriphxyz/core";
44
+
45
+ // Fetch reactions for a page
46
+ const { counts, userReactions } = await fetchReactions({
47
+ siteKey: "your-key",
48
+ pageId: "my-page",
49
+ });
50
+
51
+ // Add a reaction
52
+ await addReaction({
53
+ siteKey: "your-key",
54
+ pageId: "my-page",
55
+ reactionType: "like", // or 'clap', 'heart', etc.
56
+ });
57
+
58
+ // Remove a reaction
59
+ await removeReaction({
60
+ siteKey: "your-key",
61
+ pageId: "my-page",
62
+ reactionType: "like",
63
+ });
64
+ ```
65
+
66
+ ### Forms
67
+
68
+ ```ts
69
+ import { submitForm } from "@seriphxyz/core";
70
+
71
+ await submitForm({
72
+ siteKey: "your-key",
73
+ formSlug: "contact",
74
+ data: {
75
+ name: "John",
76
+ email: "john@example.com",
77
+ message: "Hello!",
78
+ },
79
+ });
80
+ ```
81
+
82
+ ### Subscriptions
83
+
84
+ ```ts
85
+ import { subscribe } from "@seriphxyz/core";
86
+
87
+ await subscribe({
88
+ siteKey: "your-key",
89
+ email: "user@example.com",
90
+ });
91
+ ```
92
+
93
+ ### Waitlist
94
+
95
+ ```ts
96
+ import { joinWaitlist } from "@seriphxyz/core";
97
+
98
+ await joinWaitlist({
99
+ siteKey: "your-key",
100
+ email: "user@example.com",
101
+ name: "John", // optional
102
+ source: "homepage", // optional
103
+ });
104
+ ```
105
+
106
+ ### Feedback
107
+
108
+ ```ts
109
+ import { submitFeedback } from "@seriphxyz/core";
110
+
111
+ await submitFeedback({
112
+ siteKey: "your-key",
113
+ type: "bug", // 'bug' | 'feature' | 'general'
114
+ content: "Found an issue...",
115
+ email: "user@example.com", // optional
116
+ pageUrl: "/about", // optional
117
+ });
118
+ ```
119
+
120
+ ### Polls
121
+
122
+ ```ts
123
+ import { fetchPoll, votePoll } from "@seriphxyz/core";
124
+
125
+ // Fetch poll data
126
+ const poll = await fetchPoll({
127
+ siteKey: "your-key",
128
+ pollId: 123,
129
+ });
130
+
131
+ // Vote on a poll
132
+ await votePoll({
133
+ siteKey: "your-key",
134
+ pollId: 123,
135
+ selectedOptions: ["option-1", "option-2"],
136
+ });
137
+ ```
138
+
139
+ ### Views
140
+
141
+ ```ts
142
+ import { getViewCounts, recordView } from "@seriphxyz/core";
143
+
144
+ // Get view counts
145
+ const { views, uniqueVisitors } = await getViewCounts({
146
+ siteKey: "your-key",
147
+ pageId: "my-page",
148
+ });
149
+
150
+ // Record a view
151
+ await recordView({
152
+ siteKey: "your-key",
153
+ pageId: "my-page",
154
+ });
155
+ ```
156
+
157
+ ### Announcements
158
+
159
+ ```ts
160
+ import { fetchAnnouncements, dismissAnnouncement } from "@seriphxyz/core";
161
+
162
+ // Fetch active announcements
163
+ const announcements = await fetchAnnouncements({
164
+ siteKey: "your-key",
165
+ });
166
+
167
+ // Dismiss an announcement
168
+ await dismissAnnouncement({
169
+ siteKey: "your-key",
170
+ announcementId: 123,
171
+ });
172
+ ```
173
+
174
+ ### Posts
175
+
176
+ ```ts
177
+ import { fetchPosts, fetchPost } from "@seriphxyz/core";
178
+
179
+ // Fetch all published posts
180
+ const posts = await fetchPosts({
181
+ siteKey: "your-key",
182
+ tag: "tutorials", // optional filter
183
+ limit: 10, // optional
184
+ });
185
+
186
+ // Fetch a single post
187
+ const post = await fetchPost({
188
+ siteKey: "your-key",
189
+ slug: "my-post",
190
+ });
191
+ ```
192
+
193
+ ## Headless Controllers
194
+
195
+ Controllers manage state without any DOM dependencies. Use them to build custom UI or integrate with any framework.
196
+
197
+ ```ts
198
+ import {
199
+ SubscribeController,
200
+ FormController,
201
+ ReactionsController,
202
+ CommentsController,
203
+ WaitlistController,
204
+ FeedbackController,
205
+ PollController,
206
+ AnnouncementsController,
207
+ ViewCountsController,
208
+ } from "@seriphxyz/core";
209
+
210
+ // Example: Subscribe controller
211
+ const controller = new SubscribeController({ siteKey: "your-key" });
212
+
213
+ // Subscribe to state changes
214
+ controller.subscribe((state) => {
215
+ console.log(state.status); // 'idle' | 'loading' | 'success' | 'error'
216
+ console.log(state.message);
217
+ console.log(state.error);
218
+ });
219
+
220
+ // Submit
221
+ await controller.submit("user@example.com");
222
+
223
+ // Reset
224
+ controller.reset();
225
+ ```
226
+
227
+ ### Available Controllers
228
+
229
+ | Controller | Purpose |
230
+ |------------|---------|
231
+ | `SubscribeController` | Email subscriptions |
232
+ | `FormController` | Form submissions |
233
+ | `ReactionsController` | Page reactions |
234
+ | `CommentsController` | Threaded comments |
235
+ | `WaitlistController` | Waitlist signups |
236
+ | `FeedbackController` | Feedback forms |
237
+ | `PollController` | Polls and voting |
238
+ | `AnnouncementsController` | Site announcements |
239
+ | `ViewCountsController` | Page view tracking |
240
+
241
+ ## Visitor Management
242
+
243
+ Reactions and views track visitors using localStorage. For authenticated users, you can set a custom visitor ID:
244
+
245
+ ```ts
246
+ import { setVisitorId, getVisitorId } from "@seriphxyz/core";
247
+
248
+ // Set custom visitor ID (e.g., for logged-in users)
249
+ setVisitorId("user-123");
250
+
251
+ // Get current visitor ID
252
+ const visitorId = getVisitorId();
253
+
254
+ // Revert to localStorage-based ID
255
+ setVisitorId(null);
256
+ ```
257
+
258
+ ## Types
259
+
260
+ All types are exported for TypeScript users:
261
+
262
+ ```ts
263
+ import type {
264
+ SeriphConfig,
265
+ Comment,
266
+ ReactionCounts,
267
+ SeriphPost,
268
+ Poll,
269
+ Announcement,
270
+ FeedbackType,
271
+ ControllerStatus,
272
+ } from "@seriphxyz/core";
273
+ ```
274
+
275
+ ## License
276
+
277
+ MIT
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
  export declare const DEFAULT_ENDPOINT = "https://seriph.xyz";
8
8
  export declare const API_PATH = "/api/v1";
9
+ export declare const VISITOR_STORAGE_KEY = "seriph_visitor_id";
9
10
  export interface SeriphConfig {
10
11
  /** Your site key (required) */
11
12
  siteKey: string;
@@ -52,6 +53,17 @@ export interface SeriphPost {
52
53
  export declare function buildUrl(endpoint: string | undefined, path: string): string;
53
54
  /** Get site key from config */
54
55
  export declare function getSiteKey(config: SeriphConfig): string;
56
+ /**
57
+ * Set a custom visitor ID (e.g., authenticated user ID).
58
+ * Useful for non-static sites where you have user sessions.
59
+ * Set to null to revert to localStorage-based ID.
60
+ */
61
+ export declare function setVisitorId(id: string | null): void;
62
+ /**
63
+ * Get the current visitor ID.
64
+ * Priority: custom ID > localStorage
65
+ */
66
+ export declare function getVisitorId(): string;
55
67
  export interface SubmitFormOptions extends SeriphConfig {
56
68
  formSlug: string;
57
69
  data: Record<string, unknown>;
@@ -74,7 +86,11 @@ export declare function postComment(options: PostCommentOptions): Promise<Commen
74
86
  export interface FetchReactionsOptions extends SeriphConfig {
75
87
  pageId: string;
76
88
  }
77
- export declare function fetchReactions(options: FetchReactionsOptions): Promise<ReactionCounts>;
89
+ export interface FetchReactionsResponse extends ReactionCounts {
90
+ /** Reaction types the current visitor has added (based on visitor token) */
91
+ userReactions: string[];
92
+ }
93
+ export declare function fetchReactions(options: FetchReactionsOptions): Promise<FetchReactionsResponse>;
78
94
  export interface AddReactionOptions extends SeriphConfig {
79
95
  pageId: string;
80
96
  reactionType?: string;
@@ -107,6 +123,98 @@ export interface FetchPostOptions extends SeriphConfig {
107
123
  slug: string;
108
124
  }
109
125
  export declare function fetchPost(options: FetchPostOptions): Promise<SeriphPost | null>;
126
+ export interface JoinWaitlistOptions extends SeriphConfig {
127
+ email: string;
128
+ name?: string;
129
+ /** Where the signup came from (e.g., "homepage", "blog") */
130
+ source?: string;
131
+ }
132
+ export interface JoinWaitlistResponse {
133
+ success: boolean;
134
+ message: string;
135
+ /** Position in waitlist (if site chooses to show it) */
136
+ position?: number;
137
+ }
138
+ export declare function joinWaitlist(options: JoinWaitlistOptions): Promise<JoinWaitlistResponse>;
139
+ export interface ViewCountsOptions extends SeriphConfig {
140
+ pageId: string;
141
+ }
142
+ export interface ViewCounts {
143
+ pageId: string;
144
+ views: number;
145
+ uniqueVisitors: number;
146
+ }
147
+ export interface RecordViewResponse extends ViewCounts {
148
+ isNewVisitor: boolean;
149
+ }
150
+ export declare function getViewCounts(options: ViewCountsOptions): Promise<ViewCounts>;
151
+ export declare function recordView(options: ViewCountsOptions): Promise<RecordViewResponse>;
152
+ export type FeedbackType = "bug" | "feature" | "general";
153
+ export interface SubmitFeedbackOptions extends SeriphConfig {
154
+ type: FeedbackType;
155
+ content: string;
156
+ email?: string;
157
+ /** Page URL where feedback was submitted */
158
+ pageUrl?: string;
159
+ }
160
+ export interface SubmitFeedbackResponse {
161
+ success: boolean;
162
+ message: string;
163
+ }
164
+ export declare function submitFeedback(options: SubmitFeedbackOptions): Promise<SubmitFeedbackResponse>;
165
+ export type ShowResultsMode = "always" | "after_vote" | "after_end" | "never";
166
+ export interface PollOption {
167
+ id: string;
168
+ text: string;
169
+ }
170
+ export interface PollSettings {
171
+ multiSelect: boolean;
172
+ showResults: ShowResultsMode;
173
+ }
174
+ export interface Poll {
175
+ id: number;
176
+ question: string;
177
+ options: PollOption[];
178
+ settings: PollSettings;
179
+ endsAt?: string;
180
+ isActive: boolean;
181
+ }
182
+ export interface PollWithResults extends Poll {
183
+ results: Record<string, number>;
184
+ totalVotes: number;
185
+ /** Options the current visitor has voted for */
186
+ userVotes?: string[];
187
+ }
188
+ export interface FetchPollOptions extends SeriphConfig {
189
+ pollId: number;
190
+ }
191
+ export declare function fetchPoll(options: FetchPollOptions): Promise<PollWithResults>;
192
+ export interface VotePollOptions extends SeriphConfig {
193
+ pollId: number;
194
+ selectedOptions: string[];
195
+ }
196
+ export interface VotePollResponse {
197
+ success: boolean;
198
+ results: Record<string, number>;
199
+ totalVotes: number;
200
+ }
201
+ export declare function votePoll(options: VotePollOptions): Promise<VotePollResponse>;
202
+ export type AnnouncementType = "info" | "warning" | "success" | "error";
203
+ export interface Announcement {
204
+ id: number;
205
+ content: string;
206
+ announcementType: AnnouncementType;
207
+ linkUrl?: string;
208
+ linkText?: string;
209
+ isDismissible: boolean;
210
+ }
211
+ export interface FetchAnnouncementsOptions extends SeriphConfig {
212
+ }
213
+ export declare function fetchAnnouncements(options: FetchAnnouncementsOptions): Promise<Announcement[]>;
214
+ export interface DismissAnnouncementOptions extends SeriphConfig {
215
+ announcementId: number;
216
+ }
217
+ export declare function dismissAnnouncement(options: DismissAnnouncementOptions): Promise<void>;
110
218
  export type ControllerStatus = "idle" | "loading" | "success" | "error";
111
219
  /** State for subscribe controllers */
112
220
  export interface SubscribeState {
@@ -133,6 +241,13 @@ export interface CommentsState {
133
241
  status: ControllerStatus;
134
242
  error: Error | null;
135
243
  }
244
+ /** State for waitlist controllers */
245
+ export interface WaitlistState {
246
+ status: ControllerStatus;
247
+ message: string | null;
248
+ position: number | null;
249
+ error: Error | null;
250
+ }
136
251
  export interface ControllerListener<T> {
137
252
  (state: T): void;
138
253
  }
@@ -162,6 +277,32 @@ export declare class SubscribeController {
162
277
  /** Reset to idle state */
163
278
  reset(): void;
164
279
  }
280
+ /**
281
+ * Headless controller for waitlist forms.
282
+ * Manages state without any DOM/framework dependencies.
283
+ *
284
+ * @example
285
+ * const controller = new WaitlistController({ siteKey: 'xxx' });
286
+ * controller.subscribe((state) => {
287
+ * console.log(state.status, state.message, state.position);
288
+ * });
289
+ * await controller.join('user@example.com', { name: 'John', source: 'homepage' });
290
+ */
291
+ export declare class WaitlistController {
292
+ private config;
293
+ private listeners;
294
+ private _state;
295
+ constructor(config: SeriphConfig);
296
+ getState(): WaitlistState;
297
+ subscribe(listener: ControllerListener<WaitlistState>): () => void;
298
+ private notify;
299
+ /** Join the waitlist */
300
+ join(email: string, options?: {
301
+ name?: string;
302
+ source?: string;
303
+ }): Promise<JoinWaitlistResponse>;
304
+ reset(): void;
305
+ }
165
306
  /**
166
307
  * Headless controller for forms.
167
308
  * Manages state without any DOM/framework dependencies.
@@ -217,4 +358,106 @@ export declare class CommentsController {
217
358
  parentId?: string;
218
359
  }): Promise<Comment>;
219
360
  }
361
+ /** State for feedback controllers */
362
+ export interface FeedbackState {
363
+ status: ControllerStatus;
364
+ message: string | null;
365
+ error: Error | null;
366
+ }
367
+ /**
368
+ * Headless controller for feedback forms.
369
+ * Manages state without any DOM/framework dependencies.
370
+ */
371
+ export declare class FeedbackController {
372
+ private config;
373
+ private listeners;
374
+ private _state;
375
+ constructor(config: SeriphConfig);
376
+ getState(): FeedbackState;
377
+ subscribe(listener: ControllerListener<FeedbackState>): () => void;
378
+ private notify;
379
+ submit(type: FeedbackType, content: string, options?: {
380
+ email?: string;
381
+ pageUrl?: string;
382
+ }): Promise<SubmitFeedbackResponse>;
383
+ reset(): void;
384
+ }
385
+ /** State for poll controllers */
386
+ export interface PollState {
387
+ poll: PollWithResults | null;
388
+ status: ControllerStatus;
389
+ error: Error | null;
390
+ }
391
+ /**
392
+ * Headless controller for polls.
393
+ * Manages poll state, voting, and results.
394
+ */
395
+ export declare class PollController {
396
+ private config;
397
+ private pollId;
398
+ private listeners;
399
+ private _state;
400
+ constructor(config: SeriphConfig, pollId: number);
401
+ getState(): PollState;
402
+ subscribe(listener: ControllerListener<PollState>): () => void;
403
+ private notify;
404
+ /** Fetch poll data from the server */
405
+ fetch(): Promise<PollWithResults>;
406
+ /** Vote on the poll */
407
+ vote(selectedOptions: string[]): Promise<VotePollResponse>;
408
+ /** Check if user has voted */
409
+ hasVoted(): boolean;
410
+ }
411
+ /** State for announcements controllers */
412
+ export interface AnnouncementsState {
413
+ announcements: Announcement[];
414
+ dismissed: Set<number>;
415
+ status: ControllerStatus;
416
+ error: Error | null;
417
+ }
418
+ /**
419
+ * Headless controller for announcements.
420
+ * Manages announcement list and dismissals.
421
+ */
422
+ export declare class AnnouncementsController {
423
+ private config;
424
+ private listeners;
425
+ private _state;
426
+ constructor(config: SeriphConfig);
427
+ getState(): AnnouncementsState;
428
+ /** Get visible (non-dismissed) announcements */
429
+ getVisibleAnnouncements(): Announcement[];
430
+ subscribe(listener: ControllerListener<AnnouncementsState>): () => void;
431
+ private notify;
432
+ /** Fetch announcements from the server */
433
+ fetch(): Promise<Announcement[]>;
434
+ /** Dismiss an announcement */
435
+ dismiss(announcementId: number): Promise<void>;
436
+ }
437
+ /** State for view counts controllers */
438
+ export interface ViewCountsState {
439
+ pageId: string;
440
+ views: number;
441
+ uniqueVisitors: number;
442
+ status: ControllerStatus;
443
+ error: Error | null;
444
+ }
445
+ /**
446
+ * Headless controller for view counts.
447
+ * Tracks page views and unique visitors.
448
+ */
449
+ export declare class ViewCountsController {
450
+ private config;
451
+ private pageId;
452
+ private listeners;
453
+ private _state;
454
+ constructor(config: SeriphConfig, pageId: string);
455
+ getState(): ViewCountsState;
456
+ subscribe(listener: ControllerListener<ViewCountsState>): () => void;
457
+ private notify;
458
+ /** Fetch view counts from the server */
459
+ fetch(): Promise<ViewCounts>;
460
+ /** Record a view (automatically tracks unique visitors via visitor token) */
461
+ record(): Promise<RecordViewResponse>;
462
+ }
220
463
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@
9
9
  // =============================================================================
10
10
  export const DEFAULT_ENDPOINT = "https://seriph.xyz";
11
11
  export const API_PATH = "/api/v1";
12
+ export const VISITOR_STORAGE_KEY = "seriph_visitor_id";
12
13
  // =============================================================================
13
14
  // Helpers
14
15
  // =============================================================================
@@ -24,6 +25,56 @@ export function getSiteKey(config) {
24
25
  }
25
26
  return config.siteKey;
26
27
  }
28
+ // =============================================================================
29
+ // Visitor Token Management
30
+ // =============================================================================
31
+ /** Custom visitor ID set by the site (e.g., authenticated user ID) */
32
+ let customVisitorId = null;
33
+ /** Generate a random UUID v4 */
34
+ function generateUUID() {
35
+ // Use crypto.randomUUID if available, otherwise fallback
36
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
37
+ return crypto.randomUUID();
38
+ }
39
+ // Fallback for older environments
40
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
41
+ const r = (Math.random() * 16) | 0;
42
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
43
+ return v.toString(16);
44
+ });
45
+ }
46
+ /**
47
+ * Set a custom visitor ID (e.g., authenticated user ID).
48
+ * Useful for non-static sites where you have user sessions.
49
+ * Set to null to revert to localStorage-based ID.
50
+ */
51
+ export function setVisitorId(id) {
52
+ customVisitorId = id;
53
+ }
54
+ /**
55
+ * Get the current visitor ID.
56
+ * Priority: custom ID > localStorage
57
+ */
58
+ export function getVisitorId() {
59
+ // Use custom ID if set (for authenticated users)
60
+ if (customVisitorId) {
61
+ return customVisitorId;
62
+ }
63
+ // Use localStorage for anonymous visitors
64
+ let visitorId = localStorage.getItem(VISITOR_STORAGE_KEY);
65
+ if (!visitorId) {
66
+ visitorId = generateUUID();
67
+ localStorage.setItem(VISITOR_STORAGE_KEY, visitorId);
68
+ }
69
+ return visitorId;
70
+ }
71
+ /** Get common headers for API requests */
72
+ function getHeaders(siteKey) {
73
+ return {
74
+ "X-Seriph-Key": siteKey,
75
+ "X-Seriph-Visitor": getVisitorId(),
76
+ };
77
+ }
27
78
  export async function submitForm(options) {
28
79
  const { endpoint, formSlug, data, formLoadTime } = options;
29
80
  const siteKey = getSiteKey(options);
@@ -35,8 +86,8 @@ export async function submitForm(options) {
35
86
  const response = await fetch(url, {
36
87
  method: "POST",
37
88
  headers: {
89
+ ...getHeaders(siteKey),
38
90
  "Content-Type": "application/json",
39
- "X-Seriph-Key": siteKey,
40
91
  },
41
92
  body: JSON.stringify(payload),
42
93
  });
@@ -50,9 +101,7 @@ export async function fetchComments(options) {
50
101
  const siteKey = getSiteKey(options);
51
102
  const url = buildUrl(endpoint, `/comments/${encodeURIComponent(pageId)}`);
52
103
  const response = await fetch(url, {
53
- headers: {
54
- "X-Seriph-Key": siteKey,
55
- },
104
+ headers: getHeaders(siteKey),
56
105
  });
57
106
  if (!response.ok) {
58
107
  throw new Error(`Failed to fetch comments: ${response.statusText}`);
@@ -67,8 +116,8 @@ export async function postComment(options) {
67
116
  const response = await fetch(url, {
68
117
  method: "POST",
69
118
  headers: {
119
+ ...getHeaders(siteKey),
70
120
  "Content-Type": "application/json",
71
- "X-Seriph-Key": siteKey,
72
121
  },
73
122
  body: JSON.stringify({
74
123
  authorName,
@@ -88,15 +137,16 @@ export async function fetchReactions(options) {
88
137
  const siteKey = getSiteKey(options);
89
138
  const url = buildUrl(endpoint, `/reactions/${encodeURIComponent(pageId)}`);
90
139
  const response = await fetch(url, {
91
- headers: {
92
- "X-Seriph-Key": siteKey,
93
- },
140
+ headers: getHeaders(siteKey),
94
141
  });
95
142
  if (!response.ok) {
96
143
  throw new Error(`Failed to fetch reactions: ${response.statusText}`);
97
144
  }
98
145
  const data = await response.json();
99
- return data.data;
146
+ return {
147
+ ...data.data,
148
+ userReactions: data.data.userReactions || [],
149
+ };
100
150
  }
101
151
  export async function addReaction(options) {
102
152
  const { endpoint, pageId, reactionType = "like" } = options;
@@ -105,8 +155,8 @@ export async function addReaction(options) {
105
155
  const response = await fetch(url, {
106
156
  method: "POST",
107
157
  headers: {
158
+ ...getHeaders(siteKey),
108
159
  "Content-Type": "application/json",
109
- "X-Seriph-Key": siteKey,
110
160
  },
111
161
  body: JSON.stringify({ reactionType }),
112
162
  });
@@ -123,8 +173,8 @@ export async function removeReaction(options) {
123
173
  const response = await fetch(url, {
124
174
  method: "DELETE",
125
175
  headers: {
176
+ ...getHeaders(siteKey),
126
177
  "Content-Type": "application/json",
127
- "X-Seriph-Key": siteKey,
128
178
  },
129
179
  body: JSON.stringify({ reactionType }),
130
180
  });
@@ -141,8 +191,8 @@ export async function subscribe(options) {
141
191
  const response = await fetch(url, {
142
192
  method: "POST",
143
193
  headers: {
194
+ ...getHeaders(siteKey),
144
195
  "Content-Type": "application/json",
145
- "X-Seriph-Key": siteKey,
146
196
  },
147
197
  body: JSON.stringify({ email }),
148
198
  });
@@ -161,9 +211,7 @@ export async function fetchPosts(options) {
161
211
  url.searchParams.set("tag", tag);
162
212
  }
163
213
  const response = await fetch(url.toString(), {
164
- headers: {
165
- "X-Seriph-Key": siteKey,
166
- },
214
+ headers: getHeaders(siteKey),
167
215
  });
168
216
  if (!response.ok) {
169
217
  throw new Error(`Failed to fetch posts: ${response.status} ${response.statusText}`);
@@ -176,9 +224,7 @@ export async function fetchPost(options) {
176
224
  const siteKey = getSiteKey(options);
177
225
  const baseUrl = (endpoint || DEFAULT_ENDPOINT).replace(/\/+$/, "") + API_PATH;
178
226
  const response = await fetch(`${baseUrl}/posts/${encodeURIComponent(slug)}`, {
179
- headers: {
180
- "X-Seriph-Key": siteKey,
181
- },
227
+ headers: getHeaders(siteKey),
182
228
  });
183
229
  if (response.status === 404) {
184
230
  return null;
@@ -189,6 +235,128 @@ export async function fetchPost(options) {
189
235
  const data = await response.json();
190
236
  return data.public_post || data;
191
237
  }
238
+ export async function joinWaitlist(options) {
239
+ const { endpoint, email, name, source } = options;
240
+ const siteKey = getSiteKey(options);
241
+ const url = buildUrl(endpoint, "/waitlist");
242
+ const response = await fetch(url, {
243
+ method: "POST",
244
+ headers: {
245
+ ...getHeaders(siteKey),
246
+ "Content-Type": "application/json",
247
+ },
248
+ body: JSON.stringify({ email, name, source }),
249
+ });
250
+ if (!response.ok) {
251
+ throw new Error(`Failed to join waitlist: ${response.statusText}`);
252
+ }
253
+ return response.json();
254
+ }
255
+ export async function getViewCounts(options) {
256
+ const { endpoint, pageId } = options;
257
+ const siteKey = getSiteKey(options);
258
+ const url = buildUrl(endpoint, `/views/${encodeURIComponent(pageId)}`);
259
+ const response = await fetch(url, {
260
+ headers: getHeaders(siteKey),
261
+ });
262
+ if (!response.ok) {
263
+ throw new Error(`Failed to get view counts: ${response.statusText}`);
264
+ }
265
+ const data = await response.json();
266
+ return data.data;
267
+ }
268
+ export async function recordView(options) {
269
+ const { endpoint, pageId } = options;
270
+ const siteKey = getSiteKey(options);
271
+ const url = buildUrl(endpoint, `/views/${encodeURIComponent(pageId)}`);
272
+ const response = await fetch(url, {
273
+ method: "POST",
274
+ headers: getHeaders(siteKey),
275
+ });
276
+ if (!response.ok) {
277
+ throw new Error(`Failed to record view: ${response.statusText}`);
278
+ }
279
+ const data = await response.json();
280
+ return data.data;
281
+ }
282
+ export async function submitFeedback(options) {
283
+ const { endpoint, type, content, email, pageUrl } = options;
284
+ const siteKey = getSiteKey(options);
285
+ const url = buildUrl(endpoint, "/feedback");
286
+ const response = await fetch(url, {
287
+ method: "POST",
288
+ headers: {
289
+ ...getHeaders(siteKey),
290
+ "Content-Type": "application/json",
291
+ },
292
+ body: JSON.stringify({
293
+ feedback_type: type,
294
+ content,
295
+ email,
296
+ page_url: pageUrl,
297
+ }),
298
+ });
299
+ if (!response.ok) {
300
+ throw new Error(`Failed to submit feedback: ${response.statusText}`);
301
+ }
302
+ return response.json();
303
+ }
304
+ export async function fetchPoll(options) {
305
+ const { endpoint, pollId } = options;
306
+ const siteKey = getSiteKey(options);
307
+ const url = buildUrl(endpoint, `/polls/${pollId}`);
308
+ const response = await fetch(url, {
309
+ headers: getHeaders(siteKey),
310
+ });
311
+ if (!response.ok) {
312
+ throw new Error(`Failed to fetch poll: ${response.statusText}`);
313
+ }
314
+ const data = await response.json();
315
+ return data.data;
316
+ }
317
+ export async function votePoll(options) {
318
+ const { endpoint, pollId, selectedOptions } = options;
319
+ const siteKey = getSiteKey(options);
320
+ const url = buildUrl(endpoint, `/polls/${pollId}/vote`);
321
+ const response = await fetch(url, {
322
+ method: "POST",
323
+ headers: {
324
+ ...getHeaders(siteKey),
325
+ "Content-Type": "application/json",
326
+ },
327
+ body: JSON.stringify({ selected_options: selectedOptions }),
328
+ });
329
+ if (!response.ok) {
330
+ throw new Error(`Failed to vote: ${response.statusText}`);
331
+ }
332
+ const data = await response.json();
333
+ return data.data;
334
+ }
335
+ export async function fetchAnnouncements(options) {
336
+ const { endpoint } = options;
337
+ const siteKey = getSiteKey(options);
338
+ const url = buildUrl(endpoint, "/announcements");
339
+ const response = await fetch(url, {
340
+ headers: getHeaders(siteKey),
341
+ });
342
+ if (!response.ok) {
343
+ throw new Error(`Failed to fetch announcements: ${response.statusText}`);
344
+ }
345
+ const data = await response.json();
346
+ return data.data || [];
347
+ }
348
+ export async function dismissAnnouncement(options) {
349
+ const { endpoint, announcementId } = options;
350
+ const siteKey = getSiteKey(options);
351
+ const url = buildUrl(endpoint, `/announcements/${announcementId}/dismiss`);
352
+ const response = await fetch(url, {
353
+ method: "POST",
354
+ headers: getHeaders(siteKey),
355
+ });
356
+ if (!response.ok) {
357
+ throw new Error(`Failed to dismiss announcement: ${response.statusText}`);
358
+ }
359
+ }
192
360
  /**
193
361
  * Headless controller for subscribe forms.
194
362
  * Manages state without any DOM/framework dependencies.
@@ -247,6 +415,70 @@ export class SubscribeController {
247
415
  this.notify();
248
416
  }
249
417
  }
418
+ /**
419
+ * Headless controller for waitlist forms.
420
+ * Manages state without any DOM/framework dependencies.
421
+ *
422
+ * @example
423
+ * const controller = new WaitlistController({ siteKey: 'xxx' });
424
+ * controller.subscribe((state) => {
425
+ * console.log(state.status, state.message, state.position);
426
+ * });
427
+ * await controller.join('user@example.com', { name: 'John', source: 'homepage' });
428
+ */
429
+ export class WaitlistController {
430
+ config;
431
+ listeners = new Set();
432
+ _state = { status: "idle", message: null, position: null, error: null };
433
+ constructor(config) {
434
+ this.config = config;
435
+ }
436
+ getState() {
437
+ return { ...this._state };
438
+ }
439
+ subscribe(listener) {
440
+ this.listeners.add(listener);
441
+ listener(this.getState());
442
+ return () => this.listeners.delete(listener);
443
+ }
444
+ notify() {
445
+ const state = this.getState();
446
+ for (const listener of this.listeners) {
447
+ listener(state);
448
+ }
449
+ }
450
+ /** Join the waitlist */
451
+ async join(email, options) {
452
+ this._state = { status: "loading", message: null, position: null, error: null };
453
+ this.notify();
454
+ try {
455
+ const result = await joinWaitlist({
456
+ ...this.config,
457
+ email,
458
+ name: options?.name,
459
+ source: options?.source,
460
+ });
461
+ this._state = {
462
+ status: "success",
463
+ message: result.message,
464
+ position: result.position ?? null,
465
+ error: null,
466
+ };
467
+ this.notify();
468
+ return result;
469
+ }
470
+ catch (e) {
471
+ const error = e instanceof Error ? e : new Error(String(e));
472
+ this._state = { status: "error", message: error.message, position: null, error };
473
+ this.notify();
474
+ throw error;
475
+ }
476
+ }
477
+ reset() {
478
+ this._state = { status: "idle", message: null, position: null, error: null };
479
+ this.notify();
480
+ }
481
+ }
250
482
  /**
251
483
  * Headless controller for forms.
252
484
  * Manages state without any DOM/framework dependencies.
@@ -336,7 +568,13 @@ export class ReactionsController {
336
568
  this.notify();
337
569
  try {
338
570
  const result = await fetchReactions({ ...this.config, pageId: this.pageId });
339
- this._state = { ...this._state, counts: result.counts, status: "success", error: null };
571
+ this._state = {
572
+ ...this._state,
573
+ counts: result.counts,
574
+ userReactions: result.userReactions,
575
+ status: "success",
576
+ error: null,
577
+ };
340
578
  this.notify();
341
579
  return this.getState();
342
580
  }
@@ -444,3 +682,272 @@ export class CommentsController {
444
682
  }
445
683
  }
446
684
  }
685
+ /**
686
+ * Headless controller for feedback forms.
687
+ * Manages state without any DOM/framework dependencies.
688
+ */
689
+ export class FeedbackController {
690
+ config;
691
+ listeners = new Set();
692
+ _state = { status: "idle", message: null, error: null };
693
+ constructor(config) {
694
+ this.config = config;
695
+ }
696
+ getState() {
697
+ return { ...this._state };
698
+ }
699
+ subscribe(listener) {
700
+ this.listeners.add(listener);
701
+ listener(this.getState());
702
+ return () => this.listeners.delete(listener);
703
+ }
704
+ notify() {
705
+ const state = this.getState();
706
+ for (const listener of this.listeners) {
707
+ listener(state);
708
+ }
709
+ }
710
+ async submit(type, content, options) {
711
+ this._state = { status: "loading", message: null, error: null };
712
+ this.notify();
713
+ try {
714
+ const result = await submitFeedback({
715
+ ...this.config,
716
+ type,
717
+ content,
718
+ email: options?.email,
719
+ pageUrl: options?.pageUrl,
720
+ });
721
+ this._state = { status: "success", message: result.message, error: null };
722
+ this.notify();
723
+ return result;
724
+ }
725
+ catch (e) {
726
+ const error = e instanceof Error ? e : new Error(String(e));
727
+ this._state = { status: "error", message: error.message, error };
728
+ this.notify();
729
+ throw error;
730
+ }
731
+ }
732
+ reset() {
733
+ this._state = { status: "idle", message: null, error: null };
734
+ this.notify();
735
+ }
736
+ }
737
+ /**
738
+ * Headless controller for polls.
739
+ * Manages poll state, voting, and results.
740
+ */
741
+ export class PollController {
742
+ config;
743
+ pollId;
744
+ listeners = new Set();
745
+ _state = { poll: null, status: "idle", error: null };
746
+ constructor(config, pollId) {
747
+ this.config = config;
748
+ this.pollId = pollId;
749
+ }
750
+ getState() {
751
+ return { ...this._state };
752
+ }
753
+ subscribe(listener) {
754
+ this.listeners.add(listener);
755
+ listener(this.getState());
756
+ return () => this.listeners.delete(listener);
757
+ }
758
+ notify() {
759
+ const state = this.getState();
760
+ for (const listener of this.listeners) {
761
+ listener(state);
762
+ }
763
+ }
764
+ /** Fetch poll data from the server */
765
+ async fetch() {
766
+ this._state = { ...this._state, status: "loading", error: null };
767
+ this.notify();
768
+ try {
769
+ const poll = await fetchPoll({ ...this.config, pollId: this.pollId });
770
+ this._state = { poll, status: "success", error: null };
771
+ this.notify();
772
+ return poll;
773
+ }
774
+ catch (e) {
775
+ const error = e instanceof Error ? e : new Error(String(e));
776
+ this._state = { ...this._state, status: "error", error };
777
+ this.notify();
778
+ throw error;
779
+ }
780
+ }
781
+ /** Vote on the poll */
782
+ async vote(selectedOptions) {
783
+ try {
784
+ const result = await votePoll({
785
+ ...this.config,
786
+ pollId: this.pollId,
787
+ selectedOptions,
788
+ });
789
+ // Update state with new results
790
+ if (this._state.poll) {
791
+ this._state.poll = {
792
+ ...this._state.poll,
793
+ results: result.results,
794
+ totalVotes: result.totalVotes,
795
+ userVotes: selectedOptions,
796
+ };
797
+ }
798
+ this.notify();
799
+ return result;
800
+ }
801
+ catch (e) {
802
+ const error = e instanceof Error ? e : new Error(String(e));
803
+ this._state = { ...this._state, error };
804
+ this.notify();
805
+ throw error;
806
+ }
807
+ }
808
+ /** Check if user has voted */
809
+ hasVoted() {
810
+ return !!this._state.poll?.userVotes && this._state.poll.userVotes.length > 0;
811
+ }
812
+ }
813
+ /**
814
+ * Headless controller for announcements.
815
+ * Manages announcement list and dismissals.
816
+ */
817
+ export class AnnouncementsController {
818
+ config;
819
+ listeners = new Set();
820
+ _state = {
821
+ announcements: [],
822
+ dismissed: new Set(),
823
+ status: "idle",
824
+ error: null,
825
+ };
826
+ constructor(config) {
827
+ this.config = config;
828
+ }
829
+ getState() {
830
+ return {
831
+ ...this._state,
832
+ announcements: [...this._state.announcements],
833
+ dismissed: new Set(this._state.dismissed),
834
+ };
835
+ }
836
+ /** Get visible (non-dismissed) announcements */
837
+ getVisibleAnnouncements() {
838
+ return this._state.announcements.filter((a) => !this._state.dismissed.has(a.id));
839
+ }
840
+ subscribe(listener) {
841
+ this.listeners.add(listener);
842
+ listener(this.getState());
843
+ return () => this.listeners.delete(listener);
844
+ }
845
+ notify() {
846
+ const state = this.getState();
847
+ for (const listener of this.listeners) {
848
+ listener(state);
849
+ }
850
+ }
851
+ /** Fetch announcements from the server */
852
+ async fetch() {
853
+ this._state = { ...this._state, status: "loading", error: null };
854
+ this.notify();
855
+ try {
856
+ const announcements = await fetchAnnouncements(this.config);
857
+ this._state = { ...this._state, announcements, status: "success", error: null };
858
+ this.notify();
859
+ return announcements;
860
+ }
861
+ catch (e) {
862
+ const error = e instanceof Error ? e : new Error(String(e));
863
+ this._state = { ...this._state, status: "error", error };
864
+ this.notify();
865
+ throw error;
866
+ }
867
+ }
868
+ /** Dismiss an announcement */
869
+ async dismiss(announcementId) {
870
+ try {
871
+ await dismissAnnouncement({ ...this.config, announcementId });
872
+ this._state.dismissed.add(announcementId);
873
+ this.notify();
874
+ }
875
+ catch (e) {
876
+ const error = e instanceof Error ? e : new Error(String(e));
877
+ this._state = { ...this._state, error };
878
+ this.notify();
879
+ throw error;
880
+ }
881
+ }
882
+ }
883
+ /**
884
+ * Headless controller for view counts.
885
+ * Tracks page views and unique visitors.
886
+ */
887
+ export class ViewCountsController {
888
+ config;
889
+ pageId;
890
+ listeners = new Set();
891
+ _state;
892
+ constructor(config, pageId) {
893
+ this.config = config;
894
+ this.pageId = pageId;
895
+ this._state = { pageId, views: 0, uniqueVisitors: 0, status: "idle", error: null };
896
+ }
897
+ getState() {
898
+ return { ...this._state };
899
+ }
900
+ subscribe(listener) {
901
+ this.listeners.add(listener);
902
+ listener(this.getState());
903
+ return () => this.listeners.delete(listener);
904
+ }
905
+ notify() {
906
+ const state = this.getState();
907
+ for (const listener of this.listeners) {
908
+ listener(state);
909
+ }
910
+ }
911
+ /** Fetch view counts from the server */
912
+ async fetch() {
913
+ this._state = { ...this._state, status: "loading", error: null };
914
+ this.notify();
915
+ try {
916
+ const counts = await getViewCounts({ ...this.config, pageId: this.pageId });
917
+ this._state = {
918
+ ...this._state,
919
+ views: counts.views,
920
+ uniqueVisitors: counts.uniqueVisitors,
921
+ status: "success",
922
+ error: null,
923
+ };
924
+ this.notify();
925
+ return counts;
926
+ }
927
+ catch (e) {
928
+ const error = e instanceof Error ? e : new Error(String(e));
929
+ this._state = { ...this._state, status: "error", error };
930
+ this.notify();
931
+ throw error;
932
+ }
933
+ }
934
+ /** Record a view (automatically tracks unique visitors via visitor token) */
935
+ async record() {
936
+ try {
937
+ const result = await recordView({ ...this.config, pageId: this.pageId });
938
+ this._state = {
939
+ ...this._state,
940
+ views: result.views,
941
+ uniqueVisitors: result.uniqueVisitors,
942
+ };
943
+ this.notify();
944
+ return result;
945
+ }
946
+ catch (e) {
947
+ const error = e instanceof Error ? e : new Error(String(e));
948
+ this._state = { ...this._state, error };
949
+ this.notify();
950
+ throw error;
951
+ }
952
+ }
953
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seriphxyz/core",
3
- "version": "0.1.2",
3
+ "version": "0.1.7",
4
4
  "description": "Framework-agnostic API client and types for Seriph widgets",
5
5
  "repository": {
6
6
  "type": "git",