@seriphxyz/core 0.1.2 → 0.1.8

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 > generated UUID (SSR fallback)
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,69 @@ 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 > generated UUID (SSR fallback)
57
+ */
58
+ export function getVisitorId() {
59
+ // Use custom ID if set (for authenticated users)
60
+ if (customVisitorId) {
61
+ return customVisitorId;
62
+ }
63
+ // SSR check - localStorage only exists in browser
64
+ if (typeof window === "undefined" || typeof localStorage === "undefined") {
65
+ // Return a temporary UUID for SSR - will be replaced client-side
66
+ return generateUUID();
67
+ }
68
+ // Use localStorage for anonymous visitors
69
+ let visitorId = localStorage.getItem(VISITOR_STORAGE_KEY);
70
+ if (!visitorId) {
71
+ visitorId = generateUUID();
72
+ localStorage.setItem(VISITOR_STORAGE_KEY, visitorId);
73
+ }
74
+ return visitorId;
75
+ }
76
+ /** Get common headers for API requests */
77
+ function getHeaders(siteKey) {
78
+ let visitorId;
79
+ try {
80
+ visitorId = getVisitorId();
81
+ }
82
+ catch {
83
+ // Fallback if localStorage access fails (e.g., private browsing, SSR)
84
+ visitorId = generateUUID();
85
+ }
86
+ return {
87
+ "X-Seriph-Key": siteKey,
88
+ "X-Seriph-Visitor": visitorId,
89
+ };
90
+ }
27
91
  export async function submitForm(options) {
28
92
  const { endpoint, formSlug, data, formLoadTime } = options;
29
93
  const siteKey = getSiteKey(options);
@@ -35,8 +99,8 @@ export async function submitForm(options) {
35
99
  const response = await fetch(url, {
36
100
  method: "POST",
37
101
  headers: {
102
+ ...getHeaders(siteKey),
38
103
  "Content-Type": "application/json",
39
- "X-Seriph-Key": siteKey,
40
104
  },
41
105
  body: JSON.stringify(payload),
42
106
  });
@@ -50,9 +114,7 @@ export async function fetchComments(options) {
50
114
  const siteKey = getSiteKey(options);
51
115
  const url = buildUrl(endpoint, `/comments/${encodeURIComponent(pageId)}`);
52
116
  const response = await fetch(url, {
53
- headers: {
54
- "X-Seriph-Key": siteKey,
55
- },
117
+ headers: getHeaders(siteKey),
56
118
  });
57
119
  if (!response.ok) {
58
120
  throw new Error(`Failed to fetch comments: ${response.statusText}`);
@@ -67,8 +129,8 @@ export async function postComment(options) {
67
129
  const response = await fetch(url, {
68
130
  method: "POST",
69
131
  headers: {
132
+ ...getHeaders(siteKey),
70
133
  "Content-Type": "application/json",
71
- "X-Seriph-Key": siteKey,
72
134
  },
73
135
  body: JSON.stringify({
74
136
  authorName,
@@ -88,15 +150,16 @@ export async function fetchReactions(options) {
88
150
  const siteKey = getSiteKey(options);
89
151
  const url = buildUrl(endpoint, `/reactions/${encodeURIComponent(pageId)}`);
90
152
  const response = await fetch(url, {
91
- headers: {
92
- "X-Seriph-Key": siteKey,
93
- },
153
+ headers: getHeaders(siteKey),
94
154
  });
95
155
  if (!response.ok) {
96
156
  throw new Error(`Failed to fetch reactions: ${response.statusText}`);
97
157
  }
98
158
  const data = await response.json();
99
- return data.data;
159
+ return {
160
+ ...data.data,
161
+ userReactions: data.data.userReactions || [],
162
+ };
100
163
  }
101
164
  export async function addReaction(options) {
102
165
  const { endpoint, pageId, reactionType = "like" } = options;
@@ -105,8 +168,8 @@ export async function addReaction(options) {
105
168
  const response = await fetch(url, {
106
169
  method: "POST",
107
170
  headers: {
171
+ ...getHeaders(siteKey),
108
172
  "Content-Type": "application/json",
109
- "X-Seriph-Key": siteKey,
110
173
  },
111
174
  body: JSON.stringify({ reactionType }),
112
175
  });
@@ -123,8 +186,8 @@ export async function removeReaction(options) {
123
186
  const response = await fetch(url, {
124
187
  method: "DELETE",
125
188
  headers: {
189
+ ...getHeaders(siteKey),
126
190
  "Content-Type": "application/json",
127
- "X-Seriph-Key": siteKey,
128
191
  },
129
192
  body: JSON.stringify({ reactionType }),
130
193
  });
@@ -141,8 +204,8 @@ export async function subscribe(options) {
141
204
  const response = await fetch(url, {
142
205
  method: "POST",
143
206
  headers: {
207
+ ...getHeaders(siteKey),
144
208
  "Content-Type": "application/json",
145
- "X-Seriph-Key": siteKey,
146
209
  },
147
210
  body: JSON.stringify({ email }),
148
211
  });
@@ -161,9 +224,7 @@ export async function fetchPosts(options) {
161
224
  url.searchParams.set("tag", tag);
162
225
  }
163
226
  const response = await fetch(url.toString(), {
164
- headers: {
165
- "X-Seriph-Key": siteKey,
166
- },
227
+ headers: getHeaders(siteKey),
167
228
  });
168
229
  if (!response.ok) {
169
230
  throw new Error(`Failed to fetch posts: ${response.status} ${response.statusText}`);
@@ -176,9 +237,7 @@ export async function fetchPost(options) {
176
237
  const siteKey = getSiteKey(options);
177
238
  const baseUrl = (endpoint || DEFAULT_ENDPOINT).replace(/\/+$/, "") + API_PATH;
178
239
  const response = await fetch(`${baseUrl}/posts/${encodeURIComponent(slug)}`, {
179
- headers: {
180
- "X-Seriph-Key": siteKey,
181
- },
240
+ headers: getHeaders(siteKey),
182
241
  });
183
242
  if (response.status === 404) {
184
243
  return null;
@@ -189,6 +248,128 @@ export async function fetchPost(options) {
189
248
  const data = await response.json();
190
249
  return data.public_post || data;
191
250
  }
251
+ export async function joinWaitlist(options) {
252
+ const { endpoint, email, name, source } = options;
253
+ const siteKey = getSiteKey(options);
254
+ const url = buildUrl(endpoint, "/waitlist");
255
+ const response = await fetch(url, {
256
+ method: "POST",
257
+ headers: {
258
+ ...getHeaders(siteKey),
259
+ "Content-Type": "application/json",
260
+ },
261
+ body: JSON.stringify({ email, name, source }),
262
+ });
263
+ if (!response.ok) {
264
+ throw new Error(`Failed to join waitlist: ${response.statusText}`);
265
+ }
266
+ return response.json();
267
+ }
268
+ export async function getViewCounts(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
+ headers: getHeaders(siteKey),
274
+ });
275
+ if (!response.ok) {
276
+ throw new Error(`Failed to get view counts: ${response.statusText}`);
277
+ }
278
+ const data = await response.json();
279
+ return data.data;
280
+ }
281
+ export async function recordView(options) {
282
+ const { endpoint, pageId } = options;
283
+ const siteKey = getSiteKey(options);
284
+ const url = buildUrl(endpoint, `/views/${encodeURIComponent(pageId)}`);
285
+ const response = await fetch(url, {
286
+ method: "POST",
287
+ headers: getHeaders(siteKey),
288
+ });
289
+ if (!response.ok) {
290
+ throw new Error(`Failed to record view: ${response.statusText}`);
291
+ }
292
+ const data = await response.json();
293
+ return data.data;
294
+ }
295
+ export async function submitFeedback(options) {
296
+ const { endpoint, type, content, email, pageUrl } = options;
297
+ const siteKey = getSiteKey(options);
298
+ const url = buildUrl(endpoint, "/feedback");
299
+ const response = await fetch(url, {
300
+ method: "POST",
301
+ headers: {
302
+ ...getHeaders(siteKey),
303
+ "Content-Type": "application/json",
304
+ },
305
+ body: JSON.stringify({
306
+ feedback_type: type,
307
+ content,
308
+ email,
309
+ page_url: pageUrl,
310
+ }),
311
+ });
312
+ if (!response.ok) {
313
+ throw new Error(`Failed to submit feedback: ${response.statusText}`);
314
+ }
315
+ return response.json();
316
+ }
317
+ export async function fetchPoll(options) {
318
+ const { endpoint, pollId } = options;
319
+ const siteKey = getSiteKey(options);
320
+ const url = buildUrl(endpoint, `/polls/${pollId}`);
321
+ const response = await fetch(url, {
322
+ headers: getHeaders(siteKey),
323
+ });
324
+ if (!response.ok) {
325
+ throw new Error(`Failed to fetch poll: ${response.statusText}`);
326
+ }
327
+ const data = await response.json();
328
+ return data.data;
329
+ }
330
+ export async function votePoll(options) {
331
+ const { endpoint, pollId, selectedOptions } = options;
332
+ const siteKey = getSiteKey(options);
333
+ const url = buildUrl(endpoint, `/polls/${pollId}/vote`);
334
+ const response = await fetch(url, {
335
+ method: "POST",
336
+ headers: {
337
+ ...getHeaders(siteKey),
338
+ "Content-Type": "application/json",
339
+ },
340
+ body: JSON.stringify({ selected_options: selectedOptions }),
341
+ });
342
+ if (!response.ok) {
343
+ throw new Error(`Failed to vote: ${response.statusText}`);
344
+ }
345
+ const data = await response.json();
346
+ return data.data;
347
+ }
348
+ export async function fetchAnnouncements(options) {
349
+ const { endpoint } = options;
350
+ const siteKey = getSiteKey(options);
351
+ const url = buildUrl(endpoint, "/announcements");
352
+ const response = await fetch(url, {
353
+ headers: getHeaders(siteKey),
354
+ });
355
+ if (!response.ok) {
356
+ throw new Error(`Failed to fetch announcements: ${response.statusText}`);
357
+ }
358
+ const data = await response.json();
359
+ return data.data || [];
360
+ }
361
+ export async function dismissAnnouncement(options) {
362
+ const { endpoint, announcementId } = options;
363
+ const siteKey = getSiteKey(options);
364
+ const url = buildUrl(endpoint, `/announcements/${announcementId}/dismiss`);
365
+ const response = await fetch(url, {
366
+ method: "POST",
367
+ headers: getHeaders(siteKey),
368
+ });
369
+ if (!response.ok) {
370
+ throw new Error(`Failed to dismiss announcement: ${response.statusText}`);
371
+ }
372
+ }
192
373
  /**
193
374
  * Headless controller for subscribe forms.
194
375
  * Manages state without any DOM/framework dependencies.
@@ -247,6 +428,70 @@ export class SubscribeController {
247
428
  this.notify();
248
429
  }
249
430
  }
431
+ /**
432
+ * Headless controller for waitlist forms.
433
+ * Manages state without any DOM/framework dependencies.
434
+ *
435
+ * @example
436
+ * const controller = new WaitlistController({ siteKey: 'xxx' });
437
+ * controller.subscribe((state) => {
438
+ * console.log(state.status, state.message, state.position);
439
+ * });
440
+ * await controller.join('user@example.com', { name: 'John', source: 'homepage' });
441
+ */
442
+ export class WaitlistController {
443
+ config;
444
+ listeners = new Set();
445
+ _state = { status: "idle", message: null, position: null, error: null };
446
+ constructor(config) {
447
+ this.config = config;
448
+ }
449
+ getState() {
450
+ return { ...this._state };
451
+ }
452
+ subscribe(listener) {
453
+ this.listeners.add(listener);
454
+ listener(this.getState());
455
+ return () => this.listeners.delete(listener);
456
+ }
457
+ notify() {
458
+ const state = this.getState();
459
+ for (const listener of this.listeners) {
460
+ listener(state);
461
+ }
462
+ }
463
+ /** Join the waitlist */
464
+ async join(email, options) {
465
+ this._state = { status: "loading", message: null, position: null, error: null };
466
+ this.notify();
467
+ try {
468
+ const result = await joinWaitlist({
469
+ ...this.config,
470
+ email,
471
+ name: options?.name,
472
+ source: options?.source,
473
+ });
474
+ this._state = {
475
+ status: "success",
476
+ message: result.message,
477
+ position: result.position ?? null,
478
+ error: null,
479
+ };
480
+ this.notify();
481
+ return result;
482
+ }
483
+ catch (e) {
484
+ const error = e instanceof Error ? e : new Error(String(e));
485
+ this._state = { status: "error", message: error.message, position: null, error };
486
+ this.notify();
487
+ throw error;
488
+ }
489
+ }
490
+ reset() {
491
+ this._state = { status: "idle", message: null, position: null, error: null };
492
+ this.notify();
493
+ }
494
+ }
250
495
  /**
251
496
  * Headless controller for forms.
252
497
  * Manages state without any DOM/framework dependencies.
@@ -336,7 +581,13 @@ export class ReactionsController {
336
581
  this.notify();
337
582
  try {
338
583
  const result = await fetchReactions({ ...this.config, pageId: this.pageId });
339
- this._state = { ...this._state, counts: result.counts, status: "success", error: null };
584
+ this._state = {
585
+ ...this._state,
586
+ counts: result.counts,
587
+ userReactions: result.userReactions,
588
+ status: "success",
589
+ error: null,
590
+ };
340
591
  this.notify();
341
592
  return this.getState();
342
593
  }
@@ -444,3 +695,272 @@ export class CommentsController {
444
695
  }
445
696
  }
446
697
  }
698
+ /**
699
+ * Headless controller for feedback forms.
700
+ * Manages state without any DOM/framework dependencies.
701
+ */
702
+ export class FeedbackController {
703
+ config;
704
+ listeners = new Set();
705
+ _state = { status: "idle", message: null, error: null };
706
+ constructor(config) {
707
+ this.config = config;
708
+ }
709
+ getState() {
710
+ return { ...this._state };
711
+ }
712
+ subscribe(listener) {
713
+ this.listeners.add(listener);
714
+ listener(this.getState());
715
+ return () => this.listeners.delete(listener);
716
+ }
717
+ notify() {
718
+ const state = this.getState();
719
+ for (const listener of this.listeners) {
720
+ listener(state);
721
+ }
722
+ }
723
+ async submit(type, content, options) {
724
+ this._state = { status: "loading", message: null, error: null };
725
+ this.notify();
726
+ try {
727
+ const result = await submitFeedback({
728
+ ...this.config,
729
+ type,
730
+ content,
731
+ email: options?.email,
732
+ pageUrl: options?.pageUrl,
733
+ });
734
+ this._state = { status: "success", message: result.message, error: null };
735
+ this.notify();
736
+ return result;
737
+ }
738
+ catch (e) {
739
+ const error = e instanceof Error ? e : new Error(String(e));
740
+ this._state = { status: "error", message: error.message, error };
741
+ this.notify();
742
+ throw error;
743
+ }
744
+ }
745
+ reset() {
746
+ this._state = { status: "idle", message: null, error: null };
747
+ this.notify();
748
+ }
749
+ }
750
+ /**
751
+ * Headless controller for polls.
752
+ * Manages poll state, voting, and results.
753
+ */
754
+ export class PollController {
755
+ config;
756
+ pollId;
757
+ listeners = new Set();
758
+ _state = { poll: null, status: "idle", error: null };
759
+ constructor(config, pollId) {
760
+ this.config = config;
761
+ this.pollId = pollId;
762
+ }
763
+ getState() {
764
+ return { ...this._state };
765
+ }
766
+ subscribe(listener) {
767
+ this.listeners.add(listener);
768
+ listener(this.getState());
769
+ return () => this.listeners.delete(listener);
770
+ }
771
+ notify() {
772
+ const state = this.getState();
773
+ for (const listener of this.listeners) {
774
+ listener(state);
775
+ }
776
+ }
777
+ /** Fetch poll data from the server */
778
+ async fetch() {
779
+ this._state = { ...this._state, status: "loading", error: null };
780
+ this.notify();
781
+ try {
782
+ const poll = await fetchPoll({ ...this.config, pollId: this.pollId });
783
+ this._state = { poll, status: "success", error: null };
784
+ this.notify();
785
+ return poll;
786
+ }
787
+ catch (e) {
788
+ const error = e instanceof Error ? e : new Error(String(e));
789
+ this._state = { ...this._state, status: "error", error };
790
+ this.notify();
791
+ throw error;
792
+ }
793
+ }
794
+ /** Vote on the poll */
795
+ async vote(selectedOptions) {
796
+ try {
797
+ const result = await votePoll({
798
+ ...this.config,
799
+ pollId: this.pollId,
800
+ selectedOptions,
801
+ });
802
+ // Update state with new results
803
+ if (this._state.poll) {
804
+ this._state.poll = {
805
+ ...this._state.poll,
806
+ results: result.results,
807
+ totalVotes: result.totalVotes,
808
+ userVotes: selectedOptions,
809
+ };
810
+ }
811
+ this.notify();
812
+ return result;
813
+ }
814
+ catch (e) {
815
+ const error = e instanceof Error ? e : new Error(String(e));
816
+ this._state = { ...this._state, error };
817
+ this.notify();
818
+ throw error;
819
+ }
820
+ }
821
+ /** Check if user has voted */
822
+ hasVoted() {
823
+ return !!this._state.poll?.userVotes && this._state.poll.userVotes.length > 0;
824
+ }
825
+ }
826
+ /**
827
+ * Headless controller for announcements.
828
+ * Manages announcement list and dismissals.
829
+ */
830
+ export class AnnouncementsController {
831
+ config;
832
+ listeners = new Set();
833
+ _state = {
834
+ announcements: [],
835
+ dismissed: new Set(),
836
+ status: "idle",
837
+ error: null,
838
+ };
839
+ constructor(config) {
840
+ this.config = config;
841
+ }
842
+ getState() {
843
+ return {
844
+ ...this._state,
845
+ announcements: [...this._state.announcements],
846
+ dismissed: new Set(this._state.dismissed),
847
+ };
848
+ }
849
+ /** Get visible (non-dismissed) announcements */
850
+ getVisibleAnnouncements() {
851
+ return this._state.announcements.filter((a) => !this._state.dismissed.has(a.id));
852
+ }
853
+ subscribe(listener) {
854
+ this.listeners.add(listener);
855
+ listener(this.getState());
856
+ return () => this.listeners.delete(listener);
857
+ }
858
+ notify() {
859
+ const state = this.getState();
860
+ for (const listener of this.listeners) {
861
+ listener(state);
862
+ }
863
+ }
864
+ /** Fetch announcements from the server */
865
+ async fetch() {
866
+ this._state = { ...this._state, status: "loading", error: null };
867
+ this.notify();
868
+ try {
869
+ const announcements = await fetchAnnouncements(this.config);
870
+ this._state = { ...this._state, announcements, status: "success", error: null };
871
+ this.notify();
872
+ return announcements;
873
+ }
874
+ catch (e) {
875
+ const error = e instanceof Error ? e : new Error(String(e));
876
+ this._state = { ...this._state, status: "error", error };
877
+ this.notify();
878
+ throw error;
879
+ }
880
+ }
881
+ /** Dismiss an announcement */
882
+ async dismiss(announcementId) {
883
+ try {
884
+ await dismissAnnouncement({ ...this.config, announcementId });
885
+ this._state.dismissed.add(announcementId);
886
+ this.notify();
887
+ }
888
+ catch (e) {
889
+ const error = e instanceof Error ? e : new Error(String(e));
890
+ this._state = { ...this._state, error };
891
+ this.notify();
892
+ throw error;
893
+ }
894
+ }
895
+ }
896
+ /**
897
+ * Headless controller for view counts.
898
+ * Tracks page views and unique visitors.
899
+ */
900
+ export class ViewCountsController {
901
+ config;
902
+ pageId;
903
+ listeners = new Set();
904
+ _state;
905
+ constructor(config, pageId) {
906
+ this.config = config;
907
+ this.pageId = pageId;
908
+ this._state = { pageId, views: 0, uniqueVisitors: 0, status: "idle", error: null };
909
+ }
910
+ getState() {
911
+ return { ...this._state };
912
+ }
913
+ subscribe(listener) {
914
+ this.listeners.add(listener);
915
+ listener(this.getState());
916
+ return () => this.listeners.delete(listener);
917
+ }
918
+ notify() {
919
+ const state = this.getState();
920
+ for (const listener of this.listeners) {
921
+ listener(state);
922
+ }
923
+ }
924
+ /** Fetch view counts from the server */
925
+ async fetch() {
926
+ this._state = { ...this._state, status: "loading", error: null };
927
+ this.notify();
928
+ try {
929
+ const counts = await getViewCounts({ ...this.config, pageId: this.pageId });
930
+ this._state = {
931
+ ...this._state,
932
+ views: counts.views,
933
+ uniqueVisitors: counts.uniqueVisitors,
934
+ status: "success",
935
+ error: null,
936
+ };
937
+ this.notify();
938
+ return counts;
939
+ }
940
+ catch (e) {
941
+ const error = e instanceof Error ? e : new Error(String(e));
942
+ this._state = { ...this._state, status: "error", error };
943
+ this.notify();
944
+ throw error;
945
+ }
946
+ }
947
+ /** Record a view (automatically tracks unique visitors via visitor token) */
948
+ async record() {
949
+ try {
950
+ const result = await recordView({ ...this.config, pageId: this.pageId });
951
+ this._state = {
952
+ ...this._state,
953
+ views: result.views,
954
+ uniqueVisitors: result.uniqueVisitors,
955
+ };
956
+ this.notify();
957
+ return result;
958
+ }
959
+ catch (e) {
960
+ const error = e instanceof Error ? e : new Error(String(e));
961
+ this._state = { ...this._state, error };
962
+ this.notify();
963
+ throw error;
964
+ }
965
+ }
966
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seriphxyz/core",
3
- "version": "0.1.2",
3
+ "version": "0.1.8",
4
4
  "description": "Framework-agnostic API client and types for Seriph widgets",
5
5
  "repository": {
6
6
  "type": "git",