reflet-sdk 0.1.0 → 0.1.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 +1 -1
- package/dist/{chunk-RDQP4VCA.js → chunk-AHWT4I4V.js} +4 -4
- package/dist/chunk-AHWT4I4V.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/react.js.map +1 -1
- package/dist/server.d.ts +3 -1
- package/dist/server.js +21 -16
- package/dist/server.js.map +1 -1
- package/package.json +7 -2
- package/dist/chunk-RDQP4VCA.js.map +0 -1
package/README.md
CHANGED
|
@@ -151,7 +151,7 @@ const reflet = new Reflet(config: RefletConfig);
|
|
|
151
151
|
| `publicKey` | `string` | Yes | Your board's public API key |
|
|
152
152
|
| `user` | `RefletUser` | No | User information for identification |
|
|
153
153
|
| `userToken` | `string` | No | Signed JWT from your server (alternative to `user`) |
|
|
154
|
-
| `baseUrl` | `string` | No | Custom API endpoint |
|
|
154
|
+
| `baseUrl` | `string` | No | Custom API endpoint (defaults to Reflet production API) |
|
|
155
155
|
|
|
156
156
|
#### Methods
|
|
157
157
|
|
|
@@ -29,7 +29,7 @@ var RefletNotFoundError = class extends RefletError {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
// src/client.ts
|
|
32
|
-
var
|
|
32
|
+
var DEFAULT_API_URL = "https://harmless-clam-802.convex.cloud";
|
|
33
33
|
var Reflet = class {
|
|
34
34
|
publicKey;
|
|
35
35
|
baseUrl;
|
|
@@ -37,7 +37,7 @@ var Reflet = class {
|
|
|
37
37
|
user;
|
|
38
38
|
constructor(config) {
|
|
39
39
|
this.publicKey = config.publicKey;
|
|
40
|
-
this.baseUrl = config.baseUrl ??
|
|
40
|
+
this.baseUrl = config.baseUrl ?? DEFAULT_API_URL;
|
|
41
41
|
this.userToken = config.userToken;
|
|
42
42
|
this.user = config.user;
|
|
43
43
|
if (!this.publicKey) {
|
|
@@ -237,5 +237,5 @@ var Reflet = class {
|
|
|
237
237
|
};
|
|
238
238
|
|
|
239
239
|
export { Reflet, RefletAuthError, RefletError, RefletNotFoundError, RefletValidationError };
|
|
240
|
-
//# sourceMappingURL=chunk-
|
|
241
|
-
//# sourceMappingURL=chunk-
|
|
240
|
+
//# sourceMappingURL=chunk-AHWT4I4V.js.map
|
|
241
|
+
//# sourceMappingURL=chunk-AHWT4I4V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/client.ts"],"names":[],"mappings":"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","file":"chunk-AHWT4I4V.js","sourcesContent":["/**\n * Reflet SDK Types\n */\n\n// ============================================\n// Configuration\n// ============================================\n\nexport interface RefletConfig {\n /** Your board's public API key (fb_pub_xxx) */\n publicKey: string;\n /** API base URL (optional, defaults to Reflet production API) */\n baseUrl?: string;\n /** User identification for SSO */\n user?: RefletUser;\n /** Pre-signed user token (alternative to user object) */\n userToken?: string;\n}\n\nexport interface RefletUser {\n /** Unique identifier for the user in your system */\n id: string;\n /** User's email address */\n email?: string;\n /** User's display name */\n name?: string;\n /** URL to user's avatar image */\n avatar?: string;\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n// ============================================\n// API Responses\n// ============================================\n\nexport interface BoardConfig {\n id: string;\n name: string;\n slug: string;\n description?: string;\n isPublic: boolean;\n settings?: BoardSettings;\n organization: {\n id: string;\n name: string;\n slug: string;\n logo?: string;\n primaryColor?: string;\n };\n statuses: BoardStatus[];\n}\n\nexport interface BoardSettings {\n allowAnonymousVoting?: boolean;\n requireApproval?: boolean;\n defaultStatus?: FeedbackStatus;\n}\n\nexport interface BoardStatus {\n id: string;\n name: string;\n color: string;\n icon?: string;\n order: number;\n}\n\nexport type FeedbackStatus =\n | \"open\"\n | \"under_review\"\n | \"planned\"\n | \"in_progress\"\n | \"completed\"\n | \"closed\";\n\n// ============================================\n// Feedback\n// ============================================\n\nexport interface FeedbackItem {\n id: string;\n title: string;\n description: string;\n status: FeedbackStatus;\n voteCount: number;\n commentCount: number;\n isPinned: boolean;\n hasVoted: boolean;\n createdAt: number;\n updatedAt: number;\n completedAt?: number;\n tags: FeedbackTag[];\n boardStatus: {\n id: string;\n name: string;\n color: string;\n } | null;\n author: FeedbackAuthor | null;\n}\n\nexport interface FeedbackDetail extends FeedbackItem {\n isSubscribed: boolean;\n}\n\nexport interface FeedbackTag {\n id: string;\n name: string;\n color: string;\n}\n\nexport interface FeedbackAuthor {\n name?: string;\n email?: string;\n avatar?: string;\n isExternal: boolean;\n}\n\nexport interface FeedbackListResponse {\n items: FeedbackItem[];\n total: number;\n hasMore: boolean;\n}\n\nexport interface FeedbackListParams {\n /** Filter by custom status ID */\n statusId?: string;\n /** Filter by status name */\n status?: FeedbackStatus;\n /** Search in title and description */\n search?: string;\n /** Sort order */\n sortBy?: \"votes\" | \"newest\" | \"oldest\" | \"comments\";\n /** Number of items to return (max 100) */\n limit?: number;\n /** Offset for pagination */\n offset?: number;\n}\n\nexport interface CreateFeedbackParams {\n title: string;\n description: string;\n}\n\nexport interface CreateFeedbackResponse {\n feedbackId: string;\n isApproved: boolean;\n}\n\nexport interface VoteResponse {\n voted: boolean;\n voteCount: number;\n}\n\n// ============================================\n// Comments\n// ============================================\n\nexport interface Comment {\n id: string;\n body: string;\n isOfficial: boolean;\n author: FeedbackAuthor | null;\n replies: CommentReply[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface CommentReply {\n id: string;\n body: string;\n isOfficial: boolean;\n author: FeedbackAuthor | null;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface AddCommentParams {\n feedbackId: string;\n body: string;\n parentId?: string;\n}\n\nexport interface AddCommentResponse {\n commentId: string;\n}\n\n// ============================================\n// Subscriptions\n// ============================================\n\nexport interface SubscribeResponse {\n subscribed: boolean;\n alreadySubscribed?: boolean;\n}\n\nexport interface UnsubscribeResponse {\n unsubscribed: boolean;\n wasNotSubscribed?: boolean;\n}\n\n// ============================================\n// Roadmap\n// ============================================\n\nexport interface Roadmap {\n lanes: RoadmapLane[];\n}\n\nexport interface RoadmapLane {\n id: string;\n name: string;\n color: string;\n items: RoadmapItem[];\n}\n\nexport interface RoadmapItem {\n id: string;\n title: string;\n status: FeedbackStatus;\n voteCount: number;\n}\n\n// ============================================\n// Changelog\n// ============================================\n\nexport interface ChangelogEntry {\n id: string;\n title: string;\n description?: string;\n version?: string;\n publishedAt?: number;\n feedback: { id: string; title: string }[];\n}\n\n// ============================================\n// Errors\n// ============================================\n\nexport class RefletError extends Error {\n readonly status: number;\n readonly code?: string;\n\n constructor(message: string, status: number, code?: string) {\n super(message);\n this.name = \"RefletError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport class RefletAuthError extends RefletError {\n constructor(message: string) {\n super(message, 401, \"AUTH_ERROR\");\n this.name = \"RefletAuthError\";\n }\n}\n\nexport class RefletValidationError extends RefletError {\n constructor(message: string) {\n super(message, 400, \"VALIDATION_ERROR\");\n this.name = \"RefletValidationError\";\n }\n}\n\nexport class RefletNotFoundError extends RefletError {\n constructor(message: string) {\n super(message, 404, \"NOT_FOUND\");\n this.name = \"RefletNotFoundError\";\n }\n}\n","import {\n type AddCommentParams,\n type AddCommentResponse,\n type BoardConfig,\n type ChangelogEntry,\n type Comment,\n type CreateFeedbackParams,\n type CreateFeedbackResponse,\n type FeedbackDetail,\n type FeedbackListParams,\n type FeedbackListResponse,\n RefletAuthError,\n type RefletConfig,\n RefletError,\n RefletNotFoundError,\n type RefletUser,\n type Roadmap,\n type SubscribeResponse,\n type UnsubscribeResponse,\n type VoteResponse,\n} from \"./types\";\n\n// Default to Reflet production API\nconst DEFAULT_API_URL = \"https://harmless-clam-802.convex.cloud\";\n\n/**\n * Reflet SDK Client\n *\n * @example\n * ```ts\n * import { Reflet } from 'reflet-sdk';\n *\n * const reflet = new Reflet({\n * publicKey: 'fb_pub_xxx',\n * user: { id: 'user_123', email: 'user@example.com', name: 'John' }\n * });\n *\n * // List feedback\n * const { items } = await reflet.list({ status: 'open' });\n *\n * // Vote on feedback\n * await reflet.vote('feedback_id');\n *\n * // Submit new feedback\n * await reflet.create({ title: 'Great idea', description: 'Details...' });\n * ```\n */\nexport class Reflet {\n private readonly publicKey: string;\n private readonly baseUrl: string;\n private userToken: string | undefined;\n private user: RefletUser | undefined;\n\n constructor(config: RefletConfig) {\n this.publicKey = config.publicKey;\n this.baseUrl = config.baseUrl ?? DEFAULT_API_URL;\n this.userToken = config.userToken;\n this.user = config.user;\n\n if (!this.publicKey) {\n throw new Error(\"Reflet: publicKey is required\");\n }\n }\n\n /**\n * Update the user identification\n */\n setUser(user: RefletUser | undefined): void {\n this.user = user;\n this.userToken = undefined;\n }\n\n /**\n * Set the user token directly (for server-signed tokens)\n */\n setUserToken(token: string | undefined): void {\n this.userToken = token;\n this.user = undefined;\n }\n\n /**\n * Get the board configuration\n */\n async getConfig(): Promise<BoardConfig> {\n return await this.request<BoardConfig>(\"GET\", \"/api/v1/feedback\");\n }\n\n /**\n * List feedback items with optional filtering\n */\n async list(params?: FeedbackListParams): Promise<FeedbackListResponse> {\n const searchParams = new URLSearchParams();\n\n if (params?.statusId) {\n searchParams.set(\"statusId\", params.statusId);\n }\n if (params?.status) {\n searchParams.set(\"status\", params.status);\n }\n if (params?.search) {\n searchParams.set(\"search\", params.search);\n }\n if (params?.sortBy) {\n searchParams.set(\"sortBy\", params.sortBy);\n }\n if (params?.limit) {\n searchParams.set(\"limit\", String(params.limit));\n }\n if (params?.offset) {\n searchParams.set(\"offset\", String(params.offset));\n }\n\n const query = searchParams.toString();\n const url = `/api/v1/feedback/list${query ? `?${query}` : \"\"}`;\n\n return await this.request<FeedbackListResponse>(\"GET\", url);\n }\n\n /**\n * Get a single feedback item by ID\n */\n async get(feedbackId: string): Promise<FeedbackDetail> {\n const result = await this.request<FeedbackDetail | null>(\n \"GET\",\n `/api/v1/feedback/item?id=${encodeURIComponent(feedbackId)}`\n );\n\n if (!result) {\n throw new RefletNotFoundError(\"Feedback not found\");\n }\n\n return result;\n }\n\n /**\n * Create new feedback\n * Requires user identification\n */\n async create(params: CreateFeedbackParams): Promise<CreateFeedbackResponse> {\n return await this.request<CreateFeedbackResponse>(\n \"POST\",\n \"/api/v1/feedback/create\",\n params\n );\n }\n\n /**\n * Toggle vote on feedback\n * Requires user identification\n */\n async vote(\n feedbackId: string,\n type: \"upvote\" | \"downvote\" = \"upvote\"\n ): Promise<VoteResponse> {\n return await this.request<VoteResponse>(\"POST\", \"/api/v1/feedback/vote\", {\n feedbackId,\n voteType: type,\n });\n }\n\n /**\n * Get comments for a feedback item\n */\n async getComments(\n feedbackId: string,\n sortBy: \"newest\" | \"oldest\" = \"oldest\"\n ): Promise<Comment[]> {\n return await this.request<Comment[]>(\n \"GET\",\n `/api/v1/feedback/comments?feedbackId=${encodeURIComponent(feedbackId)}&sortBy=${sortBy}`\n );\n }\n\n /**\n * Add a comment to feedback\n * Requires user identification\n */\n async comment(params: AddCommentParams): Promise<AddCommentResponse> {\n return await this.request<AddCommentResponse>(\n \"POST\",\n \"/api/v1/feedback/comment\",\n params\n );\n }\n\n /**\n * Subscribe to feedback updates\n * Requires user identification\n */\n async subscribe(feedbackId: string): Promise<SubscribeResponse> {\n return await this.request<SubscribeResponse>(\n \"POST\",\n \"/api/v1/feedback/subscribe\",\n {\n feedbackId,\n }\n );\n }\n\n /**\n * Unsubscribe from feedback updates\n * Requires user identification\n */\n async unsubscribe(feedbackId: string): Promise<UnsubscribeResponse> {\n return await this.request<UnsubscribeResponse>(\n \"POST\",\n \"/api/v1/feedback/unsubscribe\",\n {\n feedbackId,\n }\n );\n }\n\n /**\n * Get roadmap data\n */\n async getRoadmap(): Promise<Roadmap> {\n return await this.request<Roadmap>(\"GET\", \"/api/v1/feedback/roadmap\");\n }\n\n /**\n * Get changelog entries\n */\n async getChangelog(limit?: number): Promise<ChangelogEntry[]> {\n const url = limit\n ? `/api/v1/feedback/changelog?limit=${limit}`\n : \"/api/v1/feedback/changelog\";\n\n return await this.request<ChangelogEntry[]>(\"GET\", url);\n }\n\n /**\n * Make an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.publicKey}`,\n };\n\n // Add user token if available\n const token = this.userToken ?? this.generateUserToken();\n if (token) {\n headers[\"X-User-Token\"] = token;\n }\n\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n const data = (await response.json()) as T | { error: string };\n\n if (!response.ok) {\n const errorMessage =\n (data as { error?: string }).error ?? \"Request failed\";\n\n if (response.status === 401) {\n throw new RefletAuthError(errorMessage);\n }\n if (response.status === 404) {\n throw new RefletNotFoundError(errorMessage);\n }\n\n throw new RefletError(errorMessage, response.status);\n }\n\n return data as T;\n }\n\n /**\n * Generate a simple user token for client-side use\n * Note: For production, use server-side token signing\n */\n private generateUserToken(): string | undefined {\n if (!this.user) {\n return undefined;\n }\n\n // Simple base64 encoding for client-side use\n // In production, tokens should be signed server-side\n const payload = {\n id: this.user.id,\n email: this.user.email,\n name: this.user.name,\n iat: Math.floor(Date.now() / 1000),\n exp: Math.floor(Date.now() / 1000) + 86_400, // 24 hours\n };\n\n const header = btoa(JSON.stringify({ alg: \"none\", typ: \"JWT\" }));\n const payloadB64 = btoa(JSON.stringify(payload));\n\n return `${header}.${payloadB64}.`;\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
interface RefletConfig {
|
|
5
5
|
/** Your board's public API key (fb_pub_xxx) */
|
|
6
6
|
publicKey: string;
|
|
7
|
-
/** API base URL (defaults to
|
|
7
|
+
/** API base URL (optional, defaults to Reflet production API) */
|
|
8
8
|
baseUrl?: string;
|
|
9
9
|
/** User identification for SSO */
|
|
10
10
|
user?: RefletUser;
|
|
@@ -196,7 +196,7 @@ declare class RefletNotFoundError extends RefletError {
|
|
|
196
196
|
*
|
|
197
197
|
* @example
|
|
198
198
|
* ```ts
|
|
199
|
-
* import { Reflet } from '
|
|
199
|
+
* import { Reflet } from 'reflet-sdk';
|
|
200
200
|
*
|
|
201
201
|
* const reflet = new Reflet({
|
|
202
202
|
* publicKey: 'fb_pub_xxx',
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { Reflet, RefletAuthError, RefletError, RefletNotFoundError, RefletValidationError } from './chunk-
|
|
1
|
+
export { Reflet, RefletAuthError, RefletError, RefletNotFoundError, RefletValidationError } from './chunk-AHWT4I4V.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/react.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ interface RefletContextValue {
|
|
|
12
12
|
interface RefletProviderProps {
|
|
13
13
|
/** Your board's public API key */
|
|
14
14
|
publicKey: string;
|
|
15
|
-
/** API base URL (optional) */
|
|
15
|
+
/** API base URL (optional, defaults to Reflet production API) */
|
|
16
16
|
baseUrl?: string;
|
|
17
17
|
/** Initial user identification */
|
|
18
18
|
user?: RefletUser;
|
|
@@ -26,7 +26,7 @@ interface RefletProviderProps {
|
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
28
28
|
* ```tsx
|
|
29
|
-
* import { RefletProvider } from '
|
|
29
|
+
* import { RefletProvider } from 'reflet-sdk/react';
|
|
30
30
|
*
|
|
31
31
|
* function App() {
|
|
32
32
|
* return (
|
package/dist/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Reflet } from './chunk-
|
|
2
|
-
export { Reflet } from './chunk-
|
|
1
|
+
import { Reflet } from './chunk-AHWT4I4V.js';
|
|
2
|
+
export { Reflet } from './chunk-AHWT4I4V.js';
|
|
3
3
|
import { createContext, useState, useMemo, useEffect, useContext, useCallback } from 'react';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react-context.tsx","../src/react-hooks.ts"],"names":["useState","useEffect","error"],"mappings":"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","file":"react.js","sourcesContent":["import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { Reflet } from \"./client\";\nimport type { RefletConfig, RefletUser } from \"./types\";\n\n// ============================================\n// Context Types\n// ============================================\n\ninterface RefletContextValue {\n client: Reflet;\n isReady: boolean;\n user: RefletUser | undefined;\n setUser: (user: RefletUser | undefined) => void;\n}\n\n// ============================================\n// Context\n// ============================================\n\nconst RefletContext = createContext<RefletContextValue | null>(null);\n\n// ============================================\n// Provider\n// ============================================\n\nexport interface RefletProviderProps {\n /** Your board's public API key */\n publicKey: string;\n /** API base URL (optional) */\n baseUrl?: string;\n /** Initial user identification */\n user?: RefletUser;\n /** Pre-signed user token (alternative to user) */\n userToken?: string;\n /** Children */\n children: ReactNode;\n}\n\n/**\n * Provider component for Reflet SDK\n *\n * @example\n * ```tsx\n * import { RefletProvider } from '@reflet/sdk/react';\n *\n * function App() {\n * return (\n * <RefletProvider\n * publicKey=\"fb_pub_xxx\"\n * user={{ id: 'user_123', email: 'user@example.com', name: 'John' }}\n * >\n * <YourApp />\n * </RefletProvider>\n * );\n * }\n * ```\n */\nexport function RefletProvider({\n publicKey,\n baseUrl,\n user: initialUser,\n userToken,\n children,\n}: RefletProviderProps) {\n const [user, setUser] = useState<RefletUser | undefined>(initialUser);\n const [isReady, setIsReady] = useState(false);\n\n const client = useMemo(() => {\n const config: RefletConfig = {\n publicKey,\n baseUrl,\n user,\n userToken,\n };\n return new Reflet(config);\n }, [publicKey, baseUrl, user, userToken]);\n\n // Update client when user changes\n useEffect(() => {\n if (userToken) {\n client.setUserToken(userToken);\n } else {\n client.setUser(user);\n }\n }, [client, user, userToken]);\n\n // Mark as ready after mount\n useEffect(() => {\n setIsReady(true);\n }, []);\n\n const value = useMemo(\n () => ({\n client,\n isReady,\n user,\n setUser,\n }),\n [client, isReady, user]\n );\n\n return (\n <RefletContext.Provider value={value}>{children}</RefletContext.Provider>\n );\n}\n\n// ============================================\n// Hook to access context\n// ============================================\n\nexport function useRefletContext(): RefletContextValue {\n const context = useContext(RefletContext);\n if (!context) {\n throw new Error(\"useRefletContext must be used within a RefletProvider\");\n }\n return context;\n}\n\nexport function useRefletClient(): Reflet {\n const { client } = useRefletContext();\n return client;\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useRefletClient } from \"./react-context\";\nimport type {\n AddCommentParams,\n BoardConfig,\n ChangelogEntry,\n Comment,\n CreateFeedbackParams,\n FeedbackDetail,\n FeedbackItem,\n FeedbackListParams,\n Roadmap,\n} from \"./types\";\n\n// ============================================\n// Types\n// ============================================\n\ninterface UseQueryResult<T> {\n data: T | undefined;\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n}\n\ninterface UseMutationResult<TData, TVariables> {\n mutate: (variables: TVariables) => Promise<TData>;\n isLoading: boolean;\n error: Error | null;\n data: TData | undefined;\n reset: () => void;\n}\n\n// ============================================\n// Board Config Hook\n// ============================================\n\n/**\n * Hook to fetch board configuration\n */\nexport function useBoardConfig(): UseQueryResult<BoardConfig> {\n const client = useRefletClient();\n const [data, setData] = useState<BoardConfig | undefined>();\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.getConfig();\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch board config\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Feedback List Hook\n// ============================================\n\nexport interface UseFeedbackListOptions extends FeedbackListParams {\n /** Auto-fetch on mount */\n enabled?: boolean;\n}\n\n/**\n * Hook to fetch feedback list with filtering\n *\n * @example\n * ```tsx\n * const { data, isLoading } = useFeedbackList({ status: 'open', sortBy: 'votes' });\n * ```\n */\nexport function useFeedbackList(\n options: UseFeedbackListOptions = {}\n): UseQueryResult<{ items: FeedbackItem[]; total: number; hasMore: boolean }> {\n const client = useRefletClient();\n const { enabled = true, ...params } = options;\n\n // Create stable reference using individual params\n const { statusId, status, search, sortBy, limit, offset } = params;\n\n const [data, setData] = useState<{\n items: FeedbackItem[];\n total: number;\n hasMore: boolean;\n }>();\n const [isLoading, setIsLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.list({\n statusId,\n status,\n search,\n sortBy,\n limit,\n offset,\n });\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch feedback\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client, statusId, status, search, sortBy, limit, offset]);\n\n useEffect(() => {\n if (enabled) {\n fetch();\n }\n }, [fetch, enabled]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Single Feedback Hook\n// ============================================\n\n/**\n * Hook to fetch a single feedback item\n *\n * @example\n * ```tsx\n * const { data: feedback, isLoading } = useFeedback('feedback_id');\n * ```\n */\nexport function useFeedback(\n feedbackId: string | undefined\n): UseQueryResult<FeedbackDetail> {\n const client = useRefletClient();\n const [data, setData] = useState<FeedbackDetail | undefined>();\n const [isLoading, setIsLoading] = useState(!!feedbackId);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n if (!feedbackId) {\n setData(undefined);\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.get(feedbackId);\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch feedback\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client, feedbackId]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Comments Hook\n// ============================================\n\n/**\n * Hook to fetch comments for a feedback item\n */\nexport function useComments(\n feedbackId: string | undefined,\n sortBy: \"newest\" | \"oldest\" = \"oldest\"\n): UseQueryResult<Comment[]> {\n const client = useRefletClient();\n const [data, setData] = useState<Comment[] | undefined>();\n const [isLoading, setIsLoading] = useState(!!feedbackId);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n if (!feedbackId) {\n setData(undefined);\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.getComments(feedbackId, sortBy);\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch comments\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client, feedbackId, sortBy]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Roadmap Hook\n// ============================================\n\n/**\n * Hook to fetch roadmap data\n */\nexport function useRoadmap(): UseQueryResult<Roadmap> {\n const client = useRefletClient();\n const [data, setData] = useState<Roadmap | undefined>();\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.getRoadmap();\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch roadmap\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Changelog Hook\n// ============================================\n\n/**\n * Hook to fetch changelog entries\n */\nexport function useChangelog(limit?: number): UseQueryResult<ChangelogEntry[]> {\n const client = useRefletClient();\n const [data, setData] = useState<ChangelogEntry[] | undefined>();\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.getChangelog(limit);\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch changelog\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client, limit]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Create Feedback Mutation Hook\n// ============================================\n\n/**\n * Hook to create new feedback\n *\n * @example\n * ```tsx\n * const { mutate: createFeedback, isLoading } = useCreateFeedback();\n *\n * const handleSubmit = async (data) => {\n * const result = await createFeedback(data);\n * console.log('Created:', result.feedbackId);\n * };\n * ```\n */\nexport function useCreateFeedback(): UseMutationResult<\n { feedbackId: string; isApproved: boolean },\n CreateFeedbackParams\n> {\n const client = useRefletClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<{\n feedbackId: string;\n isApproved: boolean;\n }>();\n\n const mutate = useCallback(\n async (params: CreateFeedbackParams) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.create(params);\n setData(result);\n return result;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(\"Failed to create feedback\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const reset = useCallback(() => {\n setData(undefined);\n setError(null);\n }, []);\n\n return { mutate, isLoading, error, data, reset };\n}\n\n// ============================================\n// Vote Mutation Hook\n// ============================================\n\n/**\n * Hook to vote on feedback\n *\n * @example\n * ```tsx\n * const { mutate: vote } = useVote();\n *\n * <button onClick={() => vote({ feedbackId: 'xxx' })}>\n * Vote\n * </button>\n * ```\n */\nexport function useVote(): UseMutationResult<\n { voted: boolean; voteCount: number },\n { feedbackId: string; type?: \"upvote\" | \"downvote\" }\n> {\n const client = useRefletClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<{ voted: boolean; voteCount: number }>();\n\n const mutate = useCallback(\n async ({\n feedbackId,\n type = \"upvote\",\n }: {\n feedbackId: string;\n type?: \"upvote\" | \"downvote\";\n }) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.vote(feedbackId, type);\n setData(result);\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(\"Failed to vote\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const reset = useCallback(() => {\n setData(undefined);\n setError(null);\n }, []);\n\n return { mutate, isLoading, error, data, reset };\n}\n\n// ============================================\n// Comment Mutation Hook\n// ============================================\n\n/**\n * Hook to add a comment\n */\nexport function useAddComment(): UseMutationResult<\n { commentId: string },\n AddCommentParams\n> {\n const client = useRefletClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<{ commentId: string }>();\n\n const mutate = useCallback(\n async (params: AddCommentParams) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.comment(params);\n setData(result);\n return result;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(\"Failed to add comment\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const reset = useCallback(() => {\n setData(undefined);\n setError(null);\n }, []);\n\n return { mutate, isLoading, error, data, reset };\n}\n\n// ============================================\n// Subscribe Mutation Hook\n// ============================================\n\n/**\n * Hook to subscribe/unsubscribe to feedback\n */\nexport function useSubscription(): {\n subscribe: (feedbackId: string) => Promise<{ subscribed: boolean }>;\n unsubscribe: (feedbackId: string) => Promise<{ unsubscribed: boolean }>;\n isLoading: boolean;\n error: Error | null;\n} {\n const client = useRefletClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const subscribe = useCallback(\n async (feedbackId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.subscribe(feedbackId);\n return result;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(\"Failed to subscribe\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const unsubscribe = useCallback(\n async (feedbackId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.unsubscribe(feedbackId);\n return result;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(\"Failed to unsubscribe\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n return { subscribe, unsubscribe, isLoading, error };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react-context.tsx","../src/react-hooks.ts"],"names":["useState","useEffect","error"],"mappings":"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","file":"react.js","sourcesContent":["import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { Reflet } from \"./client\";\nimport type { RefletConfig, RefletUser } from \"./types\";\n\n// ============================================\n// Context Types\n// ============================================\n\ninterface RefletContextValue {\n client: Reflet;\n isReady: boolean;\n user: RefletUser | undefined;\n setUser: (user: RefletUser | undefined) => void;\n}\n\n// ============================================\n// Context\n// ============================================\n\nconst RefletContext = createContext<RefletContextValue | null>(null);\n\n// ============================================\n// Provider\n// ============================================\n\nexport interface RefletProviderProps {\n /** Your board's public API key */\n publicKey: string;\n /** API base URL (optional, defaults to Reflet production API) */\n baseUrl?: string;\n /** Initial user identification */\n user?: RefletUser;\n /** Pre-signed user token (alternative to user) */\n userToken?: string;\n /** Children */\n children: ReactNode;\n}\n\n/**\n * Provider component for Reflet SDK\n *\n * @example\n * ```tsx\n * import { RefletProvider } from 'reflet-sdk/react';\n *\n * function App() {\n * return (\n * <RefletProvider\n * publicKey=\"fb_pub_xxx\"\n * user={{ id: 'user_123', email: 'user@example.com', name: 'John' }}\n * >\n * <YourApp />\n * </RefletProvider>\n * );\n * }\n * ```\n */\nexport function RefletProvider({\n publicKey,\n baseUrl,\n user: initialUser,\n userToken,\n children,\n}: RefletProviderProps) {\n const [user, setUser] = useState<RefletUser | undefined>(initialUser);\n const [isReady, setIsReady] = useState(false);\n\n const client = useMemo(() => {\n const config: RefletConfig = {\n publicKey,\n baseUrl,\n user,\n userToken,\n };\n return new Reflet(config);\n }, [publicKey, baseUrl, user, userToken]);\n\n // Update client when user changes\n useEffect(() => {\n if (userToken) {\n client.setUserToken(userToken);\n } else {\n client.setUser(user);\n }\n }, [client, user, userToken]);\n\n // Mark as ready after mount\n useEffect(() => {\n setIsReady(true);\n }, []);\n\n const value = useMemo(\n () => ({\n client,\n isReady,\n user,\n setUser,\n }),\n [client, isReady, user]\n );\n\n return (\n <RefletContext.Provider value={value}>{children}</RefletContext.Provider>\n );\n}\n\n// ============================================\n// Hook to access context\n// ============================================\n\nexport function useRefletContext(): RefletContextValue {\n const context = useContext(RefletContext);\n if (!context) {\n throw new Error(\"useRefletContext must be used within a RefletProvider\");\n }\n return context;\n}\n\nexport function useRefletClient(): Reflet {\n const { client } = useRefletContext();\n return client;\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useRefletClient } from \"./react-context\";\nimport type {\n AddCommentParams,\n BoardConfig,\n ChangelogEntry,\n Comment,\n CreateFeedbackParams,\n FeedbackDetail,\n FeedbackItem,\n FeedbackListParams,\n Roadmap,\n} from \"./types\";\n\n// ============================================\n// Types\n// ============================================\n\ninterface UseQueryResult<T> {\n data: T | undefined;\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n}\n\ninterface UseMutationResult<TData, TVariables> {\n mutate: (variables: TVariables) => Promise<TData>;\n isLoading: boolean;\n error: Error | null;\n data: TData | undefined;\n reset: () => void;\n}\n\n// ============================================\n// Board Config Hook\n// ============================================\n\n/**\n * Hook to fetch board configuration\n */\nexport function useBoardConfig(): UseQueryResult<BoardConfig> {\n const client = useRefletClient();\n const [data, setData] = useState<BoardConfig | undefined>();\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.getConfig();\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch board config\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Feedback List Hook\n// ============================================\n\nexport interface UseFeedbackListOptions extends FeedbackListParams {\n /** Auto-fetch on mount */\n enabled?: boolean;\n}\n\n/**\n * Hook to fetch feedback list with filtering\n *\n * @example\n * ```tsx\n * const { data, isLoading } = useFeedbackList({ status: 'open', sortBy: 'votes' });\n * ```\n */\nexport function useFeedbackList(\n options: UseFeedbackListOptions = {}\n): UseQueryResult<{ items: FeedbackItem[]; total: number; hasMore: boolean }> {\n const client = useRefletClient();\n const { enabled = true, ...params } = options;\n\n // Create stable reference using individual params\n const { statusId, status, search, sortBy, limit, offset } = params;\n\n const [data, setData] = useState<{\n items: FeedbackItem[];\n total: number;\n hasMore: boolean;\n }>();\n const [isLoading, setIsLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.list({\n statusId,\n status,\n search,\n sortBy,\n limit,\n offset,\n });\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch feedback\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client, statusId, status, search, sortBy, limit, offset]);\n\n useEffect(() => {\n if (enabled) {\n fetch();\n }\n }, [fetch, enabled]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Single Feedback Hook\n// ============================================\n\n/**\n * Hook to fetch a single feedback item\n *\n * @example\n * ```tsx\n * const { data: feedback, isLoading } = useFeedback('feedback_id');\n * ```\n */\nexport function useFeedback(\n feedbackId: string | undefined\n): UseQueryResult<FeedbackDetail> {\n const client = useRefletClient();\n const [data, setData] = useState<FeedbackDetail | undefined>();\n const [isLoading, setIsLoading] = useState(!!feedbackId);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n if (!feedbackId) {\n setData(undefined);\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.get(feedbackId);\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch feedback\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client, feedbackId]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Comments Hook\n// ============================================\n\n/**\n * Hook to fetch comments for a feedback item\n */\nexport function useComments(\n feedbackId: string | undefined,\n sortBy: \"newest\" | \"oldest\" = \"oldest\"\n): UseQueryResult<Comment[]> {\n const client = useRefletClient();\n const [data, setData] = useState<Comment[] | undefined>();\n const [isLoading, setIsLoading] = useState(!!feedbackId);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n if (!feedbackId) {\n setData(undefined);\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.getComments(feedbackId, sortBy);\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch comments\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client, feedbackId, sortBy]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Roadmap Hook\n// ============================================\n\n/**\n * Hook to fetch roadmap data\n */\nexport function useRoadmap(): UseQueryResult<Roadmap> {\n const client = useRefletClient();\n const [data, setData] = useState<Roadmap | undefined>();\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.getRoadmap();\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch roadmap\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Changelog Hook\n// ============================================\n\n/**\n * Hook to fetch changelog entries\n */\nexport function useChangelog(limit?: number): UseQueryResult<ChangelogEntry[]> {\n const client = useRefletClient();\n const [data, setData] = useState<ChangelogEntry[] | undefined>();\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.getChangelog(limit);\n setData(result);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch changelog\")\n );\n } finally {\n setIsLoading(false);\n }\n }, [client, limit]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n\n// ============================================\n// Create Feedback Mutation Hook\n// ============================================\n\n/**\n * Hook to create new feedback\n *\n * @example\n * ```tsx\n * const { mutate: createFeedback, isLoading } = useCreateFeedback();\n *\n * const handleSubmit = async (data) => {\n * const result = await createFeedback(data);\n * console.log('Created:', result.feedbackId);\n * };\n * ```\n */\nexport function useCreateFeedback(): UseMutationResult<\n { feedbackId: string; isApproved: boolean },\n CreateFeedbackParams\n> {\n const client = useRefletClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<{\n feedbackId: string;\n isApproved: boolean;\n }>();\n\n const mutate = useCallback(\n async (params: CreateFeedbackParams) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.create(params);\n setData(result);\n return result;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(\"Failed to create feedback\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const reset = useCallback(() => {\n setData(undefined);\n setError(null);\n }, []);\n\n return { mutate, isLoading, error, data, reset };\n}\n\n// ============================================\n// Vote Mutation Hook\n// ============================================\n\n/**\n * Hook to vote on feedback\n *\n * @example\n * ```tsx\n * const { mutate: vote } = useVote();\n *\n * <button onClick={() => vote({ feedbackId: 'xxx' })}>\n * Vote\n * </button>\n * ```\n */\nexport function useVote(): UseMutationResult<\n { voted: boolean; voteCount: number },\n { feedbackId: string; type?: \"upvote\" | \"downvote\" }\n> {\n const client = useRefletClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<{ voted: boolean; voteCount: number }>();\n\n const mutate = useCallback(\n async ({\n feedbackId,\n type = \"upvote\",\n }: {\n feedbackId: string;\n type?: \"upvote\" | \"downvote\";\n }) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.vote(feedbackId, type);\n setData(result);\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(\"Failed to vote\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const reset = useCallback(() => {\n setData(undefined);\n setError(null);\n }, []);\n\n return { mutate, isLoading, error, data, reset };\n}\n\n// ============================================\n// Comment Mutation Hook\n// ============================================\n\n/**\n * Hook to add a comment\n */\nexport function useAddComment(): UseMutationResult<\n { commentId: string },\n AddCommentParams\n> {\n const client = useRefletClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<{ commentId: string }>();\n\n const mutate = useCallback(\n async (params: AddCommentParams) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.comment(params);\n setData(result);\n return result;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(\"Failed to add comment\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const reset = useCallback(() => {\n setData(undefined);\n setError(null);\n }, []);\n\n return { mutate, isLoading, error, data, reset };\n}\n\n// ============================================\n// Subscribe Mutation Hook\n// ============================================\n\n/**\n * Hook to subscribe/unsubscribe to feedback\n */\nexport function useSubscription(): {\n subscribe: (feedbackId: string) => Promise<{ subscribed: boolean }>;\n unsubscribe: (feedbackId: string) => Promise<{ unsubscribed: boolean }>;\n isLoading: boolean;\n error: Error | null;\n} {\n const client = useRefletClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const subscribe = useCallback(\n async (feedbackId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.subscribe(feedbackId);\n return result;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(\"Failed to subscribe\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const unsubscribe = useCallback(\n async (feedbackId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.unsubscribe(feedbackId);\n return result;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(\"Failed to unsubscribe\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n return { subscribe, unsubscribe, isLoading, error };\n}\n"]}
|
package/dist/server.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @example
|
|
6
6
|
* ```ts
|
|
7
|
-
* import { signUser } from '
|
|
7
|
+
* import { signUser } from 'reflet-sdk/server';
|
|
8
8
|
*
|
|
9
9
|
* const { token } = signUser(
|
|
10
10
|
* { id: user.id, email: user.email, name: user.name },
|
|
@@ -32,10 +32,12 @@ interface SignedUserToken {
|
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Sign a user token for secure client-side identification
|
|
35
|
+
* Uses HMAC-SHA256 for cryptographically secure signatures
|
|
35
36
|
*/
|
|
36
37
|
declare function signUser(user: SignUserOptions, secretKey: string, expiresInSeconds?: number): SignedUserToken;
|
|
37
38
|
/**
|
|
38
39
|
* Verify a user token
|
|
40
|
+
* Returns the user data if valid, null otherwise
|
|
39
41
|
*/
|
|
40
42
|
declare function verifyUser(token: string, secretKey: string): SignUserOptions | null;
|
|
41
43
|
|
package/dist/server.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createHmac } from 'crypto';
|
|
2
|
+
|
|
1
3
|
// src/server.ts
|
|
2
4
|
var PLUS_REGEX = /\+/g;
|
|
3
5
|
var SLASH_REGEX = /\//g;
|
|
@@ -26,7 +28,7 @@ function signUser(user, secretKey, expiresInSeconds = 86400) {
|
|
|
26
28
|
};
|
|
27
29
|
const headerB64 = base64UrlEncode(JSON.stringify(header));
|
|
28
30
|
const payloadB64 = base64UrlEncode(JSON.stringify(payload));
|
|
29
|
-
const signature =
|
|
31
|
+
const signature = createHmacSha256Signature(
|
|
30
32
|
`${headerB64}.${payloadB64}`,
|
|
31
33
|
secretKey
|
|
32
34
|
);
|
|
@@ -44,11 +46,11 @@ function verifyUser(token, secretKey) {
|
|
|
44
46
|
return null;
|
|
45
47
|
}
|
|
46
48
|
const [headerB64, payloadB64, signature] = parts;
|
|
47
|
-
const expectedSignature =
|
|
49
|
+
const expectedSignature = createHmacSha256Signature(
|
|
48
50
|
`${headerB64}.${payloadB64}`,
|
|
49
51
|
secretKey
|
|
50
52
|
);
|
|
51
|
-
if (signature
|
|
53
|
+
if (!constantTimeEqual(signature, expectedSignature)) {
|
|
52
54
|
return null;
|
|
53
55
|
}
|
|
54
56
|
try {
|
|
@@ -72,27 +74,30 @@ function verifyUser(token, secretKey) {
|
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
function base64UrlEncode(str) {
|
|
75
|
-
const base64 =
|
|
77
|
+
const base64 = Buffer.from(str).toString("base64");
|
|
76
78
|
return base64.replace(PLUS_REGEX, "-").replace(SLASH_REGEX, "_").replace(PADDING_REGEX, "");
|
|
77
79
|
}
|
|
78
80
|
function base64UrlDecode(str) {
|
|
79
81
|
const padding = 4 - str.length % 4;
|
|
80
82
|
const paddedStr = padding < 4 ? str + "=".repeat(padding) : str;
|
|
81
83
|
const base64 = paddedStr.replace(DASH_REGEX, "+").replace(UNDERSCORE_REGEX, "/");
|
|
82
|
-
|
|
83
|
-
return Buffer.from(base64, "base64").toString();
|
|
84
|
-
}
|
|
85
|
-
return atob(base64);
|
|
84
|
+
return Buffer.from(base64, "base64").toString();
|
|
86
85
|
}
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
function createHmacSha256Signature(data, secret) {
|
|
87
|
+
const hmac = createHmac("sha256", secret);
|
|
88
|
+
hmac.update(data);
|
|
89
|
+
const signature = hmac.digest("base64");
|
|
90
|
+
return signature.replace(PLUS_REGEX, "-").replace(SLASH_REGEX, "_").replace(PADDING_REGEX, "");
|
|
91
|
+
}
|
|
92
|
+
function constantTimeEqual(a, b) {
|
|
93
|
+
if (a.length !== b.length) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
let result = 0;
|
|
97
|
+
for (let i = 0; i < a.length; i++) {
|
|
98
|
+
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
94
99
|
}
|
|
95
|
-
return
|
|
100
|
+
return result === 0;
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
export { signUser, verifyUser };
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"names":[],"mappings":";;;AAkBA,IAAM,UAAA,GAAa,KAAA;AACnB,IAAM,WAAA,GAAc,KAAA;AACpB,IAAM,aAAA,GAAgB,KAAA;AACtB,IAAM,UAAA,GAAa,IAAA;AACnB,IAAM,gBAAA,GAAmB,IAAA;AA0BlB,SAAS,QAAA,CACd,IAAA,EACA,SAAA,EACA,gBAAA,GAAmB,KAAA,EACF;AACjB,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,EACnD;AAEA,EAAA,IAAI,CAAC,KAAK,EAAA,EAAI;AACZ,IAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AACxC,EAAA,MAAM,MAAM,GAAA,GAAM,gBAAA;AAElB,EAAA,MAAM,MAAA,GAAS,EAAE,GAAA,EAAK,OAAA,EAAS,KAAK,KAAA,EAAM;AAC1C,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,KAAK,IAAA,CAAK,EAAA;AAAA,IACV,IAAI,IAAA,CAAK,EAAA;AAAA,IACT,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,GAAA,EAAK,GAAA;AAAA,IACL;AAAA,GACF;AAEA,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA;AACxD,EAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAG1D,EAAA,MAAM,SAAA,GAAY,yBAAA;AAAA,IAChB,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAAA,IAC1B;AAAA,GACF;AAEA,EAAA,OAAO;AAAA,IACL,OAAO,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,UAAU,IAAI,SAAS,CAAA,CAAA;AAAA,IAC9C,WAAW,GAAA,GAAM;AAAA,GACnB;AACF;AAMO,SAAS,UAAA,CACd,OACA,SAAA,EACwB;AACxB,EAAA,IAAI,EAAE,SAAS,SAAA,CAAA,EAAY;AACzB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA;AAC7B,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,CAAC,SAAA,EAAW,UAAA,EAAY,SAAS,CAAA,GAAI,KAAA;AAG3C,EAAA,MAAM,iBAAA,GAAoB,yBAAA;AAAA,IACxB,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAAA,IAC1B;AAAA,GACF;AAEA,EAAA,IAAI,CAAC,iBAAA,CAAkB,SAAA,EAAW,iBAAiB,CAAA,EAAG;AACpD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,eAAA,CAAgB,UAAU,CAAC,CAAA;AAWtD,IAAA,IAAI,QAAQ,GAAA,IAAO,IAAA,CAAK,KAAI,GAAI,OAAA,CAAQ,MAAM,GAAA,EAAM;AAClD,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,EAAA,IAAM,OAAA,CAAQ,GAAA;AACrC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,MAAA;AAAA,MACJ,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,UAAU,OAAA,CAAQ;AAAA,KACpB;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMA,SAAS,gBAAgB,GAAA,EAAqB;AAC5C,EAAA,MAAM,SAAS,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,SAAS,QAAQ,CAAA;AAEjD,EAAA,OAAO,MAAA,CACJ,OAAA,CAAQ,UAAA,EAAY,GAAG,CAAA,CACvB,OAAA,CAAQ,WAAA,EAAa,GAAG,CAAA,CACxB,OAAA,CAAQ,aAAA,EAAe,EAAE,CAAA;AAC9B;AAEA,SAAS,gBAAgB,GAAA,EAAqB;AAE5C,EAAA,MAAM,OAAA,GAAU,CAAA,GAAK,GAAA,CAAI,MAAA,GAAS,CAAA;AAClC,EAAA,MAAM,YAAY,OAAA,GAAU,CAAA,GAAI,MAAM,GAAA,CAAI,MAAA,CAAO,OAAO,CAAA,GAAI,GAAA;AAG5D,EAAA,MAAM,MAAA,GAAS,UACZ,OAAA,CAAQ,UAAA,EAAY,GAAG,CAAA,CACvB,OAAA,CAAQ,kBAAkB,GAAG,CAAA;AAEhC,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ,QAAQ,EAAE,QAAA,EAAS;AAChD;AAKA,SAAS,yBAAA,CAA0B,MAAc,MAAA,EAAwB;AACvE,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,QAAA,EAAU,MAAM,CAAA;AACxC,EAAA,IAAA,CAAK,OAAO,IAAI,CAAA;AAChB,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA;AAGtC,EAAA,OAAO,SAAA,CACJ,OAAA,CAAQ,UAAA,EAAY,GAAG,CAAA,CACvB,OAAA,CAAQ,WAAA,EAAa,GAAG,CAAA,CACxB,OAAA,CAAQ,aAAA,EAAe,EAAE,CAAA;AAC9B;AAKA,SAAS,iBAAA,CAAkB,GAAW,CAAA,EAAoB;AACxD,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AAEjC,IAAA,MAAA,IAAU,EAAE,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,EAC5C;AAEA,EAAA,OAAO,MAAA,KAAW,CAAA;AACpB","file":"server.js","sourcesContent":["/**\n * Server-side utilities for Reflet SDK\n * Use these functions on your backend to securely sign user tokens\n *\n * @example\n * ```ts\n * import { signUser } from 'reflet-sdk/server';\n *\n * const { token } = signUser(\n * { id: user.id, email: user.email, name: user.name },\n * process.env.REFLET_SECRET_KEY!\n * );\n * ```\n */\n\nimport { createHmac } from \"node:crypto\";\n\n// Top-level regex patterns for base64url encoding\nconst PLUS_REGEX = /\\+/g;\nconst SLASH_REGEX = /\\//g;\nconst PADDING_REGEX = /=+$/;\nconst DASH_REGEX = /-/g;\nconst UNDERSCORE_REGEX = /_/g;\n\nexport interface SignUserOptions {\n /** User's unique ID in your system */\n id: string;\n /** User's email address */\n email?: string;\n /** User's display name */\n name?: string;\n /** URL to user's avatar image */\n avatar?: string;\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\nexport interface SignedUserToken {\n /** The signed JWT token */\n token: string;\n /** Token expiration timestamp (ms) */\n expiresAt: number;\n}\n\n/**\n * Sign a user token for secure client-side identification\n * Uses HMAC-SHA256 for cryptographically secure signatures\n */\nexport function signUser(\n user: SignUserOptions,\n secretKey: string,\n expiresInSeconds = 86_400 // 24 hours default\n): SignedUserToken {\n if (!secretKey) {\n throw new Error(\"signUser: secretKey is required\");\n }\n\n if (!user.id) {\n throw new Error(\"signUser: user.id is required\");\n }\n\n const now = Math.floor(Date.now() / 1000);\n const exp = now + expiresInSeconds;\n\n const header = { alg: \"HS256\", typ: \"JWT\" };\n const payload = {\n sub: user.id,\n id: user.id,\n email: user.email,\n name: user.name,\n avatar: user.avatar,\n metadata: user.metadata,\n iat: now,\n exp,\n };\n\n const headerB64 = base64UrlEncode(JSON.stringify(header));\n const payloadB64 = base64UrlEncode(JSON.stringify(payload));\n\n // Create signature using HMAC-SHA256\n const signature = createHmacSha256Signature(\n `${headerB64}.${payloadB64}`,\n secretKey\n );\n\n return {\n token: `${headerB64}.${payloadB64}.${signature}`,\n expiresAt: exp * 1000,\n };\n}\n\n/**\n * Verify a user token\n * Returns the user data if valid, null otherwise\n */\nexport function verifyUser(\n token: string,\n secretKey: string\n): SignUserOptions | null {\n if (!(token && secretKey)) {\n return null;\n }\n\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return null;\n }\n\n const [headerB64, payloadB64, signature] = parts;\n\n // Verify signature using constant-time comparison\n const expectedSignature = createHmacSha256Signature(\n `${headerB64}.${payloadB64}`,\n secretKey\n );\n\n if (!constantTimeEqual(signature, expectedSignature)) {\n return null;\n }\n\n try {\n const payload = JSON.parse(base64UrlDecode(payloadB64)) as {\n id?: string;\n sub?: string;\n email?: string;\n name?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n exp?: number;\n };\n\n // Check expiration\n if (payload.exp && Date.now() > payload.exp * 1000) {\n return null;\n }\n\n const userId = payload.id ?? payload.sub;\n if (!userId) {\n return null;\n }\n\n return {\n id: userId,\n email: payload.email,\n name: payload.name,\n avatar: payload.avatar,\n metadata: payload.metadata,\n };\n } catch {\n return null;\n }\n}\n\n// ============================================\n// Utility Functions\n// ============================================\n\nfunction base64UrlEncode(str: string): string {\n const base64 = Buffer.from(str).toString(\"base64\");\n\n return base64\n .replace(PLUS_REGEX, \"-\")\n .replace(SLASH_REGEX, \"_\")\n .replace(PADDING_REGEX, \"\");\n}\n\nfunction base64UrlDecode(str: string): string {\n // Restore base64 padding\n const padding = 4 - (str.length % 4);\n const paddedStr = padding < 4 ? str + \"=\".repeat(padding) : str;\n\n // Replace URL-safe characters\n const base64 = paddedStr\n .replace(DASH_REGEX, \"+\")\n .replace(UNDERSCORE_REGEX, \"/\");\n\n return Buffer.from(base64, \"base64\").toString();\n}\n\n/**\n * Create HMAC-SHA256 signature (cryptographically secure)\n */\nfunction createHmacSha256Signature(data: string, secret: string): string {\n const hmac = createHmac(\"sha256\", secret);\n hmac.update(data);\n const signature = hmac.digest(\"base64\");\n\n // Convert to base64url\n return signature\n .replace(PLUS_REGEX, \"-\")\n .replace(SLASH_REGEX, \"_\")\n .replace(PADDING_REGEX, \"\");\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks\n */\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n // biome-ignore lint/suspicious/noBitwiseOperators: intentional for constant-time comparison\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n\n return result === 0;\n}\n\n// Export types\nexport type { SignUserOptions as RefletServerUser };\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reflet-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Official Reflet SDK - Collect user feedback, feature requests, and bug reports from your app",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Reflet <hello@reflet.app>",
|
|
@@ -56,7 +56,12 @@
|
|
|
56
56
|
"build": "tsup",
|
|
57
57
|
"dev": "tsup --watch",
|
|
58
58
|
"typecheck": "tsc --noEmit",
|
|
59
|
-
"
|
|
59
|
+
"lint": "cd ../.. && bun x ultracite check packages/sdk",
|
|
60
|
+
"prepublishOnly": "npm run build",
|
|
61
|
+
"version:patch": "npm version patch && npm run release",
|
|
62
|
+
"version:minor": "npm version minor && npm run release",
|
|
63
|
+
"version:major": "npm version major && npm run release",
|
|
64
|
+
"release": "npm run build && npm publish"
|
|
60
65
|
},
|
|
61
66
|
"peerDependencies": {
|
|
62
67
|
"react": "^18.0.0 || ^19.0.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/client.ts"],"names":[],"mappings":"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","file":"chunk-RDQP4VCA.js","sourcesContent":["/**\n * Reflet SDK Types\n */\n\n// ============================================\n// Configuration\n// ============================================\n\nexport interface RefletConfig {\n /** Your board's public API key (fb_pub_xxx) */\n publicKey: string;\n /** API base URL (defaults to https://api.reflet.app) */\n baseUrl?: string;\n /** User identification for SSO */\n user?: RefletUser;\n /** Pre-signed user token (alternative to user object) */\n userToken?: string;\n}\n\nexport interface RefletUser {\n /** Unique identifier for the user in your system */\n id: string;\n /** User's email address */\n email?: string;\n /** User's display name */\n name?: string;\n /** URL to user's avatar image */\n avatar?: string;\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n// ============================================\n// API Responses\n// ============================================\n\nexport interface BoardConfig {\n id: string;\n name: string;\n slug: string;\n description?: string;\n isPublic: boolean;\n settings?: BoardSettings;\n organization: {\n id: string;\n name: string;\n slug: string;\n logo?: string;\n primaryColor?: string;\n };\n statuses: BoardStatus[];\n}\n\nexport interface BoardSettings {\n allowAnonymousVoting?: boolean;\n requireApproval?: boolean;\n defaultStatus?: FeedbackStatus;\n}\n\nexport interface BoardStatus {\n id: string;\n name: string;\n color: string;\n icon?: string;\n order: number;\n}\n\nexport type FeedbackStatus =\n | \"open\"\n | \"under_review\"\n | \"planned\"\n | \"in_progress\"\n | \"completed\"\n | \"closed\";\n\n// ============================================\n// Feedback\n// ============================================\n\nexport interface FeedbackItem {\n id: string;\n title: string;\n description: string;\n status: FeedbackStatus;\n voteCount: number;\n commentCount: number;\n isPinned: boolean;\n hasVoted: boolean;\n createdAt: number;\n updatedAt: number;\n completedAt?: number;\n tags: FeedbackTag[];\n boardStatus: {\n id: string;\n name: string;\n color: string;\n } | null;\n author: FeedbackAuthor | null;\n}\n\nexport interface FeedbackDetail extends FeedbackItem {\n isSubscribed: boolean;\n}\n\nexport interface FeedbackTag {\n id: string;\n name: string;\n color: string;\n}\n\nexport interface FeedbackAuthor {\n name?: string;\n email?: string;\n avatar?: string;\n isExternal: boolean;\n}\n\nexport interface FeedbackListResponse {\n items: FeedbackItem[];\n total: number;\n hasMore: boolean;\n}\n\nexport interface FeedbackListParams {\n /** Filter by custom status ID */\n statusId?: string;\n /** Filter by status name */\n status?: FeedbackStatus;\n /** Search in title and description */\n search?: string;\n /** Sort order */\n sortBy?: \"votes\" | \"newest\" | \"oldest\" | \"comments\";\n /** Number of items to return (max 100) */\n limit?: number;\n /** Offset for pagination */\n offset?: number;\n}\n\nexport interface CreateFeedbackParams {\n title: string;\n description: string;\n}\n\nexport interface CreateFeedbackResponse {\n feedbackId: string;\n isApproved: boolean;\n}\n\nexport interface VoteResponse {\n voted: boolean;\n voteCount: number;\n}\n\n// ============================================\n// Comments\n// ============================================\n\nexport interface Comment {\n id: string;\n body: string;\n isOfficial: boolean;\n author: FeedbackAuthor | null;\n replies: CommentReply[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface CommentReply {\n id: string;\n body: string;\n isOfficial: boolean;\n author: FeedbackAuthor | null;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface AddCommentParams {\n feedbackId: string;\n body: string;\n parentId?: string;\n}\n\nexport interface AddCommentResponse {\n commentId: string;\n}\n\n// ============================================\n// Subscriptions\n// ============================================\n\nexport interface SubscribeResponse {\n subscribed: boolean;\n alreadySubscribed?: boolean;\n}\n\nexport interface UnsubscribeResponse {\n unsubscribed: boolean;\n wasNotSubscribed?: boolean;\n}\n\n// ============================================\n// Roadmap\n// ============================================\n\nexport interface Roadmap {\n lanes: RoadmapLane[];\n}\n\nexport interface RoadmapLane {\n id: string;\n name: string;\n color: string;\n items: RoadmapItem[];\n}\n\nexport interface RoadmapItem {\n id: string;\n title: string;\n status: FeedbackStatus;\n voteCount: number;\n}\n\n// ============================================\n// Changelog\n// ============================================\n\nexport interface ChangelogEntry {\n id: string;\n title: string;\n description?: string;\n version?: string;\n publishedAt?: number;\n feedback: { id: string; title: string }[];\n}\n\n// ============================================\n// Errors\n// ============================================\n\nexport class RefletError extends Error {\n readonly status: number;\n readonly code?: string;\n\n constructor(message: string, status: number, code?: string) {\n super(message);\n this.name = \"RefletError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport class RefletAuthError extends RefletError {\n constructor(message: string) {\n super(message, 401, \"AUTH_ERROR\");\n this.name = \"RefletAuthError\";\n }\n}\n\nexport class RefletValidationError extends RefletError {\n constructor(message: string) {\n super(message, 400, \"VALIDATION_ERROR\");\n this.name = \"RefletValidationError\";\n }\n}\n\nexport class RefletNotFoundError extends RefletError {\n constructor(message: string) {\n super(message, 404, \"NOT_FOUND\");\n this.name = \"RefletNotFoundError\";\n }\n}\n","import {\n type AddCommentParams,\n type AddCommentResponse,\n type BoardConfig,\n type ChangelogEntry,\n type Comment,\n type CreateFeedbackParams,\n type CreateFeedbackResponse,\n type FeedbackDetail,\n type FeedbackListParams,\n type FeedbackListResponse,\n RefletAuthError,\n type RefletConfig,\n RefletError,\n RefletNotFoundError,\n type RefletUser,\n type Roadmap,\n type SubscribeResponse,\n type UnsubscribeResponse,\n type VoteResponse,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://grateful-butterfly-1.convex.cloud\";\n\n/**\n * Reflet SDK Client\n *\n * @example\n * ```ts\n * import { Reflet } from '@reflet/sdk';\n *\n * const reflet = new Reflet({\n * publicKey: 'fb_pub_xxx',\n * user: { id: 'user_123', email: 'user@example.com', name: 'John' }\n * });\n *\n * // List feedback\n * const { items } = await reflet.list({ status: 'open' });\n *\n * // Vote on feedback\n * await reflet.vote('feedback_id');\n *\n * // Submit new feedback\n * await reflet.create({ title: 'Great idea', description: 'Details...' });\n * ```\n */\nexport class Reflet {\n private readonly publicKey: string;\n private readonly baseUrl: string;\n private userToken: string | undefined;\n private user: RefletUser | undefined;\n\n constructor(config: RefletConfig) {\n this.publicKey = config.publicKey;\n this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n this.userToken = config.userToken;\n this.user = config.user;\n\n if (!this.publicKey) {\n throw new Error(\"Reflet: publicKey is required\");\n }\n }\n\n /**\n * Update the user identification\n */\n setUser(user: RefletUser | undefined): void {\n this.user = user;\n this.userToken = undefined;\n }\n\n /**\n * Set the user token directly (for server-signed tokens)\n */\n setUserToken(token: string | undefined): void {\n this.userToken = token;\n this.user = undefined;\n }\n\n /**\n * Get the board configuration\n */\n async getConfig(): Promise<BoardConfig> {\n return await this.request<BoardConfig>(\"GET\", \"/api/v1/feedback\");\n }\n\n /**\n * List feedback items with optional filtering\n */\n async list(params?: FeedbackListParams): Promise<FeedbackListResponse> {\n const searchParams = new URLSearchParams();\n\n if (params?.statusId) {\n searchParams.set(\"statusId\", params.statusId);\n }\n if (params?.status) {\n searchParams.set(\"status\", params.status);\n }\n if (params?.search) {\n searchParams.set(\"search\", params.search);\n }\n if (params?.sortBy) {\n searchParams.set(\"sortBy\", params.sortBy);\n }\n if (params?.limit) {\n searchParams.set(\"limit\", String(params.limit));\n }\n if (params?.offset) {\n searchParams.set(\"offset\", String(params.offset));\n }\n\n const query = searchParams.toString();\n const url = `/api/v1/feedback/list${query ? `?${query}` : \"\"}`;\n\n return await this.request<FeedbackListResponse>(\"GET\", url);\n }\n\n /**\n * Get a single feedback item by ID\n */\n async get(feedbackId: string): Promise<FeedbackDetail> {\n const result = await this.request<FeedbackDetail | null>(\n \"GET\",\n `/api/v1/feedback/item?id=${encodeURIComponent(feedbackId)}`\n );\n\n if (!result) {\n throw new RefletNotFoundError(\"Feedback not found\");\n }\n\n return result;\n }\n\n /**\n * Create new feedback\n * Requires user identification\n */\n async create(params: CreateFeedbackParams): Promise<CreateFeedbackResponse> {\n return await this.request<CreateFeedbackResponse>(\n \"POST\",\n \"/api/v1/feedback/create\",\n params\n );\n }\n\n /**\n * Toggle vote on feedback\n * Requires user identification\n */\n async vote(\n feedbackId: string,\n type: \"upvote\" | \"downvote\" = \"upvote\"\n ): Promise<VoteResponse> {\n return await this.request<VoteResponse>(\"POST\", \"/api/v1/feedback/vote\", {\n feedbackId,\n voteType: type,\n });\n }\n\n /**\n * Get comments for a feedback item\n */\n async getComments(\n feedbackId: string,\n sortBy: \"newest\" | \"oldest\" = \"oldest\"\n ): Promise<Comment[]> {\n return await this.request<Comment[]>(\n \"GET\",\n `/api/v1/feedback/comments?feedbackId=${encodeURIComponent(feedbackId)}&sortBy=${sortBy}`\n );\n }\n\n /**\n * Add a comment to feedback\n * Requires user identification\n */\n async comment(params: AddCommentParams): Promise<AddCommentResponse> {\n return await this.request<AddCommentResponse>(\n \"POST\",\n \"/api/v1/feedback/comment\",\n params\n );\n }\n\n /**\n * Subscribe to feedback updates\n * Requires user identification\n */\n async subscribe(feedbackId: string): Promise<SubscribeResponse> {\n return await this.request<SubscribeResponse>(\n \"POST\",\n \"/api/v1/feedback/subscribe\",\n {\n feedbackId,\n }\n );\n }\n\n /**\n * Unsubscribe from feedback updates\n * Requires user identification\n */\n async unsubscribe(feedbackId: string): Promise<UnsubscribeResponse> {\n return await this.request<UnsubscribeResponse>(\n \"POST\",\n \"/api/v1/feedback/unsubscribe\",\n {\n feedbackId,\n }\n );\n }\n\n /**\n * Get roadmap data\n */\n async getRoadmap(): Promise<Roadmap> {\n return await this.request<Roadmap>(\"GET\", \"/api/v1/feedback/roadmap\");\n }\n\n /**\n * Get changelog entries\n */\n async getChangelog(limit?: number): Promise<ChangelogEntry[]> {\n const url = limit\n ? `/api/v1/feedback/changelog?limit=${limit}`\n : \"/api/v1/feedback/changelog\";\n\n return await this.request<ChangelogEntry[]>(\"GET\", url);\n }\n\n /**\n * Make an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.publicKey}`,\n };\n\n // Add user token if available\n const token = this.userToken ?? this.generateUserToken();\n if (token) {\n headers[\"X-User-Token\"] = token;\n }\n\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n const data = (await response.json()) as T | { error: string };\n\n if (!response.ok) {\n const errorMessage =\n (data as { error?: string }).error ?? \"Request failed\";\n\n if (response.status === 401) {\n throw new RefletAuthError(errorMessage);\n }\n if (response.status === 404) {\n throw new RefletNotFoundError(errorMessage);\n }\n\n throw new RefletError(errorMessage, response.status);\n }\n\n return data as T;\n }\n\n /**\n * Generate a simple user token for client-side use\n * Note: For production, use server-side token signing\n */\n private generateUserToken(): string | undefined {\n if (!this.user) {\n return undefined;\n }\n\n // Simple base64 encoding for client-side use\n // In production, tokens should be signed server-side\n const payload = {\n id: this.user.id,\n email: this.user.email,\n name: this.user.name,\n iat: Math.floor(Date.now() / 1000),\n exp: Math.floor(Date.now() / 1000) + 86_400, // 24 hours\n };\n\n const header = btoa(JSON.stringify({ alg: \"none\", typ: \"JWT\" }));\n const payloadB64 = btoa(JSON.stringify(payload));\n\n return `${header}.${payloadB64}.`;\n }\n}\n"]}
|